1package examples
2
3import (
4	"flag"
5	"go/build"
6	"io/ioutil"
7	"os"
8	"os/exec"
9	"path/filepath"
10	"testing"
11)
12
13var examplesTest = flag.Bool("examples", false, "run the examples tests")
14
15var defaultURL = "https://github.com/git-fixtures/basic.git"
16
17var args = map[string][]string{
18	"branch":      {defaultURL, tempFolder()},
19	"checkout":    {defaultURL, tempFolder(), "35e85108805c84807bc66a02d91535e1e24b38b9"},
20	"clone":       {defaultURL, tempFolder()},
21	"context":     {defaultURL, tempFolder()},
22	"commit":      {cloneRepository(defaultURL, tempFolder())},
23	"custom_http": {defaultURL},
24	"open":        {cloneRepository(defaultURL, tempFolder())},
25	"progress":    {defaultURL, tempFolder()},
26	"push":        {setEmptyRemote(cloneRepository(defaultURL, tempFolder()))},
27	"revision":    {cloneRepository(defaultURL, tempFolder()), "master~2^"},
28	"showcase":    {defaultURL, tempFolder()},
29	"tag":         {cloneRepository(defaultURL, tempFolder())},
30	"pull":        {createRepositoryWithRemote(tempFolder(), defaultURL)},
31	"ls":          {cloneRepository(defaultURL, tempFolder()), "HEAD", "vendor"},
32	"merge_base":  {cloneRepository(defaultURL, tempFolder()), "--is-ancestor", "HEAD~3", "HEAD^"},
33}
34
35var ignored = map[string]bool{}
36
37var tempFolders = []string{}
38
39func TestExamples(t *testing.T) {
40	flag.Parse()
41	if !*examplesTest && os.Getenv("CI") == "" {
42		t.Skip("skipping examples tests, pass --examples to execute it")
43		return
44	}
45
46	defer deleteTempFolders()
47
48	examples, err := filepath.Glob(examplesFolder())
49	if err != nil {
50		t.Errorf("error finding tests: %s", err)
51	}
52
53	for _, example := range examples {
54		dir := filepath.Dir(example)
55		_, name := filepath.Split(dir)
56
57		if ignored[name] {
58			continue
59		}
60
61		t.Run(name, func(t *testing.T) {
62			testExample(t, name, dir)
63		})
64	}
65}
66
67func tempFolder() string {
68	path, err := ioutil.TempDir("", "")
69	CheckIfError(err)
70
71	tempFolders = append(tempFolders, path)
72	return path
73}
74
75func packageFolder() string {
76	return filepath.Join(
77		build.Default.GOPATH,
78		"src", "github.com/go-git/go-git/v5",
79	)
80}
81
82func examplesFolder() string {
83	return filepath.Join(
84		packageFolder(),
85		"_examples", "*", "main.go",
86	)
87}
88
89func cloneRepository(url, folder string) string {
90	cmd := exec.Command("git", "clone", url, folder)
91	err := cmd.Run()
92	CheckIfError(err)
93
94	return folder
95}
96
97func createBareRepository(dir string) string {
98	return createRepository(dir, true)
99}
100
101func createRepository(dir string, isBare bool) string {
102	var cmd *exec.Cmd
103	if isBare {
104		cmd = exec.Command("git", "init", "--bare", dir)
105	} else {
106		cmd = exec.Command("git", "init", dir)
107	}
108	err := cmd.Run()
109	CheckIfError(err)
110
111	return dir
112}
113
114func createRepositoryWithRemote(local, remote string) string {
115	createRepository(local, false)
116	addRemote(local, remote)
117	return local
118}
119
120func setEmptyRemote(dir string) string {
121	remote := createBareRepository(tempFolder())
122	setRemote(dir, remote)
123	return dir
124}
125
126func setRemote(local, remote string) {
127	cmd := exec.Command("git", "remote", "set-url", "origin", remote)
128	cmd.Dir = local
129	err := cmd.Run()
130	CheckIfError(err)
131}
132
133func addRemote(local, remote string) {
134	cmd := exec.Command("git", "remote", "add", "origin", remote)
135	cmd.Dir = local
136	err := cmd.Run()
137	CheckIfError(err)
138}
139
140func testExample(t *testing.T, name, dir string) {
141	arguments := append([]string{"run", dir}, args[name]...)
142	cmd := exec.Command("go", arguments...)
143
144	cmd.Stdout = os.Stdout
145	cmd.Stderr = os.Stderr
146
147	if err := cmd.Run(); err != nil {
148		t.Errorf("error running cmd %q", err)
149	}
150}
151
152func deleteTempFolders() {
153	for _, folder := range tempFolders {
154		err := os.RemoveAll(folder)
155		CheckIfError(err)
156	}
157}
158