From 1cbbce81004545315b02cc08a50375b72ebfde85 Mon Sep 17 00:00:00 2001 From: Arun Isaac Date: Mon, 30 Sep 2024 18:55:16 +0100 Subject: command-line-tool: Canonicalize inputs before embedding in G-exp. * ravanan/command-line-tool.scm (canonicalize-json): New function. (build-command-line-tool-script): Use canonicalize-json. --- ravanan/command-line-tool.scm | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/ravanan/command-line-tool.scm b/ravanan/command-line-tool.scm index 8d1f8ef..1723d96 100644 --- a/ravanan/command-line-tool.scm +++ b/ravanan/command-line-tool.scm @@ -533,6 +533,28 @@ The returned G-expression will reference an @code{inputs-directory} variable." (list id (copy-input-files input)))) inputs))) +(define (canonicalize-json tree) + "Canonicalize JSON @var{tree} by recursively sorting objects in lexicographic +order of keys." + ;; We need to canonicalize JSON trees before inserting them into + ;; G-expressions. If we don't, we would have degenerate G-expressions that + ;; produce exactly the same result. + (cond + ;; Sort objects by lexicographic order of keys, and recurse. + ((list? tree) + (sort (map (match-lambda + ((key . value) + (cons key (canonicalize-json value)))) + tree) + (match-lambda* + (((key1 . _) (key2 . _)) + (string< key1 key2))))) + ;; Do not rearrange arrays. Just recurse. + ((vector? tree) + (vector-map canonicalize-json tree)) + ;; Atoms + (else tree))) + (define (build-command-line-tool-script name manifest cwl inputs scratch store guix-daemon-socket) "Build and return script to run @code{CommandLineTool} class workflow @var{cwl} @@ -883,7 +905,7 @@ directory of the workflow." (call-with-temporary-directory (lambda (inputs-directory) - (let ((inputs #$(copy-input-files-gexp inputs)) + (let ((inputs #$(copy-input-files-gexp (canonicalize-json inputs))) (runtime `(("cores" . ,(total-processor-count))))) ;; Set environment defined by workflow. -- cgit v1.2.3