]> source.dussan.org Git - jgit.git/commitdiff
CheckoutCommand: force flag now allows overwrite 23/127823/9
authorNed Twigg <ned.twigg@diffplug.com>
Tue, 21 Aug 2018 21:44:28 +0000 (14:44 -0700)
committerDavid Pursehouse <david.pursehouse@gmail.com>
Sat, 20 Oct 2018 10:53:23 +0000 (06:53 -0400)
Before this commit, a force checkout would fail if there
were any conflicting files. After this commit, a force
checkout will overwrite the conflicting files, as expected.

Making this work required fixing a bug in DirCacheCheckout.
Before this commit, when DirCacheCheckout had
failOnConflict=false, it would delete all conflicting files
from the working copy and just leave them missing. After
this commit, DirCacheCheckout overwrites conflicting files
with the merge tree.

This change in DirCacheCheckout causes "reset --hard" and
"revert --abort" to behave as expected (previously they
would simply delete conflicting files, now they will be
overwritten from the merge tree).

Change-Id: If7e328ee792ef6511ab7d9c26d8d77c39210ec9f
Signed-off-by: Ned Twigg <ned.twigg@diffplug.com>
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java
org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java

index 71df59e1ff998912030d35ddcf1e8d83b045ae87..498005dedab5ad05c403b993fa998a90a07e35ae 100644 (file)
@@ -154,7 +154,7 @@ public class CheckoutCommandTest extends RepositoryTestCase {
        }
 
        @Test
-       public void testCheckoutWithConflict() {
+       public void testCheckoutWithConflict() throws Exception {
                CheckoutCommand co = git.checkout();
                try {
                        writeTrashFile("Test.txt", "Another change");
@@ -165,6 +165,8 @@ public class CheckoutCommandTest extends RepositoryTestCase {
                        assertEquals(Status.CONFLICTS, co.getResult().getStatus());
                        assertTrue(co.getResult().getConflictList().contains("Test.txt"));
                }
+               git.checkout().setName("master").setForce(true).call();
+               assertThat(read("Test.txt"), is("Hello world"));
        }
 
        @Test
index 11edb1089483c10eb72262a3a67a80733e67a3fb..455a2e665f821851ba9e114fdbadd2750a07ab25 100644 (file)
@@ -269,7 +269,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
                        try {
                                dco = new DirCacheCheckout(repo, headTree, dc,
                                                newCommit.getTree());
-                               dco.setFailOnConflict(true);
+                               dco.setFailOnConflict(!force);
                                dco.setProgressMonitor(monitor);
                                try {
                                        dco.checkout();
index ca1e3ab27517e287ffed10c1f35dc81ecdaa57fb..db6073f89a6230845b793d502d25929bbff187dd 100644 (file)
@@ -522,7 +522,7 @@ public class DirCacheCheckout {
                        builder.finish();
 
                        // init progress reporting
-                       int numTotal = removed.size() + updated.size();
+                       int numTotal = removed.size() + updated.size() + conflicts.size();
                        monitor.beginTask(JGitText.get().checkingOutFiles, numTotal);
 
                        performingCheckout = true;
@@ -597,6 +597,33 @@ public class DirCacheCheckout {
                                }
                                throw ex;
                        }
+                       for (String conflict : conflicts) {
+                               // the conflicts are likely to have multiple entries in the
+                               // dircache, we only want to check out the one for the "theirs"
+                               // tree
+                               int entryIdx = dc.findEntry(conflict);
+                               if (entryIdx >= 0) {
+                                       while (entryIdx < dc.getEntryCount()) {
+                                               DirCacheEntry entry = dc.getEntry(entryIdx);
+                                               if (!entry.getPathString().equals(conflict)) {
+                                                       break;
+                                               }
+                                               if (entry.getStage() == DirCacheEntry.STAGE_3) {
+                                                       checkoutEntry(repo, entry, objectReader, false,
+                                                                       null);
+                                                       break;
+                                               }
+                                               ++entryIdx;
+                                       }
+                               }
+
+                               monitor.update(1);
+                               if (monitor.isCancelled()) {
+                                       throw new CanceledException(MessageFormat.format(
+                                                       JGitText.get().operationCanceled,
+                                                       JGitText.get().checkingOutFiles));
+                               }
+                       }
                        monitor.endTask();
 
                        // commit the index builder - a new index is persisted