Preconditions.checkState(conflicts.isEmpty() || skip || abort,
"Cannot run operation while merge conflicts exist.");
Optional<Ref> ref = command(RefParse.class).setName(Ref.ORIG_HEAD).call();
File branchFile = new File(getRebaseFolder(), "branch");
RevCommit squashCommit = readSquashCommit();
if (abort) {
Preconditions.checkState(ref.isPresent() && branchFile.exists(),
"Cannot abort. You are not in the middle of a rebase process.");
command(ResetOp.class).setMode(ResetMode.HARD)
.setCommit(Suppliers.ofInstance(ref.get().getObjectId())).call();
command(UpdateRef.class).setDelete(true).setName(Ref.ORIG_HEAD).call();
branchFile.delete();
return true;
} else if (continueRebase) {
Preconditions.checkState(ref.isPresent() && branchFile.exists(),
"Cannot continue. You are not in the middle of a rebase process.");
try {
currentBranch = Files.readFirstLine(branchFile, Charsets.UTF_8);
} catch (IOException e) {
throw new IllegalStateException("Cannot read current branch info file");
}
rebaseHead = currHead.get().getObjectId();
if (squashCommit == null) {
// Commit the manually-merged changes with the info of the commit that caused the
// conflict
applyNextCommit(false);
// Commit files should already be prepared, so we do nothing else
} else {
applyCommit(squashCommit, false);
}
} else if (skip) {
Preconditions.checkState(ref.isPresent() && branchFile.exists(),
"Cannot skip. You are not in the middle of a rebase process.");
try {
currentBranch = Files.readFirstLine(branchFile, Charsets.UTF_8);
} catch (IOException e) {
throw new IllegalStateException("Cannot read current branch info file");
}
rebaseHead = currHead.get().getObjectId();
command(ResetOp.class).setCommit(Suppliers.ofInstance(rebaseHead))
.setMode(ResetMode.HARD).call();
if (squashCommit == null) {
skipCurrentCommit();
applyNextCommit(true);
} else {
return true;
}
} else {
Preconditions
.checkState(!ref.isPresent(),
"You are currently in the middle of a merge or rebase project <ORIG_HEAD is present>.");
getProgressListener().started();
command(UpdateRef.class).setName(Ref.ORIG_HEAD)
.setNewValue(currHead.get().getObjectId()).call();
// Here we prepare the files with the info about the commits to apply or, if that's not
// needed, do a fast-forward
final SymRef headRef = (SymRef) currHead.get();
currentBranch = headRef.getTarget();
if (ObjectId.NULL.equals(headRef.getObjectId())) {
// Fast-forward
command(UpdateRef.class).setName(currentBranch).setNewValue(upstream.get()).call();
command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call();
workingTree().updateWorkHead(upstream.get());
index().updateStageHead(upstream.get());
getProgressListener().complete();
return true;
}
Repository repository = repository();
final RevCommit headCommit = repository.getCommit(headRef.getObjectId());
final RevCommit targetCommit = repository.getCommit(upstream.get());
command(UpdateRef.class).setName(Ref.ORIG_HEAD).setNewValue(headCommit.getId());
Optional<ObjectId> ancestorCommit = command(FindCommonAncestor.class)
.setLeft(headCommit).setRight(targetCommit)
.setProgressListener(subProgress(10.f)).call();
Preconditions.checkState(ancestorCommit.isPresent(),
"No ancestor commit could be found.");
if (ancestorCommit.get().equals(headCommit.getId())) {
// Fast-forward
command(UpdateRef.class).setName(currentBranch).setNewValue(upstream.get()).call();
command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call();
workingTree().updateWorkHead(upstream.get());
index().updateStageHead(upstream.get());
getProgressListener().complete();
return true;
}
// Get all commits between the head commit and the ancestor.
Iterator<RevCommit> commitIterator = command(LogOp.class).call();
List<RevCommit> commitsToRebase = new ArrayList<RevCommit>();
RevCommit commit = commitIterator.next();
while (!commit.getId().equals(ancestorCommit.get())) {
commitsToRebase.add(commit);
commit = commitIterator.next();
}
// rewind the HEAD