about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--HACKING.md2
-rw-r--r--e2e-tests/jobs/command-line-tool-with-array-input.yaml3
-rw-r--r--e2e-tests/tests.yaml9
-rw-r--r--e2e-tests/tools/command-line-tool-with-array-input.scm3
-rw-r--r--ravanan/work/command-line-tool.scm72
-rw-r--r--ravanan/workflow.scm15
6 files changed, 67 insertions, 37 deletions
diff --git a/HACKING.md b/HACKING.md
index 4d8b6fe..7df6d02 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -18,8 +18,6 @@ $(guix build -L ../.guix -f ../.guix/e2e-tests.scm)
 ```
 Since ravanan depends on guix, and that guix may be too old, you may need to run this command outside the usual development environment.
 
-## Run specific end-to-end test
-
 When hacking on ravanan, you may be trying to get a specific test to pass, and may want to repeatedly run that specific test alone. You can do this by passing additional cwltest arguments. For example, to only run the `hello-world` test:
 ```
 $(guix build -L ../.guix -f ../.guix/e2e-tests.scm) -s hello-world
diff --git a/e2e-tests/jobs/command-line-tool-with-array-input.yaml b/e2e-tests/jobs/command-line-tool-with-array-input.yaml
new file mode 100644
index 0000000..a0fc50c
--- /dev/null
+++ b/e2e-tests/jobs/command-line-tool-with-array-input.yaml
@@ -0,0 +1,3 @@
+messages:
+  - foo
+  - bar
diff --git a/e2e-tests/tests.yaml b/e2e-tests/tests.yaml
index d14b93a..6604e39 100644
--- a/e2e-tests/tests.yaml
+++ b/e2e-tests/tests.yaml
@@ -241,3 +241,12 @@
       class: File
       size: 13
       checksum: sha1$47a013e660d408619d894b20806b1d5086aab03b
+- id: command-line-tool-with-array-input
+  doc: CommandLineTool with array input
+  tool: tools/command-line-tool-with-array-input.cwl
+  job: jobs/command-line-tool-with-array-input.yaml
+  output:
+    output_message:
+      class: File
+      size: 8
+      checksum: sha1$d53a205a336e07cf9eac45471b3870f9489288ec
diff --git a/e2e-tests/tools/command-line-tool-with-array-input.scm b/e2e-tests/tools/command-line-tool-with-array-input.scm
new file mode 100644
index 0000000..38a8722
--- /dev/null
+++ b/e2e-tests/tools/command-line-tool-with-array-input.scm
@@ -0,0 +1,3 @@
+(command #:inputs (messages #:type (array string))
+         #:run "echo" messages
+         #:outputs (output_message #:type stdout))
diff --git a/ravanan/work/command-line-tool.scm b/ravanan/work/command-line-tool.scm
index 843e939..95d69f5 100644
--- a/ravanan/work/command-line-tool.scm
+++ b/ravanan/work/command-line-tool.scm
@@ -351,20 +351,33 @@ the G-expressions are inserted."
 @code{<command-line-binding>} objects may be strings or G-expressions. The
 G-expressions may reference @var{inputs} and @var{runtime} variables that must
 be defined in the context in which the G-expressions are inserted."
+  (define (value->command-line-binding position prefix value)
+    (let ((type (object-type value)))
+      (cond
+       ((cwl-array-type? type)
+        (command-line-binding position
+                              prefix
+                              type
+                              (vector-map (cut value->command-line-binding
+                                               %nothing
+                                               %nothing
+                                               <>)
+                                          value)
+                              %nothing))
+       (else
+        (command-line-binding position prefix type value %nothing)))))
+
   (define (argument->command-line-binding i argument)
-    (let ((value (assoc-ref* argument "valueFrom")))
-      (command-line-binding (cond
-                             ((assoc-ref argument "position")
-                              => string->number)
-                             (else i))
-                            (maybe-assoc-ref (just argument) "prefix")
-                            (object-type value)
-                            value
-                            %nothing)))
+    (value->command-line-binding (cond
+                                  ((assoc-ref argument "position")
+                                   => string->number)
+                                  (else i))
+                                 (maybe-assoc-ref (just argument) "prefix")
+                                 (assoc-ref* argument "valueFrom")))
 
   (define (collect-bindings ids+inputs+types+bindings)
-    (append-map id+input+type-tree+binding->command-line-binding
-                ids+inputs+types+bindings))
+    (map id+input+type-tree+binding->command-line-binding
+         ids+inputs+types+bindings))
 
   (define id+input+type-tree+binding->command-line-binding
     (match-lambda
@@ -391,26 +404,25 @@ be defined in the context in which the G-expressions are inserted."
             ;; Recurse over array types.
             ;; TODO: Implement record and enum types.
             ((cwl-array-type? matched-type)
-             (list (command-line-binding
-                    position
-                    prefix
-                    matched-type
-                    (append-map (lambda (i input)
-                                  (id+input+type-tree+binding->command-line-binding
-                                   (list (append id (list i))
-                                         input
-                                         (assoc-ref type-tree "items")
-                                         (maybe-assoc-ref (just type-tree)
-                                                          "inputBinding"))))
-                                (iota (vector-length input))
-                                (vector->list input))
-                    (maybe-assoc-ref binding "itemSeparator"))))
+             (command-line-binding
+              position
+              prefix
+              matched-type
+              (vector-map-indexed (lambda (i input)
+                                    (id+input+type-tree+binding->command-line-binding
+                                     (list (append id (list i))
+                                           input
+                                           (assoc-ref type-tree "items")
+                                           (maybe-assoc-ref (just type-tree)
+                                                            "inputBinding"))))
+                                  input)
+              (maybe-assoc-ref binding "itemSeparator")))
             (else
-             (list (command-line-binding position
-                                         prefix
-                                         matched-type
-                                         (apply json-ref inputs id)
-                                         %nothing)))))))))
+             (command-line-binding position
+                                   prefix
+                                   matched-type
+                                   (apply json-ref inputs id)
+                                   %nothing))))))))
 
   ;; For details of this algorithm, see ยง4.1 Input binding of the CWL
   ;; 1.2 CommandLineTool specification:
diff --git a/ravanan/workflow.scm b/ravanan/workflow.scm
index 2fd00d6..0451f68 100644
--- a/ravanan/workflow.scm
+++ b/ravanan/workflow.scm
@@ -279,11 +279,16 @@ command-line-tool)}."
                                             #())
                                         (or (assoc-ref cwl "hints")
                                             #()))
-                  (vector-map->list (lambda (input)
-                                      (let ((input-id (assoc-ref input "id")))
-                                        (cons input-id
-                                              (json-ref step "in" input-id))))
-                                    (assoc-ref run "inputs"))
+                  (vector-filter-map->list (lambda (input)
+                                             (let ((input-id (assoc-ref* input "id")))
+                                               (match (assoc input-id
+                                                             (assoc-ref* step "in"))
+                                                 ((_ . source)
+                                                  (cons input-id source))
+                                                 ;; Optional inputs may be
+                                                 ;; missing a source; drop them.
+                                                 (#f #f))))
+                                           (assoc-ref* run "inputs"))
                   ;; Inputs that either have a default or accept null values are
                   ;; optional.
                   (vector-filter-map->list (lambda (input)