From ac805874f72fe2c6193bc959865fb525e069e45e Mon Sep 17 00:00:00 2001 From: Robin Stocker Date: Sat, 22 Sep 2012 21:27:01 +0200 Subject: [PATCH] Refuse to checkout unmerged paths from index Without this check, the checkout was done but the result was a "both deleted" status when inspecting it with C Git. Found this while working on bug 390147. Change-Id: Ic3693f2c651827239e838bf7f37da842a7ae9707 --- .../jgit/api/PathCheckoutCommandTest.java | 21 +++++++++++++++++++ .../org/eclipse/jgit/api/CheckoutCommand.java | 9 +++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java index 243d791cd..d37f57293 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java @@ -47,11 +47,13 @@ import static org.junit.Assert.assertEquals; import java.io.File; import java.io.IOException; +import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.ObjectReader; +import org.eclipse.jgit.lib.RepositoryState; import org.eclipse.jgit.lib.RepositoryTestCase; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.revwalk.RevCommit; @@ -243,4 +245,23 @@ public class PathCheckoutCommandTest extends RepositoryTestCase { assertEquals("1", read(test)); assertEquals("a", read(test2)); } + + @Test(expected = JGitInternalException.class) + public void testCheckoutOfConflictingFileShouldThrow() + throws Exception { + // Setup + git.checkout().setCreateBranch(true).setName("conflict") + .setStartPoint(initialCommit).call(); + writeTrashFile(FILE1, "Conflicting"); + RevCommit conflict = git.commit().setAll(true) + .setMessage("Conflicting change").call(); + + git.checkout().setName("master").call(); + + git.merge().include(conflict).call(); + assertEquals(RepositoryState.MERGING, db.getRepositoryState()); + + // Now check out the conflicting path + git.checkout().addPath(FILE1).call(); + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java index d8efbe7a6..57f47a496 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java @@ -64,6 +64,7 @@ import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit; import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.errors.AmbiguousObjectException; +import org.eclipse.jgit.errors.UnmergedPathException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; @@ -284,7 +285,8 @@ public class CheckoutCommand extends GitCommand { startWalk.setRecursive(true); if (!checkoutAllPaths) startWalk.setFilter(PathFilterGroup.createFromStrings(paths)); - boolean checkoutIndex = startCommit == null && startPoint == null; + final boolean checkoutIndex = startCommit == null + && startPoint == null; if (!checkoutIndex) startWalk.addTree(revWalk.parseCommit(getStartPoint()) .getTree()); @@ -299,6 +301,11 @@ public class CheckoutCommand extends GitCommand { final FileMode mode = startWalk.getFileMode(0); editor.add(new PathEdit(startWalk.getPathString()) { public void apply(DirCacheEntry ent) { + if (checkoutIndex + && ent.getStage() > DirCacheEntry.STAGE_0) { + UnmergedPathException e = new UnmergedPathException(ent); + throw new JGitInternalException(e.getMessage(), e); + } ent.setObjectId(blobId); ent.setFileMode(mode); File file = new File(workTree, ent.getPathString());