/*
 * Copyright (C) 2010-2012, Christian Halstrick <christian.halstrick@sap.com> and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package org.eclipse.jgit.api;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.jgit.api.errors.AbortedByHookException;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.EmptyCommitException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NoFilepatternException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.NoMessageException;
import org.eclipse.jgit.api.errors.ServiceUnavailableException;
import org.eclipse.jgit.api.errors.UnmergedPathsException;
import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuildIterator;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.UnmergedPathException;
import org.eclipse.jgit.hooks.CommitMsgHook;
import org.eclipse.jgit.hooks.Hooks;
import org.eclipse.jgit.hooks.PostCommitHook;
import org.eclipse.jgit.hooks.PreCommitHook;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.GpgConfig;
import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
import org.eclipse.jgit.lib.GpgSigner;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
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.lib.RepositoryState;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
import org.eclipse.jgit.util.ChangeIdUtil;

/**
 * A class used to execute a {@code Commit} command. It has setters for all
 * supported options and arguments of this command and a {@link #call()} method
 * to finally execute the command.
 *
 * @see <a
 *      href="http://www.kernel.org/pub/software/scm/git/docs/git-commit.html"
 *      >Git documentation about Commit</a>
 */
public class CommitCommand extends GitCommand<RevCommit> {
	private PersonIdent author;

	private PersonIdent committer;

	private String message;

	private boolean all;

	private List<String> only = new ArrayList<>();

	private boolean[] onlyProcessed;

	private boolean amend;

	private boolean insertChangeId;

	/**
	 * parents this commit should have. The current HEAD will be in this list
	 * and also all commits mentioned in .git/MERGE_HEAD
	 */
	private List<ObjectId> parents = new LinkedList<>();

	private String reflogComment;

	private boolean useDefaultReflogMessage = true;

	/**
	 * Setting this option bypasses the pre-commit and commit-msg hooks.
	 */
	private boolean noVerify;

	private HashMap<String, PrintStream> hookOutRedirect = new HashMap<>(3);

	private HashMap<String, PrintStream> hookErrRedirect = new HashMap<>(3);

	private Boolean allowEmpty;

	private Boolean signCommit;

	private String signingKey;

	private GpgSigner gpgSigner;

	private CredentialsProvider credentialsProvider;

	/**
	 * Constructor for CommitCommand
	 *
	 * @param repo
	 *            the {@link org.eclipse.jgit.lib.Repository}
	 */
	protected CommitCommand(Repository repo) {
		super(repo);
		this.credentialsProvider = CredentialsProvider.getDefault();
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * Executes the {@code commit} command with all the options and parameters
	 * collected by the setter methods of this class. Each instance of this
	 * class should only be used for one invocation of the command (means: one
	 * call to {@link #call()})
	 *
	 * @throws ServiceUnavailableException
	 *             if signing service is not available e.g. since it isn't
	 *             installed
	 */
	@Override
	public RevCommit call() throws GitAPIException, AbortedByHookException,
			ConcurrentRefUpdateException, NoHeadException, NoMessageException,
			ServiceUnavailableException, UnmergedPathsException,
			WrongRepositoryStateException {
		checkCallable();
		Collections.sort(only);

		try (RevWalk rw = new RevWalk(repo)) {
			RepositoryState state = repo.getRepositoryState();
			if (!state.canCommit())
				throw new WrongRepositoryStateException(MessageFormat.format(
						JGitText.get().cannotCommitOnARepoWithState,
						state.name()));

			if (!noVerify) {
				Hooks.preCommit(repo, hookOutRedirect.get(PreCommitHook.NAME),
						hookErrRedirect.get(PreCommitHook.NAME))
						.call();
			}

			processOptions(state, rw);

			if (all && !repo.isBare()) {
				try (Git git = new Git(repo)) {
					git.add()
							.addFilepattern(".") //$NON-NLS-1$
							.setUpdate(true).call();
				} catch (NoFilepatternException e) {
					// should really not happen
					throw new JGitInternalException(e.getMessage(), e);
				}
			}

			Ref head = repo.exactRef(Constants.HEAD);
			if (head == null)
				throw new NoHeadException(
						JGitText.get().commitOnRepoWithoutHEADCurrentlyNotSupported);

			// determine the current HEAD and the commit it is referring to
			ObjectId headId = repo.resolve(Constants.HEAD + "^{commit}"); //$NON-NLS-1$
			if (headId == null && amend)
				throw new WrongRepositoryStateException(
						JGitText.get().commitAmendOnInitialNotPossible);

			if (headId != null)
				if (amend) {
					RevCommit previousCommit = rw.parseCommit(headId);
					for (RevCommit p : previousCommit.getParents())
						parents.add(p.getId());
					if (author == null)
						author = previousCommit.getAuthorIdent();
				} else {
					parents.add(0, headId);
				}

			if (!noVerify) {
				message = Hooks
						.commitMsg(repo,
								hookOutRedirect.get(CommitMsgHook.NAME),
								hookErrRedirect.get(CommitMsgHook.NAME))
						.setCommitMessage(message).call();
			}

			// lock the index
			DirCache index = repo.lockDirCache();
			try (ObjectInserter odi = repo.newObjectInserter()) {
				if (!only.isEmpty())
					index = createTemporaryIndex(headId, index, rw);

				// Write the index as tree to the object database. This may
				// fail for example when the index contains unmerged paths
				// (unresolved conflicts)
				ObjectId indexTreeId = index.writeTree(odi);

				if (insertChangeId)
					insertChangeId(indexTreeId);

				// Check for empty commits
				if (headId != null && !allowEmpty.booleanValue()) {
					RevCommit headCommit = rw.parseCommit(headId);
					headCommit.getTree();
					if (indexTreeId.equals(headCommit.getTree())) {
						throw new EmptyCommitException(
								JGitText.get().emptyCommit);
					}
				}

				// Create a Commit object, populate it and write it
				CommitBuilder commit = new CommitBuilder();
				commit.setCommitter(committer);
				commit.setAuthor(author);
				commit.setMessage(message);

				commit.setParentIds(parents);
				commit.setTreeId(indexTreeId);

				if (signCommit.booleanValue()) {
					if (gpgSigner == null) {
						throw new ServiceUnavailableException(
								JGitText.get().signingServiceUnavailable);
					}
					gpgSigner.sign(commit, signingKey, committer,
							credentialsProvider);
				}

				ObjectId commitId = odi.insert(commit);
				odi.flush();

				RevCommit revCommit = rw.parseCommit(commitId);
				RefUpdate ru = repo.updateRef(Constants.HEAD);
				ru.setNewObjectId(commitId);
				if (!useDefaultReflogMessage) {
					ru.setRefLogMessage(reflogComment, false);
				} else {
					String prefix = amend ? "commit (amend): " //$NON-NLS-1$
							: parents.isEmpty() ? "commit (initial): " //$NON-NLS-1$
									: "commit: "; //$NON-NLS-1$
					ru.setRefLogMessage(prefix + revCommit.getShortMessage(),
							false);
				}
				if (headId != null)
					ru.setExpectedOldObjectId(headId);
				else
					ru.setExpectedOldObjectId(ObjectId.zeroId());
				Result rc = ru.forceUpdate();
				switch (rc) {
				case NEW:
				case FORCED:
				case FAST_FORWARD: {
					setCallable(false);
					if (state == RepositoryState.MERGING_RESOLVED
							|| isMergeDuringRebase(state)) {
						// Commit was successful. Now delete the files
						// used for merge commits
						repo.writeMergeCommitMsg(null);
						repo.writeMergeHeads(null);
					} else if (state == RepositoryState.CHERRY_PICKING_RESOLVED) {
						repo.writeMergeCommitMsg(null);
						repo.writeCherryPickHead(null);
					} else if (state == RepositoryState.REVERTING_RESOLVED) {
						repo.writeMergeCommitMsg(null);
						repo.writeRevertHead(null);
					}
					Hooks.postCommit(repo,
							hookOutRedirect.get(PostCommitHook.NAME),
							hookErrRedirect.get(PostCommitHook.NAME)).call();

					return revCommit;
				}
				case REJECTED:
				case LOCK_FAILURE:
					throw new ConcurrentRefUpdateException(
							JGitText.get().couldNotLockHEAD, ru.getRef(), rc);
				default:
					throw new JGitInternalException(MessageFormat.format(
							JGitText.get().updatingRefFailed, Constants.HEAD,
							commitId.toString(), rc));
				}
			} finally {
				index.unlock();
			}
		} catch (UnmergedPathException e) {
			throw new UnmergedPathsException(e);
		} catch (IOException e) {
			throw new JGitInternalException(
					JGitText.get().exceptionCaughtDuringExecutionOfCommitCommand, e);
		}
	}

	private void insertChangeId(ObjectId treeId) {
		ObjectId firstParentId = null;
		if (!parents.isEmpty())
			firstParentId = parents.get(0);
		ObjectId changeId = ChangeIdUtil.computeChangeId(treeId, firstParentId,
				author, committer, message);
		message = ChangeIdUtil.insertId(message, changeId);
		if (changeId != null)
			message = message.replaceAll("\nChange-Id: I" //$NON-NLS-1$
					+ ObjectId.zeroId().getName() + "\n", "\nChange-Id: I" //$NON-NLS-1$ //$NON-NLS-2$
					+ changeId.getName() + "\n"); //$NON-NLS-1$
	}

	private DirCache createTemporaryIndex(ObjectId headId, DirCache index,
			RevWalk rw)
			throws IOException {
		ObjectInserter inserter = null;

		// get DirCacheBuilder for existing index
		DirCacheBuilder existingBuilder = index.builder();

		// get DirCacheBuilder for newly created in-core index to build a
		// temporary index for this commit
		DirCache inCoreIndex = DirCache.newInCore();
		DirCacheBuilder tempBuilder = inCoreIndex.builder();

		onlyProcessed = new boolean[only.size()];
		boolean emptyCommit = true;

		try (TreeWalk treeWalk = new TreeWalk(repo)) {
			treeWalk.setOperationType(OperationType.CHECKIN_OP);
			int dcIdx = treeWalk
					.addTree(new DirCacheBuildIterator(existingBuilder));
			FileTreeIterator fti = new FileTreeIterator(repo);
			fti.setDirCacheIterator(treeWalk, 0);
			int fIdx = treeWalk.addTree(fti);
			int hIdx = -1;
			if (headId != null)
				hIdx = treeWalk.addTree(rw.parseTree(headId));
			treeWalk.setRecursive(true);

			String lastAddedFile = null;
			while (treeWalk.next()) {
				String path = treeWalk.getPathString();
				// check if current entry's path matches a specified path
				int pos = lookupOnly(path);

				CanonicalTreeParser hTree = null;
				if (hIdx != -1)
					hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);

				DirCacheIterator dcTree = treeWalk.getTree(dcIdx,
						DirCacheIterator.class);

				if (pos >= 0) {
					// include entry in commit

					FileTreeIterator fTree = treeWalk.getTree(fIdx,
							FileTreeIterator.class);

					// check if entry refers to a tracked file
					boolean tracked = dcTree != null || hTree != null;
					if (!tracked)
						continue;

					// for an unmerged path, DirCacheBuildIterator will yield 3
					// entries, we only want to add one
					if (path.equals(lastAddedFile))
						continue;

					lastAddedFile = path;

					if (fTree != null) {
						// create a new DirCacheEntry with data retrieved from
						// disk
						final DirCacheEntry dcEntry = new DirCacheEntry(path);
						long entryLength = fTree.getEntryLength();
						dcEntry.setLength(entryLength);
						dcEntry.setLastModified(fTree.getEntryLastModifiedInstant());
						dcEntry.setFileMode(fTree.getIndexFileMode(dcTree));

						boolean objectExists = (dcTree != null
								&& fTree.idEqual(dcTree))
								|| (hTree != null && fTree.idEqual(hTree));
						if (objectExists) {
							dcEntry.setObjectId(fTree.getEntryObjectId());
						} else {
							if (FileMode.GITLINK.equals(dcEntry.getFileMode()))
								dcEntry.setObjectId(fTree.getEntryObjectId());
							else {
								// insert object
								if (inserter == null)
									inserter = repo.newObjectInserter();
								long contentLength = fTree
										.getEntryContentLength();
								try (InputStream inputStream = fTree
										.openEntryStream()) {
									dcEntry.setObjectId(inserter.insert(
											Constants.OBJ_BLOB, contentLength,
											inputStream));
								}
							}
						}

						// add to existing index
						existingBuilder.add(dcEntry);
						// add to temporary in-core index
						tempBuilder.add(dcEntry);

						if (emptyCommit
								&& (hTree == null || !hTree.idEqual(fTree)
										|| hTree.getEntryRawMode() != fTree
												.getEntryRawMode()))
							// this is a change
							emptyCommit = false;
					} else {
						// if no file exists on disk, neither add it to
						// index nor to temporary in-core index

						if (emptyCommit && hTree != null)
							// this is a change
							emptyCommit = false;
					}

					// keep track of processed path
					onlyProcessed[pos] = true;
				} else {
					// add entries from HEAD for all other paths
					if (hTree != null) {
						// create a new DirCacheEntry with data retrieved from
						// HEAD
						final DirCacheEntry dcEntry = new DirCacheEntry(path);
						dcEntry.setObjectId(hTree.getEntryObjectId());
						dcEntry.setFileMode(hTree.getEntryFileMode());

						// add to temporary in-core index
						tempBuilder.add(dcEntry);
					}

					// preserve existing entry in index
					if (dcTree != null)
						existingBuilder.add(dcTree.getDirCacheEntry());
				}
			}
		}

		// there must be no unprocessed paths left at this point; otherwise an
		// untracked or unknown path has been specified
		for (int i = 0; i < onlyProcessed.length; i++)
			if (!onlyProcessed[i])
				throw new JGitInternalException(MessageFormat.format(
						JGitText.get().entryNotFoundByPath, only.get(i)));

		// there must be at least one change
		if (emptyCommit && !allowEmpty.booleanValue())
			// Would like to throw a EmptyCommitException. But this would break the API
			// TODO(ch): Change this in the next release
			throw new JGitInternalException(JGitText.get().emptyCommit);

		// update index
		existingBuilder.commit();
		// finish temporary in-core index used for this commit
		tempBuilder.finish();
		return inCoreIndex;
	}

	/**
	 * Look an entry's path up in the list of paths specified by the --only/ -o
	 * option
	 *
	 * In case the complete (file) path (e.g. "d1/d2/f1") cannot be found in
	 * <code>only</code>, lookup is also tried with (parent) directory paths
	 * (e.g. "d1/d2" and "d1").
	 *
	 * @param pathString
	 *            entry's path
	 * @return the item's index in <code>only</code>; -1 if no item matches
	 */
	private int lookupOnly(String pathString) {
		String p = pathString;
		while (true) {
			int position = Collections.binarySearch(only, p);
			if (position >= 0)
				return position;
			int l = p.lastIndexOf('/');
			if (l < 1)
				break;
			p = p.substring(0, l);
		}
		return -1;
	}

	/**
	 * Sets default values for not explicitly specified options. Then validates
	 * that all required data has been provided.
	 *
	 * @param state
	 *            the state of the repository we are working on
	 * @param rw
	 *            the RevWalk to use
	 *
	 * @throws NoMessageException
	 *             if the commit message has not been specified
	 * @throws UnsupportedSigningFormatException
	 *             if the configured gpg.format is not supported
	 */
	private void processOptions(RepositoryState state, RevWalk rw)
			throws NoMessageException, UnsupportedSigningFormatException {
		if (committer == null)
			committer = new PersonIdent(repo);
		if (author == null && !amend)
			author = committer;
		if (allowEmpty == null)
			// JGit allows empty commits by default. Only when pathes are
			// specified the commit should not be empty. This behaviour differs
			// from native git but can only be adapted in the next release.
			// TODO(ch) align the defaults with native git
			allowEmpty = (only.isEmpty()) ? Boolean.TRUE : Boolean.FALSE;

		// when doing a merge commit parse MERGE_HEAD and MERGE_MSG files
		if (state == RepositoryState.MERGING_RESOLVED
				|| isMergeDuringRebase(state)) {
			try {
				parents = repo.readMergeHeads();
				if (parents != null)
					for (int i = 0; i < parents.size(); i++) {
						RevObject ro = rw.parseAny(parents.get(i));
						if (ro instanceof RevTag)
							parents.set(i, rw.peel(ro));
					}
			} catch (IOException e) {
				throw new JGitInternalException(MessageFormat.format(
						JGitText.get().exceptionOccurredDuringReadingOfGIT_DIR,
						Constants.MERGE_HEAD, e), e);
			}
			if (message == null) {
				try {
					message = repo.readMergeCommitMsg();
				} catch (IOException e) {
					throw new JGitInternalException(MessageFormat.format(
							JGitText.get().exceptionOccurredDuringReadingOfGIT_DIR,
							Constants.MERGE_MSG, e), e);
				}
			}
		} else if (state == RepositoryState.SAFE && message == null) {
			try {
				message = repo.readSquashCommitMsg();
				if (message != null)
					repo.writeSquashCommitMsg(null /* delete */);
			} catch (IOException e) {
				throw new JGitInternalException(MessageFormat.format(
						JGitText.get().exceptionOccurredDuringReadingOfGIT_DIR,
						Constants.MERGE_MSG, e), e);
			}

		}
		if (message == null)
			// as long as we don't support -C option we have to have
			// an explicit message
			throw new NoMessageException(JGitText.get().commitMessageNotSpecified);

		GpgConfig gpgConfig = new GpgConfig(repo.getConfig());
		if (signCommit == null) {
			signCommit = gpgConfig.isSignCommits() ? Boolean.TRUE
					: Boolean.FALSE;
		}
		if (signingKey == null) {
			signingKey = gpgConfig.getSigningKey();
		}
		if (gpgSigner == null) {
			if (gpgConfig.getKeyFormat() != GpgFormat.OPENPGP) {
				throw new UnsupportedSigningFormatException(
						JGitText.get().onlyOpenPgpSupportedForSigning);
			}
			gpgSigner = GpgSigner.getDefault();
		}
	}

	private boolean isMergeDuringRebase(RepositoryState state) {
		if (state != RepositoryState.REBASING_INTERACTIVE
				&& state != RepositoryState.REBASING_MERGE)
			return false;
		try {
			return repo.readMergeHeads() != null;
		} catch (IOException e) {
			throw new JGitInternalException(MessageFormat.format(
					JGitText.get().exceptionOccurredDuringReadingOfGIT_DIR,
					Constants.MERGE_HEAD, e), e);
		}
	}

	/**
	 * Set the commit message
	 *
	 * @param message
	 *            the commit message used for the {@code commit}
	 * @return {@code this}
	 */
	public CommitCommand setMessage(String message) {
		checkCallable();
		this.message = message;
		return this;
	}

	/**
	 * Set whether to allow to create an empty commit
	 *
	 * @param allowEmpty
	 *            whether it should be allowed to create a commit which has the
	 *            same tree as it's sole predecessor (a commit which doesn't
	 *            change anything). By default when creating standard commits
	 *            (without specifying paths) JGit allows to create such commits.
	 *            When this flag is set to false an attempt to create an "empty"
	 *            standard commit will lead to an EmptyCommitException.
	 *            <p>
	 *            By default when creating a commit containing only specified
	 *            paths an attempt to create an empty commit leads to a
	 *            {@link org.eclipse.jgit.api.errors.JGitInternalException}. By
	 *            setting this flag to <code>true</code> this exception will not
	 *            be thrown.
	 * @return {@code this}
	 * @since 4.2
	 */
	public CommitCommand setAllowEmpty(boolean allowEmpty) {
		this.allowEmpty = Boolean.valueOf(allowEmpty);
		return this;
	}

	/**
	 * Get the commit message
	 *
	 * @return the commit message used for the <code>commit</code>
	 */
	public String getMessage() {
		return message;
	}

	/**
	 * Sets the committer for this {@code commit}. If no committer is explicitly
	 * specified because this method is never called or called with {@code null}
	 * value then the committer will be deduced from config info in repository,
	 * with current time.
	 *
	 * @param committer
	 *            the committer used for the {@code commit}
	 * @return {@code this}
	 */
	public CommitCommand setCommitter(PersonIdent committer) {
		checkCallable();
		this.committer = committer;
		return this;
	}

	/**
	 * Sets the committer for this {@code commit}. If no committer is explicitly
	 * specified because this method is never called then the committer will be
	 * deduced from config info in repository, with current time.
	 *
	 * @param name
	 *            the name of the committer used for the {@code commit}
	 * @param email
	 *            the email of the committer used for the {@code commit}
	 * @return {@code this}
	 */
	public CommitCommand setCommitter(String name, String email) {
		checkCallable();
		return setCommitter(new PersonIdent(name, email));
	}

	/**
	 * Get the committer
	 *
	 * @return the committer used for the {@code commit}. If no committer was
	 *         specified {@code null} is returned and the default
	 *         {@link org.eclipse.jgit.lib.PersonIdent} of this repo is used
	 *         during execution of the command
	 */
	public PersonIdent getCommitter() {
		return committer;
	}

	/**
	 * Sets the author for this {@code commit}. If no author is explicitly
	 * specified because this method is never called or called with {@code null}
	 * value then the author will be set to the committer or to the original
	 * author when amending.
	 *
	 * @param author
	 *            the author used for the {@code commit}
	 * @return {@code this}
	 */
	public CommitCommand setAuthor(PersonIdent author) {
		checkCallable();
		this.author = author;
		return this;
	}

	/**
	 * Sets the author for this {@code commit}. If no author is explicitly
	 * specified because this method is never called then the author will be set
	 * to the committer or to the original author when amending.
	 *
	 * @param name
	 *            the name of the author used for the {@code commit}
	 * @param email
	 *            the email of the author used for the {@code commit}
	 * @return {@code this}
	 */
	public CommitCommand setAuthor(String name, String email) {
		checkCallable();
		return setAuthor(new PersonIdent(name, email));
	}

	/**
	 * Get the author
	 *
	 * @return the author used for the {@code commit}. If no author was
	 *         specified {@code null} is returned and the default
	 *         {@link org.eclipse.jgit.lib.PersonIdent} of this repo is used
	 *         during execution of the command
	 */
	public PersonIdent getAuthor() {
		return author;
	}

	/**
	 * If set to true the Commit command automatically stages files that have
	 * been modified and deleted, but new files not known by the repository are
	 * not affected. This corresponds to the parameter -a on the command line.
	 *
	 * @param all
	 *            whether to auto-stage all files that have been modified and
	 *            deleted
	 * @return {@code this}
	 * @throws JGitInternalException
	 *             in case of an illegal combination of arguments/ options
	 */
	public CommitCommand setAll(boolean all) {
		checkCallable();
		if (all && !only.isEmpty())
			throw new JGitInternalException(MessageFormat.format(
					JGitText.get().illegalCombinationOfArguments, "--all", //$NON-NLS-1$
					"--only")); //$NON-NLS-1$
		this.all = all;
		return this;
	}

	/**
	 * Used to amend the tip of the current branch. If set to {@code true}, the
	 * previous commit will be amended. This is equivalent to --amend on the
	 * command line.
	 *
	 * @param amend
	 *            whether to ammend the tip of the current branch
	 * @return {@code this}
	 */
	public CommitCommand setAmend(boolean amend) {
		checkCallable();
		this.amend = amend;
		return this;
	}

	/**
	 * Commit dedicated path only.
	 * <p>
	 * This method can be called several times to add multiple paths. Full file
	 * paths are supported as well as directory paths; in the latter case this
	 * commits all files/directories below the specified path.
	 *
	 * @param only
	 *            path to commit (with <code>/</code> as separator)
	 * @return {@code this}
	 */
	public CommitCommand setOnly(String only) {
		checkCallable();
		if (all)
			throw new JGitInternalException(MessageFormat.format(
					JGitText.get().illegalCombinationOfArguments, "--only", //$NON-NLS-1$
					"--all")); //$NON-NLS-1$
		String o = only.endsWith("/") ? only.substring(0, only.length() - 1) //$NON-NLS-1$
				: only;
		// ignore duplicates
		if (!this.only.contains(o))
			this.only.add(o);
		return this;
	}

	/**
	 * If set to true a change id will be inserted into the commit message
	 *
	 * An existing change id is not replaced. An initial change id (I000...)
	 * will be replaced by the change id.
	 *
	 * @param insertChangeId
	 *            whether to insert a change id
	 * @return {@code this}
	 */
	public CommitCommand setInsertChangeId(boolean insertChangeId) {
		checkCallable();
		this.insertChangeId = insertChangeId;
		return this;
	}

	/**
	 * Override the message written to the reflog
	 *
	 * @param reflogComment
	 *            the comment to be written into the reflog or <code>null</code>
	 *            to specify that no reflog should be written
	 * @return {@code this}
	 */
	public CommitCommand setReflogComment(String reflogComment) {
		this.reflogComment = reflogComment;
		useDefaultReflogMessage = false;
		return this;
	}

	/**
	 * Sets the {@link #noVerify} option on this commit command.
	 * <p>
	 * Both the pre-commit and commit-msg hooks can block a commit by their
	 * return value; setting this option to <code>true</code> will bypass these
	 * two hooks.
	 * </p>
	 *
	 * @param noVerify
	 *            Whether this commit should be verified by the pre-commit and
	 *            commit-msg hooks.
	 * @return {@code this}
	 * @since 3.7
	 */
	public CommitCommand setNoVerify(boolean noVerify) {
		this.noVerify = noVerify;
		return this;
	}

	/**
	 * Set the output stream for all hook scripts executed by this command
	 * (pre-commit, commit-msg, post-commit). If not set it defaults to
	 * {@code System.out}.
	 *
	 * @param hookStdOut
	 *            the output stream for hook scripts executed by this command
	 * @return {@code this}
	 * @since 3.7
	 */
	public CommitCommand setHookOutputStream(PrintStream hookStdOut) {
		setHookOutputStream(PreCommitHook.NAME, hookStdOut);
		setHookOutputStream(CommitMsgHook.NAME, hookStdOut);
		setHookOutputStream(PostCommitHook.NAME, hookStdOut);
		return this;
	}

	/**
	 * Set the error stream for all hook scripts executed by this command
	 * (pre-commit, commit-msg, post-commit). If not set it defaults to
	 * {@code System.err}.
	 *
	 * @param hookStdErr
	 *            the error stream for hook scripts executed by this command
	 * @return {@code this}
	 * @since 5.6
	 */
	public CommitCommand setHookErrorStream(PrintStream hookStdErr) {
		setHookErrorStream(PreCommitHook.NAME, hookStdErr);
		setHookErrorStream(CommitMsgHook.NAME, hookStdErr);
		setHookErrorStream(PostCommitHook.NAME, hookStdErr);
		return this;
	}

	/**
	 * Set the output stream for a selected hook script executed by this command
	 * (pre-commit, commit-msg, post-commit). If not set it defaults to
	 * {@code System.out}.
	 *
	 * @param hookName
	 *            name of the hook to set the output stream for
	 * @param hookStdOut
	 *            the output stream to use for the selected hook
	 * @return {@code this}
	 * @since 4.5
	 */
	public CommitCommand setHookOutputStream(String hookName,
			PrintStream hookStdOut) {
		if (!(PreCommitHook.NAME.equals(hookName)
				|| CommitMsgHook.NAME.equals(hookName)
				|| PostCommitHook.NAME.equals(hookName))) {
			throw new IllegalArgumentException(
					MessageFormat.format(JGitText.get().illegalHookName,
							hookName));
		}
		hookOutRedirect.put(hookName, hookStdOut);
		return this;
	}

	/**
	 * Set the error stream for a selected hook script executed by this command
	 * (pre-commit, commit-msg, post-commit). If not set it defaults to
	 * {@code System.err}.
	 *
	 * @param hookName
	 *            name of the hook to set the output stream for
	 * @param hookStdErr
	 *            the output stream to use for the selected hook
	 * @return {@code this}
	 * @since 5.6
	 */
	public CommitCommand setHookErrorStream(String hookName,
			PrintStream hookStdErr) {
		if (!(PreCommitHook.NAME.equals(hookName)
				|| CommitMsgHook.NAME.equals(hookName)
				|| PostCommitHook.NAME.equals(hookName))) {
			throw new IllegalArgumentException(MessageFormat
					.format(JGitText.get().illegalHookName, hookName));
		}
		hookErrRedirect.put(hookName, hookStdErr);
		return this;
	}

	/**
	 * Sets the signing key
	 * <p>
	 * Per spec of user.signingKey: this will be sent to the GPG program as is,
	 * i.e. can be anything supported by the GPG program.
	 * </p>
	 * <p>
	 * Note, if none was set or <code>null</code> is specified a default will be
	 * obtained from the configuration.
	 * </p>
	 *
	 * @param signingKey
	 *            signing key (maybe <code>null</code>)
	 * @return {@code this}
	 * @since 5.3
	 */
	public CommitCommand setSigningKey(String signingKey) {
		checkCallable();
		this.signingKey = signingKey;
		return this;
	}

	/**
	 * Sets whether the commit should be signed.
	 *
	 * @param sign
	 *            <code>true</code> to sign, <code>false</code> to not sign and
	 *            <code>null</code> for default behavior (read from
	 *            configuration)
	 * @return {@code this}
	 * @since 5.3
	 */
	public CommitCommand setSign(Boolean sign) {
		checkCallable();
		this.signCommit = sign;
		return this;
	}

	/**
	 * Sets a {@link CredentialsProvider}
	 *
	 * @param credentialsProvider
	 *            the provider to use when querying for credentials (eg., during
	 *            signing)
	 * @since 5.3
	 */
	public void setCredentialsProvider(
			CredentialsProvider credentialsProvider) {
		this.credentialsProvider = credentialsProvider;
	}
}
