/*
 * Copyright (C) 2014, Google Inc. 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.gitrepo;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
import static org.eclipse.jgit.lib.Constants.R_REMOTES;
import static org.eclipse.jgit.lib.Constants.R_TAGS;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.TreeMap;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.GitCommand;
import org.eclipse.jgit.api.SubmoduleAddCommand;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
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.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.gitrepo.ManifestParser.IncludedFileReader;
import org.eclipse.jgit.gitrepo.RepoProject.CopyFile;
import org.eclipse.jgit.gitrepo.RepoProject.LinkFile;
import org.eclipse.jgit.gitrepo.internal.RepoText;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
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.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FileUtils;

/**
 * A class used to execute a repo command.
 *
 * This will parse a repo XML manifest, convert it into .gitmodules file and the
 * repository config file.
 *
 * If called against a bare repository, it will replace all the existing content
 * of the repository with the contents populated from the manifest.
 *
 * repo manifest allows projects overlapping, e.g. one project's manifestPath is
 * &quot;foo&quot; and another project's manifestPath is &quot;foo/bar&quot;. This won't
 * work in git submodule, so we'll skip all the sub projects
 * (&quot;foo/bar&quot; in the example) while converting.
 *
 * @see <a href="https://code.google.com/p/git-repo/">git-repo project page</a>
 * @since 3.4
 */
public class RepoCommand extends GitCommand<RevCommit> {
	private static final int LOCK_FAILURE_MAX_RETRIES = 5;

	// Retry exponentially with delays in this range
	private static final int LOCK_FAILURE_MIN_RETRY_DELAY_MILLIS = 50;

	private static final int LOCK_FAILURE_MAX_RETRY_DELAY_MILLIS = 5000;

	private String manifestPath;
	private String baseUri;
	private URI targetUri;
	private String groupsParam;
	private String branch;
	private String targetBranch = Constants.HEAD;
	private boolean recordRemoteBranch = true;
	private boolean recordSubmoduleLabels = true;
	private boolean recordShallowSubmodules = true;
	private PersonIdent author;
	private RemoteReader callback;
	private InputStream inputStream;
	private IncludedFileReader includedReader;
	private boolean ignoreRemoteFailures = false;

	private ProgressMonitor monitor;

	/**
	 * A callback to get ref sha1 of a repository from its uri.
	 *
	 * We provided a default implementation {@link DefaultRemoteReader} to
	 * use ls-remote command to read the sha1 from the repository and clone the
	 * repository to read the file. Callers may have their own quicker
	 * implementation.
	 *
	 * @since 3.4
	 */
	public interface RemoteReader {
		/**
		 * Read a remote ref sha1.
		 *
		 * @param uri
		 *            The URI of the remote repository
		 * @param ref
		 *            Name of the ref to lookup. May be a short-hand form, e.g.
		 *            "master" which is automatically expanded to
		 *            "refs/heads/master" if "refs/heads/master" already exists.
		 * @return the sha1 of the remote repository, or null if the ref does
		 *         not exist.
		 * @throws GitAPIException
		 */
		@Nullable
		public ObjectId sha1(String uri, String ref) throws GitAPIException;

		/**
		 * Read a file from a remote repository.
		 *
		 * @param uri
		 *            The URI of the remote repository
		 * @param ref
		 *            The ref (branch/tag/etc.) to read
		 * @param path
		 *            The relative path (inside the repo) to the file to read
		 * @return the file content.
		 * @throws GitAPIException
		 * @throws IOException
		 * @since 3.5
		 *
		 * @deprecated Use {@link #readFileWithMode(String, String, String)}
		 *             instead
		 */
		@Deprecated
		public default byte[] readFile(String uri, String ref, String path)
				throws GitAPIException, IOException {
			return readFileWithMode(uri, ref, path).getContents();
		}

		/**
		 * Read contents and mode (i.e. permissions) of the file from a remote
		 * repository.
		 *
		 * @param uri
		 *            The URI of the remote repository
		 * @param ref
		 *            Name of the ref to lookup. May be a short-hand form, e.g.
		 *            "master" which is automatically expanded to
		 *            "refs/heads/master" if "refs/heads/master" already exists.
		 * @param path
		 *            The relative path (inside the repo) to the file to read
		 * @return The contents and file mode of the file in the given
		 *         repository and branch. Never null.
		 * @throws GitAPIException
		 *             If the ref have an invalid or ambiguous name, or it does
		 *             not exist in the repository,
		 * @throws IOException
		 *             If the object does not exist or is too large
		 * @since 5.2
		 */
		@NonNull
		public RemoteFile readFileWithMode(String uri, String ref, String path)
				throws GitAPIException, IOException;
	}

	/**
	 * Read-only view of contents and file mode (i.e. permissions) for a file in
	 * a remote repository.
	 *
	 * @since 5.2
	 */
	public static final class RemoteFile {
		@NonNull
		private final byte[] contents;

		@NonNull
		private final FileMode fileMode;

		/**
		 * @param contents
		 *            Raw contents of the file.
		 * @param fileMode
		 *            Git file mode for this file (e.g. executable or regular)
		 */
		public RemoteFile(@NonNull byte[] contents,
				@NonNull FileMode fileMode) {
			this.contents = Objects.requireNonNull(contents);
			this.fileMode = Objects.requireNonNull(fileMode);
		}

		/**
		 * Contents of the file.
		 * <p>
		 * Callers who receive this reference must not modify its contents (as
		 * it can point to internal cached data).
		 *
		 * @return Raw contents of the file. Do not modify it.
		 */
		@NonNull
		public byte[] getContents() {
			return contents;
		}

		/**
		 * @return Git file mode for this file (e.g. executable or regular)
		 */
		@NonNull
		public FileMode getFileMode() {
			return fileMode;
		}

	}

	/** A default implementation of {@link RemoteReader} callback. */
	public static class DefaultRemoteReader implements RemoteReader {

		@Override
		public ObjectId sha1(String uri, String ref) throws GitAPIException {
			Map<String, Ref> map = Git
					.lsRemoteRepository()
					.setRemote(uri)
					.callAsMap();
			Ref r = RefDatabase.findRef(map, ref);
			return r != null ? r.getObjectId() : null;
		}

		@Override
		public RemoteFile readFileWithMode(String uri, String ref, String path)
				throws GitAPIException, IOException {
			File dir = FileUtils.createTempDir("jgit_", ".git", null); //$NON-NLS-1$ //$NON-NLS-2$
			try (Git git = Git.cloneRepository().setBare(true).setDirectory(dir)
					.setURI(uri).call()) {
				Repository repo = git.getRepository();
				ObjectId refCommitId = sha1(uri, ref);
				if (refCommitId == null) {
					throw new InvalidRefNameException(MessageFormat
							.format(JGitText.get().refNotResolved, ref));
				}
				RevCommit commit = repo.parseCommit(refCommitId);
				TreeWalk tw = TreeWalk.forPath(repo, path, commit.getTree());

				// TODO(ifrade): Cope better with big files (e.g. using
				// InputStream instead of byte[])
				return new RemoteFile(
						tw.getObjectReader().open(tw.getObjectId(0))
								.getCachedBytes(Integer.MAX_VALUE),
						tw.getFileMode(0));
			} finally {
				FileUtils.delete(dir, FileUtils.RECURSIVE);
			}
		}
	}

	@SuppressWarnings("serial")
	private static class ManifestErrorException extends GitAPIException {
		ManifestErrorException(Throwable cause) {
			super(RepoText.get().invalidManifest, cause);
		}
	}

	@SuppressWarnings("serial")
	private static class RemoteUnavailableException extends GitAPIException {
		RemoteUnavailableException(String uri) {
			super(MessageFormat.format(RepoText.get().errorRemoteUnavailable, uri));
		}
	}

	/**
	 * Constructor for RepoCommand
	 *
	 * @param repo
	 *            the {@link org.eclipse.jgit.lib.Repository}
	 */
	public RepoCommand(Repository repo) {
		super(repo);
	}

	/**
	 * Set path to the manifest XML file.
	 * <p>
	 * Calling {@link #setInputStream} will ignore the path set here.
	 *
	 * @param path
	 *            (with <code>/</code> as separator)
	 * @return this command
	 */
	public RepoCommand setPath(String path) {
		this.manifestPath = path;
		return this;
	}

	/**
	 * Set the input stream to the manifest XML.
	 * <p>
	 * Setting inputStream will ignore the path set. It will be closed in
	 * {@link #call}.
	 *
	 * @param inputStream a {@link java.io.InputStream} object.
	 * @return this command
	 * @since 3.5
	 */
	public RepoCommand setInputStream(InputStream inputStream) {
		this.inputStream = inputStream;
		return this;
	}

	/**
	 * Set base URI of the paths inside the XML. This is typically the name of
	 * the directory holding the manifest repository, eg. for
	 * https://android.googlesource.com/platform/manifest, this should be
	 * /platform (if you would run this on android.googlesource.com) or
	 * https://android.googlesource.com/platform elsewhere.
	 *
	 * @param uri
	 *            the base URI
	 * @return this command
	 */
	public RepoCommand setURI(String uri) {
		this.baseUri = uri;
		return this;
	}

	/**
	 * Set the URI of the superproject (this repository), so the .gitmodules
	 * file can specify the submodule URLs relative to the superproject.
	 *
	 * @param uri
	 *            the URI of the repository holding the superproject.
	 * @return this command
	 * @since 4.8
	 */
	public RepoCommand setTargetURI(String uri) {
		// The repo name is interpreted as a directory, for example
		// Gerrit (http://gerrit.googlesource.com/gerrit) has a
		// .gitmodules referencing ../plugins/hooks, which is
		// on http://gerrit.googlesource.com/plugins/hooks,
		this.targetUri = URI.create(uri + "/"); //$NON-NLS-1$
		return this;
	}

	/**
	 * Set groups to sync
	 *
	 * @param groups groups separated by comma, examples: default|all|G1,-G2,-G3
	 * @return this command
	 */
	public RepoCommand setGroups(String groups) {
		this.groupsParam = groups;
		return this;
	}

	/**
	 * Set default branch.
	 * <p>
	 * This is generally the name of the branch the manifest file was in. If
	 * there's no default revision (branch) specified in manifest and no
	 * revision specified in project, this branch will be used.
	 *
	 * @param branch
	 *            a branch name
	 * @return this command
	 */
	public RepoCommand setBranch(String branch) {
		this.branch = branch;
		return this;
	}

	/**
	 * Set target branch.
	 * <p>
	 * This is the target branch of the super project to be updated. If not set,
	 * default is HEAD.
	 * <p>
	 * For non-bare repositories, HEAD will always be used and this will be
	 * ignored.
	 *
	 * @param branch
	 *            branch name
	 * @return this command
	 * @since 4.1
	 */
	public RepoCommand setTargetBranch(String branch) {
		this.targetBranch = Constants.R_HEADS + branch;
		return this;
	}

	/**
	 * Set whether the branch name should be recorded in .gitmodules.
	 * <p>
	 * Submodule entries in .gitmodules can include a "branch" field
	 * to indicate what remote branch each submodule tracks.
	 * <p>
	 * That field is used by "git submodule update --remote" to update
	 * to the tip of the tracked branch when asked and by Gerrit to
	 * update the superproject when a change on that branch is merged.
	 * <p>
	 * Subprojects that request a specific commit or tag will not have
	 * a branch name recorded.
	 * <p>
	 * Not implemented for non-bare repositories.
	 *
	 * @param enable Whether to record the branch name
	 * @return this command
	 * @since 4.2
	 */
	public RepoCommand setRecordRemoteBranch(boolean enable) {
		this.recordRemoteBranch = enable;
		return this;
	}

	/**
	 * Set whether the labels field should be recorded as a label in
	 * .gitattributes.
	 * <p>
	 * Not implemented for non-bare repositories.
	 *
	 * @param enable Whether to record the labels in the .gitattributes
	 * @return this command
	 * @since 4.4
	 */
	public RepoCommand setRecordSubmoduleLabels(boolean enable) {
		this.recordSubmoduleLabels = enable;
		return this;
	}

	/**
	 * Set whether the clone-depth field should be recorded as a shallow
	 * recommendation in .gitmodules.
	 * <p>
	 * Not implemented for non-bare repositories.
	 *
	 * @param enable Whether to record the shallow recommendation.
	 * @return this command
	 * @since 4.4
	 */
	public RepoCommand setRecommendShallow(boolean enable) {
		this.recordShallowSubmodules = enable;
		return this;
	}

	/**
	 * The progress monitor associated with the clone operation. By default,
	 * this is set to <code>NullProgressMonitor</code>
	 *
	 * @see org.eclipse.jgit.lib.NullProgressMonitor
	 * @param monitor
	 *            a {@link org.eclipse.jgit.lib.ProgressMonitor}
	 * @return this command
	 */
	public RepoCommand setProgressMonitor(ProgressMonitor monitor) {
		this.monitor = monitor;
		return this;
	}

	/**
	 * Set whether to skip projects whose commits don't exist remotely.
	 * <p>
	 * When set to true, we'll just skip the manifest entry and continue
	 * on to the next one.
	 * <p>
	 * When set to false (default), we'll throw an error when remote
	 * failures occur.
	 * <p>
	 * Not implemented for non-bare repositories.
	 *
	 * @param ignore Whether to ignore the remote failures.
	 * @return this command
	 * @since 4.3
	 */
	public RepoCommand setIgnoreRemoteFailures(boolean ignore) {
		this.ignoreRemoteFailures = ignore;
		return this;
	}

	/**
	 * Set the author/committer for the bare repository commit.
	 * <p>
	 * For non-bare repositories, the current user will be used and this will be
	 * ignored.
	 *
	 * @param author
	 *            the author's {@link org.eclipse.jgit.lib.PersonIdent}
	 * @return this command
	 */
	public RepoCommand setAuthor(PersonIdent author) {
		this.author = author;
		return this;
	}

	/**
	 * Set the GetHeadFromUri callback.
	 *
	 * This is only used in bare repositories.
	 *
	 * @param callback
	 *            a {@link org.eclipse.jgit.gitrepo.RepoCommand.RemoteReader}
	 *            object.
	 * @return this command
	 */
	public RepoCommand setRemoteReader(RemoteReader callback) {
		this.callback = callback;
		return this;
	}

	/**
	 * Set the IncludedFileReader callback.
	 *
	 * @param reader
	 *            a
	 *            {@link org.eclipse.jgit.gitrepo.ManifestParser.IncludedFileReader}
	 *            object.
	 * @return this command
	 * @since 4.0
	 */
	public RepoCommand setIncludedFileReader(IncludedFileReader reader) {
		this.includedReader = reader;
		return this;
	}

	/** {@inheritDoc} */
	@Override
	public RevCommit call() throws GitAPIException {
		checkCallable();
		if (baseUri == null) {
			baseUri = ""; //$NON-NLS-1$
		}
		if (inputStream == null) {
			if (manifestPath == null || manifestPath.length() == 0)
				throw new IllegalArgumentException(
						JGitText.get().pathNotConfigured);
			try {
				inputStream = new FileInputStream(manifestPath);
			} catch (IOException e) {
				throw new IllegalArgumentException(
						JGitText.get().pathNotConfigured, e);
			}
		}

		List<RepoProject> filteredProjects;
		try {
			ManifestParser parser = new ManifestParser(includedReader,
					manifestPath, branch, baseUri, groupsParam, repo);
			parser.read(inputStream);
			filteredProjects = parser.getFilteredProjects();
		} catch (IOException e) {
			throw new ManifestErrorException(e);
		} finally {
			try {
				inputStream.close();
			} catch (IOException e) {
				// Just ignore it, it's not important.
			}
		}

		if (repo.isBare()) {
			if (author == null)
				author = new PersonIdent(repo);
			if (callback == null)
				callback = new DefaultRemoteReader();
			List<RepoProject> renamedProjects = renameProjects(filteredProjects);

			DirCache index = DirCache.newInCore();
			ObjectInserter inserter = repo.newObjectInserter();
			try (RevWalk rw = new RevWalk(repo)) {
				prepareIndex(renamedProjects, index, inserter);
				ObjectId treeId = index.writeTree(inserter);

				long prevDelay = 0;
				for (int i = 0; i < LOCK_FAILURE_MAX_RETRIES - 1; i++) {
					try {
						return commitTreeOnCurrentTip(
							inserter, rw, treeId);
					} catch (ConcurrentRefUpdateException e) {
						prevDelay = FileUtils.delay(prevDelay,
								LOCK_FAILURE_MIN_RETRY_DELAY_MILLIS,
								LOCK_FAILURE_MAX_RETRY_DELAY_MILLIS);
						Thread.sleep(prevDelay);
						repo.getRefDatabase().refresh();
					}
				}
				// In the last try, just propagate the exceptions
				return commitTreeOnCurrentTip(inserter, rw, treeId);
			} catch (GitAPIException | IOException | InterruptedException e) {
				throw new ManifestErrorException(e);
			}
		}
		try (Git git = new Git(repo)) {
			for (RepoProject proj : filteredProjects) {
				addSubmodule(proj.getName(), proj.getUrl(), proj.getPath(),
						proj.getRevision(), proj.getCopyFiles(),
						proj.getLinkFiles(), git);
			}
			return git.commit().setMessage(RepoText.get().repoCommitMessage)
					.call();
		} catch (GitAPIException | IOException e) {
			throw new ManifestErrorException(e);
		}
	}


	private void prepareIndex(List<RepoProject> projects, DirCache index,
			ObjectInserter inserter) throws IOException, GitAPIException {
		Config cfg = new Config();
		StringBuilder attributes = new StringBuilder();
		DirCacheBuilder builder = index.builder();
		for (RepoProject proj : projects) {
			String name = proj.getName();
			String path = proj.getPath();
			String url = proj.getUrl();
			ObjectId objectId;
			if (ObjectId.isId(proj.getRevision())) {
				objectId = ObjectId.fromString(proj.getRevision());
			} else {
				objectId = callback.sha1(url, proj.getRevision());
				if (objectId == null && !ignoreRemoteFailures) {
					throw new RemoteUnavailableException(url);
				}
				if (recordRemoteBranch) {
					// "branch" field is only for non-tag references.
					// Keep tags in "ref" field as hint for other tools.
					String field = proj.getRevision().startsWith(R_TAGS) ? "ref" //$NON-NLS-1$
							: "branch"; //$NON-NLS-1$
					cfg.setString("submodule", name, field, //$NON-NLS-1$
							proj.getRevision());
				}

				if (recordShallowSubmodules
						&& proj.getRecommendShallow() != null) {
					// The shallow recommendation is losing information.
					// As the repo manifests stores the recommended
					// depth in the 'clone-depth' field, while
					// git core only uses a binary 'shallow = true/false'
					// hint, we'll map any depth to 'shallow = true'
					cfg.setBoolean("submodule", name, "shallow", //$NON-NLS-1$ //$NON-NLS-2$
							true);
				}
			}
			if (recordSubmoduleLabels) {
				StringBuilder rec = new StringBuilder();
				rec.append("/"); //$NON-NLS-1$
				rec.append(path);
				for (String group : proj.getGroups()) {
					rec.append(" "); //$NON-NLS-1$
					rec.append(group);
				}
				rec.append("\n"); //$NON-NLS-1$
				attributes.append(rec.toString());
			}

			URI submodUrl = URI.create(url);
			if (targetUri != null) {
				submodUrl = relativize(targetUri, submodUrl);
			}
			cfg.setString("submodule", name, "path", path); //$NON-NLS-1$ //$NON-NLS-2$
			cfg.setString("submodule", name, "url", //$NON-NLS-1$ //$NON-NLS-2$
					submodUrl.toString());

			// create gitlink
			if (objectId != null) {
				DirCacheEntry dcEntry = new DirCacheEntry(path);
				dcEntry.setObjectId(objectId);
				dcEntry.setFileMode(FileMode.GITLINK);
				builder.add(dcEntry);

				for (CopyFile copyfile : proj.getCopyFiles()) {
					RemoteFile rf = callback.readFileWithMode(url,
							proj.getRevision(), copyfile.src);
					objectId = inserter.insert(Constants.OBJ_BLOB,
							rf.getContents());
					dcEntry = new DirCacheEntry(copyfile.dest);
					dcEntry.setObjectId(objectId);
					dcEntry.setFileMode(rf.getFileMode());
					builder.add(dcEntry);
				}
				for (LinkFile linkfile : proj.getLinkFiles()) {
					String link;
					if (linkfile.dest.contains("/")) { //$NON-NLS-1$
						link = FileUtils.relativizeGitPath(
								linkfile.dest.substring(0,
										linkfile.dest.lastIndexOf('/')),
								proj.getPath() + "/" + linkfile.src); //$NON-NLS-1$
					} else {
						link = proj.getPath() + "/" + linkfile.src; //$NON-NLS-1$
					}

					objectId = inserter.insert(Constants.OBJ_BLOB,
							link.getBytes(UTF_8));
					dcEntry = new DirCacheEntry(linkfile.dest);
					dcEntry.setObjectId(objectId);
					dcEntry.setFileMode(FileMode.SYMLINK);
					builder.add(dcEntry);
				}
			}
		}
		String content = cfg.toText();

		// create a new DirCacheEntry for .gitmodules file.
		DirCacheEntry dcEntry = new DirCacheEntry(
				Constants.DOT_GIT_MODULES);
		ObjectId objectId = inserter.insert(Constants.OBJ_BLOB,
				content.getBytes(UTF_8));
		dcEntry.setObjectId(objectId);
		dcEntry.setFileMode(FileMode.REGULAR_FILE);
		builder.add(dcEntry);

		if (recordSubmoduleLabels) {
			// create a new DirCacheEntry for .gitattributes file.
			DirCacheEntry dcEntryAttr = new DirCacheEntry(
					Constants.DOT_GIT_ATTRIBUTES);
			ObjectId attrId = inserter.insert(Constants.OBJ_BLOB,
					attributes.toString().getBytes(UTF_8));
			dcEntryAttr.setObjectId(attrId);
			dcEntryAttr.setFileMode(FileMode.REGULAR_FILE);
			builder.add(dcEntryAttr);
		}

		builder.finish();
	}

	private RevCommit commitTreeOnCurrentTip(ObjectInserter inserter,
			RevWalk rw, ObjectId treeId)
			throws IOException, ConcurrentRefUpdateException {
		ObjectId headId = repo.resolve(targetBranch + "^{commit}"); //$NON-NLS-1$
		if (headId != null && rw.parseCommit(headId).getTree().getId().equals(treeId)) {
			// No change. Do nothing.
			return rw.parseCommit(headId);
		}

		CommitBuilder commit = new CommitBuilder();
		commit.setTreeId(treeId);
		if (headId != null)
			commit.setParentIds(headId);
		commit.setAuthor(author);
		commit.setCommitter(author);
		commit.setMessage(RepoText.get().repoCommitMessage);

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

		RefUpdate ru = repo.updateRef(targetBranch);
		ru.setNewObjectId(commitId);
		ru.setExpectedOldObjectId(headId != null ? headId : ObjectId.zeroId());
		Result rc = ru.update(rw);
		switch (rc) {
			case NEW:
			case FORCED:
			case FAST_FORWARD:
				// Successful. Do nothing.
				break;
			case REJECTED:
			case LOCK_FAILURE:
				throw new ConcurrentRefUpdateException(MessageFormat
						.format(JGitText.get().cannotLock, targetBranch),
						ru.getRef(), rc);
			default:
				throw new JGitInternalException(MessageFormat.format(
						JGitText.get().updatingRefFailed,
						targetBranch, commitId.name(), rc));
		}

		return rw.parseCommit(commitId);
	}

	private void addSubmodule(String name, String url, String path,
			String revision, List<CopyFile> copyfiles, List<LinkFile> linkfiles,
			Git git) throws GitAPIException, IOException {
		assert (!repo.isBare());
		assert (git != null);
		if (!linkfiles.isEmpty()) {
			throw new UnsupportedOperationException(
					JGitText.get().nonBareLinkFilesNotSupported);
		}

		SubmoduleAddCommand add = git.submoduleAdd().setName(name).setPath(path)
				.setURI(url);
		if (monitor != null)
			add.setProgressMonitor(monitor);

		Repository subRepo = add.call();
		if (revision != null) {
			try (Git sub = new Git(subRepo)) {
				sub.checkout().setName(findRef(revision, subRepo)).call();
			}
			subRepo.close();
			git.add().addFilepattern(path).call();
		}
		for (CopyFile copyfile : copyfiles) {
			copyfile.copy();
			git.add().addFilepattern(copyfile.dest).call();
		}
	}

	/**
	 * Rename the projects if there's a conflict when converted to submodules.
	 *
	 * @param projects
	 *            parsed projects
	 * @return projects that are renamed if necessary
	 */
	private List<RepoProject> renameProjects(List<RepoProject> projects) {
		Map<String, List<RepoProject>> m = new TreeMap<>();
		for (RepoProject proj : projects) {
			List<RepoProject> l = m.get(proj.getName());
			if (l == null) {
				l = new ArrayList<>();
				m.put(proj.getName(), l);
			}
			l.add(proj);
		}

		List<RepoProject> ret = new ArrayList<>();
		for (List<RepoProject> ps : m.values()) {
			boolean nameConflict = ps.size() != 1;
			for (RepoProject proj : ps) {
				String name = proj.getName();
				if (nameConflict) {
					name += SLASH + proj.getPath();
				}
				RepoProject p = new RepoProject(name,
						proj.getPath(), proj.getRevision(), null,
						proj.getGroups(), proj.getRecommendShallow());
				p.setUrl(proj.getUrl());
				p.addCopyFiles(proj.getCopyFiles());
				p.addLinkFiles(proj.getLinkFiles());
				ret.add(p);
			}
		}
		return ret;
	}

	/*
	 * Assume we are document "a/b/index.html", what should we put in a href to get to "a/" ?
	 * Returns the child if either base or child is not a bare path. This provides a missing feature in
	 * java.net.URI (see http://bugs.java.com/view_bug.do?bug_id=6226081).
	 */
	private static final String SLASH = "/"; //$NON-NLS-1$
	static URI relativize(URI current, URI target) {
		if (!Objects.equals(current.getHost(), target.getHost())) {
			return target;
		}

		String cur = current.normalize().getPath();
		String dest = target.normalize().getPath();

		// TODO(hanwen): maybe (absolute, relative) should throw an exception.
		if (cur.startsWith(SLASH) != dest.startsWith(SLASH)) {
			return target;
		}

		while (cur.startsWith(SLASH)) {
			cur = cur.substring(1);
		}
		while (dest.startsWith(SLASH)) {
			dest = dest.substring(1);
		}

		if (cur.indexOf('/') == -1 || dest.indexOf('/') == -1) {
			// Avoid having to special-casing in the next two ifs.
			String prefix = "prefix/"; //$NON-NLS-1$
			cur = prefix + cur;
			dest = prefix + dest;
		}

		if (!cur.endsWith(SLASH)) {
			// The current file doesn't matter.
			int lastSlash = cur.lastIndexOf('/');
			cur = cur.substring(0, lastSlash);
		}
		String destFile = ""; //$NON-NLS-1$
		if (!dest.endsWith(SLASH)) {
			// We always have to provide the destination file.
			int lastSlash = dest.lastIndexOf('/');
			destFile = dest.substring(lastSlash + 1, dest.length());
			dest = dest.substring(0, dest.lastIndexOf('/'));
		}

		String[] cs = cur.split(SLASH);
		String[] ds = dest.split(SLASH);

		int common = 0;
		while (common < cs.length && common < ds.length && cs[common].equals(ds[common])) {
			common++;
		}

		StringJoiner j = new StringJoiner(SLASH);
		for (int i = common; i < cs.length; i++) {
			j.add(".."); //$NON-NLS-1$
		}
		for (int i = common; i < ds.length; i++) {
			j.add(ds[i]);
		}

		j.add(destFile);
		return URI.create(j.toString());
	}

	private static String findRef(String ref, Repository repo)
			throws IOException {
		if (!ObjectId.isId(ref)) {
			Ref r = repo.exactRef(R_REMOTES + DEFAULT_REMOTE_NAME + "/" + ref); //$NON-NLS-1$
			if (r != null)
				return r.getName();
		}
		return ref;
	}
}
