da0f601c9cef1f0a13f32db375a290e068f1eaf8

Author
TheEdgeOfRage <git@theedgeofrage.com>
Committer
TheEdgeOfRage <git@theedgeofrage.com>
Date

Message

handle redirects around bash command chains

Diff

 1diff --git a/src/core/bash.ts b/src/core/bash.ts
 2index a2520e47387152ef4fc4f80b5c1a05330fca736f..a99fc17daed09cd6a6e51bfdf9cba013e4c2c8ad 100644
 3--- a/src/core/bash.ts
 4+++ b/src/core/bash.ts
 5@@ -346,20 +346,28 @@ function commandFromNode(node: Node): BashNode {
 6 }
 7 
 8 function withRedirects(node: BashNode, redirects: readonly Node[], source: string): BashNode {
 9-  if (node.kind !== "command") return unsupported(source);
10   const parsed = redirects.map(parseRedirect);
11   if (parsed.some((redirect): redirect is undefined => redirect === undefined)) return unsupported(source);
12-  return {
13-    kind: "command",
14-    command: {
15-      ...node.command,
16-      source: source.trim(),
17-      redirects: [
18-        ...node.command.redirects,
19-        ...parsed.filter((redirect): redirect is BashRedirect => redirect !== undefined),
20-      ],
21-    },
22-  };
23+  const additions = parsed.filter((redirect): redirect is BashRedirect => redirect !== undefined);
24+  if (node.kind === "command") {
25+    return {
26+      kind: "command",
27+      command: {
28+        ...node.command,
29+        source: source.trim(),
30+        redirects: [...node.command.redirects, ...additions],
31+      },
32+    };
33+  }
34+  if (node.kind === "sequence") {
35+    return {
36+      ...node,
37+      left: withRedirects(node.left, redirects, source),
38+      right: withRedirects(node.right, redirects, source),
39+    };
40+  }
41+  if (node.kind === "scope") return { ...node, body: withRedirects(node.body, redirects, source) };
42+  return unsupported(source);
43 }
44 
45 function connectorBetween(parent: Node, left: Node, right: Node): string | undefined {
46diff --git a/test/core/deterministic.test.ts b/test/core/deterministic.test.ts
47index efcc888f75f0329cad5ab5c6c7799bd4fe2791df..232286fe2181215ff4518ab54e1ab0d3d4ee69fe 100644
48--- a/test/core/deterministic.test.ts
49+++ b/test/core/deterministic.test.ts
50@@ -50,6 +50,7 @@ const allowed = [
51   "ls safe/Sources/*.swift",
52   "cd safe && wc -l Sources/*.swift",
53   "echo text | wc -c",
54+  "ls -la safe && ls safe/Sources 2>/dev/null | head -30",
55 ];
56 
57 test.each(allowed)("deterministically allows %s", async (command) => {