11import logging
2+ import subprocess
3+ import tempfile
4+ from pathlib import Path
5+
6+ from minisweagent .environments .docker import DockerEnvironment
27
38
49def assert_zero_exit_code (
@@ -10,3 +15,101 @@ def assert_zero_exit_code(
1015 logger .error (msg )
1116 raise RuntimeError (msg )
1217 return result
18+
19+
20+ def copy_between_containers (
21+ src_container : DockerEnvironment ,
22+ dest_container : DockerEnvironment ,
23+ src_path : str | Path ,
24+ dest_path : str | Path ,
25+ ):
26+ """
27+ Copy files from one Docker container to another via a temporary local directory.
28+ """
29+ with tempfile .TemporaryDirectory () as temp_dir :
30+ temp_path = Path (temp_dir ) / Path (src_path ).name
31+
32+ # Copy from source container to temporary local directory
33+ cmd_src = [
34+ "docker" ,
35+ "cp" ,
36+ f"{ src_container .container_id } :{ src_path } " ,
37+ str (temp_path ),
38+ ]
39+ result_src = subprocess .run (
40+ cmd_src , check = False , capture_output = True , text = True
41+ )
42+ if result_src .returncode != 0 :
43+ raise RuntimeError (
44+ f"Failed to copy from { src_container .container_id } to local temp: { result_src .stdout } { result_src .stderr } "
45+ )
46+
47+ # Ensure destination folder exists
48+ assert_zero_exit_code (
49+ dest_container .execute (f"mkdir -p { Path (dest_path ).parent } " )
50+ )
51+
52+ # Copy from temporary local directory to destination container
53+ cmd_dest = [
54+ "docker" ,
55+ "cp" ,
56+ str (temp_path ),
57+ f"{ dest_container .container_id } :{ dest_path } " ,
58+ ]
59+ result_dest = subprocess .run (
60+ cmd_dest , check = False , capture_output = True , text = True
61+ )
62+ if result_dest .returncode != 0 :
63+ raise RuntimeError (
64+ f"Failed to copy from local temp to { dest_container .container_id } : { result_dest .stdout } { result_dest .stderr } "
65+ )
66+
67+
68+ def copy_file_to_container (
69+ container : DockerEnvironment ,
70+ src_path : str | Path ,
71+ dest_path : str | Path ,
72+ ):
73+ """
74+ Copy a file from the local filesystem to a Docker container.
75+ """
76+ if not str (dest_path ).startswith ("/" ):
77+ # If not an absolute path, assume relative to container's cwd
78+ dest_path = f"{ container .config .cwd } /{ dest_path } "
79+ cmd = [
80+ "docker" ,
81+ "cp" ,
82+ str (src_path ),
83+ f"{ container .container_id } :{ dest_path } " ,
84+ ]
85+ # Ensure destination folder exists
86+ assert_zero_exit_code (container .execute (f"mkdir -p { Path (dest_path ).parent } " ))
87+ result = subprocess .run (cmd , check = False , capture_output = True , text = True )
88+ if result .returncode != 0 :
89+ raise RuntimeError (
90+ f"Failed to copy { src_path } to { container .container_id } :{ dest_path } : { result .stdout } { result .stderr } "
91+ )
92+ return result
93+
94+
95+ def copy_file_from_container (
96+ container : DockerEnvironment ,
97+ src_path : str | Path ,
98+ dest_path : str | Path ,
99+ ):
100+ """
101+ Copy a file from a Docker container to the local filesystem.
102+ """
103+ cmd = [
104+ "docker" ,
105+ "cp" ,
106+ f"{ container .container_id } :{ src_path } " ,
107+ str (dest_path ),
108+ ]
109+ Path (dest_path ).parent .mkdir (parents = True , exist_ok = True )
110+ result = subprocess .run (cmd , check = False , capture_output = True , text = True )
111+ if result .returncode != 0 :
112+ raise RuntimeError (
113+ f"Failed to copy { container .container_id } :{ src_path } to { dest_path } : { result .stdout } { result .stderr } "
114+ )
115+ return result
0 commit comments