Support cherry-picking a root commit
Handle the case of the commit to be picked not having any parents. Since JGit implements cherry-pick as a 3-way-merge between the commit to be picked and the target commit, using the parent of the picked commit as merge base, this is super simple: just don't set a base tree. The merger will not find any merge base and will supply an empty tree iterator for the base. Bug: 581832 Change-Id: I88985f1b1723db5b35ce58bf228bc48d23d6fca3 Signed-off-by: Thomas Wolf <twolf@apache.org>
This commit is contained in:
parent
3ed4cdda6b
commit
8bc13fb79d
|
@ -101,14 +101,15 @@ private void doTestCherryPick(boolean noCommit) throws IOException,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSequentialCherryPick() throws IOException, JGitInternalException,
|
public void testSequentialCherryPick()
|
||||||
GitAPIException {
|
throws IOException, JGitInternalException, GitAPIException {
|
||||||
try (Git git = new Git(db)) {
|
try (Git git = new Git(db)) {
|
||||||
writeTrashFile("a", "first line\nsec. line\nthird line\n");
|
writeTrashFile("a", "first line\nsec. line\nthird line\n");
|
||||||
git.add().addFilepattern("a").call();
|
git.add().addFilepattern("a").call();
|
||||||
RevCommit firstCommit = git.commit().setMessage("create a").call();
|
RevCommit firstCommit = git.commit().setMessage("create a").call();
|
||||||
|
|
||||||
writeTrashFile("a", "first line\nsec. line\nthird line\nfourth line\n");
|
writeTrashFile("a",
|
||||||
|
"first line\nsec. line\nthird line\nfourth line\n");
|
||||||
git.add().addFilepattern("a").call();
|
git.add().addFilepattern("a").call();
|
||||||
RevCommit enlargingA = git.commit().setMessage("enlarged a").call();
|
RevCommit enlargingA = git.commit().setMessage("enlarged a").call();
|
||||||
|
|
||||||
|
@ -117,15 +118,18 @@ public void testSequentialCherryPick() throws IOException, JGitInternalException
|
||||||
git.add().addFilepattern("a").call();
|
git.add().addFilepattern("a").call();
|
||||||
RevCommit fixingA = git.commit().setMessage("fixed a").call();
|
RevCommit fixingA = git.commit().setMessage("fixed a").call();
|
||||||
|
|
||||||
git.branchCreate().setName("side").setStartPoint(firstCommit).call();
|
git.branchCreate().setName("side").setStartPoint(firstCommit)
|
||||||
|
.call();
|
||||||
checkoutBranch("refs/heads/side");
|
checkoutBranch("refs/heads/side");
|
||||||
|
|
||||||
writeTrashFile("b", "nothing to do with a");
|
writeTrashFile("b", "nothing to do with a");
|
||||||
git.add().addFilepattern("b").call();
|
git.add().addFilepattern("b").call();
|
||||||
git.commit().setMessage("create b").call();
|
git.commit().setMessage("create b").call();
|
||||||
|
|
||||||
CherryPickResult result = git.cherryPick().include(enlargingA).include(fixingA).call();
|
CherryPickResult result = git.cherryPick().include(enlargingA)
|
||||||
assertEquals(CherryPickResult.CherryPickStatus.OK, result.getStatus());
|
.include(fixingA).call();
|
||||||
|
assertEquals(CherryPickResult.CherryPickStatus.OK,
|
||||||
|
result.getStatus());
|
||||||
|
|
||||||
Iterator<RevCommit> history = git.log().call().iterator();
|
Iterator<RevCommit> history = git.log().call().iterator();
|
||||||
assertEquals("fixed a", history.next().getFullMessage());
|
assertEquals("fixed a", history.next().getFullMessage());
|
||||||
|
@ -136,6 +140,34 @@ public void testSequentialCherryPick() throws IOException, JGitInternalException
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRootCherryPick()
|
||||||
|
throws IOException, JGitInternalException, GitAPIException {
|
||||||
|
try (Git git = new Git(db)) {
|
||||||
|
writeTrashFile("a", "a");
|
||||||
|
writeTrashFile("b", "b");
|
||||||
|
git.add().addFilepattern("a").addFilepattern("b").call();
|
||||||
|
RevCommit firstCommit = git.commit().setMessage("Create a and b")
|
||||||
|
.call();
|
||||||
|
|
||||||
|
git.checkout().setOrphan(true).setName("orphan").call();
|
||||||
|
git.rm().addFilepattern("a").addFilepattern("b").call();
|
||||||
|
writeTrashFile("a", "a");
|
||||||
|
git.add().addFilepattern("a").call();
|
||||||
|
git.commit().setMessage("Orphan a").call();
|
||||||
|
|
||||||
|
CherryPickResult result = git.cherryPick().include(firstCommit)
|
||||||
|
.call();
|
||||||
|
assertEquals(CherryPickResult.CherryPickStatus.OK,
|
||||||
|
result.getStatus());
|
||||||
|
|
||||||
|
Iterator<RevCommit> history = git.log().call().iterator();
|
||||||
|
assertEquals("Create a and b", history.next().getFullMessage());
|
||||||
|
assertEquals("Orphan a", history.next().getFullMessage());
|
||||||
|
assertFalse(history.hasNext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCherryPickDirtyIndex() throws Exception {
|
public void testCherryPickDirtyIndex() throws Exception {
|
||||||
try (Git git = new Git(db)) {
|
try (Git git = new Git(db)) {
|
||||||
|
|
|
@ -142,7 +142,9 @@ public CherryPickResult call() throws GitAPIException, NoMessageException,
|
||||||
new String[] { "BASE", ourName, cherryPickName }); //$NON-NLS-1$
|
new String[] { "BASE", ourName, cherryPickName }); //$NON-NLS-1$
|
||||||
resolveMerger
|
resolveMerger
|
||||||
.setWorkingTreeIterator(new FileTreeIterator(repo));
|
.setWorkingTreeIterator(new FileTreeIterator(repo));
|
||||||
|
if (srcParent != null) {
|
||||||
resolveMerger.setBase(srcParent.getTree());
|
resolveMerger.setBase(srcParent.getTree());
|
||||||
|
}
|
||||||
noProblems = merger.merge(newHead, srcCommit);
|
noProblems = merger.merge(newHead, srcCommit);
|
||||||
failingPaths = resolveMerger.getFailingPaths();
|
failingPaths = resolveMerger.getFailingPaths();
|
||||||
unmergedPaths = resolveMerger.getUnmergedPaths();
|
unmergedPaths = resolveMerger.getUnmergedPaths();
|
||||||
|
@ -217,12 +219,16 @@ private RevCommit getParentCommit(RevCommit srcCommit, RevWalk revWalk)
|
||||||
IOException {
|
IOException {
|
||||||
final RevCommit srcParent;
|
final RevCommit srcParent;
|
||||||
if (mainlineParentNumber == null) {
|
if (mainlineParentNumber == null) {
|
||||||
if (srcCommit.getParentCount() != 1)
|
int nOfParents = srcCommit.getParentCount();
|
||||||
|
if (nOfParents == 0) {
|
||||||
|
return null;
|
||||||
|
} else if (nOfParents != 1) {
|
||||||
throw new MultipleParentsNotAllowedException(
|
throw new MultipleParentsNotAllowedException(
|
||||||
MessageFormat.format(
|
MessageFormat.format(
|
||||||
JGitText.get().canOnlyCherryPickCommitsWithOneParent,
|
JGitText.get().canOnlyCherryPickCommitsWithOneParent,
|
||||||
srcCommit.name(),
|
srcCommit.name(),
|
||||||
Integer.valueOf(srcCommit.getParentCount())));
|
Integer.valueOf(srcCommit.getParentCount())));
|
||||||
|
}
|
||||||
srcParent = srcCommit.getParent(0);
|
srcParent = srcCommit.getParent(0);
|
||||||
} else {
|
} else {
|
||||||
if (mainlineParentNumber.intValue() > srcCommit.getParentCount()) {
|
if (mainlineParentNumber.intValue() > srcCommit.getParentCount()) {
|
||||||
|
|
Loading…
Reference in New Issue