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;
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;
}
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);
}
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();
}
}