|
5 | 5 | import os |
6 | 6 | import platform |
7 | 7 | import shlex |
| 8 | +import shutil |
8 | 9 | import subprocess |
9 | 10 | import sys |
10 | 11 | import typing |
@@ -169,6 +170,9 @@ def __init__( |
169 | 170 | self.cwd = cwd |
170 | 171 | self.name: str | None = None |
171 | 172 | self.engine = engine |
| 173 | + self.host_tar_format = "" |
| 174 | + if sys.platform.startswith("darwin"): |
| 175 | + self.host_tar_format = "--format gnutar" |
172 | 176 |
|
173 | 177 | def _get_platform_args(self, *, oci_platform: OCIPlatform | None = None) -> tuple[str, str]: |
174 | 178 | if oci_platform is None: |
@@ -311,10 +315,38 @@ def __exit__( |
311 | 315 | def copy_into(self, from_path: Path, to_path: PurePath) -> None: |
312 | 316 | if from_path.is_dir(): |
313 | 317 | self.call(["mkdir", "-p", to_path]) |
314 | | - call(self.engine.name, "cp", f"{from_path}/.", f"{self.name}:{to_path}") |
| 318 | + subprocess.run( |
| 319 | + f"tar -c {self.host_tar_format} -f - . | {self.engine.name} exec -i {self.name} tar --no-same-owner -xC {shell_quote(to_path)} -f -", |
| 320 | + shell=True, |
| 321 | + check=True, |
| 322 | + cwd=from_path, |
| 323 | + ) |
315 | 324 | else: |
316 | | - self.call(["mkdir", "-p", to_path.parent]) |
317 | | - call(self.engine.name, "cp", from_path, f"{self.name}:{to_path}") |
| 325 | + exec_process: subprocess.Popen[bytes] |
| 326 | + with subprocess.Popen( |
| 327 | + [ |
| 328 | + self.engine.name, |
| 329 | + "exec", |
| 330 | + "-i", |
| 331 | + str(self.name), |
| 332 | + "sh", |
| 333 | + "-c", |
| 334 | + f"cat > {shell_quote(to_path)}", |
| 335 | + ], |
| 336 | + stdin=subprocess.PIPE, |
| 337 | + ) as exec_process: |
| 338 | + assert exec_process.stdin |
| 339 | + with open(from_path, "rb") as from_file: |
| 340 | + # Bug in mypy, https://github.com/python/mypy/issues/15031 |
| 341 | + shutil.copyfileobj(from_file, exec_process.stdin) # type: ignore[misc] |
| 342 | + |
| 343 | + exec_process.stdin.close() |
| 344 | + exec_process.wait() |
| 345 | + |
| 346 | + if exec_process.returncode: |
| 347 | + raise subprocess.CalledProcessError( |
| 348 | + exec_process.returncode, exec_process.args, None, None |
| 349 | + ) |
318 | 350 |
|
319 | 351 | def copy_out(self, from_path: PurePath, to_path: Path) -> None: |
320 | 352 | # note: we assume from_path is a dir |
|
0 commit comments