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>
This commit is contained in:
Matthias Sohn 2011-08-02 17:54:20 +02:00
parent 6d293c7b06
commit 1067f82f56
3 changed files with 122 additions and 68 deletions

View File

@ -66,6 +66,7 @@
import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result; import org.eclipse.jgit.lib.RefUpdate.Result;
@ -266,9 +267,14 @@ public void apply(DirCacheEntry ent) {
} }
File workTree = repo.getWorkTree(); File workTree = repo.getWorkTree();
ObjectReader r = repo.getObjectDatabase().newReader();
try {
for (String file : files) for (String file : files)
DirCacheCheckout.checkoutEntry(repo, new File(workTree, file), DirCacheCheckout.checkoutEntry(repo, new File(workTree,
dc.getEntry(file)); file), dc.getEntry(file), r);
} finally {
r.release();
}
} finally { } finally {
dc.unlock(); dc.unlock();
revWalk.release(); revWalk.release();

View File

@ -60,6 +60,7 @@
import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.CanonicalTreeParser;
@ -386,6 +387,9 @@ private boolean doCheckout() throws CorruptObjectException, IOException,
MissingObjectException, IncorrectObjectTypeException, MissingObjectException, IncorrectObjectTypeException,
CheckoutConflictException, IndexWriteException { CheckoutConflictException, IndexWriteException {
toBeDeleted.clear(); toBeDeleted.clear();
ObjectReader objectReader = repo.getObjectDatabase().newReader();
try {
if (headCommitTree != null) if (headCommitTree != null)
preScanTwoTrees(); preScanTwoTrees();
else else
@ -434,16 +438,17 @@ private boolean doCheckout() throws CorruptObjectException, IOException,
if (FileMode.GITLINK.equals(entry.getRawMode())) if (FileMode.GITLINK.equals(entry.getRawMode()))
continue; continue;
checkoutEntry(repo, file, entry); checkoutEntry(repo, file, entry, objectReader);
} }
// commit the index builder - a new index is persisted // commit the index builder - a new index is persisted
if (!builder.commit()) { if (!builder.commit()) {
dc.unlock(); dc.unlock();
throw new IndexWriteException(); throw new IndexWriteException();
} }
} finally {
objectReader.release();
}
return toBeDeleted.size() == 0; return toBeDeleted.size() == 0;
} }
@ -848,12 +853,19 @@ private boolean isModified(String path) throws CorruptObjectException, IOExcepti
* Updates the file in the working tree with content and mode from an entry * 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 * 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 * the same directory as the real file. Then that new file is renamed to the
* final filename. * 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 * TODO: this method works directly on File IO, we may need another
* abstraction (like WorkingTreeIterator). This way we could tell e.g. * abstraction (like WorkingTreeIterator). This way we could tell e.g.
* Eclipse that Files in the workspace got changed * Eclipse that Files in the workspace got changed
* @param repo * </p>
*
* @param repository
* @param f * @param f
* the file to be modified. The parent directory for this file * the file to be modified. The parent directory for this file
* has to exist already * has to exist already
@ -861,9 +873,41 @@ private boolean isModified(String path) throws CorruptObjectException, IOExcepti
* the entry containing new mode and content * the entry containing new mode and content
* @throws IOException * @throws IOException
*/ */
public static void checkoutEntry(final Repository repo, File f, public static void checkoutEntry(final Repository repository, File f,
DirCacheEntry entry) throws IOException { DirCacheEntry entry) throws IOException {
ObjectLoader ol = repo.open(entry.getObjectId()); 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, ObjectReader or) throws IOException {
ObjectLoader ol = or.open(entry.getObjectId());
File parentDir = f.getParentFile(); File parentDir = f.getParentFile();
File tmpFile = File.createTempFile("._" + f.getName(), null, parentDir); File tmpFile = File.createTempFile("._" + f.getName(), null, parentDir);
FileOutputStream channel = new FileOutputStream(tmpFile); FileOutputStream channel = new FileOutputStream(tmpFile);

View File

@ -238,13 +238,14 @@ protected boolean mergeImpl() throws IOException {
} }
private void checkout() throws NoWorkTreeException, IOException { private void checkout() throws NoWorkTreeException, IOException {
for (Map.Entry<String, DirCacheEntry> entry : toBeCheckedOut.entrySet()) { ObjectReader r = db.getObjectDatabase().newReader();
try {
for (Map.Entry<String, DirCacheEntry> entry : toBeCheckedOut
.entrySet()) {
File f = new File(db.getWorkTree(), entry.getKey()); File f = new File(db.getWorkTree(), entry.getKey());
if (entry.getValue() != null) { if (entry.getValue() != null) {
createDir(f.getParentFile()); createDir(f.getParentFile());
DirCacheCheckout.checkoutEntry(db, DirCacheCheckout.checkoutEntry(db, f, entry.getValue(), r);
f,
entry.getValue());
} else { } else {
if (!f.delete()) if (!f.delete())
failingPaths.put(entry.getKey(), failingPaths.put(entry.getKey(),
@ -252,6 +253,9 @@ private void checkout() throws NoWorkTreeException, IOException {
} }
modifiedFiles.add(entry.getKey()); modifiedFiles.add(entry.getKey());
} }
} finally {
r.release();
}
} }
private void createDir(File f) throws IOException { private void createDir(File f) throws IOException {