/*
 * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
 * Copyright (C) 2011, Matthias Sohn <matthias.sohn@sap.com>
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.eclipse.jgit.api;

import static org.eclipse.jgit.treewalk.TreeWalk.OperationType.CHECKOUT_OP;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.eclipse.jgit.api.CheckoutResult.Status;
import org.eclipse.jgit.api.errors.CheckoutConflictException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.UnmergedPathException;
import org.eclipse.jgit.events.WorkingTreeModifiedEvent;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;

/**
 * Checkout a branch to the working tree.
 * <p>
 * Examples (<code>git</code> is a {@link org.eclipse.jgit.api.Git} instance):
 * <p>
 * Check out an existing branch:
 *
 * <pre>
 * git.checkout().setName(&quot;feature&quot;).call();
 * </pre>
 * <p>
 * Check out paths from the index:
 *
 * <pre>
 * git.checkout().addPath(&quot;file1.txt&quot;).addPath(&quot;file2.txt&quot;).call();
 * </pre>
 * <p>
 * Check out a path from a commit:
 *
 * <pre>
 * git.checkout().setStartPoint(&quot;HEAD&circ;&quot;).addPath(&quot;file1.txt&quot;).call();
 * </pre>
 *
 * <p>
 * Create a new branch and check it out:
 *
 * <pre>
 * git.checkout().setCreateBranch(true).setName(&quot;newbranch&quot;).call();
 * </pre>
 * <p>
 * Create a new tracking branch for a remote branch and check it out:
 *
 * <pre>
 * git.checkout().setCreateBranch(true).setName(&quot;stable&quot;)
 * 		.setUpstreamMode(SetupUpstreamMode.SET_UPSTREAM)
 * 		.setStartPoint(&quot;origin/stable&quot;).call();
 * </pre>
 *
 * @see <a href=
 *      "http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html" >Git
 *      documentation about Checkout</a>
 */
public class CheckoutCommand extends GitCommand<Ref> {

	/**
	 * Stage to check out, see {@link CheckoutCommand#setStage(Stage)}.
	 */
	public static enum Stage {
		/**
		 * Base stage (#1)
		 */
		BASE(DirCacheEntry.STAGE_1),

		/**
		 * Ours stage (#2)
		 */
		OURS(DirCacheEntry.STAGE_2),

		/**
		 * Theirs stage (#3)
		 */
		THEIRS(DirCacheEntry.STAGE_3);

		private final int number;

		private Stage(int number) {
			this.number = number;
		}
	}

	private String name;

	private boolean force = false;

	private boolean createBranch = false;

	private boolean orphan = false;

	private CreateBranchCommand.SetupUpstreamMode upstreamMode;

	private String startPoint = null;

	private RevCommit startCommit;

	private Stage checkoutStage = null;

	private CheckoutResult status;

	private List<String> paths;

	private boolean checkoutAllPaths;

	private Set<String> actuallyModifiedPaths;

	private ProgressMonitor monitor = NullProgressMonitor.INSTANCE;

	/**
	 * Constructor for CheckoutCommand
	 *
	 * @param repo
	 *            the {@link org.eclipse.jgit.lib.Repository}
	 */
	protected CheckoutCommand(Repository repo) {
		super(repo);
		this.paths = new LinkedList<>();
	}

	/** {@inheritDoc} */
	@Override
	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(!force);
				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(force);
			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;
		}
	}

	private String getShortBranchName(Ref headRef) {
		if (headRef.isSymbolic()) {
			return Repository.shortenRefName(headRef.getTarget().getName());
		}
		// Detached HEAD. Every non-symbolic ref in the ref database has an
		// object id, so this cannot be null.
		ObjectId id = headRef.getObjectId();
		if (id == null) {
			throw new NullPointerException();
		}
		return id.getName();
	}

	/**
	 * @param monitor
	 *            a progress monitor
	 * @return this instance
	 * @since 4.11
	 */
	public CheckoutCommand setProgressMonitor(ProgressMonitor monitor) {
		if (monitor == null) {
			monitor = NullProgressMonitor.INSTANCE;
		}
		this.monitor = monitor;
		return this;
	}

	/**
	 * Add a single slash-separated path to the list of paths to check out. To
	 * check out all paths, use {@link #setAllPaths(boolean)}.
	 * <p>
	 * If this option is set, neither the {@link #setCreateBranch(boolean)} nor
	 * {@link #setName(String)} option is considered. In other words, these
	 * options are exclusive.
	 *
	 * @param path
	 *            path to update in the working tree and index (with
	 *            <code>/</code> as separator)
	 * @return {@code this}
	 */
	public CheckoutCommand addPath(String path) {
		checkCallable();
		this.paths.add(path);
		return this;
	}

	/**
	 * Add multiple slash-separated paths to the list of paths to check out. To
	 * check out all paths, use {@link #setAllPaths(boolean)}.
	 * <p>
	 * If this option is set, neither the {@link #setCreateBranch(boolean)} nor
	 * {@link #setName(String)} option is considered. In other words, these
	 * options are exclusive.
	 *
	 * @param p
	 *            paths to update in the working tree and index (with
	 *            <code>/</code> as separator)
	 * @return {@code this}
	 * @since 4.6
	 */
	public CheckoutCommand addPaths(List<String> p) {
		checkCallable();
		this.paths.addAll(p);
		return this;
	}

	/**
	 * Set whether to checkout all paths.
	 * <p>
	 * This options should be used when you want to do a path checkout on the
	 * entire repository and so calling {@link #addPath(String)} is not possible
	 * since empty paths are not allowed.
	 * <p>
	 * If this option is set, neither the {@link #setCreateBranch(boolean)} nor
	 * {@link #setName(String)} option is considered. In other words, these
	 * options are exclusive.
	 *
	 * @param all
	 *            <code>true</code> to checkout all paths, <code>false</code>
	 *            otherwise
	 * @return {@code this}
	 * @since 2.0
	 */
	public CheckoutCommand setAllPaths(boolean all) {
		checkoutAllPaths = all;
		return this;
	}

	/**
	 * Checkout paths into index and working directory, firing a
	 * {@link org.eclipse.jgit.events.WorkingTreeModifiedEvent} if the working
	 * tree was modified.
	 *
	 * @return this instance
	 * @throws java.io.IOException
	 * @throws org.eclipse.jgit.api.errors.RefNotFoundException
	 */
	protected CheckoutCommand checkoutPaths() throws IOException,
			RefNotFoundException {
		actuallyModifiedPaths = new HashSet<>();
		DirCache dc = repo.lockDirCache();
		try (RevWalk revWalk = new RevWalk(repo);
				TreeWalk treeWalk = new TreeWalk(repo,
						revWalk.getObjectReader())) {
			treeWalk.setRecursive(true);
			if (!checkoutAllPaths)
				treeWalk.setFilter(PathFilterGroup.createFromStrings(paths));
			if (isCheckoutIndex())
				checkoutPathsFromIndex(treeWalk, dc);
			else {
				RevCommit commit = revWalk.parseCommit(getStartPointObjectId());
				checkoutPathsFromCommit(treeWalk, dc, commit);
			}
		} finally {
			try {
				dc.unlock();
			} finally {
				WorkingTreeModifiedEvent event = new WorkingTreeModifiedEvent(
						actuallyModifiedPaths, null);
				actuallyModifiedPaths = null;
				if (!event.isEmpty()) {
					repo.fireEvent(event);
				}
			}
		}
		return this;
	}

	private void checkoutPathsFromIndex(TreeWalk treeWalk, DirCache dc)
			throws IOException {
		DirCacheIterator dci = new DirCacheIterator(dc);
		treeWalk.addTree(dci);

		String previousPath = null;

		final ObjectReader r = treeWalk.getObjectReader();
		DirCacheEditor editor = dc.editor();
		while (treeWalk.next()) {
			String path = treeWalk.getPathString();
			// Only add one edit per path
			if (path.equals(previousPath))
				continue;

			final EolStreamType eolStreamType = treeWalk
					.getEolStreamType(CHECKOUT_OP);
			final String filterCommand = treeWalk
					.getFilterCommand(Constants.ATTR_FILTER_TYPE_SMUDGE);
			editor.add(new PathEdit(path) {
				@Override
				public void apply(DirCacheEntry ent) {
					int stage = ent.getStage();
					if (stage > DirCacheEntry.STAGE_0) {
						if (checkoutStage != null) {
							if (stage == checkoutStage.number) {
								checkoutPath(ent, r, new CheckoutMetadata(
										eolStreamType, filterCommand));
								actuallyModifiedPaths.add(path);
							}
						} else {
							UnmergedPathException e = new UnmergedPathException(
									ent);
							throw new JGitInternalException(e.getMessage(), e);
						}
					} else {
						checkoutPath(ent, r, new CheckoutMetadata(eolStreamType,
								filterCommand));
						actuallyModifiedPaths.add(path);
					}
				}
			});

			previousPath = path;
		}
		editor.commit();
	}

	private void checkoutPathsFromCommit(TreeWalk treeWalk, DirCache dc,
			RevCommit commit) throws IOException {
		treeWalk.addTree(commit.getTree());
		final ObjectReader r = treeWalk.getObjectReader();
		DirCacheEditor editor = dc.editor();
		while (treeWalk.next()) {
			final ObjectId blobId = treeWalk.getObjectId(0);
			final FileMode mode = treeWalk.getFileMode(0);
			final EolStreamType eolStreamType = treeWalk
					.getEolStreamType(CHECKOUT_OP);
			final String filterCommand = treeWalk
					.getFilterCommand(Constants.ATTR_FILTER_TYPE_SMUDGE);
			final String path = treeWalk.getPathString();
			editor.add(new PathEdit(path) {
				@Override
				public void apply(DirCacheEntry ent) {
					ent.setObjectId(blobId);
					ent.setFileMode(mode);
					checkoutPath(ent, r,
							new CheckoutMetadata(eolStreamType, filterCommand));
					actuallyModifiedPaths.add(path);
				}
			});
		}
		editor.commit();
	}

	private void checkoutPath(DirCacheEntry entry, ObjectReader reader,
			CheckoutMetadata checkoutMetadata) {
		try {
			DirCacheCheckout.checkoutEntry(repo, entry, reader, true,
					checkoutMetadata);
		} catch (IOException e) {
			throw new JGitInternalException(MessageFormat.format(
					JGitText.get().checkoutConflictWithFile,
					entry.getPathString()), e);
		}
	}

	private boolean isCheckoutIndex() {
		return startCommit == null && startPoint == null;
	}

	private ObjectId getStartPointObjectId() throws AmbiguousObjectException,
			RefNotFoundException, IOException {
		if (startCommit != null)
			return startCommit.getId();

		String startPointOrHead = (startPoint != null) ? startPoint
				: Constants.HEAD;
		ObjectId result = repo.resolve(startPointOrHead);
		if (result == null)
			throw new RefNotFoundException(MessageFormat.format(
					JGitText.get().refNotResolved, startPointOrHead));
		return result;
	}

	private void processOptions() throws InvalidRefNameException,
			RefAlreadyExistsException, IOException {
		if (((!checkoutAllPaths && paths.isEmpty()) || orphan)
				&& (name == null || !Repository
						.isValidRefName(Constants.R_HEADS + name)))
			throw new InvalidRefNameException(MessageFormat.format(JGitText
					.get().branchNameInvalid, name == null ? "<null>" : name)); //$NON-NLS-1$

		if (orphan) {
			Ref refToCheck = repo.exactRef(getBranchName());
			if (refToCheck != null)
				throw new RefAlreadyExistsException(MessageFormat.format(
						JGitText.get().refAlreadyExists, name));
		}
	}

	private String getBranchName() {
		if (name.startsWith(Constants.R_REFS))
			return name;

		return Constants.R_HEADS + name;
	}

	/**
	 * Specify the name of the branch or commit to check out, or the new branch
	 * name.
	 * <p>
	 * When only checking out paths and not switching branches, use
	 * {@link #setStartPoint(String)} or {@link #setStartPoint(RevCommit)} to
	 * specify from which branch or commit to check out files.
	 * <p>
	 * When {@link #setCreateBranch(boolean)} is set to <code>true</code>, use
	 * this method to set the name of the new branch to create and
	 * {@link #setStartPoint(String)} or {@link #setStartPoint(RevCommit)} to
	 * specify the start point of the branch.
	 *
	 * @param name
	 *            the name of the branch or commit
	 * @return this instance
	 */
	public CheckoutCommand setName(String name) {
		checkCallable();
		this.name = name;
		return this;
	}

	/**
	 * Specify whether to create a new branch.
	 * <p>
	 * If <code>true</code> is used, the name of the new branch must be set
	 * using {@link #setName(String)}. The commit at which to start the new
	 * branch can be set using {@link #setStartPoint(String)} or
	 * {@link #setStartPoint(RevCommit)}; if not specified, HEAD is used. Also
	 * see {@link #setUpstreamMode} for setting up branch tracking.
	 *
	 * @param createBranch
	 *            if <code>true</code> a branch will be created as part of the
	 *            checkout and set to the specified start point
	 * @return this instance
	 */
	public CheckoutCommand setCreateBranch(boolean createBranch) {
		checkCallable();
		this.createBranch = createBranch;
		return this;
	}

	/**
	 * Specify whether to create a new orphan branch.
	 * <p>
	 * If <code>true</code> is used, the name of the new orphan branch must be
	 * set using {@link #setName(String)}. The commit at which to start the new
	 * orphan branch can be set using {@link #setStartPoint(String)} or
	 * {@link #setStartPoint(RevCommit)}; if not specified, HEAD is used.
	 *
	 * @param orphan
	 *            if <code>true</code> a orphan branch will be created as part
	 *            of the checkout to the specified start point
	 * @return this instance
	 * @since 3.3
	 */
	public CheckoutCommand setOrphan(boolean orphan) {
		checkCallable();
		this.orphan = orphan;
		return this;
	}

	/**
	 * Specify to force the ref update in case of a branch switch.
	 *
	 * @param force
	 *            if <code>true</code> and the branch with the given name
	 *            already exists, the start-point of an existing branch will be
	 *            set to a new start-point; if false, the existing branch will
	 *            not be changed
	 * @return this instance
	 */
	public CheckoutCommand setForce(boolean force) {
		checkCallable();
		this.force = force;
		return this;
	}

	/**
	 * Set the name of the commit that should be checked out.
	 * <p>
	 * When checking out files and this is not specified or <code>null</code>,
	 * the index is used.
	 * <p>
	 * When creating a new branch, this will be used as the start point. If not
	 * specified or <code>null</code>, the current HEAD is used.
	 *
	 * @param startPoint
	 *            commit name to check out
	 * @return this instance
	 */
	public CheckoutCommand setStartPoint(String startPoint) {
		checkCallable();
		this.startPoint = startPoint;
		this.startCommit = null;
		checkOptions();
		return this;
	}

	/**
	 * Set the commit that should be checked out.
	 * <p>
	 * When creating a new branch, this will be used as the start point. If not
	 * specified or <code>null</code>, the current HEAD is used.
	 * <p>
	 * When checking out files and this is not specified or <code>null</code>,
	 * the index is used.
	 *
	 * @param startCommit
	 *            commit to check out
	 * @return this instance
	 */
	public CheckoutCommand setStartPoint(RevCommit startCommit) {
		checkCallable();
		this.startCommit = startCommit;
		this.startPoint = null;
		checkOptions();
		return this;
	}

	/**
	 * When creating a branch with {@link #setCreateBranch(boolean)}, this can
	 * be used to configure branch tracking.
	 *
	 * @param mode
	 *            corresponds to the --track/--no-track options; may be
	 *            <code>null</code>
	 * @return this instance
	 */
	public CheckoutCommand setUpstreamMode(
			CreateBranchCommand.SetupUpstreamMode mode) {
		checkCallable();
		this.upstreamMode = mode;
		return this;
	}

	/**
	 * When checking out the index, check out the specified stage (ours or
	 * theirs) for unmerged paths.
	 * <p>
	 * This can not be used when checking out a branch, only when checking out
	 * the index.
	 *
	 * @param stage
	 *            the stage to check out
	 * @return this
	 */
	public CheckoutCommand setStage(Stage stage) {
		checkCallable();
		this.checkoutStage = stage;
		checkOptions();
		return this;
	}

	/**
	 * Get the result, never <code>null</code>
	 *
	 * @return the result, never <code>null</code>
	 */
	public CheckoutResult getResult() {
		if (status == null)
			return CheckoutResult.NOT_TRIED_RESULT;
		return status;
	}

	private void checkOptions() {
		if (checkoutStage != null && !isCheckoutIndex())
			throw new IllegalStateException(
					JGitText.get().cannotCheckoutOursSwitchBranch);
	}
}
