Browse Source

CheckoutCommand: force flag now allows overwrite

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>
stable-5.2
Ned Twigg 6 years ago committed by David Pursehouse
parent
commit
d056a54384
  1. 4
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java
  2. 2
      org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
  3. 29
      org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java

4
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java

@ -154,7 +154,7 @@ public class CheckoutCommandTest extends RepositoryTestCase {
} }
@Test @Test
public void testCheckoutWithConflict() { public void testCheckoutWithConflict() throws Exception {
CheckoutCommand co = git.checkout(); CheckoutCommand co = git.checkout();
try { try {
writeTrashFile("Test.txt", "Another change"); writeTrashFile("Test.txt", "Another change");
@ -165,6 +165,8 @@ public class CheckoutCommandTest extends RepositoryTestCase {
assertEquals(Status.CONFLICTS, co.getResult().getStatus()); assertEquals(Status.CONFLICTS, co.getResult().getStatus());
assertTrue(co.getResult().getConflictList().contains("Test.txt")); assertTrue(co.getResult().getConflictList().contains("Test.txt"));
} }
git.checkout().setName("master").setForce(true).call();
assertThat(read("Test.txt"), is("Hello world"));
} }
@Test @Test

2
org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java

@ -269,7 +269,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
try { try {
dco = new DirCacheCheckout(repo, headTree, dc, dco = new DirCacheCheckout(repo, headTree, dc,
newCommit.getTree()); newCommit.getTree());
dco.setFailOnConflict(true); dco.setFailOnConflict(!force);
dco.setProgressMonitor(monitor); dco.setProgressMonitor(monitor);
try { try {
dco.checkout(); dco.checkout();

29
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java vendored

@ -522,7 +522,7 @@ public class DirCacheCheckout {
builder.finish(); builder.finish();
// init progress reporting // init progress reporting
int numTotal = removed.size() + updated.size(); int numTotal = removed.size() + updated.size() + conflicts.size();
monitor.beginTask(JGitText.get().checkingOutFiles, numTotal); monitor.beginTask(JGitText.get().checkingOutFiles, numTotal);
performingCheckout = true; performingCheckout = true;
@ -597,6 +597,33 @@ public class DirCacheCheckout {
} }
throw ex; 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(); monitor.endTask();
// commit the index builder - a new index is persisted // commit the index builder - a new index is persisted

Loading…
Cancel
Save