From 83e43f7960de7e62dd1e7b2950ceed24ce85e8ac Mon Sep 17 00:00:00 2001 From: Christian Halstrick Date: Tue, 27 Sep 2016 15:38:53 +0200 Subject: [PATCH] Fix CheckoutCommand to return updated files even on NONDELETED status CheckoutCommand was not returning updated and removed files in case of an overall status of NONDELETED. That's status which occurs especially on the Windows platform when Checkout wanted to delete files but the filesystem doesn't allow this. The situation is more seldom on linux/mac because open filehandles don't stop a deletion attempt and checkout succeeds more often. Change-Id: I4828008e58c09bd8f9edaf0f7eda0a79c629fb57 --- .../eclipse/jgit/api/CheckoutCommandTest.java | 33 +++++++++++++++++++ .../org/eclipse/jgit/api/CheckoutCommand.java | 4 ++- .../org/eclipse/jgit/api/CheckoutResult.java | 26 +++++++++++++-- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java index 998b5fbfc2..3c196724a9 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java @@ -89,6 +89,7 @@ import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.util.FileUtils; +import org.eclipse.jgit.util.SystemReader; import org.junit.Before; import org.junit.Test; @@ -791,6 +792,38 @@ public class CheckoutCommandTest extends RepositoryTestCase { } } + @Test + public void testNonDeletableFilesOnWindows() + throws GitAPIException, IOException { + // Only on windows a FileInputStream blocks us from deleting a file + org.junit.Assume.assumeTrue(SystemReader.getInstance().isWindows()); + writeTrashFile("toBeModified.txt", "a"); + writeTrashFile("toBeDeleted.txt", "a"); + git.add().addFilepattern(".").call(); + RevCommit addFiles = git.commit().setMessage("add more files").call(); + + git.rm().setCached(false).addFilepattern("Test.txt") + .addFilepattern("toBeDeleted.txt").call(); + writeTrashFile("toBeModified.txt", "b"); + writeTrashFile("toBeCreated.txt", "a"); + git.add().addFilepattern(".").call(); + RevCommit crudCommit = git.commit().setMessage("delete, modify, add") + .call(); + git.checkout().setName(addFiles.getName()).call(); + try ( FileInputStream fis=new FileInputStream(new File(db.getWorkTree(), "Test.txt")) ) { + CheckoutCommand coCommand = git.checkout(); + coCommand.setName(crudCommit.getName()).call(); + CheckoutResult result = coCommand.getResult(); + assertEquals(Status.NONDELETED, result.getStatus()); + assertEquals("[Test.txt, toBeDeleted.txt]", + result.getRemovedList().toString()); + assertEquals("[toBeCreated.txt, toBeModified.txt]", + result.getModifiedList().toString()); + assertEquals("[Test.txt]", result.getUndeletedList().toString()); + assertTrue(result.getConflictList().isEmpty()); + } + } + private File writeTempFile(String body) throws IOException { File f = File.createTempFile("AddCommandTest_", ""); JGitTestUtil.write(f, body); 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 65508eff40..20d0704509 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java @@ -318,7 +318,9 @@ public class CheckoutCommand extends GitCommand { if (!dco.getToBeDeleted().isEmpty()) { status = new CheckoutResult(Status.NONDELETED, - dco.getToBeDeleted()); + dco.getToBeDeleted(), + new ArrayList(dco.getUpdated().keySet()), + dco.getRemoved()); } else status = new CheckoutResult(new ArrayList(dco .getUpdated().keySet()), dco.getRemoved()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutResult.java index 6a1bfb8f0e..92a67f46af 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutResult.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutResult.java @@ -113,6 +113,28 @@ public class CheckoutResult { * {@link Status#CONFLICTS} or {@link Status#NONDELETED}. */ CheckoutResult(Status status, List fileList) { + this(status, fileList, null, null); + } + + /** + * Create a new fail result. If status is {@link Status#CONFLICTS}, + * fileList is a list of conflicting files, if status is + * {@link Status#NONDELETED}, fileList is a list of not deleted + * files. All other values ignore fileList. To create a result + * for {@link Status#OK}, see {@link #CheckoutResult(List, List)}. + * + * @param status + * the failure status + * @param fileList + * the list of files to store, status has to be either + * {@link Status#CONFLICTS} or {@link Status#NONDELETED}. + * @param modified + * the modified files + * @param removed + * the removed files. + */ + CheckoutResult(Status status, List fileList, List modified, + List removed) { myStatus = status; if (status == Status.CONFLICTS) this.conflictList = fileList; @@ -123,8 +145,8 @@ public class CheckoutResult { else this.undeletedList = new ArrayList(0); - this.modifiedList = new ArrayList(0); - this.removedList = new ArrayList(0); + this.modifiedList = modified; + this.removedList = removed; } /** -- 2.39.5