]> source.dussan.org Git - jgit.git/commitdiff
Reuse ObjectReader for all objects touched during checkout 09/3809/5
authorMatthias Sohn <matthias.sohn@sap.com>
Tue, 2 Aug 2011 15:54:20 +0000 (17:54 +0200)
committerMatthias Sohn <matthias.sohn@sap.com>
Tue, 2 Aug 2011 15:54:20 +0000 (17:54 +0200)
Bug: 349361
Change-Id: I61ffcb7694eb8b99ebaf4d0d0acd63e0ee91bcb3
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

index f3a2e536022f71d52be97a85359222054103c355..8caff062928e812d8cf11b01b46255f4a774ff14 100644 (file)
@@ -66,6 +66,7 @@ import org.eclipse.jgit.errors.CheckoutConflictException;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectReader;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.RefUpdate.Result;
@@ -266,9 +267,14 @@ public class CheckoutCommand extends GitCommand<Ref> {
                        }
 
                        File workTree = repo.getWorkTree();
-                       for (String file : files)
-                               DirCacheCheckout.checkoutEntry(repo, new File(workTree, file),
-                                               dc.getEntry(file));
+                       ObjectReader r = repo.getObjectDatabase().newReader();
+                       try {
+                               for (String file : files)
+                                       DirCacheCheckout.checkoutEntry(repo, new File(workTree,
+                                                       file), dc.getEntry(file), r);
+                       } finally {
+                               r.release();
+                       }
                } finally {
                        dc.unlock();
                        revWalk.release();
index 79f2297b2630db0d7cba823272f2fedaddcbe649..85594832920db389258232fbc97b1a6382358e97 100644 (file)
@@ -60,6 +60,7 @@ import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectReader;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
@@ -386,64 +387,68 @@ public class DirCacheCheckout {
                        MissingObjectException, IncorrectObjectTypeException,
                        CheckoutConflictException, IndexWriteException {
                toBeDeleted.clear();
-               if (headCommitTree != null)
-                       preScanTwoTrees();
-               else
-                       prescanOneTree();
 
-               if (!conflicts.isEmpty()) {
-                       if (failOnConflict) {
-                               dc.unlock();
-                               throw new CheckoutConflictException(conflicts.toArray(new String[conflicts.size()]));
-                       } else
-                               cleanUpConflicts();
-               }
+               ObjectReader objectReader = repo.getObjectDatabase().newReader();
+               try {
+                       if (headCommitTree != null)
+                               preScanTwoTrees();
+                       else
+                               prescanOneTree();
 
-               // update our index
-               builder.finish();
-
-               File file=null;
-               String last = "";
-               // when deleting files process them in the opposite order as they have
-               // been reported. This ensures the files are deleted before we delete
-               // their parent folders
-               for (int i = removed.size() - 1; i >= 0; i--) {
-                       String r = removed.get(i);
-                       file = new File(repo.getWorkTree(), r);
-                       if (!file.delete() && file.exists())
-                                       toBeDeleted.add(r);
-                       else {
-                               if (!isSamePrefix(r, last))
-                                       removeEmptyParents(new File(repo.getWorkTree(), last));
-                               last = r;
+                       if (!conflicts.isEmpty()) {
+                               if (failOnConflict) {
+                                       dc.unlock();
+                                       throw new CheckoutConflictException(conflicts.toArray(new String[conflicts.size()]));
+                               } else
+                                       cleanUpConflicts();
                        }
-               }
-               if (file != null)
-                       removeEmptyParents(file);
 
-               for (String path : updated.keySet()) {
-                       // ... create/overwrite this file ...
-                       file = new File(repo.getWorkTree(), path);
-                       if (!file.getParentFile().mkdirs()) {
-                               // ignore
+                       // update our index
+                       builder.finish();
+
+                       File file = null;
+                       String last = "";
+                       // when deleting files process them in the opposite order as they have
+                       // been reported. This ensures the files are deleted before we delete
+                       // their parent folders
+                       for (int i = removed.size() - 1; i >= 0; i--) {
+                               String r = removed.get(i);
+                               file = new File(repo.getWorkTree(), r);
+                               if (!file.delete() && file.exists())
+                                       toBeDeleted.add(r);
+                               else {
+                                       if (!isSamePrefix(r, last))
+                                               removeEmptyParents(new File(repo.getWorkTree(), last));
+                                       last = r;
+                               }
                        }
+                       if (file != null)
+                               removeEmptyParents(file);
+
+                       for (String path : updated.keySet()) {
+                               // ... create/overwrite this file ...
+                               file = new File(repo.getWorkTree(), path);
+                               if (!file.getParentFile().mkdirs()) {
+                                       // ignore
+                               }
 
-                       DirCacheEntry entry = dc.getEntry(path);
-
-                       // submodules are handled with separate operations
-                       if (FileMode.GITLINK.equals(entry.getRawMode()))
-                               continue;
+                               DirCacheEntry entry = dc.getEntry(path);
 
-                       checkoutEntry(repo, file, entry);
-               }
+                               // submodules are handled with separate operations
+                               if (FileMode.GITLINK.equals(entry.getRawMode()))
+                                       continue;
 
+                               checkoutEntry(repo, file, entry, objectReader);
+                       }
 
-               // commit the index builder - a new index is persisted
-               if (!builder.commit()) {
-                       dc.unlock();
-                       throw new IndexWriteException();
+                       // commit the index builder - a new index is persisted
+                       if (!builder.commit()) {
+                               dc.unlock();
+                               throw new IndexWriteException();
+                       }
+               } finally {
+                       objectReader.release();
                }
-
                return toBeDeleted.size() == 0;
        }
 
@@ -844,26 +849,65 @@ public class DirCacheCheckout {
                return false;
        }
 
+       /**
+        * Updates the file in the working tree with content and mode from an entry
+        * in the index. The new content is first written to a new temporary file in
+        * the same directory as the real file. Then that new file is renamed to the
+        * final filename. Use this method only for checkout of a single entry.
+        * Otherwise use
+        * {@code checkoutEntry(Repository, File f, DirCacheEntry, ObjectReader)}
+        * instead which allows to reuse one {@code ObjectReader} for multiple
+        * entries.
+        *
+        * <p>
+        * TODO: this method works directly on File IO, we may need another
+        * abstraction (like WorkingTreeIterator). This way we could tell e.g.
+        * Eclipse that Files in the workspace got changed
+        * </p>
+        *
+        * @param repository
+        * @param f
+        *            the file to be modified. The parent directory for this file
+        *            has to exist already
+        * @param entry
+        *            the entry containing new mode and content
+        * @throws IOException
+        */
+       public static void checkoutEntry(final Repository repository, File f,
+                       DirCacheEntry entry) throws IOException {
+               ObjectReader or = repository.newObjectReader();
+               try {
+                       checkoutEntry(repository, f, entry, repository.newObjectReader());
+               } finally {
+                       or.release();
+               }
+       }
+
        /**
         * Updates the file in the working tree with content and mode from an entry
         * in the index. The new content is first written to a new temporary file in
         * the same directory as the real file. Then that new file is renamed to the
         * final filename.
         *
+        * <p>
         * TODO: this method works directly on File IO, we may need another
         * abstraction (like WorkingTreeIterator). This way we could tell e.g.
         * Eclipse that Files in the workspace got changed
+        * </p>
+        *
         * @param repo
         * @param f
         *            the file to be modified. The parent directory for this file
         *            has to exist already
         * @param entry
         *            the entry containing new mode and content
+        * @param or
+        *            object reader to use for checkout
         * @throws IOException
         */
        public static void checkoutEntry(final Repository repo, File f,
-                       DirCacheEntry entry) throws IOException {
-               ObjectLoader ol = repo.open(entry.getObjectId());
+                       DirCacheEntry entry, ObjectReader or) throws IOException {
+               ObjectLoader ol = or.open(entry.getObjectId());
                File parentDir = f.getParentFile();
                File tmpFile = File.createTempFile("._" + f.getName(), null, parentDir);
                FileOutputStream channel = new FileOutputStream(tmpFile);
index d347b59a0b49e803aadf482d94c3baea64de6c14..b763568951596ff8dc374ebc2b758c3a0b8261ca 100644 (file)
@@ -238,19 +238,23 @@ public class ResolveMerger extends ThreeWayMerger {
        }
 
        private void checkout() throws NoWorkTreeException, IOException {
-               for (Map.Entry<String, DirCacheEntry> entry : toBeCheckedOut.entrySet()) {
-                       File f = new File(db.getWorkTree(), entry.getKey());
-                       if (entry.getValue() != null) {
-                               createDir(f.getParentFile());
-                               DirCacheCheckout.checkoutEntry(db,
-                                               f,
-                                               entry.getValue());
-                       } else {
-                               if (!f.delete())
-                                       failingPaths.put(entry.getKey(),
-                                                       MergeFailureReason.COULD_NOT_DELETE);
+               ObjectReader r = db.getObjectDatabase().newReader();
+               try {
+                       for (Map.Entry<String, DirCacheEntry> entry : toBeCheckedOut
+                                       .entrySet()) {
+                               File f = new File(db.getWorkTree(), entry.getKey());
+                               if (entry.getValue() != null) {
+                                       createDir(f.getParentFile());
+                                       DirCacheCheckout.checkoutEntry(db, f, entry.getValue(), r);
+                               } else {
+                                       if (!f.delete())
+                                               failingPaths.put(entry.getKey(),
+                                                               MergeFailureReason.COULD_NOT_DELETE);
+                               }
+                               modifiedFiles.add(entry.getKey());
                        }
-                       modifiedFiles.add(entry.getKey());
+               } finally {
+                       r.release();
                }
        }