1package tests
2
3import (
4 "fmt"
5 "github.com/MichaelMure/git-bug/bug"
6 "github.com/MichaelMure/git-bug/bug/operations"
7 "github.com/MichaelMure/git-bug/repository"
8 "io/ioutil"
9 "log"
10 "os"
11 "testing"
12)
13
14func createRepo(bare bool) *repository.GitRepo {
15 dir, err := ioutil.TempDir("", "")
16 if err != nil {
17 log.Fatal(err)
18 }
19
20 fmt.Println("Creating repo:", dir)
21
22 var creator func(string) (*repository.GitRepo, error)
23
24 if bare {
25 creator = repository.InitBareGitRepo
26 } else {
27 creator = repository.InitGitRepo
28 }
29
30 repo, err := creator(dir)
31 if err != nil {
32 log.Fatal(err)
33 }
34
35 return repo
36}
37
38func cleanupRepo(repo repository.Repo) error {
39 path := repo.GetPath()
40 fmt.Println("Cleaning repo:", path)
41 return os.RemoveAll(path)
42}
43
44func setupRepos(t *testing.T) (repoA, repoB, remote *repository.GitRepo) {
45 repoA = createRepo(false)
46 repoB = createRepo(false)
47 remote = createRepo(true)
48
49 remoteAddr := "file://" + remote.GetPath()
50
51 err := repoA.AddRemote("origin", remoteAddr)
52 if err != nil {
53 t.Fatal(err)
54 }
55
56 err = repoB.AddRemote("origin", remoteAddr)
57 if err != nil {
58 t.Fatal(err)
59 }
60
61 return repoA, repoB, remote
62}
63
64func cleanupRepos(repoA, repoB, remote *repository.GitRepo) {
65 cleanupRepo(repoA)
66 cleanupRepo(repoB)
67 cleanupRepo(remote)
68}
69
70func TestPushPull(t *testing.T) {
71 repoA, repoB, remote := setupRepos(t)
72 defer cleanupRepos(repoA, repoB, remote)
73
74 bug1, err := operations.Create(rene, "bug1", "message")
75 checkErr(t, err)
76 bug1.Commit(repoA)
77 checkErr(t, err)
78
79 // A --> remote --> B
80 _, err = bug.Push(repoA, "origin")
81 checkErr(t, err)
82
83 err = bug.Pull(repoB, os.Stdout, "origin")
84 checkErr(t, err)
85
86 bugs := allBugs(t, bug.ReadAllLocalBugs(repoB))
87
88 if len(bugs) != 1 {
89 t.Fatal("Unexpected number of bugs")
90 }
91
92 // B --> remote --> A
93 bug2, err := operations.Create(rene, "bug2", "message")
94 checkErr(t, err)
95 bug2.Commit(repoB)
96 checkErr(t, err)
97
98 _, err = bug.Push(repoB, "origin")
99 checkErr(t, err)
100
101 err = bug.Pull(repoA, os.Stdout, "origin")
102 checkErr(t, err)
103
104 bugs = allBugs(t, bug.ReadAllLocalBugs(repoA))
105
106 if len(bugs) != 2 {
107 t.Fatal("Unexpected number of bugs")
108 }
109}
110
111func checkErr(t *testing.T, err error) {
112 if err != nil {
113 t.Fatal(err)
114 }
115}
116
117func allBugs(t *testing.T, bugs <-chan bug.StreamedBug) []*bug.Bug {
118 var result []*bug.Bug
119 for streamed := range bugs {
120 if streamed.Err != nil {
121 t.Fatal(streamed.Err)
122 }
123 result = append(result, streamed.Bug)
124 }
125 return result
126}
127
128func TestRebaseTheirs(t *testing.T) {
129 repoA, repoB, remote := setupRepos(t)
130 defer cleanupRepos(repoA, repoB, remote)
131
132 bug1, err := operations.Create(rene, "bug1", "message")
133 checkErr(t, err)
134 bug1.Commit(repoA)
135 checkErr(t, err)
136
137 // A --> remote
138 _, err = bug.Push(repoA, "origin")
139 checkErr(t, err)
140
141 // remote --> B
142 err = bug.Pull(repoB, os.Stdout, "origin")
143 checkErr(t, err)
144
145 bug2, err := bug.ReadLocalBug(repoB, bug1.Id())
146 checkErr(t, err)
147
148 operations.Comment(bug2, rene, "message2")
149 operations.Comment(bug2, rene, "message3")
150 operations.Comment(bug2, rene, "message4")
151 bug2.Commit(repoB)
152 checkErr(t, err)
153
154 // B --> remote
155 _, err = bug.Push(repoB, "origin")
156 checkErr(t, err)
157
158 // remote --> A
159 err = bug.Pull(repoA, os.Stdout, "origin")
160 checkErr(t, err)
161
162 bugs := allBugs(t, bug.ReadAllLocalBugs(repoB))
163
164 if len(bugs) != 1 {
165 t.Fatal("Unexpected number of bugs")
166 }
167
168 bug3, err := bug.ReadLocalBug(repoA, bug1.Id())
169 checkErr(t, err)
170
171 if nbOps(bug3) != 4 {
172 t.Fatal("Unexpected number of operations")
173 }
174}
175
176func TestRebaseOurs(t *testing.T) {
177 repoA, repoB, remote := setupRepos(t)
178 defer cleanupRepos(repoA, repoB, remote)
179
180 bug1, err := operations.Create(rene, "bug1", "message")
181 checkErr(t, err)
182 bug1.Commit(repoA)
183 checkErr(t, err)
184
185 // A --> remote
186 _, err = bug.Push(repoA, "origin")
187 checkErr(t, err)
188
189 // remote --> B
190 err = bug.Pull(repoB, os.Stdout, "origin")
191 checkErr(t, err)
192
193 operations.Comment(bug1, rene, "message2")
194 operations.Comment(bug1, rene, "message3")
195 operations.Comment(bug1, rene, "message4")
196 bug1.Commit(repoA)
197 checkErr(t, err)
198
199 operations.Comment(bug1, rene, "message5")
200 operations.Comment(bug1, rene, "message6")
201 operations.Comment(bug1, rene, "message7")
202 bug1.Commit(repoA)
203 checkErr(t, err)
204
205 operations.Comment(bug1, rene, "message8")
206 operations.Comment(bug1, rene, "message9")
207 operations.Comment(bug1, rene, "message10")
208 bug1.Commit(repoA)
209 checkErr(t, err)
210
211 // remote --> A
212 err = bug.Pull(repoA, os.Stdout, "origin")
213 checkErr(t, err)
214
215 bugs := allBugs(t, bug.ReadAllLocalBugs(repoA))
216
217 if len(bugs) != 1 {
218 t.Fatal("Unexpected number of bugs")
219 }
220
221 bug2, err := bug.ReadLocalBug(repoA, bug1.Id())
222 checkErr(t, err)
223
224 if nbOps(bug2) != 10 {
225 t.Fatal("Unexpected number of operations")
226 }
227}
228
229func nbOps(b *bug.Bug) int {
230 it := bug.NewOperationIterator(b)
231 counter := 0
232 for it.Next() {
233 counter++
234 }
235 return counter
236}
237
238func TestRebaseConflict(t *testing.T) {
239 repoA, repoB, remote := setupRepos(t)
240 defer cleanupRepos(repoA, repoB, remote)
241
242 bug1, err := operations.Create(rene, "bug1", "message")
243 checkErr(t, err)
244 bug1.Commit(repoA)
245 checkErr(t, err)
246
247 // A --> remote
248 _, err = bug.Push(repoA, "origin")
249 checkErr(t, err)
250
251 // remote --> B
252 err = bug.Pull(repoB, os.Stdout, "origin")
253 checkErr(t, err)
254
255 operations.Comment(bug1, rene, "message2")
256 operations.Comment(bug1, rene, "message3")
257 operations.Comment(bug1, rene, "message4")
258 bug1.Commit(repoA)
259 checkErr(t, err)
260
261 operations.Comment(bug1, rene, "message5")
262 operations.Comment(bug1, rene, "message6")
263 operations.Comment(bug1, rene, "message7")
264 bug1.Commit(repoA)
265 checkErr(t, err)
266
267 operations.Comment(bug1, rene, "message8")
268 operations.Comment(bug1, rene, "message9")
269 operations.Comment(bug1, rene, "message10")
270 bug1.Commit(repoA)
271 checkErr(t, err)
272
273 bug2, err := bug.ReadLocalBug(repoB, bug1.Id())
274 checkErr(t, err)
275
276 operations.Comment(bug2, rene, "message11")
277 operations.Comment(bug2, rene, "message12")
278 operations.Comment(bug2, rene, "message13")
279 bug2.Commit(repoB)
280 checkErr(t, err)
281
282 operations.Comment(bug2, rene, "message14")
283 operations.Comment(bug2, rene, "message15")
284 operations.Comment(bug2, rene, "message16")
285 bug2.Commit(repoB)
286 checkErr(t, err)
287
288 operations.Comment(bug2, rene, "message17")
289 operations.Comment(bug2, rene, "message18")
290 operations.Comment(bug2, rene, "message19")
291 bug2.Commit(repoB)
292 checkErr(t, err)
293
294 // A --> remote
295 _, err = bug.Push(repoA, "origin")
296 checkErr(t, err)
297
298 // remote --> B
299 err = bug.Pull(repoB, os.Stdout, "origin")
300 checkErr(t, err)
301
302 bugs := allBugs(t, bug.ReadAllLocalBugs(repoB))
303
304 if len(bugs) != 1 {
305 t.Fatal("Unexpected number of bugs")
306 }
307
308 bug3, err := bug.ReadLocalBug(repoB, bug1.Id())
309 checkErr(t, err)
310
311 if nbOps(bug3) != 19 {
312 t.Fatal("Unexpected number of operations")
313 }
314
315 // B --> remote
316 _, err = bug.Push(repoB, "origin")
317 checkErr(t, err)
318
319 // remote --> A
320 err = bug.Pull(repoA, os.Stdout, "origin")
321 checkErr(t, err)
322
323 bugs = allBugs(t, bug.ReadAllLocalBugs(repoA))
324
325 if len(bugs) != 1 {
326 t.Fatal("Unexpected number of bugs")
327 }
328
329 bug4, err := bug.ReadLocalBug(repoA, bug1.Id())
330 checkErr(t, err)
331
332 if nbOps(bug4) != 19 {
333 t.Fatal("Unexpected number of operations")
334 }
335}