/*
 * 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();
			DirCacheBuilder builder = index.builder();
			ObjectInserter inserter = repo.newObjectInserter();
			try (RevWalk rw = new RevWalk(repo)) {
				Config cfg = new Config();
				StringBuilder attributes = new StringBuilder();
				for (RepoProject proj : renamedProjects) {
					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" : "branch"; //$NON-NLS-1$ //$NON-NLS-2$
							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.
				final 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.
					final 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();
				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 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;
	}
}
