Strip comments in a shell script
diff --git a/ninja.go b/ninja.go
index 6932e47..48cea9b 100644
--- a/ninja.go
+++ b/ninja.go
@@ -29,6 +29,36 @@
}
}
+func stripShellComment(s string) string {
+ if strings.IndexByte(s, '#') < 0 {
+ // Fast path.
+ return s
+ }
+ var escape bool
+ var quote rune
+ for i, c := range s {
+ if quote > 0 {
+ if quote == c && (quote == '\'' || !escape) {
+ quote = 0
+ }
+ } else if !escape {
+ if c == '#' {
+ return s[:i]
+ } else if c == '\'' || c == '"' || c == '`' {
+ quote = c
+ }
+ }
+ if escape {
+ escape = false
+ } else if c == '\\' {
+ escape = true
+ } else {
+ escape = false
+ }
+ }
+ return s
+}
+
func genShellScript(runners []runner) string {
var buf bytes.Buffer
for i, r := range runners {
@@ -39,7 +69,8 @@
buf.WriteString(" && ")
}
}
- cmd := trimLeftSpace(r.cmd)
+ cmd := stripShellComment(r.cmd)
+ cmd = trimLeftSpace(cmd)
cmd = strings.Replace(cmd, "\\\n", " ", -1)
cmd = strings.TrimRight(cmd, " \t\n;")
cmd = strings.Replace(cmd, "$", "$$", -1)
diff --git a/ninja_test.go b/ninja_test.go
new file mode 100644
index 0000000..8bf9717
--- /dev/null
+++ b/ninja_test.go
@@ -0,0 +1,56 @@
+package main
+
+import "testing"
+
+func TestStripShellComment(t *testing.T) {
+ for _, tc := range []struct {
+ in string
+ want string
+ }{
+ {
+ in: `foo`,
+ want: `foo`,
+ },
+ {
+ in: `foo # bar`,
+ want: `foo `,
+ },
+ {
+ in: `foo '# bar'`,
+ want: `foo '# bar'`,
+ },
+ {
+ in: `foo '\'# bar'`,
+ want: `foo '\'`,
+ },
+ {
+ in: `foo "# bar"`,
+ want: `foo "# bar"`,
+ },
+ {
+ in: `foo "\"# bar"`,
+ want: `foo "\"# bar"`,
+ },
+ {
+ in: `foo "\\"# bar"`,
+ want: `foo "\\"`,
+ },
+ {
+ in: "foo `# bar`",
+ want: "foo `# bar`",
+ },
+ {
+ in: "foo `\\`# bar`",
+ want: "foo `\\`# bar`",
+ },
+ {
+ in: "foo `\\\\`# bar`",
+ want: "foo `\\\\`",
+ },
+ } {
+ got := stripShellComment(tc.in)
+ if got != tc.want {
+ t.Errorf(`stripShellComment(%q)=%q, want %q`, tc.in, got, tc.want)
+ }
+ }
+}