1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.api;
44
45 import static org.hamcrest.CoreMatchers.equalTo;
46 import static org.hamcrest.CoreMatchers.not;
47 import static org.hamcrest.MatcherAssert.assertThat;
48 import static org.junit.Assert.assertEquals;
49 import static org.junit.Assert.assertFalse;
50 import static org.junit.Assert.assertNotNull;
51 import static org.junit.Assert.assertTrue;
52 import static org.junit.Assert.fail;
53
54 import java.io.BufferedReader;
55 import java.io.File;
56 import java.io.FileInputStream;
57 import java.io.IOException;
58 import java.io.InputStreamReader;
59 import java.util.Collections;
60 import java.util.Iterator;
61 import java.util.List;
62
63 import org.eclipse.jgit.api.MergeResult.MergeStatus;
64 import org.eclipse.jgit.api.RebaseCommand.InteractiveHandler;
65 import org.eclipse.jgit.api.RebaseCommand.Operation;
66 import org.eclipse.jgit.api.RebaseResult.Status;
67 import org.eclipse.jgit.api.errors.InvalidRebaseStepException;
68 import org.eclipse.jgit.api.errors.RefNotFoundException;
69 import org.eclipse.jgit.api.errors.UnmergedPathsException;
70 import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
71 import org.eclipse.jgit.diff.DiffEntry;
72 import org.eclipse.jgit.dircache.DirCacheCheckout;
73 import org.eclipse.jgit.errors.AmbiguousObjectException;
74 import org.eclipse.jgit.errors.IllegalTodoFileModification;
75 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
76 import org.eclipse.jgit.errors.MissingObjectException;
77 import org.eclipse.jgit.junit.RepositoryTestCase;
78 import org.eclipse.jgit.lib.AbbreviatedObjectId;
79 import org.eclipse.jgit.lib.ConfigConstants;
80 import org.eclipse.jgit.lib.Constants;
81 import org.eclipse.jgit.lib.ObjectId;
82 import org.eclipse.jgit.lib.ObjectLoader;
83 import org.eclipse.jgit.lib.PersonIdent;
84 import org.eclipse.jgit.lib.RebaseTodoLine;
85 import org.eclipse.jgit.lib.RebaseTodoLine.Action;
86 import org.eclipse.jgit.lib.RefUpdate;
87 import org.eclipse.jgit.lib.ReflogEntry;
88 import org.eclipse.jgit.lib.RepositoryState;
89 import org.eclipse.jgit.merge.MergeStrategy;
90 import org.eclipse.jgit.revwalk.RevCommit;
91 import org.eclipse.jgit.revwalk.RevSort;
92 import org.eclipse.jgit.revwalk.RevWalk;
93 import org.eclipse.jgit.treewalk.TreeWalk;
94 import org.eclipse.jgit.treewalk.filter.TreeFilter;
95 import org.eclipse.jgit.util.FileUtils;
96 import org.eclipse.jgit.util.IO;
97 import org.eclipse.jgit.util.RawParseUtils;
98 import org.junit.Before;
99 import org.junit.Test;
100
101 public class RebaseCommandTest extends RepositoryTestCase {
102 private static final String GIT_REBASE_TODO = "rebase-merge/git-rebase-todo";
103
104 private static final String FILE1 = "file1";
105
106 protected Git git;
107
108 @Override
109 @Before
110 public void setUp() throws Exception {
111 super.setUp();
112 this.git = new Git(db);
113 }
114
115 private void checkoutCommit(RevCommit commit) throws IllegalStateException,
116 IOException {
117 RevCommit head;
118 try (RevWalk walk = new RevWalk(db)) {
119 head = walk.parseCommit(db.resolve(Constants.HEAD));
120 DirCacheCheckout dco = new DirCacheCheckout(db, head.getTree(),
121 db.lockDirCache(), commit.getTree());
122 dco.setFailOnConflict(true);
123 dco.checkout();
124 }
125
126 RefUpdate refUpdate = db.updateRef(Constants.HEAD, true);
127 refUpdate.setNewObjectId(commit);
128 refUpdate.setRefLogMessage("checkout: moving to " + head.getName(),
129 false);
130 refUpdate.forceUpdate();
131 }
132
133 @Test
134 public void testFastForwardWithNewFile() throws Exception {
135
136 writeTrashFile(FILE1, FILE1);
137 git.add().addFilepattern(FILE1).call();
138 RevCommit first = git.commit().setMessage("Add file1").call();
139
140 assertTrue(new File(db.getWorkTree(), FILE1).exists());
141
142 createBranch(first, "refs/heads/topic");
143
144 File file2 = writeTrashFile("file2", "file2");
145 git.add().addFilepattern("file2").call();
146 RevCommit second = git.commit().setMessage("Add file2").call();
147 assertTrue(new File(db.getWorkTree(), "file2").exists());
148
149 checkoutBranch("refs/heads/topic");
150 assertFalse(new File(db.getWorkTree(), "file2").exists());
151
152 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
153 assertTrue(new File(db.getWorkTree(), "file2").exists());
154 checkFile(file2, "file2");
155 assertEquals(Status.FAST_FORWARD, res.getStatus());
156
157 List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
158 .getReverseEntries();
159 List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
160 .getReverseEntries();
161 List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
162 .getReverseEntries();
163 assertEquals("rebase finished: returning to refs/heads/topic", headLog
164 .get(0).getComment());
165 assertEquals("checkout: moving from topic to " + second.getName(),
166 headLog.get(1).getComment());
167 assertEquals(2, masterLog.size());
168 assertEquals(2, topicLog.size());
169 assertEquals(
170 "rebase finished: refs/heads/topic onto " + second.getName(),
171 topicLog.get(0).getComment());
172 }
173
174 @Test
175 public void testFastForwardWithMultipleCommits() throws Exception {
176
177 writeTrashFile(FILE1, FILE1);
178 git.add().addFilepattern(FILE1).call();
179 RevCommit first = git.commit().setMessage("Add file1").call();
180
181 assertTrue(new File(db.getWorkTree(), FILE1).exists());
182
183 createBranch(first, "refs/heads/topic");
184
185 File file2 = writeTrashFile("file2", "file2");
186 git.add().addFilepattern("file2").call();
187 git.commit().setMessage("Add file2").call();
188 assertTrue(new File(db.getWorkTree(), "file2").exists());
189
190 writeTrashFile("file2", "file2 new content");
191 git.add().addFilepattern("file2").call();
192 RevCommit second = git.commit().setMessage("Change content of file2")
193 .call();
194
195 checkoutBranch("refs/heads/topic");
196 assertFalse(new File(db.getWorkTree(), "file2").exists());
197
198 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
199 assertTrue(new File(db.getWorkTree(), "file2").exists());
200 checkFile(file2, "file2 new content");
201 assertEquals(Status.FAST_FORWARD, res.getStatus());
202
203 List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
204 .getReverseEntries();
205 List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
206 .getReverseEntries();
207 List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
208 .getReverseEntries();
209 assertEquals("rebase finished: returning to refs/heads/topic", headLog
210 .get(0).getComment());
211 assertEquals("checkout: moving from topic to " + second.getName(),
212 headLog.get(1).getComment());
213 assertEquals(3, masterLog.size());
214 assertEquals(2, topicLog.size());
215 assertEquals(
216 "rebase finished: refs/heads/topic onto " + second.getName(),
217 topicLog.get(0).getComment());
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244 @Test
245 public void testRebaseShouldIgnoreMergeCommits()
246 throws Exception {
247
248 writeTrashFile(FILE1, FILE1);
249 git.add().addFilepattern(FILE1).call();
250 RevCommit a = git.commit().setMessage("Add file1").call();
251 assertTrue(new File(db.getWorkTree(), FILE1).exists());
252
253
254 createBranch(a, "refs/heads/topic");
255
256
257 writeTrashFile(FILE1, "blah");
258 git.add().addFilepattern(FILE1).call();
259 RevCommit b = git.commit().setMessage("updated file1 on master").call();
260
261 checkoutBranch("refs/heads/topic");
262 writeTrashFile("file3", "more changess");
263 git.add().addFilepattern("file3").call();
264 RevCommit c = git.commit()
265 .setMessage("update file3 on topic").call();
266
267
268 createBranch(c, "refs/heads/side");
269
270
271 writeTrashFile("file2", "file2");
272 git.add().addFilepattern("file2").call();
273 RevCommit d = git.commit().setMessage("Add file2").call();
274 assertTrue(new File(db.getWorkTree(), "file2").exists());
275
276
277 checkoutBranch("refs/heads/side");
278 writeTrashFile("file3", "more change");
279 git.add().addFilepattern("file3").call();
280 RevCommit e = git.commit().setMessage("update file2 on side")
281 .call();
282
283
284 checkoutBranch("refs/heads/topic");
285 MergeResult result = git.merge().include(e.getId())
286 .setStrategy(MergeStrategy.RESOLVE).call();
287 assertEquals(MergeStatus.MERGED, result.getMergeStatus());
288 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
289 assertEquals(Status.OK, res.getStatus());
290
291 try (RevWalk rw = new RevWalk(db)) {
292 rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
293 assertDerivedFrom(rw.next(), e);
294 assertDerivedFrom(rw.next(), d);
295 assertDerivedFrom(rw.next(), c);
296 assertEquals(b, rw.next());
297 assertEquals(a, rw.next());
298 }
299
300 List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
301 .getReverseEntries();
302 List<ReflogEntry> sideLog = db.getReflogReader("refs/heads/side")
303 .getReverseEntries();
304 List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
305 .getReverseEntries();
306 List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
307 .getReverseEntries();
308 assertEquals("rebase finished: returning to refs/heads/topic", headLog
309 .get(0).getComment());
310 assertEquals("rebase: update file2 on side", headLog.get(1)
311 .getComment());
312 assertEquals("rebase: Add file2", headLog.get(2).getComment());
313 assertEquals("rebase: update file3 on topic", headLog.get(3)
314 .getComment());
315 assertEquals("checkout: moving from topic to " + b.getName(), headLog
316 .get(4).getComment());
317 assertEquals(2, masterLog.size());
318 assertEquals(2, sideLog.size());
319 assertEquals(5, topicLog.size());
320 assertEquals("rebase finished: refs/heads/topic onto " + b.getName(),
321 topicLog.get(0).getComment());
322 }
323
324 static void assertDerivedFrom(RevCommit derived, RevCommit original) {
325 assertThat(derived, not(equalTo(original)));
326 assertEquals(original.getFullMessage(), derived.getFullMessage());
327 }
328
329 @Test
330 public void testRebasePreservingMerges1() throws Exception {
331 doTestRebasePreservingMerges(true);
332 }
333
334 @Test
335 public void testRebasePreservingMerges2() throws Exception {
336 doTestRebasePreservingMerges(false);
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356 private void doTestRebasePreservingMerges(boolean testConflict)
357 throws Exception {
358
359 writeTrashFile(FILE1, FILE1);
360 git.add().addFilepattern(FILE1).call();
361 RevCommit a = git.commit().setMessage("commit a").call();
362
363
364 createBranch(a, "refs/heads/topic");
365
366
367 writeTrashFile(FILE1, "blah");
368 writeTrashFile("conflict", "b");
369 git.add().addFilepattern(".").call();
370 RevCommit b = git.commit().setMessage("commit b").call();
371
372 checkoutBranch("refs/heads/topic");
373 writeTrashFile("file3", "more changess");
374 git.add().addFilepattern("file3").call();
375 RevCommit c = git.commit().setMessage("commit c").call();
376
377
378 createBranch(c, "refs/heads/side");
379
380
381 writeTrashFile("file2", "file2");
382 if (testConflict)
383 writeTrashFile("conflict", "d");
384 git.add().addFilepattern(".").call();
385 RevCommit d = git.commit().setMessage("commit d").call();
386 assertTrue(new File(db.getWorkTree(), "file2").exists());
387
388
389 checkoutBranch("refs/heads/side");
390 writeTrashFile("file3", "more change");
391 if (testConflict)
392 writeTrashFile("conflict", "e");
393 git.add().addFilepattern(".").call();
394 RevCommit e = git.commit().setMessage("commit e").call();
395
396
397 checkoutBranch("refs/heads/topic");
398 MergeResult result = git.merge().include(e.getId())
399 .setStrategy(MergeStrategy.RESOLVE).call();
400 final RevCommit f;
401 if (testConflict) {
402 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
403 assertEquals(Collections.singleton("conflict"), git.status().call()
404 .getConflicting());
405
406 writeTrashFile("conflict", "f resolved");
407 git.add().addFilepattern("conflict").call();
408 f = git.commit().setMessage("commit f").call();
409 } else {
410 assertEquals(MergeStatus.MERGED, result.getMergeStatus());
411 try (RevWalk rw = new RevWalk(db)) {
412 f = rw.parseCommit(result.getNewHead());
413 }
414 }
415
416 RebaseResult res = git.rebase().setUpstream("refs/heads/master")
417 .setPreserveMerges(true).call();
418 if (testConflict) {
419
420 assertEquals(Status.STOPPED, res.getStatus());
421 assertEquals(Collections.singleton("conflict"), git.status().call()
422 .getConflicting());
423 assertTrue(read("conflict").contains("\nb\n=======\nd\n"));
424
425 writeTrashFile("conflict", "d new");
426 git.add().addFilepattern("conflict").call();
427 res = git.rebase().setOperation(Operation.CONTINUE).call();
428
429
430 assertEquals(Status.STOPPED, res.getStatus());
431 assertEquals(Collections.singleton("conflict"), git.status().call()
432 .getConflicting());
433 assertTrue(read("conflict").contains("\nb\n=======\ne\n"));
434
435 writeTrashFile("conflict", "e new");
436 git.add().addFilepattern("conflict").call();
437 res = git.rebase().setOperation(Operation.CONTINUE).call();
438
439
440 assertEquals(Status.STOPPED, res.getStatus());
441 assertEquals(Collections.singleton("conflict"), git.status().call()
442 .getConflicting());
443 assertTrue(read("conflict").contains("\nd new\n=======\ne new\n"));
444
445 writeTrashFile("conflict", "f new resolved");
446 git.add().addFilepattern("conflict").call();
447 res = git.rebase().setOperation(Operation.CONTINUE).call();
448 }
449 assertEquals(Status.OK, res.getStatus());
450
451 if (testConflict)
452 assertEquals("f new resolved", read("conflict"));
453 assertEquals("blah", read(FILE1));
454 assertEquals("file2", read("file2"));
455 assertEquals("more change", read("file3"));
456
457 try (RevWalk rw = new RevWalk(db)) {
458 rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
459 RevCommit newF = rw.next();
460 assertDerivedFrom(newF, f);
461 assertEquals(2, newF.getParentCount());
462 RevCommit newD = rw.next();
463 assertDerivedFrom(newD, d);
464 if (testConflict)
465 assertEquals("d new", readFile("conflict", newD));
466 RevCommit newE = rw.next();
467 assertDerivedFrom(newE, e);
468 if (testConflict)
469 assertEquals("e new", readFile("conflict", newE));
470 assertEquals(newD, newF.getParent(0));
471 assertEquals(newE, newF.getParent(1));
472 assertDerivedFrom(rw.next(), c);
473 assertEquals(b, rw.next());
474 assertEquals(a, rw.next());
475 }
476 }
477
478 private String readFile(String path, RevCommit commit) throws IOException {
479 try (TreeWalk walk = TreeWalk.forPath(db, path, commit.getTree())) {
480 ObjectLoader loader = db.open(walk.getObjectId(0),
481 Constants.OBJ_BLOB);
482 String result = RawParseUtils.decode(loader.getCachedBytes());
483 return result;
484 }
485 }
486
487 @Test
488 public void testRebasePreservingMergesWithUnrelatedSide1() throws Exception {
489 doTestRebasePreservingMergesWithUnrelatedSide(true);
490 }
491
492 @Test
493 public void testRebasePreservingMergesWithUnrelatedSide2() throws Exception {
494 doTestRebasePreservingMergesWithUnrelatedSide(false);
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521 private void doTestRebasePreservingMergesWithUnrelatedSide(
522 boolean testConflict) throws Exception {
523 try (RevWalk rw = new RevWalk(db)) {
524 rw.sort(RevSort.TOPO);
525
526 writeTrashFile(FILE1, FILE1);
527 git.add().addFilepattern(FILE1).call();
528 RevCommit a = git.commit().setMessage("commit a").call();
529
530 writeTrashFile("file2", "blah");
531 git.add().addFilepattern("file2").call();
532 RevCommit b = git.commit().setMessage("commit b").call();
533
534
535 createBranch(b, "refs/heads/topic");
536 checkoutBranch("refs/heads/topic");
537
538 writeTrashFile("file3", "more changess");
539 writeTrashFile(FILE1, "preparing conflict");
540 git.add().addFilepattern("file3").addFilepattern(FILE1).call();
541 RevCommit c = git.commit().setMessage("commit c").call();
542
543 createBranch(a, "refs/heads/side");
544 checkoutBranch("refs/heads/side");
545 writeTrashFile("conflict", "e");
546 writeTrashFile(FILE1, FILE1 + "\n" + "line 2");
547 git.add().addFilepattern(".").call();
548 RevCommit e = git.commit().setMessage("commit e").call();
549
550
551 checkoutBranch("refs/heads/topic");
552 MergeResult result = git.merge().include(e)
553 .setStrategy(MergeStrategy.RESOLVE).call();
554
555 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
556 assertEquals(result.getConflicts().keySet(),
557 Collections.singleton(FILE1));
558 writeTrashFile(FILE1, "merge resolution");
559 git.add().addFilepattern(FILE1).call();
560 RevCommit d = git.commit().setMessage("commit d").call();
561
562 RevCommit f = commitFile("file2", "new content two", "topic");
563
564 checkoutBranch("refs/heads/master");
565 writeTrashFile("fileg", "fileg");
566 if (testConflict)
567 writeTrashFile("conflict", "g");
568 git.add().addFilepattern(".").call();
569 RevCommit g = git.commit().setMessage("commit g").call();
570
571 checkoutBranch("refs/heads/topic");
572 RebaseResult res = git.rebase().setUpstream("refs/heads/master")
573 .setPreserveMerges(true).call();
574 if (testConflict) {
575 assertEquals(Status.STOPPED, res.getStatus());
576 assertEquals(Collections.singleton("conflict"), git.status().call()
577 .getConflicting());
578
579 writeTrashFile("conflict", "e");
580 git.add().addFilepattern("conflict").call();
581 res = git.rebase().setOperation(Operation.CONTINUE).call();
582 }
583 assertEquals(Status.OK, res.getStatus());
584
585 assertEquals("merge resolution", read(FILE1));
586 assertEquals("new content two", read("file2"));
587 assertEquals("more changess", read("file3"));
588 assertEquals("fileg", read("fileg"));
589
590 rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
591 RevCommit newF = rw.next();
592 assertDerivedFrom(newF, f);
593 RevCommit newD = rw.next();
594 assertDerivedFrom(newD, d);
595 assertEquals(2, newD.getParentCount());
596 RevCommit newC = rw.next();
597 assertDerivedFrom(newC, c);
598 RevCommit newE = rw.next();
599 assertEquals(e, newE);
600 assertEquals(newC, newD.getParent(0));
601 assertEquals(e, newD.getParent(1));
602 assertEquals(g, rw.next());
603 assertEquals(b, rw.next());
604 assertEquals(a, rw.next());
605 }
606 }
607
608 @Test
609 public void testRebaseParentOntoHeadShouldBeUptoDate() throws Exception {
610 writeTrashFile(FILE1, FILE1);
611 git.add().addFilepattern(FILE1).call();
612 RevCommit parent = git.commit().setMessage("parent comment").call();
613
614 writeTrashFile(FILE1, "another change");
615 git.add().addFilepattern(FILE1).call();
616 git.commit().setMessage("head commit").call();
617
618 RebaseResult result = git.rebase().setUpstream(parent).call();
619 assertEquals(Status.UP_TO_DATE, result.getStatus());
620
621 assertEquals(2, db.getReflogReader(Constants.HEAD).getReverseEntries()
622 .size());
623 assertEquals(2, db.getReflogReader("refs/heads/master")
624 .getReverseEntries().size());
625 }
626
627 @Test
628 public void testUpToDate() throws Exception {
629
630 writeTrashFile(FILE1, FILE1);
631 git.add().addFilepattern(FILE1).call();
632 RevCommit first = git.commit().setMessage("Add file1").call();
633
634 assertTrue(new File(db.getWorkTree(), FILE1).exists());
635
636 RebaseResult res = git.rebase().setUpstream(first).call();
637 assertEquals(Status.UP_TO_DATE, res.getStatus());
638
639 assertEquals(1, db.getReflogReader(Constants.HEAD).getReverseEntries()
640 .size());
641 assertEquals(1, db.getReflogReader("refs/heads/master")
642 .getReverseEntries().size());
643 }
644
645 @Test
646 public void testUnknownUpstream() throws Exception {
647
648 writeTrashFile(FILE1, FILE1);
649 git.add().addFilepattern(FILE1).call();
650 git.commit().setMessage("Add file1").call();
651
652 assertTrue(new File(db.getWorkTree(), FILE1).exists());
653
654 try {
655 git.rebase().setUpstream("refs/heads/xyz").call();
656 fail("expected exception was not thrown");
657 } catch (RefNotFoundException e) {
658
659 }
660 }
661
662 @Test
663 public void testConflictFreeWithSingleFile() throws Exception {
664
665 File theFile = writeTrashFile(FILE1, "1\n2\n3\n");
666 git.add().addFilepattern(FILE1).call();
667 RevCommit second = git.commit().setMessage("Add file1").call();
668 assertTrue(new File(db.getWorkTree(), FILE1).exists());
669
670 writeTrashFile(FILE1, "1master\n2\n3\n");
671 checkFile(theFile, "1master\n2\n3\n");
672 git.add().addFilepattern(FILE1).call();
673 RevCommit lastMasterChange = git.commit().setMessage(
674 "change file1 in master").call();
675
676
677 createBranch(second, "refs/heads/topic");
678 checkoutBranch("refs/heads/topic");
679
680 checkFile(theFile, "1\n2\n3\n");
681
682 assertTrue(new File(db.getWorkTree(), FILE1).exists());
683
684 writeTrashFile(FILE1, "1\n2\n3\ntopic\n");
685 git.add().addFilepattern(FILE1).call();
686 RevCommit origHead = git.commit().setMessage("change file1 in topic")
687 .call();
688
689 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
690 assertEquals(Status.OK, res.getStatus());
691 checkFile(theFile, "1master\n2\n3\ntopic\n");
692
693 assertEquals("refs/heads/topic", db.getFullBranch());
694 try (RevWalk rw = new RevWalk(db)) {
695 assertEquals(lastMasterChange, rw.parseCommit(
696 db.resolve(Constants.HEAD)).getParent(0));
697 }
698 assertEquals(origHead, db.readOrigHead());
699 List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
700 .getReverseEntries();
701 List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
702 .getReverseEntries();
703 List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
704 .getReverseEntries();
705 assertEquals(2, masterLog.size());
706 assertEquals(3, topicLog.size());
707 assertEquals("rebase finished: refs/heads/topic onto "
708 + lastMasterChange.getName(), topicLog.get(0).getComment());
709 assertEquals("rebase finished: returning to refs/heads/topic", headLog
710 .get(0).getComment());
711 }
712
713 @Test
714 public void testDetachedHead() throws Exception {
715
716 File theFile = writeTrashFile(FILE1, "1\n2\n3\n");
717 git.add().addFilepattern(FILE1).call();
718 RevCommit second = git.commit().setMessage("Add file1").call();
719 assertTrue(new File(db.getWorkTree(), FILE1).exists());
720
721 writeTrashFile(FILE1, "1master\n2\n3\n");
722 checkFile(theFile, "1master\n2\n3\n");
723 git.add().addFilepattern(FILE1).call();
724 RevCommit lastMasterChange = git.commit().setMessage(
725 "change file1 in master").call();
726
727
728 createBranch(second, "refs/heads/topic");
729 checkoutBranch("refs/heads/topic");
730
731 checkFile(theFile, "1\n2\n3\n");
732
733 assertTrue(new File(db.getWorkTree(), FILE1).exists());
734
735 writeTrashFile(FILE1, "1\n2\n3\ntopic\n");
736 git.add().addFilepattern(FILE1).call();
737 RevCommit topicCommit = git.commit()
738 .setMessage("change file1 in topic").call();
739 checkoutBranch("refs/heads/master");
740 checkoutCommit(topicCommit);
741 assertEquals(topicCommit.getId().getName(), db.getFullBranch());
742
743 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
744 assertEquals(Status.OK, res.getStatus());
745 checkFile(theFile, "1master\n2\n3\ntopic\n");
746 try (RevWalk rw = new RevWalk(db)) {
747 assertEquals(lastMasterChange, rw.parseCommit(
748 db.resolve(Constants.HEAD)).getParent(0));
749 }
750
751 List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
752 .getReverseEntries();
753 assertEquals(8, headLog.size());
754 assertEquals("rebase: change file1 in topic", headLog.get(0)
755 .getComment());
756 assertEquals("checkout: moving from " + topicCommit.getName() + " to "
757 + lastMasterChange.getName(), headLog.get(1).getComment());
758 }
759
760 @Test
761 public void testFilesAddedFromTwoBranches() throws Exception {
762
763 writeTrashFile(FILE1, FILE1);
764 git.add().addFilepattern(FILE1).call();
765 RevCommit masterCommit = git.commit().setMessage("Add file1 to master")
766 .call();
767
768
769 createBranch(masterCommit, "refs/heads/file2");
770 checkoutBranch("refs/heads/file2");
771 writeTrashFile("file2", "file2");
772 git.add().addFilepattern("file2").call();
773 RevCommit addFile2 = git.commit().setMessage(
774 "Add file2 to branch file2").call();
775
776
777 createBranch(masterCommit, "refs/heads/file3");
778 checkoutBranch("refs/heads/file3");
779 writeTrashFile("file3", "file3");
780 git.add().addFilepattern("file3").call();
781 git.commit().setMessage("Add file3 to branch file3").call();
782
783 assertTrue(new File(db.getWorkTree(), FILE1).exists());
784 assertFalse(new File(db.getWorkTree(), "file2").exists());
785 assertTrue(new File(db.getWorkTree(), "file3").exists());
786
787 RebaseResult res = git.rebase().setUpstream("refs/heads/file2").call();
788 assertEquals(Status.OK, res.getStatus());
789
790 assertTrue(new File(db.getWorkTree(), FILE1).exists());
791 assertTrue(new File(db.getWorkTree(), "file2").exists());
792 assertTrue(new File(db.getWorkTree(), "file3").exists());
793
794
795 assertEquals("refs/heads/file3", db.getFullBranch());
796 try (RevWalk rw = new RevWalk(db)) {
797 assertEquals(addFile2, rw.parseCommit(
798 db.resolve(Constants.HEAD)).getParent(0));
799 }
800
801 checkoutBranch("refs/heads/file2");
802 assertTrue(new File(db.getWorkTree(), FILE1).exists());
803 assertTrue(new File(db.getWorkTree(), "file2").exists());
804 assertFalse(new File(db.getWorkTree(), "file3").exists());
805 }
806
807 @Test
808 public void testStopOnConflict() throws Exception {
809
810 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
811 "2", "3");
812
813 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
814 checkFile(FILE1, "1master", "2", "3");
815
816 createBranch(firstInMaster, "refs/heads/topic");
817 checkoutBranch("refs/heads/topic");
818
819 checkFile(FILE1, "1", "2", "3");
820
821
822 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1", "2",
823 "3", "topic4");
824
825
826 RevCommit conflicting = writeFileAndCommit(FILE1,
827 "change file1 in topic", "1topic", "2", "3", "topic4");
828
829 RevCommit lastTopicCommit = writeFileAndCommit(FILE1,
830 "change file1 in topic again", "1topic", "2", "3", "topic4");
831
832 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
833 assertEquals(Status.STOPPED, res.getStatus());
834 assertEquals(conflicting, res.getCurrentCommit());
835 checkFile(FILE1,
836 "<<<<<<< Upstream, based on master\n1master\n=======\n1topic",
837 ">>>>>>> e0d1dea change file1 in topic\n2\n3\ntopic4");
838
839 assertEquals(RepositoryState.REBASING_MERGE, db
840 .getRepositoryState());
841 assertTrue(new File(db.getDirectory(), "rebase-merge").exists());
842
843
844 assertEquals(1, countPicks());
845
846
847 try {
848 git.rebase().setUpstream("refs/heads/master").call();
849 fail("Expected exception was not thrown");
850 } catch (WrongRepositoryStateException e) {
851
852 }
853
854
855 res = git.rebase().setOperation(Operation.ABORT).call();
856 assertEquals(res.getStatus(), Status.ABORTED);
857 assertEquals("refs/heads/topic", db.getFullBranch());
858 checkFile(FILE1, "1topic", "2", "3", "topic4");
859 try (RevWalk rw = new RevWalk(db)) {
860 assertEquals(lastTopicCommit,
861 rw.parseCommit(db.resolve(Constants.HEAD)));
862 }
863 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
864
865
866 assertFalse(new File(db.getDirectory(), "rebase-merge").exists());
867 }
868
869 @Test
870 public void testStopOnConflictAndAbortWithDetachedHEAD() throws Exception {
871
872 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
873 "2", "3");
874
875 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
876 checkFile(FILE1, "1master", "2", "3");
877
878 createBranch(firstInMaster, "refs/heads/topic");
879 checkoutBranch("refs/heads/topic");
880
881 checkFile(FILE1, "1", "2", "3");
882
883
884 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1", "2",
885 "3", "topic4");
886
887
888 RevCommit conflicting = writeFileAndCommit(FILE1,
889 "change file1 in topic", "1topic", "2", "3", "topic4");
890
891 RevCommit lastTopicCommit = writeFileAndCommit(FILE1,
892 "change file1 in topic again", "1topic", "2", "3", "topic4");
893
894 git.checkout().setName(lastTopicCommit.getName()).call();
895
896 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
897 assertEquals(Status.STOPPED, res.getStatus());
898 assertEquals(conflicting, res.getCurrentCommit());
899 checkFile(FILE1,
900 "<<<<<<< Upstream, based on master\n1master\n=======\n1topic",
901 ">>>>>>> e0d1dea change file1 in topic\n2\n3\ntopic4");
902
903 assertEquals(RepositoryState.REBASING_MERGE,
904 db.getRepositoryState());
905 assertTrue(new File(db.getDirectory(), "rebase-merge").exists());
906
907
908 assertEquals(1, countPicks());
909
910
911 try {
912 git.rebase().setUpstream("refs/heads/master").call();
913 fail("Expected exception was not thrown");
914 } catch (WrongRepositoryStateException e) {
915
916 }
917
918
919 res = git.rebase().setOperation(Operation.ABORT).call();
920 assertEquals(res.getStatus(), Status.ABORTED);
921 assertEquals(lastTopicCommit.getName(), db.getFullBranch());
922 checkFile(FILE1, "1topic", "2", "3", "topic4");
923 try (RevWalk rw = new RevWalk(db)) {
924 assertEquals(lastTopicCommit,
925 rw.parseCommit(db.resolve(Constants.HEAD)));
926 }
927 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
928
929
930 assertFalse(new File(db.getDirectory(), "rebase-merge").exists());
931 }
932
933 @Test
934 public void testStopOnConflictAndContinue() throws Exception {
935
936 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
937 "2", "3");
938
939 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
940
941 checkFile(FILE1, "1master", "2", "3");
942
943 createBranch(firstInMaster, "refs/heads/topic");
944 checkoutBranch("refs/heads/topic");
945
946 checkFile(FILE1, "1", "2", "3");
947
948
949 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1", "2",
950 "3", "4topic");
951
952
953 writeFileAndCommit(FILE1,
954 "change file1 in topic\n\nThis is conflicting", "1topic", "2",
955 "3", "4topic");
956
957
958 writeFileAndCommit(FILE1, "change file1 in topic again", "1topic",
959 "2topic", "3", "4topic");
960
961 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
962 assertEquals(Status.STOPPED, res.getStatus());
963
964
965 try {
966 res = git.rebase().setOperation(Operation.CONTINUE).call();
967 fail("Expected Exception not thrown");
968 } catch (UnmergedPathsException e) {
969
970 }
971
972
973 writeFileAndAdd(FILE1, "1topic", "2", "3", "4topic");
974
975 res = git.rebase().setOperation(Operation.CONTINUE).call();
976 assertNotNull(res);
977 assertEquals(Status.OK, res.getStatus());
978 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
979
980 ObjectId headId = db.resolve(Constants.HEAD);
981 try (RevWalk rw = new RevWalk(db)) {
982 RevCommit rc = rw.parseCommit(headId);
983 RevCommit parent = rw.parseCommit(rc.getParent(0));
984 assertEquals("change file1 in topic\n\nThis is conflicting", parent
985 .getFullMessage());
986 }
987 }
988
989 @Test
990 public void testStopOnConflictAndContinueWithNoDeltaToMaster()
991 throws Exception {
992
993 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
994 "2", "3");
995
996 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
997
998 checkFile(FILE1, "1master", "2", "3");
999
1000 createBranch(firstInMaster, "refs/heads/topic");
1001 checkoutBranch("refs/heads/topic");
1002
1003 checkFile(FILE1, "1", "2", "3");
1004
1005
1006 writeFileAndCommit(FILE1,
1007 "change file1 in topic\n\nThis is conflicting", "1topic", "2",
1008 "3", "4topic");
1009
1010 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
1011 assertEquals(Status.STOPPED, res.getStatus());
1012
1013
1014 try {
1015 res = git.rebase().setOperation(Operation.CONTINUE).call();
1016 fail("Expected Exception not thrown");
1017 } catch (UnmergedPathsException e) {
1018
1019 }
1020
1021
1022 writeFileAndAdd(FILE1, "1master", "2", "3");
1023
1024 res = git.rebase().setOperation(Operation.CONTINUE).call();
1025 assertNotNull(res);
1026 assertEquals(Status.NOTHING_TO_COMMIT, res.getStatus());
1027 assertEquals(RepositoryState.REBASING_MERGE,
1028 db.getRepositoryState());
1029
1030 git.rebase().setOperation(Operation.SKIP).call();
1031
1032 ObjectId headId = db.resolve(Constants.HEAD);
1033 try (RevWalk rw = new RevWalk(db)) {
1034 RevCommit rc = rw.parseCommit(headId);
1035 assertEquals("change file1 in master", rc.getFullMessage());
1036 }
1037 }
1038
1039 @Test
1040 public void testStopOnConflictAndFailContinueIfFileIsDirty()
1041 throws Exception {
1042
1043 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
1044 "2", "3");
1045
1046 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
1047
1048 checkFile(FILE1, "1master", "2", "3");
1049
1050 createBranch(firstInMaster, "refs/heads/topic");
1051 checkoutBranch("refs/heads/topic");
1052
1053 checkFile(FILE1, "1", "2", "3");
1054
1055
1056 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1", "2",
1057 "3", "4topic");
1058
1059
1060 writeFileAndCommit(FILE1,
1061 "change file1 in topic\n\nThis is conflicting", "1topic", "2",
1062 "3", "4topic");
1063
1064
1065 writeFileAndCommit(FILE1, "change file1 in topic again", "1topic",
1066 "2topic", "3", "4topic");
1067
1068 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
1069 assertEquals(Status.STOPPED, res.getStatus());
1070
1071 git.add().addFilepattern(FILE1).call();
1072 File trashFile = writeTrashFile(FILE1, "Some local change");
1073
1074 res = git.rebase().setOperation(Operation.CONTINUE).call();
1075 assertNotNull(res);
1076 assertEquals(Status.STOPPED, res.getStatus());
1077 checkFile(trashFile, "Some local change");
1078 }
1079
1080 @Test
1081 public void testStopOnLastConflictAndContinue() throws Exception {
1082
1083 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
1084 "2", "3");
1085
1086 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
1087
1088 checkFile(FILE1, "1master", "2", "3");
1089
1090 createBranch(firstInMaster, "refs/heads/topic");
1091 checkoutBranch("refs/heads/topic");
1092
1093 checkFile(FILE1, "1", "2", "3");
1094
1095
1096 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1", "2",
1097 "3", "4topic");
1098
1099
1100 writeFileAndCommit(FILE1,
1101 "change file1 in topic\n\nThis is conflicting", "1topic", "2",
1102 "3", "4topic");
1103
1104 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
1105 assertEquals(Status.STOPPED, res.getStatus());
1106
1107
1108 writeFileAndAdd(FILE1, "1topic", "2", "3", "4topic");
1109
1110 res = git.rebase().setOperation(Operation.CONTINUE).call();
1111 assertNotNull(res);
1112 assertEquals(Status.OK, res.getStatus());
1113 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
1114 }
1115
1116 @Test
1117 public void testStopOnLastConflictAndSkip() throws Exception {
1118
1119 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
1120 "2", "3");
1121
1122 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
1123
1124 checkFile(FILE1, "1master", "2", "3");
1125
1126 createBranch(firstInMaster, "refs/heads/topic");
1127 checkoutBranch("refs/heads/topic");
1128
1129 checkFile(FILE1, "1", "2", "3");
1130
1131
1132 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1", "2",
1133 "3", "4topic");
1134
1135
1136 writeFileAndCommit(FILE1,
1137 "change file1 in topic\n\nThis is conflicting", "1topic", "2",
1138 "3", "4topic");
1139
1140 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
1141 assertEquals(Status.STOPPED, res.getStatus());
1142
1143
1144 writeFileAndAdd(FILE1, "1topic", "2", "3", "4topic");
1145
1146 res = git.rebase().setOperation(Operation.SKIP).call();
1147 assertNotNull(res);
1148 assertEquals(Status.OK, res.getStatus());
1149 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
1150 }
1151
1152 @Test
1153 public void testMergeFirstStopOnLastConflictAndSkip() throws Exception {
1154
1155 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
1156 "2", "3");
1157
1158 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
1159
1160 checkFile(FILE1, "1master", "2", "3");
1161
1162 createBranch(firstInMaster, "refs/heads/topic");
1163 checkoutBranch("refs/heads/topic");
1164
1165 checkFile(FILE1, "1", "2", "3");
1166
1167
1168 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1topic",
1169 "2", "3", "4topic");
1170
1171
1172 writeFileAndCommit(FILE1,
1173 "change file1 in topic\n\nThis is conflicting", "1topicagain",
1174 "2", "3", "4topic");
1175
1176 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
1177 assertEquals(Status.STOPPED, res.getStatus());
1178
1179 writeFileAndAdd(FILE1, "merged");
1180
1181 res = git.rebase().setOperation(Operation.CONTINUE).call();
1182 assertEquals(Status.STOPPED, res.getStatus());
1183
1184 res = git.rebase().setOperation(Operation.SKIP).call();
1185 assertNotNull(res);
1186 assertEquals(Status.OK, res.getStatus());
1187 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
1188 checkFile(FILE1, "merged");
1189 }
1190
1191 @Test
1192 public void testStopOnConflictAndSkipNoConflict() throws Exception {
1193
1194 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
1195 "2", "3");
1196
1197 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
1198
1199 checkFile(FILE1, "1master", "2", "3");
1200
1201 createBranch(firstInMaster, "refs/heads/topic");
1202 checkoutBranch("refs/heads/topic");
1203
1204 checkFile(FILE1, "1", "2", "3");
1205
1206
1207 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1", "2",
1208 "3", "4topic");
1209
1210
1211 writeFileAndCommit(FILE1,
1212 "change file1 in topic\n\nThis is conflicting", "1topic", "2",
1213 "3", "4topic");
1214
1215
1216 writeFileAndCommit(FILE1, "change file1 in topic again", "1topic", "2",
1217 "3topic", "4topic");
1218
1219 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
1220 assertEquals(Status.STOPPED, res.getStatus());
1221
1222 res = git.rebase().setOperation(Operation.SKIP).call();
1223
1224 checkFile(FILE1, "1master", "2", "3topic", "4topic");
1225 assertEquals(Status.OK, res.getStatus());
1226 }
1227
1228 @Test
1229 public void testStopOnConflictAndSkipWithConflict() throws Exception {
1230
1231 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
1232 "2", "3", "4");
1233
1234 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2",
1235 "3master", "4");
1236
1237 checkFile(FILE1, "1master", "2", "3master", "4");
1238
1239 createBranch(firstInMaster, "refs/heads/topic");
1240 checkoutBranch("refs/heads/topic");
1241
1242 checkFile(FILE1, "1", "2", "3", "4");
1243
1244
1245 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1", "2",
1246 "3", "4", "5topic");
1247
1248
1249 writeFileAndCommit(FILE1,
1250 "change file1 in topic\n\nThis is conflicting", "1topic", "2",
1251 "3", "4", "5topic");
1252
1253
1254 writeFileAndCommit(FILE1, "change file1 in topic again", "1topic", "2",
1255 "3topic", "4", "5topic");
1256
1257 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
1258 assertEquals(Status.STOPPED, res.getStatus());
1259
1260 res = git.rebase().setOperation(Operation.SKIP).call();
1261
1262 checkFile(
1263 FILE1,
1264 "1master\n2\n<<<<<<< Upstream, based on master\n3master\n=======\n3topic",
1265 ">>>>>>> 5afc8df change file1 in topic again\n4\n5topic");
1266 assertEquals(Status.STOPPED, res.getStatus());
1267 }
1268
1269 @Test
1270 public void testStopOnConflictCommitAndContinue() throws Exception {
1271
1272 RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1",
1273 "2", "3");
1274
1275 writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3");
1276
1277 checkFile(FILE1, "1master", "2", "3");
1278
1279 createBranch(firstInMaster, "refs/heads/topic");
1280 checkoutBranch("refs/heads/topic");
1281
1282 checkFile(FILE1, "1", "2", "3");
1283
1284
1285 writeFileAndCommit(FILE1, "add a line to file1 in topic", "1", "2",
1286 "3", "4topic");
1287
1288
1289 writeFileAndCommit(FILE1,
1290 "change file1 in topic\n\nThis is conflicting", "1topic", "2",
1291 "3", "4topic");
1292
1293
1294 writeFileAndCommit(FILE1, "change file1 in topic again", "1topic", "2",
1295 "3topic", "4topic");
1296
1297 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
1298 assertEquals(Status.STOPPED, res.getStatus());
1299
1300
1301 try {
1302 res = git.rebase().setOperation(Operation.CONTINUE).call();
1303 fail("Expected Exception not thrown");
1304 } catch (UnmergedPathsException e) {
1305
1306 }
1307
1308
1309 writeFileAndCommit(FILE1, "A different commit message", "1topic", "2",
1310 "3", "4topic");
1311
1312 res = git.rebase().setOperation(Operation.CONTINUE).call();
1313 assertNotNull(res);
1314
1315
1316
1317
1318 assertEquals(Status.NOTHING_TO_COMMIT, res.getStatus());
1319 assertEquals(RepositoryState.REBASING_MERGE,
1320 db.getRepositoryState());
1321
1322 git.rebase().setOperation(Operation.SKIP).call();
1323
1324 ObjectId headId = db.resolve(Constants.HEAD);
1325 try (RevWalk rw = new RevWalk(db)) {
1326 RevCommit rc = rw.parseCommit(headId);
1327 RevCommit parent = rw.parseCommit(rc.getParent(0));
1328 assertEquals("A different commit message", parent.getFullMessage());
1329 }
1330 }
1331
1332 private RevCommit writeFileAndCommit(String fileName, String commitMessage,
1333 String... lines) throws Exception {
1334 StringBuilder sb = new StringBuilder();
1335 for (String line : lines) {
1336 sb.append(line);
1337 sb.append('\n');
1338 }
1339 writeTrashFile(fileName, sb.toString());
1340 git.add().addFilepattern(fileName).call();
1341 return git.commit().setMessage(commitMessage).call();
1342 }
1343
1344 private void writeFileAndAdd(String fileName, String... lines)
1345 throws Exception {
1346 StringBuilder sb = new StringBuilder();
1347 for (String line : lines) {
1348 sb.append(line);
1349 sb.append('\n');
1350 }
1351 writeTrashFile(fileName, sb.toString());
1352 git.add().addFilepattern(fileName).call();
1353 }
1354
1355 private void checkFile(String fileName, String... lines) throws Exception {
1356 File file = new File(db.getWorkTree(), fileName);
1357 StringBuilder sb = new StringBuilder();
1358 for (String line : lines) {
1359 sb.append(line);
1360 sb.append('\n');
1361 }
1362 checkFile(file, sb.toString());
1363 }
1364
1365 @Test
1366 public void testStopOnConflictFileCreationAndDeletion() throws Exception {
1367
1368 writeTrashFile(FILE1, "Hello World");
1369 git.add().addFilepattern(FILE1).call();
1370
1371 File file2 = writeTrashFile("file2", "Hello World 2");
1372 git.add().addFilepattern("file2").call();
1373
1374 File file3 = writeTrashFile("file3", "Hello World 3");
1375 git.add().addFilepattern("file3").call();
1376
1377 RevCommit firstInMaster = git.commit()
1378 .setMessage("Add file 1, 2 and 3").call();
1379
1380
1381 File file4 = writeTrashFile("file4", "Hello World 4");
1382 git.add().addFilepattern("file4").call();
1383
1384 deleteTrashFile("file2");
1385 git.add().setUpdate(true).addFilepattern("file2").call();
1386
1387
1388 writeTrashFile("folder6/file1", "Hello World folder6");
1389 git.add().addFilepattern("folder6/file1").call();
1390
1391 git.commit().setMessage(
1392 "Add file 4 and folder folder6, delete file2 on master").call();
1393
1394
1395 createBranch(firstInMaster, "refs/heads/topic");
1396 checkoutBranch("refs/heads/topic");
1397
1398 deleteTrashFile("file3");
1399 git.add().setUpdate(true).addFilepattern("file3").call();
1400
1401 File file5 = writeTrashFile("file5", "Hello World 5");
1402 git.add().addFilepattern("file5").call();
1403 git.commit().setMessage("Delete file3 and add file5 in topic").call();
1404
1405
1406 writeTrashFile("folder6", "Hello World 6");
1407 git.add().addFilepattern("folder6").call();
1408
1409 File file7 = writeTrashFile("file7", "Hello World 7");
1410 git.add().addFilepattern("file7").call();
1411
1412 deleteTrashFile("file5");
1413 git.add().setUpdate(true).addFilepattern("file5").call();
1414 RevCommit conflicting = git.commit().setMessage(
1415 "Delete file5, add file folder6 and file7 in topic").call();
1416
1417 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
1418 assertEquals(Status.STOPPED, res.getStatus());
1419 assertEquals(conflicting, res.getCurrentCommit());
1420
1421 assertEquals(RepositoryState.REBASING_MERGE, db
1422 .getRepositoryState());
1423 assertTrue(new File(db.getDirectory(), "rebase-merge").exists());
1424
1425
1426 assertEquals(0, countPicks());
1427
1428 assertFalse(file2.exists());
1429 assertFalse(file3.exists());
1430 assertTrue(file4.exists());
1431 assertFalse(file5.exists());
1432 assertTrue(file7.exists());
1433
1434
1435 res = git.rebase().setOperation(Operation.ABORT).call();
1436 assertEquals(res.getStatus(), Status.ABORTED);
1437 assertEquals("refs/heads/topic", db.getFullBranch());
1438 try (RevWalk rw = new RevWalk(db)) {
1439 assertEquals(conflicting, rw.parseCommit(db.resolve(Constants.HEAD)));
1440 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
1441 }
1442
1443
1444 assertFalse(new File(db.getDirectory(), "rebase-merge").exists());
1445
1446 assertTrue(file2.exists());
1447 assertFalse(file3.exists());
1448 assertFalse(file4.exists());
1449 assertFalse(file5.exists());
1450 assertTrue(file7.exists());
1451
1452 }
1453
1454 @Test
1455 public void testAuthorScriptConverter() throws Exception {
1456
1457 PersonIdent ident = new PersonIdent("Author name", "a.mail@some.com",
1458 123456789123L, -60);
1459 String convertedAuthor = git.rebase().toAuthorScript(ident);
1460 String[] lines = convertedAuthor.split("\n");
1461 assertEquals("GIT_AUTHOR_NAME='Author name'", lines[0]);
1462 assertEquals("GIT_AUTHOR_EMAIL='a.mail@some.com'", lines[1]);
1463 assertEquals("GIT_AUTHOR_DATE='@123456789 -0100'", lines[2]);
1464
1465 PersonIdent parsedIdent = git.rebase().parseAuthor(
1466 convertedAuthor.getBytes("UTF-8"));
1467 assertEquals(ident.getName(), parsedIdent.getName());
1468 assertEquals(ident.getEmailAddress(), parsedIdent.getEmailAddress());
1469
1470 assertEquals(123456789000L, parsedIdent.getWhen().getTime());
1471 assertEquals(ident.getTimeZoneOffset(), parsedIdent.getTimeZoneOffset());
1472
1473
1474 ident = new PersonIdent("Author name", "a.mail@some.com",
1475 123456789123L, +570);
1476 convertedAuthor = git.rebase().toAuthorScript(ident);
1477 lines = convertedAuthor.split("\n");
1478 assertEquals("GIT_AUTHOR_NAME='Author name'", lines[0]);
1479 assertEquals("GIT_AUTHOR_EMAIL='a.mail@some.com'", lines[1]);
1480 assertEquals("GIT_AUTHOR_DATE='@123456789 +0930'", lines[2]);
1481
1482 parsedIdent = git.rebase().parseAuthor(
1483 convertedAuthor.getBytes("UTF-8"));
1484 assertEquals(ident.getName(), parsedIdent.getName());
1485 assertEquals(ident.getEmailAddress(), parsedIdent.getEmailAddress());
1486 assertEquals(123456789000L, parsedIdent.getWhen().getTime());
1487 assertEquals(ident.getTimeZoneOffset(), parsedIdent.getTimeZoneOffset());
1488 }
1489
1490 @Test
1491 public void testRepositoryStateChecks() throws Exception {
1492 try {
1493 git.rebase().setOperation(Operation.ABORT).call();
1494 fail("Expected Exception not thrown");
1495 } catch (WrongRepositoryStateException e) {
1496
1497 }
1498 try {
1499 git.rebase().setOperation(Operation.SKIP).call();
1500 fail("Expected Exception not thrown");
1501 } catch (WrongRepositoryStateException e) {
1502
1503 }
1504 try {
1505 git.rebase().setOperation(Operation.CONTINUE).call();
1506 fail("Expected Exception not thrown");
1507 } catch (WrongRepositoryStateException e) {
1508
1509 }
1510 }
1511
1512 @Test
1513 public void testRebaseWithUntrackedFile() throws Exception {
1514
1515 writeTrashFile(FILE1, "file1");
1516 git.add().addFilepattern(FILE1).call();
1517 RevCommit commit = git.commit().setMessage("commit1").call();
1518
1519
1520 createBranch(commit, "refs/heads/topic");
1521 checkoutBranch("refs/heads/topic");
1522 writeTrashFile("file2", "file2");
1523 git.add().addFilepattern("file2").call();
1524 git.commit().setMessage("commit2").call();
1525
1526
1527 checkoutBranch("refs/heads/master");
1528 writeTrashFile(FILE1, "modified file1");
1529 git.add().addFilepattern(FILE1).call();
1530 git.commit().setMessage("commit3").call();
1531
1532
1533 checkoutBranch("refs/heads/topic");
1534 writeTrashFile("file3", "untracked file3");
1535
1536
1537 assertEquals(Status.OK, git.rebase().setUpstream("refs/heads/master")
1538 .call().getStatus());
1539 }
1540
1541 @Test
1542 public void testRebaseWithUnstagedTopicChange() throws Exception {
1543
1544 writeTrashFile(FILE1, "file1");
1545 git.add().addFilepattern(FILE1).call();
1546 RevCommit commit = git.commit().setMessage("commit1").call();
1547
1548
1549 createBranch(commit, "refs/heads/topic");
1550 checkoutBranch("refs/heads/topic");
1551 writeTrashFile("file2", "file2");
1552 git.add().addFilepattern("file2").call();
1553 git.commit().setMessage("commit2").call();
1554
1555
1556 checkoutBranch("refs/heads/master");
1557 writeTrashFile(FILE1, "modified file1");
1558 git.add().addFilepattern(FILE1).call();
1559 git.commit().setMessage("commit3").call();
1560
1561
1562 checkoutBranch("refs/heads/topic");
1563 writeTrashFile("file2", "unstaged file2");
1564
1565
1566 RebaseResult result = git.rebase().setUpstream("refs/heads/master")
1567 .call();
1568 assertEquals(Status.UNCOMMITTED_CHANGES, result.getStatus());
1569 assertEquals(1, result.getUncommittedChanges().size());
1570 assertEquals("file2", result.getUncommittedChanges().get(0));
1571 }
1572
1573 @Test
1574 public void testRebaseWithUncommittedTopicChange() throws Exception {
1575
1576 writeTrashFile(FILE1, "file1");
1577 git.add().addFilepattern(FILE1).call();
1578 RevCommit commit = git.commit().setMessage("commit1").call();
1579
1580
1581 createBranch(commit, "refs/heads/topic");
1582 checkoutBranch("refs/heads/topic");
1583 writeTrashFile("file2", "file2");
1584 git.add().addFilepattern("file2").call();
1585 git.commit().setMessage("commit2").call();
1586
1587
1588 checkoutBranch("refs/heads/master");
1589 writeTrashFile(FILE1, "modified file1");
1590 git.add().addFilepattern(FILE1).call();
1591 git.commit().setMessage("commit3").call();
1592
1593
1594 checkoutBranch("refs/heads/topic");
1595 File uncommittedFile = writeTrashFile("file2", "uncommitted file2");
1596 git.add().addFilepattern("file2").call();
1597
1598
1599 RebaseResult result = git.rebase().setUpstream("refs/heads/master")
1600 .call();
1601 assertEquals(Status.UNCOMMITTED_CHANGES, result.getStatus());
1602 assertEquals(1, result.getUncommittedChanges().size());
1603 assertEquals("file2", result.getUncommittedChanges().get(0));
1604
1605 checkFile(uncommittedFile, "uncommitted file2");
1606 assertEquals(RepositoryState.SAFE, git.getRepository().getRepositoryState());
1607 }
1608
1609 @Test
1610 public void testRebaseWithUnstagedMasterChange() throws Exception {
1611
1612 writeTrashFile(FILE1, "file1");
1613 git.add().addFilepattern(FILE1).call();
1614 RevCommit commit = git.commit().setMessage("commit1").call();
1615
1616
1617 createBranch(commit, "refs/heads/topic");
1618 checkoutBranch("refs/heads/topic");
1619 writeTrashFile("file2", "file2");
1620 git.add().addFilepattern("file2").call();
1621 git.commit().setMessage("commit2").call();
1622
1623
1624 checkoutBranch("refs/heads/master");
1625 writeTrashFile(FILE1, "modified file1");
1626 git.add().addFilepattern(FILE1).call();
1627 git.commit().setMessage("commit3").call();
1628
1629
1630 checkoutBranch("refs/heads/topic");
1631 writeTrashFile(FILE1, "unstaged modified file1");
1632
1633
1634 RebaseResult result = git.rebase().setUpstream("refs/heads/master")
1635 .call();
1636 assertEquals(Status.UNCOMMITTED_CHANGES, result.getStatus());
1637 assertEquals(1, result.getUncommittedChanges().size());
1638 assertEquals(FILE1, result.getUncommittedChanges().get(0));
1639 }
1640
1641 @Test
1642 public void testRebaseWithUncommittedMasterChange() throws Exception {
1643
1644 writeTrashFile(FILE1, "file1");
1645 git.add().addFilepattern(FILE1).call();
1646 RevCommit commit = git.commit().setMessage("commit1").call();
1647
1648
1649 createBranch(commit, "refs/heads/topic");
1650 checkoutBranch("refs/heads/topic");
1651 writeTrashFile("file2", "file2");
1652 git.add().addFilepattern("file2").call();
1653 git.commit().setMessage("commit2").call();
1654
1655
1656 checkoutBranch("refs/heads/master");
1657 writeTrashFile(FILE1, "modified file1");
1658 git.add().addFilepattern(FILE1).call();
1659 git.commit().setMessage("commit3").call();
1660
1661
1662 checkoutBranch("refs/heads/topic");
1663 writeTrashFile(FILE1, "uncommitted modified file1");
1664 git.add().addFilepattern(FILE1).call();
1665
1666
1667
1668 RebaseResult result = git.rebase().setUpstream("refs/heads/master")
1669 .call();
1670 assertEquals(Status.UNCOMMITTED_CHANGES, result.getStatus());
1671 assertEquals(1, result.getUncommittedChanges().size());
1672 assertEquals(FILE1, result.getUncommittedChanges().get(0));
1673 }
1674
1675 @Test
1676 public void testRebaseWithUnstagedMasterChangeBaseCommit() throws Exception {
1677
1678 writeTrashFile("file0", "file0");
1679 writeTrashFile(FILE1, "file1");
1680 git.add().addFilepattern("file0").addFilepattern(FILE1).call();
1681 RevCommit commit = git.commit().setMessage("commit1").call();
1682
1683
1684 createBranch(commit, "refs/heads/topic");
1685 checkoutBranch("refs/heads/topic");
1686 writeTrashFile("file2", "file2");
1687 git.add().addFilepattern("file2").call();
1688 git.commit().setMessage("commit2").call();
1689
1690
1691 checkoutBranch("refs/heads/master");
1692 writeTrashFile(FILE1, "modified file1");
1693 git.add().addFilepattern(FILE1).call();
1694 git.commit().setMessage("commit3").call();
1695
1696
1697 checkoutBranch("refs/heads/topic");
1698 writeTrashFile("file0", "unstaged modified file0");
1699
1700
1701 assertEquals(Status.UNCOMMITTED_CHANGES,
1702 git.rebase().setUpstream("refs/heads/master")
1703 .call().getStatus());
1704 }
1705
1706 @Test
1707 public void testRebaseWithUncommittedMasterChangeBaseCommit()
1708 throws Exception {
1709
1710 File file0 = writeTrashFile("file0", "file0");
1711 writeTrashFile(FILE1, "file1");
1712 git.add().addFilepattern("file0").addFilepattern(FILE1).call();
1713 RevCommit commit = git.commit().setMessage("commit1").call();
1714
1715
1716 createBranch(commit, "refs/heads/topic");
1717 checkoutBranch("refs/heads/topic");
1718 writeTrashFile("file2", "file2");
1719 git.add().addFilepattern("file2").call();
1720 git.commit().setMessage("commit2").call();
1721
1722
1723 checkoutBranch("refs/heads/master");
1724 writeTrashFile(FILE1, "modified file1");
1725 git.add().addFilepattern(FILE1).call();
1726 git.commit().setMessage("commit3").call();
1727
1728
1729 checkoutBranch("refs/heads/topic");
1730 write(file0, "unstaged modified file0");
1731 git.add().addFilepattern("file0").call();
1732
1733
1734
1735 String indexState = indexState(CONTENT);
1736
1737
1738 RebaseResult result = git.rebase().setUpstream("refs/heads/master")
1739 .call();
1740 assertEquals(Status.UNCOMMITTED_CHANGES, result.getStatus());
1741 assertEquals(1, result.getUncommittedChanges().size());
1742
1743 assertEquals(indexState, indexState(CONTENT));
1744 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
1745 }
1746
1747 @Test
1748 public void testRebaseWithUnstagedMasterChangeOtherCommit()
1749 throws Exception {
1750
1751 writeTrashFile("file0", "file0");
1752 git.add().addFilepattern("file0").call();
1753 git.commit().setMessage("commit0").call();
1754
1755 writeTrashFile(FILE1, "file1");
1756 git.add().addFilepattern(FILE1).call();
1757 RevCommit commit = git.commit().setMessage("commit1").call();
1758
1759
1760 createBranch(commit, "refs/heads/topic");
1761 checkoutBranch("refs/heads/topic");
1762 writeTrashFile("file2", "file2");
1763 git.add().addFilepattern("file2").call();
1764 git.commit().setMessage("commit2").call();
1765
1766
1767 checkoutBranch("refs/heads/master");
1768 writeTrashFile(FILE1, "modified file1");
1769 git.add().addFilepattern(FILE1).call();
1770 git.commit().setMessage("commit3").call();
1771
1772
1773 checkoutBranch("refs/heads/topic");
1774 writeTrashFile("file0", "unstaged modified file0");
1775
1776
1777 assertEquals(Status.UNCOMMITTED_CHANGES,
1778 git.rebase().setUpstream("refs/heads/master")
1779 .call().getStatus());
1780 }
1781
1782 @Test
1783 public void testRebaseWithUncommittedMasterChangeOtherCommit()
1784 throws Exception {
1785
1786 File file0 = writeTrashFile("file0", "file0");
1787 git.add().addFilepattern("file0").call();
1788 git.commit().setMessage("commit0").call();
1789
1790 writeTrashFile(FILE1, "file1");
1791 git.add().addFilepattern(FILE1).call();
1792 RevCommit commit = git.commit().setMessage("commit1").call();
1793
1794
1795 createBranch(commit, "refs/heads/topic");
1796 checkoutBranch("refs/heads/topic");
1797 writeTrashFile("file2", "file2");
1798 git.add().addFilepattern("file2").call();
1799 git.commit().setMessage("commit2").call();
1800
1801
1802 checkoutBranch("refs/heads/master");
1803 writeTrashFile(FILE1, "modified file1");
1804 git.add().addFilepattern(FILE1).call();
1805 git.commit().setMessage("commit3").call();
1806
1807
1808 checkoutBranch("refs/heads/topic");
1809 write(file0, "unstaged modified file0");
1810 git.add().addFilepattern("file0").call();
1811
1812
1813
1814 String indexState = indexState(CONTENT);
1815
1816
1817 RebaseResult result = git.rebase().setUpstream("refs/heads/master")
1818 .call();
1819 assertEquals(Status.UNCOMMITTED_CHANGES, result.getStatus());
1820
1821 assertEquals(1, result.getUncommittedChanges().size());
1822 assertEquals("unstaged modified file0", read(file0));
1823
1824 assertEquals(indexState, indexState(CONTENT));
1825 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
1826 }
1827
1828 @Test
1829 public void testFastForwardRebaseWithModification() throws Exception {
1830
1831 writeTrashFile("file0", "file0");
1832 writeTrashFile(FILE1, "file1");
1833 git.add().addFilepattern("file0").addFilepattern(FILE1).call();
1834 RevCommit commit = git.commit().setMessage("commit1").call();
1835
1836
1837 createBranch(commit, "refs/heads/topic");
1838
1839
1840 writeTrashFile(FILE1, "modified file1");
1841 git.add().addFilepattern(FILE1).call();
1842 git.commit().setMessage("commit2").call();
1843
1844
1845 checkoutBranch("refs/heads/topic");
1846 writeTrashFile("file0", "modified file0 in index");
1847 git.add().addFilepattern("file0").addFilepattern(FILE1).call();
1848
1849 writeTrashFile("file0", "modified file0");
1850
1851
1852 RebaseResult result = git.rebase().setUpstream("refs/heads/master")
1853 .call();
1854 assertEquals(Status.FAST_FORWARD, result.getStatus());
1855 checkFile(new File(db.getWorkTree(), "file0"), "modified file0");
1856 checkFile(new File(db.getWorkTree(), FILE1), "modified file1");
1857 assertEquals("[file0, mode:100644, content:modified file0 in index]"
1858 + "[file1, mode:100644, content:modified file1]",
1859 indexState(CONTENT));
1860 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
1861 }
1862
1863 @Test
1864 public void testRebaseWithModificationShouldNotDeleteData()
1865 throws Exception {
1866
1867 writeTrashFile("file0", "file0");
1868 writeTrashFile(FILE1, "file1");
1869 git.add().addFilepattern("file0").addFilepattern(FILE1).call();
1870 RevCommit commit = git.commit().setMessage("commit1").call();
1871
1872
1873 createBranch(commit, "refs/heads/topic");
1874
1875
1876 writeTrashFile(FILE1, "modified file1");
1877 git.add().addFilepattern(FILE1).call();
1878 git.commit().setMessage("commit2").call();
1879
1880
1881 checkoutBranch("refs/heads/topic");
1882 writeTrashFile(FILE1, "modified file1 on topic");
1883 git.add().addFilepattern(FILE1).call();
1884 git.commit().setMessage("commit3").call();
1885
1886 writeTrashFile("file0", "modified file0");
1887
1888 RebaseResult result = git.rebase().setUpstream("refs/heads/master")
1889 .call();
1890
1891
1892
1893 if (result.getStatus() == Status.STOPPED)
1894 git.rebase().setOperation(Operation.ABORT).call();
1895
1896 checkFile(new File(db.getWorkTree(), "file0"), "modified file0");
1897 checkFile(new File(db.getWorkTree(), FILE1),
1898 "modified file1 on topic");
1899 assertEquals("[file0, mode:100644, content:file0]"
1900 + "[file1, mode:100644, content:modified file1 on topic]",
1901 indexState(CONTENT));
1902 }
1903
1904 @Test
1905 public void testRebaseWithUncommittedDelete() throws Exception {
1906
1907 File file0 = writeTrashFile("file0", "file0");
1908 writeTrashFile(FILE1, "file1");
1909 git.add().addFilepattern("file0").addFilepattern(FILE1).call();
1910 RevCommit commit = git.commit().setMessage("commit1").call();
1911
1912
1913 createBranch(commit, "refs/heads/topic");
1914
1915
1916 writeTrashFile(FILE1, "modified file1");
1917 git.add().addFilepattern(FILE1).call();
1918 git.commit().setMessage("commit2").call();
1919
1920
1921 checkoutBranch("refs/heads/topic");
1922 git.rm().addFilepattern("file0").call();
1923
1924
1925
1926 RebaseResult result = git.rebase().setUpstream("refs/heads/master")
1927 .call();
1928 assertEquals(Status.FAST_FORWARD, result.getStatus());
1929 assertFalse("File should still be deleted", file0.exists());
1930
1931 assertEquals("[file1, mode:100644, content:modified file1]",
1932 indexState(CONTENT));
1933 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
1934 }
1935
1936 @Test
1937 public void testRebaseWithAutoStash()
1938 throws Exception {
1939
1940 db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
1941 ConfigConstants.CONFIG_KEY_AUTOSTASH, true);
1942 writeTrashFile("file0", "file0");
1943 git.add().addFilepattern("file0").call();
1944 git.commit().setMessage("commit0").call();
1945
1946 writeTrashFile(FILE1, "file1");
1947 git.add().addFilepattern(FILE1).call();
1948 RevCommit commit = git.commit().setMessage("commit1").call();
1949
1950
1951 createBranch(commit, "refs/heads/topic");
1952 checkoutBranch("refs/heads/topic");
1953 writeTrashFile("file2", "file2");
1954 git.add().addFilepattern("file2").call();
1955 git.commit().setMessage("commit2").call();
1956
1957
1958 checkoutBranch("refs/heads/master");
1959 writeTrashFile(FILE1, "modified file1");
1960 git.add().addFilepattern(FILE1).call();
1961 git.commit().setMessage("commit3").call();
1962
1963
1964 checkoutBranch("refs/heads/topic");
1965 writeTrashFile("file0", "unstaged modified file0");
1966
1967
1968 assertEquals(Status.OK,
1969 git.rebase().setUpstream("refs/heads/master").call()
1970 .getStatus());
1971 checkFile(new File(db.getWorkTree(), "file0"),
1972 "unstaged modified file0");
1973 checkFile(new File(db.getWorkTree(), FILE1), "modified file1");
1974 checkFile(new File(db.getWorkTree(), "file2"), "file2");
1975 assertEquals("[file0, mode:100644, content:file0]"
1976 + "[file1, mode:100644, content:modified file1]"
1977 + "[file2, mode:100644, content:file2]",
1978 indexState(CONTENT));
1979 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
1980 }
1981
1982 @Test
1983 public void testRebaseWithAutoStashConflictOnApply() throws Exception {
1984
1985 db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
1986 ConfigConstants.CONFIG_KEY_AUTOSTASH, true);
1987 writeTrashFile("file0", "file0");
1988 git.add().addFilepattern("file0").call();
1989 git.commit().setMessage("commit0").call();
1990
1991 writeTrashFile(FILE1, "file1");
1992 git.add().addFilepattern(FILE1).call();
1993 RevCommit commit = git.commit().setMessage("commit1").call();
1994
1995
1996 createBranch(commit, "refs/heads/topic");
1997 checkoutBranch("refs/heads/topic");
1998 writeTrashFile("file2", "file2");
1999 git.add().addFilepattern("file2").call();
2000 git.commit().setMessage("commit2").call();
2001
2002
2003 checkoutBranch("refs/heads/master");
2004 writeTrashFile(FILE1, "modified file1");
2005 git.add().addFilepattern(FILE1).call();
2006 git.commit().setMessage("commit3").call();
2007
2008
2009 checkoutBranch("refs/heads/topic");
2010 writeTrashFile("file1", "unstaged modified file1");
2011
2012
2013 assertEquals(Status.STASH_APPLY_CONFLICTS,
2014 git.rebase().setUpstream("refs/heads/master").call()
2015 .getStatus());
2016 checkFile(new File(db.getWorkTree(), "file0"), "file0");
2017 checkFile(
2018 new File(db.getWorkTree(), FILE1),
2019 "<<<<<<< HEAD\nmodified file1\n=======\nunstaged modified file1\n>>>>>>> stash\n");
2020 checkFile(new File(db.getWorkTree(), "file2"), "file2");
2021 assertEquals(
2022 "[file0, mode:100644, content:file0]"
2023 + "[file1, mode:100644, stage:1, content:file1]"
2024 + "[file1, mode:100644, stage:2, content:modified file1]"
2025 + "[file1, mode:100644, stage:3, content:unstaged modified file1]"
2026 + "[file2, mode:100644, content:file2]",
2027 indexState(CONTENT));
2028 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
2029
2030 List<DiffEntry> diffs = getStashedDiff();
2031 assertEquals(1, diffs.size());
2032 assertEquals(DiffEntry.ChangeType.MODIFY, diffs.get(0).getChangeType());
2033 assertEquals("file1", diffs.get(0).getOldPath());
2034 }
2035
2036 @Test
2037 public void testFastForwardRebaseWithAutoStash() throws Exception {
2038
2039 db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
2040 ConfigConstants.CONFIG_KEY_AUTOSTASH, true);
2041 writeTrashFile("file0", "file0");
2042 git.add().addFilepattern("file0").call();
2043 git.commit().setMessage("commit0").call();
2044
2045 writeTrashFile(FILE1, "file1");
2046 git.add().addFilepattern(FILE1).call();
2047 RevCommit commit = git.commit().setMessage("commit1").call();
2048
2049
2050 createBranch(commit, "refs/heads/topic");
2051
2052
2053 checkoutBranch("refs/heads/master");
2054 writeTrashFile(FILE1, "modified file1");
2055 git.add().addFilepattern(FILE1).call();
2056 git.commit().setMessage("commit3").call();
2057
2058
2059 checkoutBranch("refs/heads/topic");
2060 writeTrashFile("file0", "unstaged modified file0");
2061
2062
2063 assertEquals(Status.FAST_FORWARD,
2064 git.rebase().setUpstream("refs/heads/master")
2065 .call().getStatus());
2066 checkFile(new File(db.getWorkTree(), "file0"),
2067 "unstaged modified file0");
2068 checkFile(new File(db.getWorkTree(), FILE1), "modified file1");
2069 assertEquals("[file0, mode:100644, content:file0]"
2070 + "[file1, mode:100644, content:modified file1]",
2071 indexState(CONTENT));
2072 assertEquals(RepositoryState.SAFE, db.getRepositoryState());
2073 }
2074
2075 private List<DiffEntry> getStashedDiff() throws AmbiguousObjectException,
2076 IncorrectObjectTypeException, IOException, MissingObjectException {
2077 ObjectId stashId = db.resolve("stash@{0}");
2078 RevWalk revWalk = new RevWalk(db);
2079 RevCommit stashCommit = revWalk.parseCommit(stashId);
2080 List<DiffEntry> diffs = diffWorkingAgainstHead(stashCommit, revWalk);
2081 return diffs;
2082 }
2083
2084 private TreeWalk createTreeWalk() {
2085 TreeWalk walk = new TreeWalk(db);
2086 walk.setRecursive(true);
2087 walk.setFilter(TreeFilter.ANY_DIFF);
2088 return walk;
2089 }
2090
2091 private List<DiffEntry> diffWorkingAgainstHead(final RevCommit commit,
2092 RevWalk revWalk)
2093 throws IOException {
2094 RevCommit parentCommit = revWalk.parseCommit(commit.getParent(0));
2095 try (TreeWalk walk = createTreeWalk()) {
2096 walk.addTree(parentCommit.getTree());
2097 walk.addTree(commit.getTree());
2098 return DiffEntry.scan(walk);
2099 }
2100 }
2101
2102 private int countPicks() throws IOException {
2103 int count = 0;
2104 File todoFile = getTodoFile();
2105 BufferedReader br = new BufferedReader(new InputStreamReader(
2106 new FileInputStream(todoFile), "UTF-8"));
2107 try {
2108 String line = br.readLine();
2109 while (line != null) {
2110 int firstBlank = line.indexOf(' ');
2111 if (firstBlank != -1) {
2112 String actionToken = line.substring(0, firstBlank);
2113 Action action = null;
2114 try {
2115 action = Action.parse(actionToken);
2116 } catch (Exception e) {
2117
2118 }
2119 if (Action.PICK.equals(action))
2120 count++;
2121 }
2122 line = br.readLine();
2123 }
2124 return count;
2125 } finally {
2126 br.close();
2127 }
2128 }
2129
2130 @Test
2131 public void testFastForwardWithMultipleCommitsOnDifferentBranches()
2132 throws Exception {
2133
2134 writeTrashFile(FILE1, FILE1);
2135 git.add().addFilepattern(FILE1).call();
2136 RevCommit first = git.commit().setMessage("Add file1").call();
2137 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2138
2139
2140 createBranch(first, "refs/heads/topic");
2141
2142
2143 writeTrashFile("file2", "file2");
2144 git.add().addFilepattern("file2").call();
2145 RevCommit second = git.commit().setMessage("Add file2").call();
2146 assertTrue(new File(db.getWorkTree(), "file2").exists());
2147
2148
2149 createBranch(second, "refs/heads/side");
2150
2151
2152 writeTrashFile(FILE1, "blah");
2153 git.add().addFilepattern(FILE1).call();
2154 git.commit().setMessage("updated file1 on master")
2155 .call();
2156
2157
2158 checkoutBranch("refs/heads/side");
2159 writeTrashFile("file2", "more change");
2160 git.add().addFilepattern("file2").call();
2161 RevCommit fourth = git.commit().setMessage("update file2 on side")
2162 .call();
2163
2164
2165 checkoutBranch("refs/heads/master");
2166 MergeResult result = git.merge().include(fourth.getId())
2167 .setStrategy(MergeStrategy.RESOLVE).call();
2168 assertEquals(MergeStatus.MERGED, result.getMergeStatus());
2169
2170
2171 checkoutBranch("refs/heads/topic");
2172 RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
2173 assertTrue(new File(db.getWorkTree(), "file2").exists());
2174 checkFile(new File(db.getWorkTree(), "file2"), "more change");
2175 assertEquals(Status.FAST_FORWARD, res.getStatus());
2176 }
2177
2178 @Test
2179 public void testRebaseShouldLeaveWorkspaceUntouchedWithUnstagedChangesConflict()
2180 throws Exception {
2181 writeTrashFile(FILE1, "initial file");
2182 git.add().addFilepattern(FILE1).call();
2183 RevCommit initial = git.commit().setMessage("initial commit").call();
2184 createBranch(initial, "refs/heads/side");
2185
2186 writeTrashFile(FILE1, "updated file");
2187 git.add().addFilepattern(FILE1).call();
2188 git.commit().setMessage("updated FILE1 on master").call();
2189
2190
2191 checkoutBranch("refs/heads/side");
2192 writeTrashFile(FILE1, "side update");
2193 git.add().addFilepattern(FILE1).call();
2194 git.commit().setMessage("updated FILE1 on side").call();
2195
2196 File theFile = writeTrashFile(FILE1, "dirty the file");
2197
2198
2199 RebaseResult rebaseResult = git.rebase()
2200 .setUpstream("refs/heads/master").call();
2201 assertEquals(Status.UNCOMMITTED_CHANGES, rebaseResult.getStatus());
2202 assertEquals(1, rebaseResult.getUncommittedChanges().size());
2203 assertEquals(FILE1, rebaseResult.getUncommittedChanges().get(0));
2204
2205 checkFile(theFile, "dirty the file");
2206
2207 assertEquals(RepositoryState.SAFE, git.getRepository()
2208 .getRepositoryState());
2209 }
2210
2211 @Test
2212 public void testAbortShouldAlsoAbortNonInteractiveRebaseWithRebaseApplyDir()
2213 throws Exception {
2214 writeTrashFile(FILE1, "initial file");
2215 git.add().addFilepattern(FILE1).call();
2216 git.commit().setMessage("initial commit").call();
2217
2218 File applyDir = new File(db.getDirectory(), "rebase-apply");
2219 File headName = new File(applyDir, "head-name");
2220 FileUtils.mkdir(applyDir);
2221 write(headName, "master");
2222 db.writeOrigHead(db.resolve(Constants.HEAD));
2223
2224 git.rebase().setOperation(Operation.ABORT).call();
2225
2226 assertFalse("Abort should clean up .git/rebase-apply",
2227 applyDir.exists());
2228 assertEquals(RepositoryState.SAFE, git.getRepository()
2229 .getRepositoryState());
2230 }
2231
2232 @Test
2233 public void testRebaseShouldBeAbleToHandleEmptyLinesInRebaseTodoFile()
2234 throws IOException {
2235 String emptyLine = "\n";
2236 String todo = "pick 1111111 Commit 1\n" + emptyLine
2237 + "pick 2222222 Commit 2\n" + emptyLine
2238 + "# Comment line at end\n";
2239 write(getTodoFile(), todo);
2240
2241 List<RebaseTodoLine> steps = db.readRebaseTodo(GIT_REBASE_TODO, false);
2242 assertEquals(2, steps.size());
2243 assertEquals("1111111", steps.get(0).getCommit().name());
2244 assertEquals("2222222", steps.get(1).getCommit().name());
2245 }
2246
2247 @Test
2248 public void testRebaseShouldBeAbleToHandleLinesWithoutCommitMessageInRebaseTodoFile()
2249 throws IOException {
2250 String todo = "pick 1111111 \n" + "pick 2222222 Commit 2\n"
2251 + "# Comment line at end\n";
2252 write(getTodoFile(), todo);
2253
2254 List<RebaseTodoLine> steps = db.readRebaseTodo(GIT_REBASE_TODO, false);
2255 assertEquals(2, steps.size());
2256 assertEquals("1111111", steps.get(0).getCommit().name());
2257 assertEquals("2222222", steps.get(1).getCommit().name());
2258 }
2259
2260 @Test
2261 public void testRebaseShouldNotFailIfUserAddCommentLinesInPrepareSteps()
2262 throws Exception {
2263 commitFile(FILE1, FILE1, "master");
2264 RevCommit c2 = commitFile("file2", "file2", "master");
2265
2266
2267 commitFile(FILE1, "blah", "master");
2268 RevCommit c4 = commitFile("file2", "more change", "master");
2269
2270 RebaseResult res = git.rebase().setUpstream("HEAD~2")
2271 .runInteractively(new InteractiveHandler() {
2272 public void prepareSteps(List<RebaseTodoLine> steps) {
2273 steps.add(0, new RebaseTodoLine(
2274 "# Comment that should not be processed"));
2275 }
2276
2277 public String modifyCommitMessage(String commit) {
2278 fail("modifyCommitMessage() was not expected to be called");
2279 return commit;
2280 }
2281 }).call();
2282
2283 assertEquals(RebaseResult.Status.FAST_FORWARD, res.getStatus());
2284
2285 RebaseResult res2 = git.rebase().setUpstream("HEAD~2")
2286 .runInteractively(new InteractiveHandler() {
2287 public void prepareSteps(List<RebaseTodoLine> steps) {
2288 try {
2289
2290 steps.get(0).setAction(Action.COMMENT);
2291 } catch (IllegalTodoFileModification e) {
2292 fail("unexpected exception: " + e);
2293 }
2294 }
2295
2296 public String modifyCommitMessage(String commit) {
2297 fail("modifyCommitMessage() was not expected to be called");
2298 return commit;
2299 }
2300 }).call();
2301
2302 assertEquals(RebaseResult.Status.OK, res2.getStatus());
2303
2304 ObjectId headId = db.resolve(Constants.HEAD);
2305 try (RevWalk rw = new RevWalk(db)) {
2306 RevCommit rc = rw.parseCommit(headId);
2307
2308 ObjectId head1Id = db.resolve(Constants.HEAD + "~1");
2309 RevCommit rc1 = rw.parseCommit(head1Id);
2310
2311 assertEquals(rc.getFullMessage(), c4.getFullMessage());
2312 assertEquals(rc1.getFullMessage(), c2.getFullMessage());
2313 }
2314 }
2315
2316 @Test
2317 public void testParseRewordCommand() throws Exception {
2318 String todo = "pick 1111111 Commit 1\n"
2319 + "reword 2222222 Commit 2\n";
2320 write(getTodoFile(), todo);
2321
2322 List<RebaseTodoLine> steps = db.readRebaseTodo(GIT_REBASE_TODO, false);
2323
2324 assertEquals(2, steps.size());
2325 assertEquals("1111111", steps.get(0).getCommit().name());
2326 assertEquals("2222222", steps.get(1).getCommit().name());
2327 assertEquals(Action.REWORD, steps.get(1).getAction());
2328 }
2329
2330 @Test
2331 public void testEmptyRebaseTodo() throws Exception {
2332 write(getTodoFile(), "");
2333 assertEquals(0, db.readRebaseTodo(GIT_REBASE_TODO, true).size());
2334 assertEquals(0, db.readRebaseTodo(GIT_REBASE_TODO, false).size());
2335 }
2336
2337 @Test
2338 public void testOnlyCommentRebaseTodo() throws Exception {
2339 write(getTodoFile(), "# a b c d e\n# e f");
2340 assertEquals(0, db.readRebaseTodo(GIT_REBASE_TODO, false).size());
2341 List<RebaseTodoLine> lines = db.readRebaseTodo(GIT_REBASE_TODO, true);
2342 assertEquals(2, lines.size());
2343 for (RebaseTodoLine line : lines)
2344 assertEquals(Action.COMMENT, line.getAction());
2345 write(getTodoFile(), "# a b c d e\n# e f\n");
2346 assertEquals(0, db.readRebaseTodo(GIT_REBASE_TODO, false).size());
2347 lines = db.readRebaseTodo(GIT_REBASE_TODO, true);
2348 assertEquals(2, lines.size());
2349 for (RebaseTodoLine line : lines)
2350 assertEquals(Action.COMMENT, line.getAction());
2351 write(getTodoFile(), " \r\n# a b c d e\r\n# e f\r\n#");
2352 assertEquals(0, db.readRebaseTodo(GIT_REBASE_TODO, false).size());
2353 lines = db.readRebaseTodo(GIT_REBASE_TODO, true);
2354 assertEquals(4, lines.size());
2355 for (RebaseTodoLine line : lines)
2356 assertEquals(Action.COMMENT, line.getAction());
2357 }
2358
2359 @Test
2360 public void testLeadingSpacesRebaseTodo() throws Exception {
2361 String todo = " \t\t pick 1111111 Commit 1\n"
2362 + "\t\n"
2363 + "\treword 2222222 Commit 2\n";
2364 write(getTodoFile(), todo);
2365
2366 List<RebaseTodoLine> steps = db.readRebaseTodo(GIT_REBASE_TODO, false);
2367
2368 assertEquals(2, steps.size());
2369 assertEquals("1111111", steps.get(0).getCommit().name());
2370 assertEquals("2222222", steps.get(1).getCommit().name());
2371 assertEquals(Action.REWORD, steps.get(1).getAction());
2372 }
2373
2374 @Test
2375 public void testRebaseShouldTryToParseValidLineMarkedAsComment()
2376 throws IOException {
2377 String todo = "# pick 1111111 Valid line commented out with space\n"
2378 + "#edit 2222222 Valid line commented out without space\n"
2379 + "# pick invalidLine Comment line at end\n";
2380 write(getTodoFile(), todo);
2381
2382 List<RebaseTodoLine> steps = db.readRebaseTodo(GIT_REBASE_TODO, true);
2383 assertEquals(3, steps.size());
2384
2385 RebaseTodoLine firstLine = steps.get(0);
2386
2387 assertEquals("1111111", firstLine.getCommit().name());
2388 assertEquals("Valid line commented out with space",
2389 firstLine.getShortMessage());
2390 assertEquals("comment", firstLine.getAction().toToken());
2391
2392 try {
2393 firstLine.setAction(Action.PICK);
2394 assertEquals("1111111", firstLine.getCommit().name());
2395 assertEquals("pick", firstLine.getAction().toToken());
2396 } catch (Exception e) {
2397 fail("Valid parsable RebaseTodoLine that has been commented out should allow to change the action, but failed");
2398 }
2399
2400 assertEquals("2222222", steps.get(1).getCommit().name());
2401 assertEquals("comment", steps.get(1).getAction().toToken());
2402
2403 assertEquals(null, steps.get(2).getCommit());
2404 assertEquals(null, steps.get(2).getShortMessage());
2405 assertEquals("comment", steps.get(2).getAction().toToken());
2406 assertEquals("# pick invalidLine Comment line at end", steps.get(2)
2407 .getComment());
2408 try {
2409 steps.get(2).setAction(Action.PICK);
2410 fail("A comment RebaseTodoLine that doesn't contain a valid parsable line should fail, but doesn't");
2411 } catch (Exception e) {
2412
2413 }
2414
2415 }
2416
2417 @SuppressWarnings("unused")
2418 @Test
2419 public void testRebaseTodoLineSetComment() throws Exception {
2420 try {
2421 new RebaseTodoLine("This is a invalid comment");
2422 fail("Constructing a comment line with invalid comment string should fail, but doesn't");
2423 } catch (IllegalArgumentException e) {
2424
2425 }
2426 RebaseTodoLine validCommentLine = new RebaseTodoLine(
2427 "# This is a comment");
2428 assertEquals(Action.COMMENT, validCommentLine.getAction());
2429 assertEquals("# This is a comment", validCommentLine.getComment());
2430
2431 RebaseTodoLine actionLineToBeChanged = new RebaseTodoLine(Action.EDIT,
2432 AbbreviatedObjectId.fromString("1111111"), "short Message");
2433 assertEquals(null, actionLineToBeChanged.getComment());
2434
2435 try {
2436 actionLineToBeChanged.setComment("invalid comment");
2437 fail("Setting a invalid comment string should fail but doesn't");
2438 } catch (IllegalArgumentException e) {
2439 assertEquals(null, actionLineToBeChanged.getComment());
2440 }
2441
2442 actionLineToBeChanged.setComment("# valid comment");
2443 assertEquals("# valid comment", actionLineToBeChanged.getComment());
2444 try {
2445 actionLineToBeChanged.setComment("invalid comment");
2446 fail("Setting a invalid comment string should fail but doesn't");
2447 } catch (IllegalArgumentException e) {
2448
2449
2450
2451 assertEquals("# valid comment", actionLineToBeChanged.getComment());
2452 }
2453 try {
2454 actionLineToBeChanged.setComment("# line1 \n line2");
2455 actionLineToBeChanged.setComment("line1 \n line2");
2456 actionLineToBeChanged.setComment("\n");
2457 actionLineToBeChanged.setComment("# line1 \r line2");
2458 actionLineToBeChanged.setComment("line1 \r line2");
2459 actionLineToBeChanged.setComment("\r");
2460 actionLineToBeChanged.setComment("# line1 \n\r line2");
2461 actionLineToBeChanged.setComment("line1 \n\r line2");
2462 actionLineToBeChanged.setComment("\n\r");
2463 fail("Setting a multiline comment string should fail but doesn't");
2464 } catch (IllegalArgumentException e) {
2465
2466 }
2467
2468 actionLineToBeChanged.setComment("# valid comment");
2469 assertEquals("# valid comment", actionLineToBeChanged.getComment());
2470
2471 actionLineToBeChanged.setComment("# \t \t valid comment");
2472 assertEquals("# \t \t valid comment",
2473 actionLineToBeChanged.getComment());
2474
2475 actionLineToBeChanged.setComment("# ");
2476 assertEquals("# ", actionLineToBeChanged.getComment());
2477
2478 actionLineToBeChanged.setComment("");
2479 assertEquals("", actionLineToBeChanged.getComment());
2480
2481 actionLineToBeChanged.setComment(" ");
2482 assertEquals(" ", actionLineToBeChanged.getComment());
2483
2484 actionLineToBeChanged.setComment("\t\t");
2485 assertEquals("\t\t", actionLineToBeChanged.getComment());
2486
2487 actionLineToBeChanged.setComment(null);
2488 assertEquals(null, actionLineToBeChanged.getComment());
2489 }
2490
2491 @Test
2492 public void testRebaseInteractiveReword() throws Exception {
2493
2494 writeTrashFile(FILE1, FILE1);
2495 git.add().addFilepattern(FILE1).call();
2496 git.commit().setMessage("Add file1").call();
2497 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2498
2499
2500 writeTrashFile("file2", "file2");
2501 git.add().addFilepattern("file2").call();
2502 git.commit().setMessage("Add file2").call();
2503 assertTrue(new File(db.getWorkTree(), "file2").exists());
2504
2505
2506 writeTrashFile(FILE1, "blah");
2507 git.add().addFilepattern(FILE1).call();
2508 git.commit().setMessage("updated file1 on master").call();
2509
2510 writeTrashFile("file2", "more change");
2511 git.add().addFilepattern("file2").call();
2512 git.commit().setMessage("update file2 on side").call();
2513
2514 RebaseResult res = git.rebase().setUpstream("HEAD~2")
2515 .runInteractively(new InteractiveHandler() {
2516
2517 public void prepareSteps(List<RebaseTodoLine> steps) {
2518 try {
2519 steps.get(0).setAction(Action.REWORD);
2520 } catch (IllegalTodoFileModification e) {
2521 fail("unexpected exception: " + e);
2522 }
2523 }
2524
2525 public String modifyCommitMessage(String commit) {
2526 return "rewritten commit message";
2527 }
2528 }).call();
2529 assertTrue(new File(db.getWorkTree(), "file2").exists());
2530 checkFile(new File(db.getWorkTree(), "file2"), "more change");
2531 assertEquals(Status.OK, res.getStatus());
2532 Iterator<RevCommit> logIterator = git.log().all().call().iterator();
2533 logIterator.next();
2534 String actualCommitMag = logIterator.next().getShortMessage();
2535 assertEquals("rewritten commit message", actualCommitMag);
2536 }
2537
2538 @Test
2539 public void testRebaseInteractiveEdit() throws Exception {
2540
2541 writeTrashFile(FILE1, FILE1);
2542 git.add().addFilepattern(FILE1).call();
2543 git.commit().setMessage("Add file1").call();
2544 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2545
2546
2547 writeTrashFile("file2", "file2");
2548 git.add().addFilepattern("file2").call();
2549 git.commit().setMessage("Add file2").call();
2550 assertTrue(new File(db.getWorkTree(), "file2").exists());
2551
2552
2553 writeTrashFile(FILE1, "blah");
2554 git.add().addFilepattern(FILE1).call();
2555 git.commit().setMessage("updated file1 on master").call();
2556
2557 writeTrashFile("file2", "more change");
2558 git.add().addFilepattern("file2").call();
2559 git.commit().setMessage("update file2 on side").call();
2560
2561 RebaseResult res = git.rebase().setUpstream("HEAD~2")
2562 .runInteractively(new InteractiveHandler() {
2563 public void prepareSteps(List<RebaseTodoLine> steps) {
2564 try {
2565 steps.get(0).setAction(Action.EDIT);
2566 } catch (IllegalTodoFileModification e) {
2567 fail("unexpected exception: " + e);
2568 }
2569 }
2570
2571 public String modifyCommitMessage(String commit) {
2572 return "";
2573 }
2574 }).call();
2575 assertEquals(Status.EDIT, res.getStatus());
2576 RevCommit toBeEditted = git.log().call().iterator().next();
2577 assertEquals("updated file1 on master", toBeEditted.getFullMessage());
2578
2579
2580 writeTrashFile("file1", "edited");
2581 git.commit().setAll(true).setAmend(true)
2582 .setMessage("edited commit message").call();
2583
2584 res = git.rebase().setOperation(Operation.CONTINUE).call();
2585
2586 checkFile(new File(db.getWorkTree(), "file1"), "edited");
2587 assertEquals(Status.OK, res.getStatus());
2588 Iterator<RevCommit> logIterator = git.log().all().call().iterator();
2589 logIterator.next();
2590 String actualCommitMag = logIterator.next().getShortMessage();
2591 assertEquals("edited commit message", actualCommitMag);
2592 }
2593
2594 @Test
2595 public void testParseSquashFixupSequenceCount() {
2596 int count = RebaseCommand
2597 .parseSquashFixupSequenceCount("# This is a combination of 3 commits.\n# newline");
2598 assertEquals(3, count);
2599 }
2600
2601 @Test
2602 public void testRebaseInteractiveSingleSquashAndModifyMessage() throws Exception {
2603
2604 writeTrashFile(FILE1, FILE1);
2605 git.add().addFilepattern(FILE1).call();
2606 git.commit().setMessage("Add file1\nnew line").call();
2607 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2608
2609
2610 writeTrashFile("file2", "file2");
2611 git.add().addFilepattern("file2").call();
2612 git.commit().setMessage("Add file2\nnew line").call();
2613 assertTrue(new File(db.getWorkTree(), "file2").exists());
2614
2615
2616 writeTrashFile(FILE1, "blah");
2617 git.add().addFilepattern(FILE1).call();
2618 git.commit().setMessage("updated file1 on master\nnew line").call();
2619
2620 writeTrashFile("file2", "more change");
2621 git.add().addFilepattern("file2").call();
2622 git.commit().setMessage("update file2 on master\nnew line").call();
2623
2624 git.rebase().setUpstream("HEAD~3")
2625 .runInteractively(new InteractiveHandler() {
2626
2627 public void prepareSteps(List<RebaseTodoLine> steps) {
2628 try {
2629 steps.get(1).setAction(Action.SQUASH);
2630 } catch (IllegalTodoFileModification e) {
2631 fail("unexpected exception: " + e);
2632 }
2633 }
2634
2635 public String modifyCommitMessage(String commit) {
2636 final File messageSquashFile = new File(db
2637 .getDirectory(), "rebase-merge/message-squash");
2638 final File messageFixupFile = new File(db
2639 .getDirectory(), "rebase-merge/message-fixup");
2640
2641 assertFalse(messageFixupFile.exists());
2642 assertTrue(messageSquashFile.exists());
2643 assertEquals(
2644 "# This is a combination of 2 commits.\n# The first commit's message is:\nAdd file2\nnew line\n# This is the 2nd commit message:\nupdated file1 on master\nnew line",
2645 commit);
2646
2647 try {
2648 byte[] messageSquashBytes = IO
2649 .readFully(messageSquashFile);
2650 int end = RawParseUtils.prevLF(messageSquashBytes,
2651 messageSquashBytes.length);
2652 String messageSquashContent = RawParseUtils.decode(
2653 messageSquashBytes, 0, end + 1);
2654 assertEquals(messageSquashContent, commit);
2655 } catch (Throwable t) {
2656 fail(t.getMessage());
2657 }
2658
2659 return "changed";
2660 }
2661 }).call();
2662
2663 try (RevWalk walk = new RevWalk(db)) {
2664 ObjectId headId = db.resolve(Constants.HEAD);
2665 RevCommit headCommit = walk.parseCommit(headId);
2666 assertEquals(headCommit.getFullMessage(),
2667 "update file2 on master\nnew line");
2668
2669 ObjectId head2Id = db.resolve(Constants.HEAD + "^1");
2670 RevCommit head1Commit = walk.parseCommit(head2Id);
2671 assertEquals("changed", head1Commit.getFullMessage());
2672 }
2673 }
2674
2675 @Test
2676 public void testRebaseInteractiveMultipleSquash() throws Exception {
2677
2678 writeTrashFile("file0", "file0");
2679 git.add().addFilepattern("file0").call();
2680 git.commit().setMessage("Add file0\nnew line").call();
2681 assertTrue(new File(db.getWorkTree(), "file0").exists());
2682
2683
2684 writeTrashFile(FILE1, FILE1);
2685 git.add().addFilepattern(FILE1).call();
2686 git.commit().setMessage("Add file1\nnew line").call();
2687 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2688
2689
2690 writeTrashFile("file2", "file2");
2691 git.add().addFilepattern("file2").call();
2692 git.commit().setMessage("Add file2\nnew line").call();
2693 assertTrue(new File(db.getWorkTree(), "file2").exists());
2694
2695
2696 writeTrashFile(FILE1, "blah");
2697 git.add().addFilepattern(FILE1).call();
2698 git.commit().setMessage("updated file1 on master\nnew line").call();
2699
2700 writeTrashFile("file2", "more change");
2701 git.add().addFilepattern("file2").call();
2702 git.commit().setMessage("update file2 on master\nnew line").call();
2703
2704 git.rebase().setUpstream("HEAD~4")
2705 .runInteractively(new InteractiveHandler() {
2706
2707 public void prepareSteps(List<RebaseTodoLine> steps) {
2708 try {
2709 steps.get(1).setAction(Action.SQUASH);
2710 steps.get(2).setAction(Action.SQUASH);
2711 } catch (IllegalTodoFileModification e) {
2712 fail("unexpected exception: " + e);
2713 }
2714 }
2715
2716 public String modifyCommitMessage(String commit) {
2717 final File messageSquashFile = new File(db.getDirectory(),
2718 "rebase-merge/message-squash");
2719 final File messageFixupFile = new File(db.getDirectory(),
2720 "rebase-merge/message-fixup");
2721 assertFalse(messageFixupFile.exists());
2722 assertTrue(messageSquashFile.exists());
2723 assertEquals(
2724 "# This is a combination of 3 commits.\n# The first commit's message is:\nAdd file1\nnew line\n# This is the 2nd commit message:\nAdd file2\nnew line\n# This is the 3rd commit message:\nupdated file1 on master\nnew line",
2725 commit);
2726
2727 try {
2728 byte[] messageSquashBytes = IO
2729 .readFully(messageSquashFile);
2730 int end = RawParseUtils.prevLF(messageSquashBytes,
2731 messageSquashBytes.length);
2732 String messageSquashContend = RawParseUtils.decode(
2733 messageSquashBytes, 0, end + 1);
2734 assertEquals(messageSquashContend, commit);
2735 } catch (Throwable t) {
2736 fail(t.getMessage());
2737 }
2738
2739 return "# This is a combination of 3 commits.\n# The first commit's message is:\nAdd file1\nnew line\n# This is the 2nd commit message:\nAdd file2\nnew line\n# This is the 3rd commit message:\nupdated file1 on master\nnew line";
2740 }
2741 }).call();
2742
2743 try (RevWalk walk = new RevWalk(db)) {
2744 ObjectId headId = db.resolve(Constants.HEAD);
2745 RevCommit headCommit = walk.parseCommit(headId);
2746 assertEquals(headCommit.getFullMessage(),
2747 "update file2 on master\nnew line");
2748
2749 ObjectId head2Id = db.resolve(Constants.HEAD + "^1");
2750 RevCommit head1Commit = walk.parseCommit(head2Id);
2751 assertEquals(
2752 "Add file1\nnew line\nAdd file2\nnew line\nupdated file1 on master\nnew line",
2753 head1Commit.getFullMessage());
2754 }
2755 }
2756
2757 @Test
2758 public void testRebaseInteractiveMixedSquashAndFixup() throws Exception {
2759
2760 writeTrashFile("file0", "file0");
2761 git.add().addFilepattern("file0").call();
2762 git.commit().setMessage("Add file0\nnew line").call();
2763 assertTrue(new File(db.getWorkTree(), "file0").exists());
2764
2765
2766 writeTrashFile(FILE1, FILE1);
2767 git.add().addFilepattern(FILE1).call();
2768 git.commit().setMessage("Add file1\nnew line").call();
2769 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2770
2771
2772 writeTrashFile("file2", "file2");
2773 git.add().addFilepattern("file2").call();
2774 git.commit().setMessage("Add file2\nnew line").call();
2775 assertTrue(new File(db.getWorkTree(), "file2").exists());
2776
2777
2778 writeTrashFile(FILE1, "blah");
2779 git.add().addFilepattern(FILE1).call();
2780 git.commit().setMessage("updated file1 on master\nnew line").call();
2781
2782 writeTrashFile("file2", "more change");
2783 git.add().addFilepattern("file2").call();
2784 git.commit().setMessage("update file2 on master\nnew line").call();
2785
2786 git.rebase().setUpstream("HEAD~4")
2787 .runInteractively(new InteractiveHandler() {
2788
2789 public void prepareSteps(List<RebaseTodoLine> steps) {
2790 try {
2791 steps.get(1).setAction(Action.FIXUP);
2792 steps.get(2).setAction(Action.SQUASH);
2793 } catch (IllegalTodoFileModification e) {
2794 fail("unexpected exception: " + e);
2795 }
2796 }
2797
2798 public String modifyCommitMessage(String commit) {
2799 final File messageSquashFile = new File(db
2800 .getDirectory(), "rebase-merge/message-squash");
2801 final File messageFixupFile = new File(db
2802 .getDirectory(), "rebase-merge/message-fixup");
2803
2804 assertFalse(messageFixupFile.exists());
2805 assertTrue(messageSquashFile.exists());
2806 assertEquals(
2807 "# This is a combination of 3 commits.\n# The first commit's message is:\nAdd file1\nnew line\n# The 2nd commit message will be skipped:\n# Add file2\n# new line\n# This is the 3rd commit message:\nupdated file1 on master\nnew line",
2808 commit);
2809
2810 try {
2811 byte[] messageSquashBytes = IO
2812 .readFully(messageSquashFile);
2813 int end = RawParseUtils.prevLF(messageSquashBytes,
2814 messageSquashBytes.length);
2815 String messageSquashContend = RawParseUtils.decode(
2816 messageSquashBytes, 0, end + 1);
2817 assertEquals(messageSquashContend, commit);
2818 } catch (Throwable t) {
2819 fail(t.getMessage());
2820 }
2821
2822 return "changed";
2823 }
2824 }).call();
2825
2826 try (RevWalk walk = new RevWalk(db)) {
2827 ObjectId headId = db.resolve(Constants.HEAD);
2828 RevCommit headCommit = walk.parseCommit(headId);
2829 assertEquals(headCommit.getFullMessage(),
2830 "update file2 on master\nnew line");
2831
2832 ObjectId head2Id = db.resolve(Constants.HEAD + "^1");
2833 RevCommit head1Commit = walk.parseCommit(head2Id);
2834 assertEquals("changed", head1Commit.getFullMessage());
2835 }
2836 }
2837
2838 @Test
2839 public void testRebaseInteractiveSingleFixup() throws Exception {
2840
2841 writeTrashFile(FILE1, FILE1);
2842 git.add().addFilepattern(FILE1).call();
2843 git.commit().setMessage("Add file1\nnew line").call();
2844 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2845
2846
2847 writeTrashFile("file2", "file2");
2848 git.add().addFilepattern("file2").call();
2849 git.commit().setMessage("Add file2\nnew line").call();
2850 assertTrue(new File(db.getWorkTree(), "file2").exists());
2851
2852
2853 writeTrashFile(FILE1, "blah");
2854 git.add().addFilepattern(FILE1).call();
2855 git.commit().setMessage("updated file1 on master\nnew line").call();
2856
2857 writeTrashFile("file2", "more change");
2858 git.add().addFilepattern("file2").call();
2859 git.commit().setMessage("update file2 on master\nnew line").call();
2860
2861 git.rebase().setUpstream("HEAD~3")
2862 .runInteractively(new InteractiveHandler() {
2863
2864 public void prepareSteps(List<RebaseTodoLine> steps) {
2865 try {
2866 steps.get(1).setAction(Action.FIXUP);
2867 } catch (IllegalTodoFileModification e) {
2868 fail("unexpected exception: " + e);
2869 }
2870 }
2871
2872 public String modifyCommitMessage(String commit) {
2873 fail("No callback to modify commit message expected for single fixup");
2874 return commit;
2875 }
2876 }).call();
2877
2878 try (RevWalk walk = new RevWalk(db)) {
2879 ObjectId headId = db.resolve(Constants.HEAD);
2880 RevCommit headCommit = walk.parseCommit(headId);
2881 assertEquals("update file2 on master\nnew line",
2882 headCommit.getFullMessage());
2883
2884 ObjectId head1Id = db.resolve(Constants.HEAD + "^1");
2885 RevCommit head1Commit = walk.parseCommit(head1Id);
2886 assertEquals("Add file2\nnew line",
2887 head1Commit.getFullMessage());
2888 }
2889 }
2890
2891 @Test
2892 public void testRebaseInteractiveFixupWithBlankLines() throws Exception {
2893
2894 writeTrashFile(FILE1, FILE1);
2895 git.add().addFilepattern(FILE1).call();
2896 git.commit().setMessage("Add file1\nnew line").call();
2897 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2898
2899
2900 writeTrashFile("file2", "file2");
2901 git.add().addFilepattern("file2").call();
2902 git.commit().setMessage("Add file2").call();
2903 assertTrue(new File(db.getWorkTree(), "file2").exists());
2904
2905
2906 writeTrashFile(FILE1, "blah");
2907 git.add().addFilepattern(FILE1).call();
2908 git.commit().setMessage("updated file1 on master\n\nsome text").call();
2909
2910 git.rebase().setUpstream("HEAD~2")
2911 .runInteractively(new InteractiveHandler() {
2912
2913 public void prepareSteps(List<RebaseTodoLine> steps) {
2914 try {
2915 steps.get(1).setAction(Action.FIXUP);
2916 } catch (IllegalTodoFileModification e) {
2917 fail("unexpected exception: " + e);
2918 }
2919 }
2920
2921 public String modifyCommitMessage(String commit) {
2922 fail("No callback to modify commit message expected for single fixup");
2923 return commit;
2924 }
2925 }).call();
2926
2927 try (RevWalk walk = new RevWalk(db)) {
2928 ObjectId headId = db.resolve(Constants.HEAD);
2929 RevCommit headCommit = walk.parseCommit(headId);
2930 assertEquals("Add file2",
2931 headCommit.getFullMessage());
2932 }
2933 }
2934
2935 @Test(expected = InvalidRebaseStepException.class)
2936 public void testRebaseInteractiveFixupFirstCommitShouldFail()
2937 throws Exception {
2938
2939 writeTrashFile(FILE1, FILE1);
2940 git.add().addFilepattern(FILE1).call();
2941 git.commit().setMessage("Add file1\nnew line").call();
2942 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2943
2944
2945 writeTrashFile("file2", "file2");
2946 git.add().addFilepattern("file2").call();
2947 git.commit().setMessage("Add file2\nnew line").call();
2948 assertTrue(new File(db.getWorkTree(), "file2").exists());
2949
2950 git.rebase().setUpstream("HEAD~1")
2951 .runInteractively(new InteractiveHandler() {
2952
2953 public void prepareSteps(List<RebaseTodoLine> steps) {
2954 try {
2955 steps.get(0).setAction(Action.FIXUP);
2956 } catch (IllegalTodoFileModification e) {
2957 fail("unexpected exception: " + e);
2958 }
2959 }
2960
2961 public String modifyCommitMessage(String commit) {
2962 return commit;
2963 }
2964 }).call();
2965 }
2966
2967 @Test(expected = InvalidRebaseStepException.class)
2968 public void testRebaseInteractiveSquashFirstCommitShouldFail()
2969 throws Exception {
2970
2971 writeTrashFile(FILE1, FILE1);
2972 git.add().addFilepattern(FILE1).call();
2973 git.commit().setMessage("Add file1\nnew line").call();
2974 assertTrue(new File(db.getWorkTree(), FILE1).exists());
2975
2976
2977 writeTrashFile("file2", "file2");
2978 git.add().addFilepattern("file2").call();
2979 git.commit().setMessage("Add file2\nnew line").call();
2980 assertTrue(new File(db.getWorkTree(), "file2").exists());
2981
2982 git.rebase().setUpstream("HEAD~1")
2983 .runInteractively(new InteractiveHandler() {
2984
2985 public void prepareSteps(List<RebaseTodoLine> steps) {
2986 try {
2987 steps.get(0).setAction(Action.SQUASH);
2988 } catch (IllegalTodoFileModification e) {
2989 fail("unexpected exception: " + e);
2990 }
2991 }
2992
2993 public String modifyCommitMessage(String commit) {
2994 return commit;
2995 }
2996 }).call();
2997 }
2998
2999 @Test
3000 public void testRebaseEndsIfLastStepIsEdit() throws Exception {
3001
3002 writeTrashFile(FILE1, FILE1);
3003 git.add().addFilepattern(FILE1).call();
3004 git.commit().setMessage("Add file1\nnew line").call();
3005 assertTrue(new File(db.getWorkTree(), FILE1).exists());
3006
3007
3008 writeTrashFile("file2", "file2");
3009 git.add().addFilepattern("file2").call();
3010 git.commit().setMessage("Add file2\nnew line").call();
3011 assertTrue(new File(db.getWorkTree(), "file2").exists());
3012
3013 git.rebase().setUpstream("HEAD~1")
3014 .runInteractively(new InteractiveHandler() {
3015
3016 public void prepareSteps(List<RebaseTodoLine> steps) {
3017 try {
3018 steps.get(0).setAction(Action.EDIT);
3019 } catch (IllegalTodoFileModification e) {
3020 fail("unexpected exception: " + e);
3021 }
3022 }
3023
3024 public String modifyCommitMessage(String commit) {
3025 return commit;
3026 }
3027 }).call();
3028 git.commit().setAmend(true)
3029 .setMessage("Add file2\nnew line\nanother line").call();
3030 RebaseResult result = git.rebase().setOperation(Operation.CONTINUE)
3031 .call();
3032 assertEquals(Status.OK, result.getStatus());
3033
3034 }
3035
3036 @Test
3037 public void testRebaseShouldStopForEditInCaseOfConflict()
3038 throws Exception {
3039
3040 writeTrashFile(FILE1, FILE1);
3041 git.add().addFilepattern(FILE1).call();
3042 git.commit().setMessage("Add file1\nnew line").call();
3043 assertTrue(new File(db.getWorkTree(), FILE1).exists());
3044
3045
3046 writeTrashFile(FILE1, FILE1 + "a");
3047 git.add().addFilepattern(FILE1).call();
3048 git.commit().setMessage("Change file1").call();
3049
3050
3051 writeTrashFile(FILE1, FILE1 + "b");
3052 git.add().addFilepattern(FILE1).call();
3053 git.commit().setMessage("Change file1").call();
3054
3055 RebaseResult result = git.rebase().setUpstream("HEAD~2")
3056 .runInteractively(new InteractiveHandler() {
3057
3058 public void prepareSteps(List<RebaseTodoLine> steps) {
3059 steps.remove(0);
3060 try {
3061 steps.get(0).setAction(Action.EDIT);
3062 } catch (IllegalTodoFileModification e) {
3063 fail("unexpected exception: " + e);
3064 }
3065 }
3066
3067 public String modifyCommitMessage(String commit) {
3068 return commit;
3069 }
3070 }).call();
3071 assertEquals(Status.STOPPED, result.getStatus());
3072 git.add().addFilepattern(FILE1).call();
3073 result = git.rebase().setOperation(Operation.CONTINUE).call();
3074 assertEquals(Status.EDIT, result.getStatus());
3075
3076 }
3077
3078 @Test
3079 public void testRebaseShouldStopForRewordInCaseOfConflict()
3080 throws Exception {
3081
3082 writeTrashFile(FILE1, FILE1);
3083 git.add().addFilepattern(FILE1).call();
3084 git.commit().setMessage("Add file1\nnew line").call();
3085 assertTrue(new File(db.getWorkTree(), FILE1).exists());
3086
3087
3088 writeTrashFile(FILE1, FILE1 + "a");
3089 git.add().addFilepattern(FILE1).call();
3090 git.commit().setMessage("Change file1").call();
3091
3092
3093 writeTrashFile(FILE1, FILE1 + "b");
3094 git.add().addFilepattern(FILE1).call();
3095 git.commit().setMessage("Change file1").call();
3096
3097 RebaseResult result = git.rebase().setUpstream("HEAD~2")
3098 .runInteractively(new InteractiveHandler() {
3099
3100 public void prepareSteps(List<RebaseTodoLine> steps) {
3101 steps.remove(0);
3102 try {
3103 steps.get(0).setAction(Action.REWORD);
3104 } catch (IllegalTodoFileModification e) {
3105 fail("unexpected exception: " + e);
3106 }
3107 }
3108
3109 public String modifyCommitMessage(String commit) {
3110 return "rewritten commit message";
3111 }
3112 }).call();
3113 assertEquals(Status.STOPPED, result.getStatus());
3114 git.add().addFilepattern(FILE1).call();
3115 result = git.rebase().runInteractively(new InteractiveHandler() {
3116
3117 public void prepareSteps(List<RebaseTodoLine> steps) {
3118 steps.remove(0);
3119 try {
3120 steps.get(0).setAction(Action.REWORD);
3121 } catch (IllegalTodoFileModification e) {
3122 fail("unexpected exception: " + e);
3123 }
3124 }
3125
3126 public String modifyCommitMessage(String commit) {
3127 return "rewritten commit message";
3128 }
3129 }).setOperation(Operation.CONTINUE).call();
3130 assertEquals(Status.OK, result.getStatus());
3131 Iterator<RevCommit> logIterator = git.log().all().call().iterator();
3132 String actualCommitMag = logIterator.next().getShortMessage();
3133 assertEquals("rewritten commit message", actualCommitMag);
3134
3135 }
3136
3137 @Test
3138 public void testRebaseShouldSquashInCaseOfConflict() throws Exception {
3139
3140 writeTrashFile(FILE1, FILE1);
3141 git.add().addFilepattern(FILE1).call();
3142 git.commit().setMessage("Add file1\nnew line").call();
3143 assertTrue(new File(db.getWorkTree(), FILE1).exists());
3144
3145
3146 writeTrashFile("file2", "file2");
3147 git.add().addFilepattern("file2").call();
3148 git.commit().setMessage("Change file2").call();
3149
3150
3151 writeTrashFile(FILE1, FILE1 + "a");
3152 git.add().addFilepattern(FILE1).call();
3153 git.commit().setMessage("Change file1").call();
3154
3155
3156 writeTrashFile(FILE1, FILE1 + "b");
3157 git.add().addFilepattern(FILE1).call();
3158 git.commit().setMessage("Change file1").call();
3159
3160 RebaseResult result = git.rebase().setUpstream("HEAD~3")
3161 .runInteractively(new InteractiveHandler() {
3162
3163 public void prepareSteps(List<RebaseTodoLine> steps) {
3164 try {
3165 steps.get(0).setAction(Action.PICK);
3166 steps.remove(1);
3167 steps.get(1).setAction(Action.SQUASH);
3168 } catch (IllegalTodoFileModification e) {
3169 fail("unexpected exception: " + e);
3170 }
3171 }
3172
3173 public String modifyCommitMessage(String commit) {
3174 return "squashed message";
3175 }
3176 }).call();
3177 assertEquals(Status.STOPPED, result.getStatus());
3178 git.add().addFilepattern(FILE1).call();
3179 result = git.rebase().runInteractively(new InteractiveHandler() {
3180
3181 public void prepareSteps(List<RebaseTodoLine> steps) {
3182 try {
3183 steps.get(0).setAction(Action.PICK);
3184 steps.remove(1);
3185 steps.get(1).setAction(Action.SQUASH);
3186 } catch (IllegalTodoFileModification e) {
3187 fail("unexpected exception: " + e);
3188 }
3189 }
3190
3191 public String modifyCommitMessage(String commit) {
3192 return "squashed message";
3193 }
3194 }).setOperation(Operation.CONTINUE).call();
3195 assertEquals(Status.OK, result.getStatus());
3196 Iterator<RevCommit> logIterator = git.log().all().call().iterator();
3197 String actualCommitMag = logIterator.next().getShortMessage();
3198 assertEquals("squashed message", actualCommitMag);
3199 }
3200
3201 @Test
3202 public void testRebaseShouldFixupInCaseOfConflict() throws Exception {
3203
3204 writeTrashFile(FILE1, FILE1);
3205 git.add().addFilepattern(FILE1).call();
3206 git.commit().setMessage("Add file1").call();
3207 assertTrue(new File(db.getWorkTree(), FILE1).exists());
3208
3209
3210 writeTrashFile("file2", "file2");
3211 git.add().addFilepattern("file2").call();
3212 git.commit().setMessage("Change file2").call();
3213
3214
3215 writeTrashFile(FILE1, FILE1 + "a");
3216 git.add().addFilepattern(FILE1).call();
3217 git.commit().setMessage("Change file1").call();
3218
3219
3220 writeTrashFile(FILE1, FILE1 + "b");
3221 writeTrashFile("file3", "file3");
3222 git.add().addFilepattern(FILE1).call();
3223 git.add().addFilepattern("file3").call();
3224 git.commit().setMessage("Change file1, add file3").call();
3225
3226 RebaseResult result = git.rebase().setUpstream("HEAD~3")
3227 .runInteractively(new InteractiveHandler() {
3228
3229 public void prepareSteps(List<RebaseTodoLine> steps) {
3230 try {
3231 steps.get(0).setAction(Action.PICK);
3232 steps.remove(1);
3233 steps.get(1).setAction(Action.FIXUP);
3234 } catch (IllegalTodoFileModification e) {
3235 fail("unexpected exception: " + e);
3236 }
3237 }
3238
3239 public String modifyCommitMessage(String commit) {
3240 return commit;
3241 }
3242 }).call();
3243 assertEquals(Status.STOPPED, result.getStatus());
3244 git.add().addFilepattern(FILE1).call();
3245 result = git.rebase().runInteractively(new InteractiveHandler() {
3246
3247 public void prepareSteps(List<RebaseTodoLine> steps) {
3248 try {
3249 steps.get(0).setAction(Action.PICK);
3250 steps.remove(1);
3251 steps.get(1).setAction(Action.FIXUP);
3252 } catch (IllegalTodoFileModification e) {
3253 fail("unexpected exception: " + e);
3254 }
3255 }
3256
3257 public String modifyCommitMessage(String commit) {
3258 return "commit";
3259 }
3260 }).setOperation(Operation.CONTINUE).call();
3261 assertEquals(Status.OK, result.getStatus());
3262 Iterator<RevCommit> logIterator = git.log().all().call().iterator();
3263 String actualCommitMsg = logIterator.next().getShortMessage();
3264 assertEquals("Change file2", actualCommitMsg);
3265 actualCommitMsg = logIterator.next().getShortMessage();
3266 assertEquals("Add file1", actualCommitMsg);
3267 assertTrue(new File(db.getWorkTree(), "file3").exists());
3268
3269 }
3270
3271 @Test
3272 public void testInteractiveRebaseWithModificationShouldNotDeleteDataOnAbort()
3273 throws Exception {
3274
3275 writeTrashFile("file0", "file0");
3276 writeTrashFile(FILE1, "file1");
3277 git.add().addFilepattern("file0").addFilepattern(FILE1).call();
3278 git.commit().setMessage("commit1").call();
3279
3280
3281 writeTrashFile(FILE1, "modified file1");
3282 git.add().addFilepattern(FILE1).call();
3283 git.commit().setMessage("commit2").call();
3284
3285
3286 writeTrashFile(FILE1, "modified file1 a second time");
3287 git.add().addFilepattern(FILE1).call();
3288 git.commit().setMessage("commit3").call();
3289
3290
3291 writeTrashFile("file0", "modified file0 in index");
3292 git.add().addFilepattern("file0").addFilepattern(FILE1).call();
3293
3294 writeTrashFile("file0", "modified file0");
3295
3296
3297 RebaseResult result = git.rebase().setUpstream("HEAD~2")
3298 .runInteractively(new InteractiveHandler() {
3299
3300 public void prepareSteps(List<RebaseTodoLine> steps) {
3301 try {
3302 steps.get(0).setAction(Action.EDIT);
3303 steps.get(1).setAction(Action.PICK);
3304 } catch (IllegalTodoFileModification e) {
3305 fail("unexpected exception: " + e);
3306 }
3307 }
3308
3309 public String modifyCommitMessage(String commit) {
3310 return commit;
3311 }
3312 }).call();
3313
3314
3315
3316 if (result.getStatus() == Status.EDIT)
3317 git.rebase().setOperation(Operation.ABORT).call();
3318
3319 checkFile(new File(db.getWorkTree(), "file0"), "modified file0");
3320 checkFile(new File(db.getWorkTree(), "file1"),
3321 "modified file1 a second time");
3322 assertEquals("[file0, mode:100644, content:modified file0 in index]"
3323 + "[file1, mode:100644, content:modified file1 a second time]",
3324 indexState(CONTENT));
3325
3326 }
3327
3328 private File getTodoFile() {
3329 File todoFile = new File(db.getDirectory(), GIT_REBASE_TODO);
3330 return todoFile;
3331 }
3332 }