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