in org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java [494:627]
private boolean doCheckout() throws CorruptObjectException, IOException,
MissingObjectException, IncorrectObjectTypeException,
CheckoutConflictException, IndexWriteException, CanceledException {
toBeDeleted.clear();
options = repo.getConfig()
.get(WorkingTreeOptions.KEY);
try (ObjectReader objectReader = repo.getObjectDatabase().newReader()) {
if (headCommitTree != null)
preScanTwoTrees();
else
prescanOneTree();
if (!conflicts.isEmpty()) {
if (failOnConflict) {
throw new CheckoutConflictException(conflicts.toArray(new String[0]));
}
cleanUpConflicts();
}
// update our index
builder.finish();
// init progress reporting
int numTotal = removed.size() + updated.size() + conflicts.size();
monitor.beginTask(JGitText.get().checkingOutFiles, numTotal);
performingCheckout = true;
File file = null;
String last = null;
// 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
IntList nonDeleted = new IntList();
for (int i = removed.size() - 1; i >= 0; i--) {
String r = removed.get(i);
file = new File(repo.getWorkTree(), r);
if (!file.delete() && repo.getFS().exists(file)) {
// The list of stuff to delete comes from the index
// which will only contain a directory if it is
// a submodule, in which case we shall not attempt
// to delete it. A submodule is not empty, so it
// is safe to check this after a failed delete.
if (!repo.getFS().isDirectory(file)) {
nonDeleted.add(i);
toBeDeleted.add(r);
}
} else {
if (last != null && !isSamePrefix(r, last))
removeEmptyParents(new File(repo.getWorkTree(), last));
last = r;
}
monitor.update(1);
if (monitor.isCancelled()) {
throw new CanceledException(MessageFormat.format(
JGitText.get().operationCanceled,
JGitText.get().checkingOutFiles));
}
}
if (file != null) {
removeEmptyParents(file);
}
removed = filterOut(removed, nonDeleted);
nonDeleted = null;
Iterator<Map.Entry<String, CheckoutMetadata>> toUpdate = updated
.entrySet().iterator();
Map.Entry<String, CheckoutMetadata> e = null;
try {
while (toUpdate.hasNext()) {
e = toUpdate.next();
String path = e.getKey();
CheckoutMetadata meta = e.getValue();
DirCacheEntry entry = dc.getEntry(path);
if (FileMode.GITLINK.equals(entry.getRawMode())) {
checkoutGitlink(path, entry);
} else {
checkoutEntry(repo, entry, objectReader, false, meta,
options);
}
e = null;
monitor.update(1);
if (monitor.isCancelled()) {
throw new CanceledException(MessageFormat.format(
JGitText.get().operationCanceled,
JGitText.get().checkingOutFiles));
}
}
} catch (Exception ex) {
// We didn't actually modify the current entry nor any that
// might follow.
if (e != null) {
toUpdate.remove();
}
while (toUpdate.hasNext()) {
e = toUpdate.next();
toUpdate.remove();
}
throw ex;
}
for (String conflict : conflicts) {
// the conflicts are likely to have multiple entries in the
// dircache, we only want to check out the one for the "theirs"
// tree
int entryIdx = dc.findEntry(conflict);
if (entryIdx >= 0) {
while (entryIdx < dc.getEntryCount()) {
DirCacheEntry entry = dc.getEntry(entryIdx);
if (!entry.getPathString().equals(conflict)) {
break;
}
if (entry.getStage() == DirCacheEntry.STAGE_3) {
checkoutEntry(repo, entry, objectReader, false,
null, options);
break;
}
++entryIdx;
}
}
monitor.update(1);
if (monitor.isCancelled()) {
throw new CanceledException(MessageFormat.format(
JGitText.get().operationCanceled,
JGitText.get().checkingOutFiles));
}
}
monitor.endTask();
// commit the index builder - a new index is persisted
if (!builder.commit())
throw new IndexWriteException();
}
return toBeDeleted.isEmpty();
}