Repository: DataBiosphere/toil

Issue:
CWL: some inputs paths get percent encoded but not decoded
In https://github.com/DataBiosphere/toil/pull/3972#issue-1085931737 @douglowe wrote

> Correcting logical checks inside upload_directory and
upload_file, to use schema_salad.ref_resolver.uri_file_path
for resolving file:/// paths. This ensures that encoded
special characters within the path are properly decoded again.

later

> My problem path was an output directory we were naming after a mutation (A:Gln2Cys) - the file string for this became: "file:///Users/douglowe/cwl-mutations/A%3AGln2Cys".

┆Issue is synchronized with this [Jira Task](https://ucsc-cgl.atlassian.net/browse/TOIL-1113)
┆friendlyId: TOIL-1113



Discussion:

Resolving patch:
diff --git a/src/toil/cwl/cwltoil.py b/src/toil/cwl/cwltoil.py
--- a/src/toil/cwl/cwltoil.py
+++ b/src/toil/cwl/cwltoil.py
@@ -1531,7 +1531,9 @@ def upload_directory(
         location = directory_metadata["location"] = schema_salad.ref_resolver.file_uri(
             cast(str, directory_metadata["path"])
         )
-    if location.startswith("file://") and not os.path.isdir(location[len("file://") :]):
+    if location.startswith("file://") and not os.path.isdir(
+        schema_salad.ref_resolver.uri_file_path(location)
+    ):
         if skip_broken:
             return
         else:
@@ -1579,7 +1581,7 @@ def upload_file(
             cast(str, file_metadata["path"])
         )
     if location.startswith("file://") and not os.path.isfile(
-        location[len("file://") :]
+        schema_salad.ref_resolver.uri_file_path(location)
     ):
         if skip_broken:
             return


Test patch:
diff --git a/src/toil/test/cwl/colon_test_output.cwl b/src/toil/test/cwl/colon_test_output.cwl
new file mode 100755
--- /dev/null
+++ b/src/toil/test/cwl/colon_test_output.cwl
@@ -0,0 +1,20 @@
+#!/usr/bin/env cwl-runner
+class: CommandLineTool
+cwlVersion: v1.0
+hints:
+  DockerRequirement:
+    dockerPull: docker.io/bash:4.4
+inputs:
+  input_file: File
+  outdir_name: string
+
+baseCommand: [ bash, -c ]
+arguments:
+ - |
+   mkdir $(inputs.outdir_name);
+   cp $(inputs.input_file.path) $(inputs.outdir_name)/;
+outputs:
+  result:
+    type: Directory
+    outputBinding:
+      glob: $(inputs.outdir_name)
diff --git a/src/toil/test/cwl/colon_test_output_job.yaml b/src/toil/test/cwl/colon_test_output_job.yaml
new file mode 100644
--- /dev/null
+++ b/src/toil/test/cwl/colon_test_output_job.yaml
@@ -0,0 +1,4 @@
+input_file:
+ class: File
+ path: whale.txt
+outdir_name: A:Gln2Cys_result
diff --git a/src/toil/test/cwl/cwlTest.py b/src/toil/test/cwl/cwlTest.py
--- a/src/toil/test/cwl/cwlTest.py
+++ b/src/toil/test/cwl/cwlTest.py
@@ -264,6 +264,14 @@ def test_run_revsort2(self):
     def test_run_revsort_debug_worker(self):
         self.revsort('revsort.cwl', self._debug_worker_tester)
 
+    def test_run_colon_output(self):
+        self._tester(
+            "src/toil/test/cwl/colon_test_output.cwl",
+            "src/toil/test/cwl/colon_test_output_job.yaml",
+            self._expected_colon_output(self.outDir),
+            out_name="result",
+        )
+
     @needs_aws_s3
     def test_run_s3(self):
         self.download('download_s3.json', self._tester)
@@ -471,6 +479,28 @@ def _expected_download_output(outDir):
                 'class': 'File',
                 'checksum': 'sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709'}}
 
+    @staticmethod
+    def _expected_colon_output(outDir):
+        loc = "file://" + os.path.join(outDir, "A%3AGln2Cys_result")
+        return {
+            "result": {
+                "location": loc,
+                "basename": "A:Gln2Cys_result",
+                "class": "Directory",
+                "listing": [
+                    {
+                        "class": "File",
+                        "location": f"{loc}/whale.txt",
+                        "basename": "whale.txt",
+                        "checksum": "sha1$327fc7aedf4f6b69a42a7c8b808dc5a7aff61376",
+                        "size": 1111,
+                        "nameroot": "whale",
+                        "nameext": ".txt",
+                    }
+                ],
+            }
+        }
+
 
 @needs_cwl
 class CWLv11Test(ToilTest):