Skip to content

Commit

Permalink
fix: file ownership of files copied into/from the container
Browse files Browse the repository at this point in the history
Use `docker cp -a` to copy files in/out of the container.
This requires to create the container with `--user` for the command not to fail.
  • Loading branch information
mayeut committed Sep 14, 2024
1 parent c779eab commit 0eed012
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 3 deletions.
7 changes: 4 additions & 3 deletions cibuildwheel/oci_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ def __enter__(self) -> Self:
"create",
"--env=CIBUILDWHEEL",
"--env=SOURCE_DATE_EPOCH",
"--user=root",
f"--name={self.name}",
"--interactive",
*(["--volume=/:/host"] if not self.engine.disable_host_mount else []),
Expand Down Expand Up @@ -311,15 +312,15 @@ def __exit__(
def copy_into(self, from_path: Path, to_path: PurePath) -> None:
if from_path.is_dir():
self.call(["mkdir", "-p", to_path])
call(self.engine.name, "cp", f"{from_path}/.", f"{self.name}:{to_path}")
call(self.engine.name, "cp", "-a", f"{from_path}/.", f"{self.name}:{to_path}")
else:
self.call(["mkdir", "-p", to_path.parent])
call(self.engine.name, "cp", from_path, f"{self.name}:{to_path}")
call(self.engine.name, "cp", "-a", from_path, f"{self.name}:{to_path}")

def copy_out(self, from_path: PurePath, to_path: Path) -> None:
# note: we assume from_path is a dir
to_path.mkdir(parents=True, exist_ok=True)
call(self.engine.name, "cp", f"{self.name}:{from_path}/.", to_path)
call(self.engine.name, "cp", "-a", f"{self.name}:{from_path}/.", to_path)

def glob(self, path: PurePosixPath, pattern: str) -> list[PurePosixPath]:
glob_pattern = path.joinpath(pattern)
Expand Down
14 changes: 14 additions & 0 deletions unit_test/oci_container_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ def test_file_operation(tmp_path: Path, container_engine):

container.copy_into(original_test_file, dst_file)

owner = container.call(["stat", "-c", "%u:%g", dst_file], capture_output=True).strip()
assert owner == "0:0"

output = container.call(["cat", dst_file], capture_output=True)
assert test_binary_data == bytes(output, encoding="utf8", errors="surrogateescape")

Expand All @@ -266,6 +269,12 @@ def test_dir_operations(tmp_path: Path, container_engine):
dst_file = dst_dir / "test.dat"
container.copy_into(test_dir, dst_dir)

owner = container.call(["stat", "-c", "%u:%g", dst_dir], capture_output=True).strip()
assert owner == "0:0"

owner = container.call(["stat", "-c", "%u:%g", dst_file], capture_output=True).strip()
assert owner == "0:0"

output = container.call(["cat", dst_file], capture_output=True)
assert test_binary_data == bytes(output, encoding="utf8", errors="surrogateescape")

Expand All @@ -276,6 +285,11 @@ def test_dir_operations(tmp_path: Path, container_engine):
new_test_dir = tmp_path / "test_dir_new"
container.copy_out(dst_dir, new_test_dir)

assert os.getuid() == new_test_dir.stat().st_uid
assert os.getgid() == new_test_dir.stat().st_gid
assert os.getuid() == (new_test_dir / "test.dat").stat().st_uid
assert os.getgid() == (new_test_dir / "test.dat").stat().st_gid

assert test_binary_data == (new_test_dir / "test.dat").read_bytes()


Expand Down

0 comments on commit 0eed012

Please sign in to comment.