Skip to content

Commit 52796b8

Browse files
authored
Merge pull request #912 from psafont/fix-move
Fix folder relocations on existing folders
2 parents 91e9e9f + 50f7c35 commit 52796b8

File tree

4 files changed

+72
-26
lines changed

4 files changed

+72
-26
lines changed

cwltool/docker.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,10 @@ def add_volumes(self, pathmapper, runtime, secret_store=None):
218218
if not vol.staged:
219219
continue
220220
host_outdir_tgt = None # type: Optional[Text]
221-
if vol.target.startswith(container_outdir+"/"):
221+
if vol.target.startswith(container_outdir + "/"):
222222
host_outdir_tgt = os.path.join(
223223
host_outdir, vol.target[len(container_outdir)+1:])
224+
224225
if vol.type in ("File", "Directory"):
225226
if not vol.resolved.startswith("_:"):
226227
_check_docker_machine_path(docker_windows_path_adjust(
@@ -244,7 +245,8 @@ def add_volumes(self, pathmapper, runtime, secret_store=None):
244245
elif vol.type == "WritableDirectory":
245246
if vol.resolved.startswith("_:"):
246247
if host_outdir_tgt:
247-
os.makedirs(host_outdir_tgt, 0o0755)
248+
if not os.path.exists(host_outdir_tgt):
249+
os.makedirs(host_outdir_tgt, 0o0755)
248250
else:
249251
raise WorkflowException(
250252
"Unable to compute host_outdir_tgt for "
@@ -268,6 +270,9 @@ def add_volumes(self, pathmapper, runtime, secret_store=None):
268270
else:
269271
contents = vol.resolved
270272
if host_outdir_tgt:
273+
dirname = os.path.dirname(host_outdir_tgt)
274+
if not os.path.exists(dirname):
275+
os.makedirs(dirname, 0o0755)
271276
with open(host_outdir_tgt, "wb") as file_literal:
272277
file_literal.write(contents.encode("utf-8"))
273278
else:

cwltool/process.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -299,29 +299,30 @@ def _relocate(src, dst):
299299
if src == dst:
300300
return
301301

302-
if action == "move":
303-
# do not move anything if we are trying to move an entity from
304-
# outside of the source directories
305-
if any(src.startswith(path + "/") for path in source_directories):
306-
_logger.debug("Moving %s to %s", src, dst)
307-
if fs_access.isdir(src) and fs_access.isdir(dst):
308-
# merge directories
309-
for dir_entry in scandir(src):
310-
_relocate(dir_entry, fs_access.join(
311-
dst, dir_entry.name))
312-
else:
313-
shutil.move(src, dst)
314-
return
315-
316-
_logger.debug("Copying %s to %s", src, dst)
317-
if fs_access.isdir(src):
318-
if os.path.isdir(dst):
319-
shutil.rmtree(dst)
320-
elif os.path.isfile(dst):
321-
os.unlink(dst)
322-
shutil.copytree(src, dst)
323-
else:
324-
shutil.copy2(src, dst)
302+
# If the source is not contained in source_directories we're not allowed to delete it
303+
src_can_deleted = any(os.path.commonprefix([p, src]) == p for p in source_directories)
304+
305+
_action = "move" if action == "move" and src_can_deleted else "copy"
306+
307+
if _action == "move":
308+
_logger.debug("Moving %s to %s", src, dst)
309+
if fs_access.isdir(src) and fs_access.isdir(dst):
310+
# merge directories
311+
for dir_entry in scandir(src):
312+
_relocate(dir_entry.path, fs_access.join(dst, dir_entry.name))
313+
else:
314+
shutil.move(src, dst)
315+
316+
elif _action == "copy":
317+
_logger.debug("Copying %s to %s", src, dst)
318+
if fs_access.isdir(src):
319+
if os.path.isdir(dst):
320+
shutil.rmtree(dst)
321+
elif os.path.isfile(dst):
322+
os.unlink(dst)
323+
shutil.copytree(src, dst)
324+
else:
325+
shutil.copy2(src, dst)
325326

326327
outfiles = list(_collectDirEntries(outputObj))
327328
pm = path_mapper(outfiles, "", destination_path, separateDirs=False)
@@ -357,7 +358,8 @@ def relink(relinked, # type: Dict[Text, Text]
357358
os.unlink(path)
358359
os.symlink(os.path.relpath(link_name, path), path)
359360
else:
360-
if any(real_path.startswith(path + "/") for path in source_directories):
361+
if any(os.path.commonprefix([path, real_path]) == path \
362+
for path in source_directories):
361363
os.unlink(path)
362364
os.rename(real_path, path)
363365
relinked[real_path] = path

tests/test_relocate.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from cwltool.main import main
2+
3+
from .util import get_data, needs_docker
4+
5+
@needs_docker
6+
def test_for_910():
7+
assert main([get_data('tests/wf/910.cwl')]) == 0
8+
assert main([get_data('tests/wf/910.cwl')]) == 0

tests/wf/910.cwl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
cwlVersion: v1.0
2+
class: CommandLineTool
3+
4+
requirements:
5+
- class: InlineJavascriptRequirement
6+
- class: InitialWorkDirRequirement
7+
listing: |
8+
${
9+
return [{"class": "Directory",
10+
"basename": "default",
11+
"listing": [{"class": "File",
12+
"basename": "file.txt",
13+
"contents": "Hello world"}
14+
],
15+
"writable": true}]
16+
}
17+
18+
hints:
19+
- class: DockerRequirement
20+
dockerPull: ubuntu
21+
22+
inputs: []
23+
24+
outputs:
25+
26+
output_folder:
27+
type: Directory
28+
outputBinding:
29+
glob: "*"
30+
31+
baseCommand: [ls]

0 commit comments

Comments
 (0)