]> source.dussan.org Git - jgit.git/commitdiff
Fix CheckoutCommand to return updated files even on NONDELETED status 98/81998/1
authorChristian Halstrick <christian.halstrick@sap.com>
Tue, 27 Sep 2016 13:38:53 +0000 (15:38 +0200)
committerChristian Halstrick <christian.halstrick@sap.com>
Tue, 27 Sep 2016 13:58:24 +0000 (15:58 +0200)
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

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/api/CheckoutResult.java

index 998b5fbfc2c998c6864742cd30d0858e24693e74..3c196724a96e7762b9f83c405b5c5d29a451bbb2 100644 (file)
@@ -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);
index 65508eff4054aced91a2f94ea9d37b37181fadf1..20d0704509f8368358e153173645bd612b4076cf 100644 (file)
@@ -318,7 +318,9 @@ public class CheckoutCommand extends GitCommand<Ref> {
 
                        if (!dco.getToBeDeleted().isEmpty()) {
                                status = new CheckoutResult(Status.NONDELETED,
-                                               dco.getToBeDeleted());
+                                               dco.getToBeDeleted(),
+                                               new ArrayList<String>(dco.getUpdated().keySet()),
+                                               dco.getRemoved());
                        } else
                                status = new CheckoutResult(new ArrayList<String>(dco
                                                .getUpdated().keySet()), dco.getRemoved());
index 6a1bfb8f0ebfd915e1574e3897e65515220078e2..92a67f46af96aff3a44570393bada6f26432d292 100644 (file)
@@ -113,6 +113,28 @@ public class CheckoutResult {
         *            {@link Status#CONFLICTS} or {@link Status#NONDELETED}.
         */
        CheckoutResult(Status status, List<String> fileList) {
+               this(status, fileList, null, null);
+       }
+
+       /**
+        * Create a new fail result. If status is {@link Status#CONFLICTS},
+        * <code>fileList</code> is a list of conflicting files, if status is
+        * {@link Status#NONDELETED}, <code>fileList</code> is a list of not deleted
+        * files. All other values ignore <code>fileList</code>. 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<String> fileList, List<String> modified,
+                       List<String> removed) {
                myStatus = status;
                if (status == Status.CONFLICTS)
                        this.conflictList = fileList;
@@ -123,8 +145,8 @@ public class CheckoutResult {
                else
                        this.undeletedList = new ArrayList<String>(0);
 
-               this.modifiedList = new ArrayList<String>(0);
-               this.removedList = new ArrayList<String>(0);
+               this.modifiedList = modified;
+               this.removedList = removed;
        }
 
        /**