internal/gitutil/endofoptions_test.go

bd5cf5d7d1f34fa780660fd7562b9ffd9746ee27
gitbay/internal/gitutil/endofoptions_test.go history · blame · raw

55 lines · 2611 bytes

 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}