package com.beijunyi.parallelgit.filesystem.commands;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import javax.annotation.Nonnull;
import com.beijunyi.parallelgit.filesystem.GfsStatusProvider;
import com.beijunyi.parallelgit.filesystem.GitFileSystem;
import com.beijunyi.parallelgit.filesystem.exceptions.NoBranchException;
import com.beijunyi.parallelgit.filesystem.io.GfsCheckoutConflict;
import com.beijunyi.parallelgit.filesystem.io.GfsDefaultCheckout;
import com.beijunyi.parallelgit.utils.BranchUtils;
import com.beijunyi.parallelgit.utils.CommitUtils;
import com.beijunyi.parallelgit.utils.RefUtils;
import com.beijunyi.parallelgit.utils.exceptions.NoSuchBranchException;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import static java.util.Collections.unmodifiableMap;
public class GfsCheckout extends GfsCommand<GfsCheckout.Result> {
private String target;
private boolean force = false;
private boolean detach = false;
private String targetBranch;
private RevCommit targetCommit;
public GfsCheckout(GitFileSystem gfs) {
super(gfs);
}
@Nonnull
@Override
protected Result doExecute(GfsStatusProvider.Update update) throws IOException {
prepareFileSystem();
prepareTarget();
GfsDefaultCheckout checkout = new GfsDefaultCheckout(gfs, false);
checkout.checkout(targetCommit.getTree());
if(checkout.hasConflicts())
return Result.checkoutConflicts(checkout.getConflicts());
store.getRoot().updateOrigin(targetCommit.getTree());
updateHead(update);
return Result.success();
}
@Nonnull
public GfsCheckout target(String target) {
this.target = target;
return this;
}
@Nonnull
public GfsCheckout force(boolean force) {
this.force = force;
return this;
}
@Nonnull
public GfsCheckout detach(boolean detach) {
this.detach = detach;
return this;
}
private void prepareFileSystem() {
if(force)
store.getRoot().reset();
}
private void prepareTarget() throws IOException {
if(target == null)
throw new NoBranchException();
if(!detach) {
if(BranchUtils.branchExists(target, repo)) {
Ref branchRef = RefUtils.getBranchRef(target, repo);
targetBranch = branchRef.getName();
targetCommit = CommitUtils.getCommit(targetBranch, repo);
}
}
if(targetCommit == null) {
if(CommitUtils.exists(target, repo))
targetCommit = CommitUtils.getCommit(target, repo);
else
throw new NoSuchBranchException(target);
}
}
private void updateHead(GfsStatusProvider.Update update) {
if(targetBranch == null)
update.detach();
else
update.branch(targetBranch);
update.commit(targetCommit);
}
public static class Result implements GfsCommandResult {
private final boolean successful;
private final Map<String, GfsCheckoutConflict> conflicts;
private Result(boolean successful, Map<String, GfsCheckoutConflict> conflicts) {
this.successful = successful;
this.conflicts = unmodifiableMap(conflicts);
}
@Nonnull
public static Result success() {
return new Result(true, Collections.<String, GfsCheckoutConflict>emptyMap());
}
@Nonnull
public static Result checkoutConflicts(Map<String, GfsCheckoutConflict> conflicts) {
return new Result(false, conflicts);
}
@Override
public boolean isSuccessful() {
return successful;
}
public boolean hasConflicts() {
return !conflicts.isEmpty();
}
@Nonnull
public Map<String, GfsCheckoutConflict> getConflicts() {
return conflicts;
}
}
}