Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Sohn2011-08-02 15:54:20 +0000
committerMatthias Sohn2011-08-02 15:54:20 +0000
commit1067f82f562231cca1a7d75c6f0c2d2ce04c7381 (patch)
tree5c02669fe8756e12030f5994f70eebe916a88239
parent6d293c7b06e219086959e80d495b5febe8ae530d (diff)
downloadjgit-1067f82f562231cca1a7d75c6f0c2d2ce04c7381.tar.gz
jgit-1067f82f562231cca1a7d75c6f0c2d2ce04c7381.tar.xz
jgit-1067f82f562231cca1a7d75c6f0c2d2ce04c7381.zip
Reuse ObjectReader for all objects touched during checkout
Bug: 349361 Change-Id: I61ffcb7694eb8b99ebaf4d0d0acd63e0ee91bcb3 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java144
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java28
3 files changed, 119 insertions, 65 deletions
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 f3a2e53602..8caff06292 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
@@ -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();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 79f2297b26..8559483292 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -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;
}
@@ -848,22 +853,61 @@ public class DirCacheCheckout {
* 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);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
index d347b59a0b..b763568951 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
@@ -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();
}
}

Back to the top