|
4 | 4 | # This source code is licensed under the BSD-style license found in the |
5 | 5 | # LICENSE file in the root directory of this source tree. |
6 | 6 |
|
| 7 | +import fnmatch |
7 | 8 | import io |
8 | 9 | import logging |
9 | 10 | import posixpath |
10 | 11 | import tarfile |
11 | 12 | import tempfile |
12 | | -from typing import IO, TYPE_CHECKING, Optional, Dict, Tuple, Mapping |
| 13 | +from typing import IO, TYPE_CHECKING, Optional, Dict, Tuple, Mapping, Iterable |
13 | 14 |
|
14 | 15 | import fsspec |
15 | 16 | import torchx |
@@ -129,17 +130,44 @@ def _build_context(img: str, workspace: str) -> IO[bytes]: |
129 | 130 | return f |
130 | 131 |
|
131 | 132 |
|
132 | | -def _copy_to_tarfile(workspace: str, tf: tarfile.TarFile) -> None: |
133 | | - # TODO(d4l3k) implement docker ignore files |
| 133 | +def _ignore(s: str, patterns: Iterable[str]) -> bool: |
| 134 | + match = False |
| 135 | + for pattern in patterns: |
| 136 | + if pattern.startswith("!") and fnmatch.fnmatch(s, pattern[1:]): |
| 137 | + match = False |
| 138 | + elif fnmatch.fnmatch(s, pattern): |
| 139 | + match = True |
| 140 | + return match |
| 141 | + |
134 | 142 |
|
| 143 | +def _copy_to_tarfile(workspace: str, tf: tarfile.TarFile) -> None: |
135 | 144 | fs, path = fsspec.core.url_to_fs(workspace) |
136 | 145 | assert isinstance(path, str), "path must be str" |
137 | 146 |
|
| 147 | + # load dockerignore |
| 148 | + # https://docs.docker.com/engine/reference/builder/#dockerignore-file |
| 149 | + ignore_patterns = [] |
| 150 | + ignore_path = posixpath.join(path, ".dockerignore") |
| 151 | + if fs.exists(ignore_path): |
| 152 | + with fs.open(ignore_path, "rt") as f: |
| 153 | + lines = f.readlines() |
| 154 | + for line in lines: |
| 155 | + line, _, _ = line.partition("#") |
| 156 | + line = line.strip() |
| 157 | + if len(line) == 0 or line == ".": |
| 158 | + continue |
| 159 | + ignore_patterns.append(line) |
| 160 | + |
138 | 161 | for dir, dirs, files in fs.walk(path, detail=True): |
139 | 162 | assert isinstance(dir, str), "path must be str" |
140 | 163 | relpath = posixpath.relpath(dir, path) |
| 164 | + if _ignore(relpath, ignore_patterns): |
| 165 | + continue |
141 | 166 | for file, info in files.items(): |
142 | 167 | with fs.open(info["name"], "rb") as f: |
143 | | - tinfo = tarfile.TarInfo(posixpath.join(relpath, file)) |
| 168 | + filepath = posixpath.join(relpath, file) if relpath != "." else file |
| 169 | + if _ignore(filepath, ignore_patterns): |
| 170 | + continue |
| 171 | + tinfo = tarfile.TarInfo(filepath) |
144 | 172 | tinfo.size = info["size"] |
145 | 173 | tf.addfile(tinfo, f) |
0 commit comments