internal/gitutil/endofoptions_test.go
55 lines · 2611 bytes
1 symbol in this file
1package gitutil
2
3import (
4 "bytes"
5 "os"
6 "path/filepath"
7 "testing"
8)
9
10// A ref reaching gitutil is user input: a URL segment or an argument. Every
11// git invocation ends option parsing before it, so a ref shaped like an
12// option is a bad revision, never a flag (#135). The payload here is an
13// option several subcommands accept, whose effect would be a file.
14func TestRefsAreNotOptions(t *testing.T) {
15 dir := t.TempDir()
16 git(t, dir, "init", "-q", "-b", "main")
17 write(t, dir, "f.txt", "hi\n")
18 git(t, dir, "add", ".")
19 git(t, dir, "commit", "-q", "-m", "base")
20 pwn := filepath.Join(t.TempDir(), "pwned")
21 ref := "--output=" + pwn
22
23 var sink bytes.Buffer
24 calls := map[string]func() error{
25 "CountCommits": func() error { CountCommits(dir, ref); return nil },
26 "Contributors": func() error { Contributors(dir, ref); return nil },
27 "Languages": func() error { Languages(dir, ref, func(string) string { return "x" }); return nil },
28 "RevList": func() error { _, err := RevList(dir, ref, 1); return err },
29 "RevListPath": func() error { _, err := RevListPath(dir, ref, "f.txt", 1); return err },
30 "PeelToCommit": func() error { _, err := PeelToCommit(dir, ref); return err },
31 "ReadCommit": func() error { _, err := ReadCommit(dir, ref); return err },
32 "ListTree": func() error { _, err := ListTree(dir, ref, ""); return err },
33 "ReadBlob": func() error { _, err := ReadBlob(dir, ref, "f.txt", 1<<20); return err },
34 "ResolveRef": func() error { _, err := ResolveRef(dir, ref); return err },
35 "Reachable": func() error { _, err := Reachable(dir, ref); return err },
36 "Archive": func() error { return Archive(dir, ref, "x", &sink) },
37 "Grep": func() error { _, err := Grep(dir, ref, "hi", 10); return err },
38 "MergeBase": func() error { _, err := MergeBase(dir, ref, "main"); return err },
39 "Diff": func() error { _, _, err := Diff(dir, ref, "main", 1<<20); return err },
40 "DiffFiles": func() error { _, err := DiffFiles(dir, ref, "main"); return err },
41 "RevListRange": func() error { _, err := RevListRange(dir, "main", ref); return err },
42 "Blame": func() error { _, err := Blame(dir, ref, "f.txt", 1, 1); return err },
43 "TipCommit": func() error { TipCommit(dir, ref); return nil },
44 "StatPath": func() error { StatPath(dir, ref, "f.txt"); return nil },
45 }
46 for name, call := range calls {
47 call()
48 if _, err := os.Stat(pwn); err == nil {
49 t.Fatalf("%s: ref %q was parsed as an option and wrote a file", name, ref)
50 }
51 }
52 if _, err := ResolveRef(dir, ref); err == nil {
53 t.Fatal("option-shaped ref resolved")
54 }
55}