all repos

mugit @ 0e60f3e8c9dd4b47906fc94725266ef04b0a752d

🐮 git server that your cow will love

mugit/internal/git/repo_test.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
goimports -local 'olexsmir.xyz' -w ., 1 month ago
1
package git
2
3
import (
4
	"os"
5
	"path/filepath"
6
	"testing"
7
8
	"github.com/go-git/go-git/v5/plumbing"
9
10
	"olexsmir.xyz/x/is"
11
)
12
13
func TestRepo_Name(t *testing.T) {
14
	tests := []struct {
15
		name string
16
		path string
17
		want string
18
	}{
19
		{name: "name", path: "/repos/myrepo", want: "myrepo"},
20
		{name: "with .git", path: "/repos/myrepo.git", want: "myrepo"},
21
		{name: "nested path", path: "/home/user/code/project", want: "project"},
22
		{name: "nested with .git", path: "/home/user/repos/awesome-project.git", want: "awesome-project"},
23
	}
24
25
	for _, tt := range tests {
26
		t.Run(tt.name, func(t *testing.T) {
27
			r := &Repo{path: tt.path}
28
			is.Equal(t, r.Name(), tt.want)
29
		})
30
	}
31
}
32
33
func TestRepo_IsEmpty(t *testing.T) {
34
	t.Run("empty repo", func(t *testing.T) {
35
		r := &Repo{h: plumbing.ZeroHash}
36
		is.Equal(t, r.IsEmpty(), true)
37
	})
38
39
	t.Run("non-empty repo", func(t *testing.T) {
40
		r := &Repo{h: plumbing.NewHash("abc123def456789abc123def456789abc123def4")}
41
		is.Equal(t, r.IsEmpty(), false)
42
	})
43
}
44
45
func TestInit(t *testing.T) {
46
	t.Run("creates bare repo", func(t *testing.T) {
47
		dir := t.TempDir()
48
		repoPath := filepath.Join(dir, "test.git")
49
50
		err := Init(repoPath)
51
		is.Err(t, err, nil)
52
53
		_, err = os.Stat(filepath.Join(repoPath, "HEAD"))
54
		is.Err(t, err, nil)
55
	})
56
57
	t.Run("fails on existing repo", func(t *testing.T) {
58
		dir := t.TempDir()
59
		repoPath := filepath.Join(dir, "test.git")
60
61
		err := Init(repoPath)
62
		is.Err(t, err, nil)
63
64
		is.Err(t, Init(repoPath), "repository already exists")
65
	})
66
}
67
68
func TestOpen(t *testing.T) {
69
	t.Run("opens repo at HEAD", func(t *testing.T) {
70
		r := newTestRepo(t)
71
		r.commitFile("README.md", "Test", "Initial commit")
72
73
		repo, err := Open(r.path, "")
74
		is.Equal(t, repo.IsEmpty(), false)
75
		is.Err(t, err, nil)
76
	})
77
78
	t.Run("opens repo at specific ref", func(t *testing.T) {
79
		r := newTestRepo(t)
80
		firstHash := r.commitFile("file1.txt", "first", "first commit")
81
		r.commitFile("file2.txt", "second", "second commit")
82
83
		repo := r.open(firstHash.String())
84
		commit, err := repo.LastCommit()
85
		is.Equal(t, commit.Message, "first commit")
86
		is.Err(t, err, nil)
87
	})
88
89
	t.Run("fails on invalid path", func(t *testing.T) {
90
		_, err := Open("/nonexistent/path", "")
91
		is.Err(t, err, ErrRepoNotFound)
92
	})
93
94
	t.Run("fails on invalid ref", func(t *testing.T) {
95
		r := newTestRepo(t)
96
		r.commitFile("README.md", "# Test", "Initial commit")
97
98
		_, err := Open(r.path, "nonexistent-ref")
99
		is.Err(t, err, "resolving rev ")
100
	})
101
}
102
103
func TestOpenPublic(t *testing.T) {
104
	t.Run("opens public repo", func(t *testing.T) {
105
		r := newTestRepo(t)
106
		r.commitFile("README.md", "# Test", "Initial commit")
107
108
		repo, err := OpenPublic(r.path, "")
109
		is.Equal(t, repo.IsEmpty(), false)
110
		is.Err(t, err, nil)
111
	})
112
113
	t.Run("returns ErrPrivate for private repo", func(t *testing.T) {
114
		r := newTestRepo(t)
115
		r.commitFile("README.md", "# Test", "Initial commit")
116
117
		err := r.open().SetPrivate(true)
118
		is.Err(t, err, nil)
119
120
		_, err = OpenPublic(r.path, "")
121
		is.Err(t, err, ErrPrivate)
122
	})
123
}
124
125
func TestRepo_Commits(t *testing.T) {
126
	t.Run("returns commits in reverse chronological order", func(t *testing.T) {
127
		r := newTestRepo(t)
128
		r.commitFile("README.md", "# Test", "Initial commit")
129
		r.commitFile("a.txt", "a", "Add a")
130
		r.commitFile("b.txt", "b", "Add b")
131
		r.commitFile("c.txt", "c", "Add c")
132
133
		commits, err := r.open().Commits("")
134
		is.Err(t, err, nil)
135
136
		is.Equal(t, len(commits), 4)
137
		is.Equal(t, commits[0].Message, "Add c")
138
		is.Equal(t, commits[1].Message, "Add b")
139
		is.Equal(t, commits[2].Message, "Add a")
140
		is.Equal(t, commits[3].Message, "Initial commit")
141
	})
142
143
	t.Run("pagination with after cursor", func(t *testing.T) {
144
		r := newTestRepo(t)
145
		r.commitFile("README.md", "# Test", "Initial commit")
146
		r.commitFile("a.txt", "a", "Add a")
147
		r.commitFile("b.txt", "b", "Add b")
148
149
		// get all commits first
150
		all, err := r.open().Commits("")
151
		is.Equal(t, len(all), 3)
152
		is.Err(t, err, nil)
153
154
		// get commits after the first one
155
		after, err := r.open().Commits(all[0].HashShort)
156
		is.Err(t, err, nil)
157
		is.Equal(t, len(after), 2)
158
		is.Equal(t, after[0].Message, "Add a")
159
	})
160
161
	t.Run("empty repo returns empty slice", func(t *testing.T) {
162
		r := newTestRepo(t)
163
		commits, err := r.open().Commits("")
164
		is.Equal(t, len(commits), 0)
165
		is.Err(t, err, nil)
166
	})
167
}
168
169
func TestRepo_LastCommit(t *testing.T) {
170
	t.Run("returns HEAD commit", func(t *testing.T) {
171
		r := newTestRepo(t)
172
		r.commitFile("readme", "test", "init")
173
		r.commitFile("latest.txt", "latest", "latest commit")
174
175
		commit, err := r.open().LastCommit()
176
		is.Err(t, err, nil)
177
		is.Equal(t, commit.Message, "latest commit")
178
	})
179
180
	t.Run("empty repo returns empty commit", func(t *testing.T) {
181
		commit, err := newTestRepo(t).open().LastCommit()
182
		is.Err(t, err, nil)
183
		is.Equal(t, commit.Message, "")
184
	})
185
}
186
187
func TestRepo_LastFileCommit(t *testing.T) {
188
	t.Run("returns last commit for root file", func(t *testing.T) {
189
		r := newTestRepo(t)
190
		r.commitFile("README.md", "v1\n", "init readme")
191
		last := r.commitFile("README.md", "v2\n", "update readme")
192
193
		c, err := r.open().LastFileCommit(t.Context(), "README.md")
194
		is.Err(t, err, nil)
195
		is.Equal(t, c.Hash, last.String())
196
		is.Equal(t, c.Message, "update readme")
197
	})
198
199
	t.Run("returns last commit for nested file", func(t *testing.T) {
200
		r := newTestRepo(t)
201
		r.commitFile("docs/guide.md", "v1\n", "add guide")
202
		last := r.commitFile("docs/guide.md", "v2\n", "update guide")
203
		r.commitFile("README.md", "root\n", "touch root")
204
205
		c, err := r.open().LastFileCommit(t.Context(), "docs/guide.md")
206
		is.Err(t, err, nil)
207
		is.Equal(t, c.Hash, last.String())
208
		is.Equal(t, c.Message, "update guide")
209
	})
210
}
211
212
func TestRepo_Branches(t *testing.T) {
213
	r := newTestRepo(t)
214
	hash := r.commitFile("file.txt", "content", "A commit")
215
	r.createBranch("feature", hash)
216
	r.createBranch("develop", hash)
217
218
	branches, err := r.open().Branches()
219
	is.Err(t, err, nil)
220
221
	names := make(map[string]bool, len(branches))
222
	for _, b := range branches {
223
		names[b.Name] = true
224
	}
225
226
	is.Equal(t, names["master"], true) // got on init
227
	is.Equal(t, names["feature"], true)
228
	is.Equal(t, names["develop"], true)
229
}
230
231
func TestRepo_IsGoMod(t *testing.T) {
232
	t.Run("without go.mod", func(t *testing.T) {
233
		r := newTestRepo(t)
234
		r.commitFile("readme", "test", "init")
235
		is.Equal(t, r.open().IsGoMod(), false)
236
	})
237
238
	t.Run("with go.mod", func(t *testing.T) {
239
		r := newTestRepo(t)
240
		r.commitFile("go.mod", "module example.com/test\n\ngo 1.21\n", "Add go.mod")
241
		is.Equal(t, r.open().IsGoMod(), true)
242
	})
243
}
244
245
func TestRepo_DefaultBranch(t *testing.T) {
246
	t.Run("works", func(t *testing.T) {
247
		r := newTestRepo(t)
248
		r.commitFile("readme", "test", "init")
249
250
		branch, err := r.open().DefaultBranch()
251
		is.Equal(t, branch, "master")
252
		is.Err(t, err, nil)
253
	})
254
255
	t.Run("multiple branches", func(t *testing.T) {
256
		r := newTestRepo(t)
257
		r.commitFile("readme", "test", "init")
258
		m := r.commitFile("main", "test", "init2")
259
		r.createBranch("develop", m)
260
261
		branch, err := r.open().DefaultBranch()
262
		is.Equal(t, branch, "master")
263
		is.Err(t, err, nil)
264
	})
265
}
266
267
func TestRepo_SetDefaultBranch(t *testing.T) {
268
	t.Run("works", func(t *testing.T) {
269
		r := newTestRepo(t)
270
		r.commitFile("readme", "test", "init")
271
272
		rr := r.open()
273
274
		branch, err := rr.DefaultBranch()
275
		is.Equal(t, branch, "master")
276
		is.Err(t, err, nil)
277
278
		h := r.commitFile("thing", "hello worldie", "new feature")
279
		r.createBranch("develop", h)
280
		is.Err(t, rr.SetDefaultBranch("develop"), nil)
281
282
		branch, err = rr.DefaultBranch()
283
		is.Equal(t, branch, "develop")
284
		is.Err(t, err, nil)
285
	})
286
287
	t.Run("sets only existent branches", func(t *testing.T) {
288
		r := newTestRepo(t)
289
		r.commitFile("readme", "test", "init")
290
291
		rr := r.open()
292
		err := rr.SetDefaultBranch("tesites")
293
		is.Err(t, err, `not found:`)
294
	})
295
}