Skip to content

Commit 1fd9831

Browse files
committed
Implement & test copying a directory
1 parent 3d5e078 commit 1fd9831

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

core/testcontainers/core/container.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,20 @@ def copy_into_container(self, transferable: Transferable, destination_in_contain
323323

324324
def _transfer_into_container(self, transferable: Transferable, destination_in_container: str, mode: int) -> None:
325325
if isinstance(transferable, bytes):
326-
file_content = transferable
326+
self._transfer_file_content_into_container(transferable, destination_in_container, mode)
327327
elif isinstance(transferable, pathlib.Path):
328-
assert transferable.is_file() # Temporary, only copying file supported
329-
file_content = transferable.read_bytes()
328+
if transferable.is_file():
329+
self._transfer_file_content_into_container(transferable.read_bytes(), destination_in_container, mode)
330+
elif transferable.is_dir():
331+
self._transfer_directory_into_container(transferable, destination_in_container, mode)
332+
else:
333+
raise TypeError(f"Path {transferable} is neither a file nor directory")
330334
else:
331335
raise TypeError("source must be bytes or PathLike")
332336

337+
def _transfer_file_content_into_container(
338+
self, file_content: bytes, destination_in_container: str, mode: int
339+
) -> None:
333340
fileobj = io.BytesIO()
334341
with tarfile.open(fileobj=fileobj, mode="w") as tar:
335342
tarinfo = tarfile.TarInfo(name=destination_in_container)
@@ -341,6 +348,20 @@ def _transfer_into_container(self, transferable: Transferable, destination_in_co
341348
rv = self._container.put_archive(path="/", data=fileobj.getvalue())
342349
assert rv is True
343350

351+
def _transfer_directory_into_container(
352+
self, source_directory: pathlib.Path, destination_in_container: str, mode: int
353+
) -> None:
354+
assert self._container is not None
355+
result = self._container.exec_run(["mkdir", "-p", destination_in_container])
356+
assert result.exit_code == 0
357+
358+
fileobj = io.BytesIO()
359+
with tarfile.open(fileobj=fileobj, mode="w") as tar:
360+
tar.add(source_directory, arcname=source_directory.name)
361+
fileobj.seek(0)
362+
rv = self._container.put_archive(path=destination_in_container, data=fileobj.getvalue())
363+
assert rv is True
364+
344365
def copy_from_container(self, source_in_container: str, destination_on_host: pathlib.Path) -> None:
345366
assert self._container is not None
346367
tar_stream, _ = self._container.get_archive(source_in_container)

core/tests/test_core.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,32 @@ def test_copy_file_from_container(tmp_path: Path):
125125
# Then
126126
assert destination_on_host.is_file()
127127
assert destination_on_host.read_text() == "hello world"
128+
129+
130+
def test_copy_directory_into_container(tmp_path: Path):
131+
# Given
132+
source_dir = tmp_path / "my_directory"
133+
source_dir.mkdir()
134+
my_file = source_dir / "my_file"
135+
my_file.write_bytes(b"hello world")
136+
137+
destination_in_container = "/tmp/my_destination_directory"
138+
139+
with DockerContainer("bash", command="sleep infinity") as container:
140+
# When
141+
container.copy_into_container(source_dir, destination_in_container)
142+
result = container.exec(f"ls {destination_in_container}")
143+
144+
# Then - my_directory exists
145+
assert result.exit_code == 0
146+
assert result.output == b"my_directory\n"
147+
148+
# Then - my_file is in directory
149+
result = container.exec(f"ls {destination_in_container}/my_directory")
150+
assert result.exit_code == 0
151+
assert result.output == b"my_file\n"
152+
153+
# Then - my_file contents are correct
154+
result = container.exec(f"cat {destination_in_container}/my_directory/my_file")
155+
assert result.exit_code == 0
156+
assert result.output == b"hello world"

0 commit comments

Comments
 (0)