in org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java [171:312]
public Ref call() throws GitAPIException, RefAlreadyExistsException,
RefNotFoundException, InvalidRefNameException,
CheckoutConflictException {
checkCallable();
try {
processOptions();
if (checkoutAllPaths || !paths.isEmpty()) {
checkoutPaths();
status = new CheckoutResult(Status.OK, paths);
setCallable(false);
return null;
}
if (createBranch) {
try (Git git = new Git(repo)) {
CreateBranchCommand command = git.branchCreate();
command.setName(name);
if (startCommit != null)
command.setStartPoint(startCommit);
else
command.setStartPoint(startPoint);
if (upstreamMode != null)
command.setUpstreamMode(upstreamMode);
command.call();
}
}
Ref headRef = repo.exactRef(Constants.HEAD);
if (headRef == null) {
// TODO Git CLI supports checkout from unborn branch, we should
// also allow this
throw new UnsupportedOperationException(
JGitText.get().cannotCheckoutFromUnbornBranch);
}
String shortHeadRef = getShortBranchName(headRef);
String refLogMessage = "checkout: moving from " + shortHeadRef; //$NON-NLS-1$
ObjectId branch;
if (orphan) {
if (startPoint == null && startCommit == null) {
Result r = repo.updateRef(Constants.HEAD).link(
getBranchName());
if (!EnumSet.of(Result.NEW, Result.FORCED).contains(r))
throw new JGitInternalException(MessageFormat.format(
JGitText.get().checkoutUnexpectedResult,
r.name()));
this.status = CheckoutResult.NOT_TRIED_RESULT;
return repo.exactRef(Constants.HEAD);
}
branch = getStartPointObjectId();
} else {
branch = repo.resolve(name);
if (branch == null)
throw new RefNotFoundException(MessageFormat.format(
JGitText.get().refNotResolved, name));
}
RevCommit headCommit = null;
RevCommit newCommit = null;
try (RevWalk revWalk = new RevWalk(repo)) {
AnyObjectId headId = headRef.getObjectId();
headCommit = headId == null ? null
: revWalk.parseCommit(headId);
newCommit = revWalk.parseCommit(branch);
}
RevTree headTree = headCommit == null ? null : headCommit.getTree();
DirCacheCheckout dco;
DirCache dc = repo.lockDirCache();
try {
dco = new DirCacheCheckout(repo, headTree, dc,
newCommit.getTree());
dco.setFailOnConflict(true);
dco.setForce(forced);
if (forced) {
dco.setFailOnConflict(false);
}
dco.setProgressMonitor(monitor);
try {
dco.checkout();
} catch (org.eclipse.jgit.errors.CheckoutConflictException e) {
status = new CheckoutResult(Status.CONFLICTS,
dco.getConflicts());
throw new CheckoutConflictException(dco.getConflicts(), e);
}
} finally {
dc.unlock();
}
Ref ref = repo.findRef(name);
if (ref != null && !ref.getName().startsWith(Constants.R_HEADS))
ref = null;
String toName = Repository.shortenRefName(name);
RefUpdate refUpdate = repo.updateRef(Constants.HEAD, ref == null);
refUpdate.setForceUpdate(forceRefUpdate);
refUpdate.setRefLogMessage(refLogMessage + " to " + toName, false); //$NON-NLS-1$
Result updateResult;
if (ref != null)
updateResult = refUpdate.link(ref.getName());
else if (orphan) {
updateResult = refUpdate.link(getBranchName());
ref = repo.exactRef(Constants.HEAD);
} else {
refUpdate.setNewObjectId(newCommit);
updateResult = refUpdate.forceUpdate();
}
setCallable(false);
boolean ok = false;
switch (updateResult) {
case NEW:
ok = true;
break;
case NO_CHANGE:
case FAST_FORWARD:
case FORCED:
ok = true;
break;
default:
break;
}
if (!ok)
throw new JGitInternalException(MessageFormat.format(JGitText
.get().checkoutUnexpectedResult, updateResult.name()));
if (!dco.getToBeDeleted().isEmpty()) {
status = new CheckoutResult(Status.NONDELETED,
dco.getToBeDeleted(),
new ArrayList<>(dco.getUpdated().keySet()),
dco.getRemoved());
} else
status = new CheckoutResult(new ArrayList<>(dco
.getUpdated().keySet()), dco.getRemoved());
return ref;
} catch (IOException ioe) {
throw new JGitInternalException(ioe.getMessage(), ioe);
} finally {
if (status == null)
status = CheckoutResult.ERROR_RESULT;
}
}