/*
 * Copyright (C) 2009-2010, 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.junit;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
import org.eclipse.jgit.dircache.DirCacheEditor.DeleteTree;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.ObjectWritingException;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.internal.storage.file.LockFile;
import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
import org.eclipse.jgit.internal.storage.file.Pack;
import org.eclipse.jgit.internal.storage.file.PackFile;
import org.eclipse.jgit.internal.storage.file.PackIndex.MutableEntry;
import org.eclipse.jgit.internal.storage.pack.PackExt;
import org.eclipse.jgit.internal.storage.pack.PackWriter;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectChecker;
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.RefWriter;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TagBuilder;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.ThreeWayMerger;
import org.eclipse.jgit.revwalk.ObjectWalk;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
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;
import org.eclipse.jgit.util.ChangeIdUtil;
import org.eclipse.jgit.util.FileUtils;

/**
 * Wrapper to make creating test data easier.
 *
 * @param <R>
 *            type of Repository the test data is stored on.
 */
public class TestRepository<R extends Repository> implements AutoCloseable {

	/** Constant <code>AUTHOR="J. Author"</code> */
	public static final String AUTHOR = "J. Author";

	/** Constant <code>AUTHOR_EMAIL="jauthor@example.com"</code> */
	public static final String AUTHOR_EMAIL = "jauthor@example.com";

	/** Constant <code>COMMITTER="J. Committer"</code> */
	public static final String COMMITTER = "J. Committer";

	/** Constant <code>COMMITTER_EMAIL="jcommitter@example.com"</code> */
	public static final String COMMITTER_EMAIL = "jcommitter@example.com";

	private final PersonIdent defaultAuthor;

	private final PersonIdent defaultCommitter;

	private final R db;

	private final Git git;

	private final RevWalk pool;

	private final ObjectInserter inserter;

	private final MockSystemReader mockSystemReader;

	/**
	 * Wrap a repository with test building tools.
	 *
	 * @param db
	 *            the test repository to write into.
	 * @throws IOException
	 *             if an IO error occurred
	 */
	public TestRepository(R db) throws IOException {
		this(db, new RevWalk(db), new MockSystemReader());
	}

	/**
	 * Wrap a repository with test building tools.
	 *
	 * @param db
	 *            the test repository to write into.
	 * @param rw
	 *            the RevObject pool to use for object lookup.
	 * @throws IOException
	 *             if an IO error occurred
	 */
	public TestRepository(R db, RevWalk rw) throws IOException {
		this(db, rw, new MockSystemReader());
	}

	/**
	 * Wrap a repository with test building tools.
	 *
	 * @param db
	 *            the test repository to write into.
	 * @param rw
	 *            the RevObject pool to use for object lookup.
	 * @param reader
	 *            the MockSystemReader to use for clock and other system
	 *            operations.
	 * @throws IOException
	 *             if an IO error occurred
	 * @since 4.2
	 */
	public TestRepository(R db, RevWalk rw, MockSystemReader reader)
			throws IOException {
		this.db = db;
		this.git = Git.wrap(db);
		this.pool = rw;
		this.inserter = db.newObjectInserter();
		this.mockSystemReader = reader;
		long now = mockSystemReader.getCurrentTime();
		int tz = mockSystemReader.getTimezone(now);
		defaultAuthor = new PersonIdent(AUTHOR, AUTHOR_EMAIL, now, tz);
		defaultCommitter = new PersonIdent(COMMITTER, COMMITTER_EMAIL, now, tz);
	}

	/**
	 * Get repository
	 *
	 * @return the repository this helper class operates against.
	 */
	public R getRepository() {
		return db;
	}

	/**
	 * Get RevWalk
	 *
	 * @return get the RevWalk pool all objects are allocated through.
	 */
	public RevWalk getRevWalk() {
		return pool;
	}

	/**
	 * Return Git API wrapper
	 *
	 * @return an API wrapper for the underlying repository. This wrapper does
	 *         not allocate any new resources and need not be closed (but
	 *         closing it is harmless).
	 */
	public Git git() {
		return git;
	}

	/**
	 * Get date
	 *
	 * @return current date.
	 * @since 4.2
	 */
	public Date getDate() {
		return new Date(mockSystemReader.getCurrentTime());
	}

	/**
	 * Get instant
	 *
	 * @return current instant.
	 * @since 6.8
	 */
	public Instant getInstant() {
		return Instant.ofEpochMilli(mockSystemReader.getCurrentTime());
	}

	/**
	 * Get timezone
	 *
	 * @return timezone used for default identities.
	 */
	public TimeZone getTimeZone() {
		return mockSystemReader.getTimeZone();
	}

	/**
	 * Adjust the current time that will used by the next commit.
	 *
	 * @param secDelta
	 *            number of seconds to add to the current time.
	 */
	public void tick(int secDelta) {
		mockSystemReader.tick(secDelta);
	}

	/**
	 * Set the author and committer using {@link #getDate()}.
	 *
	 * @param c
	 *            the commit builder to store.
	 */
	public void setAuthorAndCommitter(org.eclipse.jgit.lib.CommitBuilder c) {
		c.setAuthor(new PersonIdent(defaultAuthor, getDate()));
		c.setCommitter(new PersonIdent(defaultCommitter, getDate()));
	}

	/**
	 * Create a new blob object in the repository.
	 *
	 * @param content
	 *            file content, will be UTF-8 encoded.
	 * @return reference to the blob.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevBlob blob(String content) throws Exception {
		return blob(content.getBytes(UTF_8));
	}

	/**
	 * Create a new blob object in the repository.
	 *
	 * @param content
	 *            binary file content.
	 * @return the new, fully parsed blob.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevBlob blob(byte[] content) throws Exception {
		ObjectId id;
		try (ObjectInserter ins = inserter) {
			id = ins.insert(Constants.OBJ_BLOB, content);
			ins.flush();
		}
		return (RevBlob) pool.parseAny(id);
	}

	/**
	 * Construct a regular file mode tree entry.
	 *
	 * @param path
	 *            path of the file.
	 * @param blob
	 *            a blob, previously constructed in the repository.
	 * @return the entry.
	 * @throws Exception
	 *             if an error occurred
	 */
	public DirCacheEntry file(String path, RevBlob blob)
			throws Exception {
		final DirCacheEntry e = new DirCacheEntry(path);
		e.setFileMode(FileMode.REGULAR_FILE);
		e.setObjectId(blob);
		return e;
	}

	/**
	 * Construct a symlink mode tree entry.
	 *
	 * @param path
	 *            path of the symlink.
	 * @param blob
	 *            a blob, previously constructed in the repository.
	 * @return the entry.
	 * @throws Exception
	 *             if an error occurred
	 * @since 6.3
	 */
	public DirCacheEntry link(String path, RevBlob blob) throws Exception {
		DirCacheEntry e = new DirCacheEntry(path);
		e.setFileMode(FileMode.SYMLINK);
		e.setObjectId(blob);
		return e;
	}

	/**
	 * Construct a tree from a specific listing of file entries.
	 *
	 * @param entries
	 *            the files to include in the tree. The collection does not need
	 *            to be sorted properly and may be empty.
	 * @return the new, fully parsed tree specified by the entry list.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevTree tree(DirCacheEntry... entries) throws Exception {
		final DirCache dc = DirCache.newInCore();
		final DirCacheBuilder b = dc.builder();
		for (DirCacheEntry e : entries) {
			b.add(e);
		}
		b.finish();
		ObjectId root;
		try (ObjectInserter ins = inserter) {
			root = dc.writeTree(ins);
			ins.flush();
		}
		return pool.parseTree(root);
	}

	/**
	 * Lookup an entry stored in a tree, failing if not present.
	 *
	 * @param tree
	 *            the tree to search.
	 * @param path
	 *            the path to find the entry of.
	 * @return the parsed object entry at this path, never null.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevObject get(RevTree tree, String path)
			throws Exception {
		try (TreeWalk tw = new TreeWalk(pool.getObjectReader())) {
			tw.setFilter(PathFilterGroup.createFromStrings(Collections
					.singleton(path)));
			tw.reset(tree);
			while (tw.next()) {
				if (tw.isSubtree() && !path.equals(tw.getPathString())) {
					tw.enterSubtree();
					continue;
				}
				final ObjectId entid = tw.getObjectId(0);
				final FileMode entmode = tw.getFileMode(0);
				return pool.lookupAny(entid, entmode.getObjectType());
			}
		}
		fail("Can't find " + path + " in tree " + tree.name());
		return null; // never reached.
	}

	/**
	 * Create a new, unparsed commit.
	 * <p>
	 * See {@link #unparsedCommit(int, RevTree, ObjectId...)}. The tree is the
	 * empty tree (no files or subdirectories).
	 *
	 * @param parents
	 *            zero or more IDs of the commit's parents.
	 * @return the ID of the new commit.
	 * @throws Exception
	 *             if an error occurred
	 * @since 5.5
	 */
	public ObjectId unparsedCommit(ObjectId... parents) throws Exception {
		return unparsedCommit(1, tree(), parents);
	}

	/**
	 * Create a new commit.
	 * <p>
	 * See {@link #commit(int, RevTree, RevCommit...)}. The tree is the empty
	 * tree (no files or subdirectories).
	 *
	 * @param parents
	 *            zero or more parents of the commit.
	 * @return the new commit.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevCommit commit(RevCommit... parents) throws Exception {
		return commit(1, tree(), parents);
	}

	/**
	 * Create a new commit.
	 * <p>
	 * See {@link #commit(int, RevTree, RevCommit...)}.
	 *
	 * @param tree
	 *            the root tree for the commit.
	 * @param parents
	 *            zero or more parents of the commit.
	 * @return the new commit.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevCommit commit(RevTree tree, RevCommit... parents)
			throws Exception {
		return commit(1, tree, parents);
	}

	/**
	 * Create a new commit.
	 * <p>
	 * See {@link #commit(int, RevTree, RevCommit...)}. The tree is the empty
	 * tree (no files or subdirectories).
	 *
	 * @param secDelta
	 *            number of seconds to advance {@link #tick(int)} by.
	 * @param parents
	 *            zero or more parents of the commit.
	 * @return the new commit.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevCommit commit(int secDelta, RevCommit... parents)
			throws Exception {
		return commit(secDelta, tree(), parents);
	}

	/**
	 * Create a new commit.
	 * <p>
	 * The author and committer identities are stored using the current
	 * timestamp, after being incremented by {@code secDelta}. The message body
	 * is empty.
	 *
	 * @param secDelta
	 *            number of seconds to advance {@link #tick(int)} by.
	 * @param tree
	 *            the root tree for the commit.
	 * @param parents
	 *            zero or more parents of the commit.
	 * @return the new, fully parsed commit.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevCommit commit(final int secDelta, final RevTree tree,
			final RevCommit... parents) throws Exception {
		ObjectId id = unparsedCommit(secDelta, tree, parents);
		return pool.parseCommit(id);
	}

	/**
	 * Create a new, unparsed commit.
	 * <p>
	 * The author and committer identities are stored using the current
	 * timestamp, after being incremented by {@code secDelta}. The message body
	 * is empty.
	 *
	 * @param secDelta
	 *            number of seconds to advance {@link #tick(int)} by.
	 * @param tree
	 *            the root tree for the commit.
	 * @param parents
	 *            zero or more IDs of the commit's parents.
	 * @return the ID of the new commit.
	 * @throws Exception
	 *             if an error occurred
	 * @since 5.5
	 */
	public ObjectId unparsedCommit(final int secDelta, final RevTree tree,
			final ObjectId... parents) throws Exception {
		tick(secDelta);

		final org.eclipse.jgit.lib.CommitBuilder c;

		c = new org.eclipse.jgit.lib.CommitBuilder();
		c.setTreeId(tree);
		c.setParentIds(parents);
		c.setAuthor(new PersonIdent(defaultAuthor, getDate()));
		c.setCommitter(new PersonIdent(defaultCommitter, getDate()));
		c.setMessage("");
		ObjectId id;
		try (ObjectInserter ins = inserter) {
			id = ins.insert(c);
			ins.flush();
		}
		return id;
	}

	/**
	 * Create commit builder
	 *
	 * @return a new commit builder.
	 */
	public CommitBuilder commit() {
		return new CommitBuilder();
	}

	/**
	 * Construct an annotated tag object pointing at another object.
	 * <p>
	 * The tagger is the committer identity, at the current time as specified by
	 * {@link #tick(int)}. The time is not increased.
	 * <p>
	 * The tag message is empty.
	 *
	 * @param name
	 *            name of the tag. Traditionally a tag name should not start
	 *            with {@code refs/tags/}.
	 * @param dst
	 *            object the tag should be pointed at.
	 * @return the new, fully parsed annotated tag object.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevTag tag(String name, RevObject dst) throws Exception {
		final TagBuilder t = new TagBuilder();
		t.setObjectId(dst);
		t.setTag(name);
		t.setTagger(new PersonIdent(defaultCommitter, getDate()));
		t.setMessage("");
		ObjectId id;
		try (ObjectInserter ins = inserter) {
			id = ins.insert(t);
			ins.flush();
		}
		return pool.parseTag(id);
	}

	/**
	 * Update a reference to point to an object.
	 *
	 * @param ref
	 *            the name of the reference to update to. If {@code ref} does
	 *            not start with {@code refs/} and is not the magic names
	 *            {@code HEAD} {@code FETCH_HEAD} or {@code MERGE_HEAD}, then
	 *            {@code refs/heads/} will be prefixed in front of the given
	 *            name, thereby assuming it is a branch.
	 * @param to
	 *            the target object.
	 * @return the target object.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevCommit update(String ref, CommitBuilder to) throws Exception {
		return update(ref, to.create());
	}

	/**
	 * Amend an existing ref.
	 *
	 * @param ref
	 *            the name of the reference to amend, which must already exist.
	 *            If {@code ref} does not start with {@code refs/} and is not
	 *            the magic names {@code HEAD} {@code FETCH_HEAD} or {@code
	 *            MERGE_HEAD}, then {@code refs/heads/} will be prefixed in
	 *            front of the given name, thereby assuming it is a branch.
	 * @return commit builder that amends the branch on commit.
	 * @throws Exception
	 *             if an error occurred
	 */
	public CommitBuilder amendRef(String ref) throws Exception {
		String name = normalizeRef(ref);
		Ref r = db.exactRef(name);
		if (r == null)
			throw new IOException("Not a ref: " + ref);
		return amend(pool.parseCommit(r.getObjectId()), branch(name).commit());
	}

	/**
	 * Amend an existing commit.
	 *
	 * @param id
	 *            the id of the commit to amend.
	 * @return commit builder.
	 * @throws Exception
	 *             if an error occurred
	 */
	public CommitBuilder amend(AnyObjectId id) throws Exception {
		return amend(pool.parseCommit(id), commit());
	}

	private CommitBuilder amend(RevCommit old, CommitBuilder b) throws Exception {
		pool.parseBody(old);
		b.author(old.getAuthorIdent());
		b.committer(old.getCommitterIdent());
		b.message(old.getFullMessage());
		// Use the committer name from the old commit, but update it after ticking
		// the clock in CommitBuilder#create().
		b.updateCommitterTime = true;

		// Reset parents to original parents.
		b.noParents();
		for (int i = 0; i < old.getParentCount(); i++)
			b.parent(old.getParent(i));

		// Reset tree to original tree; resetting parents reset tree contents to the
		// first parent.
		b.tree.clear();
		try (TreeWalk tw = new TreeWalk(db)) {
			tw.reset(old.getTree());
			tw.setRecursive(true);
			while (tw.next()) {
				b.edit(new PathEdit(tw.getPathString()) {
					@Override
					public void apply(DirCacheEntry ent) {
						ent.setFileMode(tw.getFileMode(0));
						ent.setObjectId(tw.getObjectId(0));
					}
				});
			}
		}

		return b;
	}

	/**
	 * Update a reference to point to an object.
	 *
	 * @param <T>
	 *            type of the target object.
	 * @param ref
	 *            the name of the reference to update to. If {@code ref} does
	 *            not start with {@code refs/} and is not the magic names
	 *            {@code HEAD} {@code FETCH_HEAD} or {@code MERGE_HEAD}, then
	 *            {@code refs/heads/} will be prefixed in front of the given
	 *            name, thereby assuming it is a branch.
	 * @param obj
	 *            the target object.
	 * @return the target object.
	 * @throws Exception
	 *             if an error occurred
	 */
	public <T extends AnyObjectId> T update(String ref, T obj) throws Exception {
		ref = normalizeRef(ref);
		RefUpdate u = db.updateRef(ref);
		u.setNewObjectId(obj);
		switch (u.forceUpdate()) {
		case FAST_FORWARD:
		case FORCED:
		case NEW:
		case NO_CHANGE:
			updateServerInfo();
			return obj;

		default:
			throw new IOException("Cannot write " + ref + " " + u.getResult());
		}
	}

	/**
	 * Delete a reference.
	 *
	 * @param ref
	 *            the name of the reference to delete. This is normalized in the
	 *            same way as {@link #update(String, AnyObjectId)}.
	 * @throws Exception
	 *             if an error occurred
	 * @since 4.4
	 */
	public void delete(String ref) throws Exception {
		ref = normalizeRef(ref);
		RefUpdate u = db.updateRef(ref);
		u.setForceUpdate(true);
		switch (u.delete()) {
		case FAST_FORWARD:
		case FORCED:
		case NEW:
		case NO_CHANGE:
			updateServerInfo();
			return;

		default:
			throw new IOException("Cannot delete " + ref + " " + u.getResult());
		}
	}

	private static String normalizeRef(String ref) {
		if (Constants.HEAD.equals(ref)) {
			// nothing
		} else if ("FETCH_HEAD".equals(ref)) {
			// nothing
		} else if ("MERGE_HEAD".equals(ref)) {
			// nothing
		} else if (ref.startsWith(Constants.R_REFS)) {
			// nothing
		} else
			ref = Constants.R_HEADS + ref;
		return ref;
	}

	/**
	 * Soft-reset HEAD to a detached state.
	 *
	 * @param id
	 *            ID of detached head.
	 * @throws Exception
	 *             if an error occurred
	 * @see #reset(String)
	 */
	public void reset(AnyObjectId id) throws Exception {
		RefUpdate ru = db.updateRef(Constants.HEAD, true);
		ru.setNewObjectId(id);
		RefUpdate.Result result = ru.forceUpdate();
		switch (result) {
			case FAST_FORWARD:
			case FORCED:
			case NEW:
			case NO_CHANGE:
				break;
			default:
				throw new IOException(String.format(
						"Checkout \"%s\" failed: %s", id.name(), result));
		}
	}

	/**
	 * Soft-reset HEAD to a different commit.
	 * <p>
	 * This is equivalent to {@code git reset --soft} in that it modifies HEAD
	 * but not the index or the working tree of a non-bare repository.
	 *
	 * @param name
	 *            revision string; either an existing ref name, or something
	 *            that can be parsed to an object ID.
	 * @throws Exception
	 *             if an error occurred
	 */
	public void reset(String name) throws Exception {
		RefUpdate.Result result;
		ObjectId id = db.resolve(name);
		if (id == null)
			throw new IOException("Not a revision: " + name);
		RefUpdate ru = db.updateRef(Constants.HEAD, false);
		ru.setNewObjectId(id);
		result = ru.forceUpdate();
		switch (result) {
			case FAST_FORWARD:
			case FORCED:
			case NEW:
			case NO_CHANGE:
				break;
			default:
				throw new IOException(String.format(
						"Checkout \"%s\" failed: %s", name, result));
		}
	}

	/**
	 * Cherry-pick a commit onto HEAD.
	 * <p>
	 * This differs from {@code git cherry-pick} in that it works in a bare
	 * repository. As a result, any merge failure results in an exception, as
	 * there is no way to recover.
	 *
	 * @param id
	 *            commit-ish to cherry-pick.
	 * @return the new, fully parsed commit, or null if no work was done due to
	 *         the resulting tree being identical.
	 * @throws Exception
	 *             if an error occurred
	 */
	public RevCommit cherryPick(AnyObjectId id) throws Exception {
		RevCommit commit = pool.parseCommit(id);
		pool.parseBody(commit);
		if (commit.getParentCount() != 1)
			throw new IOException(String.format(
					"Expected 1 parent for %s, found: %s",
					id.name(), Arrays.asList(commit.getParents())));
		RevCommit parent = commit.getParent(0);
		pool.parseHeaders(parent);

		Ref headRef = db.exactRef(Constants.HEAD);
		if (headRef == null)
			throw new IOException("Missing HEAD");
		RevCommit head = pool.parseCommit(headRef.getObjectId());

		ThreeWayMerger merger = MergeStrategy.RECURSIVE.newMerger(db, true);
		merger.setBase(parent.getTree());
		if (merger.merge(head, commit)) {
			if (AnyObjectId.isEqual(head.getTree(), merger.getResultTreeId()))
				return null;
			tick(1);
			org.eclipse.jgit.lib.CommitBuilder b =
					new org.eclipse.jgit.lib.CommitBuilder();
			b.setParentId(head);
			b.setTreeId(merger.getResultTreeId());
			b.setAuthor(commit.getAuthorIdent());
			b.setCommitter(new PersonIdent(defaultCommitter, getDate()));
			b.setMessage(commit.getFullMessage());
			ObjectId result;
			try (ObjectInserter ins = inserter) {
				result = ins.insert(b);
				ins.flush();
			}
			update(Constants.HEAD, result);
			return pool.parseCommit(result);
		}
		throw new IOException("Merge conflict");
	}

	/**
	 * Update the dumb client server info files.
	 *
	 * @throws Exception
	 *             if an error occurred
	 */
	public void updateServerInfo() throws Exception {
		if (db instanceof FileRepository) {
			final FileRepository fr = (FileRepository) db;
			RefWriter rw = new RefWriter(fr.getRefDatabase().getRefs()) {
				@Override
				protected void writeFile(String name, byte[] bin)
						throws IOException {
					File path = new File(fr.getDirectory(), name);
					TestRepository.this.writeFile(path, bin);
				}
			};
			rw.writePackedRefs();
			rw.writeInfoRefs();

			final StringBuilder w = new StringBuilder();
			for (Pack p : fr.getObjectDatabase().getPacks()) {
				w.append("P ");
				w.append(p.getPackFile().getName());
				w.append('\n');
			}
			writeFile(new File(new File(fr.getObjectDatabase().getDirectory(),
					"info"), "packs"), Constants.encodeASCII(w.toString()));
		}
	}

	/**
	 * Ensure the body of the given object has been parsed.
	 *
	 * @param <T>
	 *            type of object, e.g. {@link org.eclipse.jgit.revwalk.RevTag}
	 *            or {@link org.eclipse.jgit.revwalk.RevCommit}.
	 * @param object
	 *            reference to the (possibly unparsed) object to force body
	 *            parsing of.
	 * @return {@code object}
	 * @throws Exception
	 *             if an error occurred
	 */
	public <T extends RevObject> T parseBody(T object) throws Exception {
		pool.parseBody(object);
		return object;
	}

	/**
	 * Create a new branch builder for this repository.
	 *
	 * @param ref
	 *            name of the branch to be constructed. If {@code ref} does not
	 *            start with {@code refs/} the prefix {@code refs/heads/} will
	 *            be added.
	 * @return builder for the named branch.
	 */
	public BranchBuilder branch(String ref) {
		if (Constants.HEAD.equals(ref)) {
			// nothing
		} else if (ref.startsWith(Constants.R_REFS)) {
			// nothing
		} else
			ref = Constants.R_HEADS + ref;
		return new BranchBuilder(ref);
	}

	/**
	 * Tag an object using a lightweight tag.
	 *
	 * @param name
	 *            the tag name. The /refs/tags/ prefix will be added if the name
	 *            doesn't start with it
	 * @param obj
	 *            the object to tag
	 * @return the tagged object
	 * @throws Exception
	 *             if an error occurred
	 */
	public ObjectId lightweightTag(String name, ObjectId obj) throws Exception {
		if (!name.startsWith(Constants.R_TAGS))
			name = Constants.R_TAGS + name;
		return update(name, obj);
	}

	/**
	 * Run consistency checks against the object database.
	 * <p>
	 * This method completes silently if the checks pass. A temporary revision
	 * pool is constructed during the checking.
	 *
	 * @param tips
	 *            the tips to start checking from; if not supplied the refs of
	 *            the repository are used instead.
	 * @throws MissingObjectException
	 *             if object is missing
	 * @throws IncorrectObjectTypeException
	 *             if object has unexpected type
	 * @throws IOException
	 *             if an IO error occurred
	 */
	public void fsck(RevObject... tips) throws MissingObjectException,
			IncorrectObjectTypeException, IOException {
		try (ObjectWalk ow = new ObjectWalk(db)) {
			if (tips.length != 0) {
				for (RevObject o : tips)
					ow.markStart(ow.parseAny(o));
			} else {
				for (Ref r : db.getRefDatabase().getRefs())
					ow.markStart(ow.parseAny(r.getObjectId()));
			}

			ObjectChecker oc = new ObjectChecker();
			for (;;) {
				final RevCommit o = ow.next();
				if (o == null)
					break;

				final byte[] bin = db.open(o, o.getType()).getCachedBytes();
				oc.checkCommit(o, bin);
				assertHash(o, bin);
			}

			for (;;) {
				final RevObject o = ow.nextObject();
				if (o == null)
					break;

				final byte[] bin = db.open(o, o.getType()).getCachedBytes();
				oc.check(o, o.getType(), bin);
				assertHash(o, bin);
			}
		}
	}

	private static void assertHash(RevObject id, byte[] bin) {
		MessageDigest md = Constants.newMessageDigest();
		md.update(Constants.encodedTypeString(id.getType()));
		md.update((byte) ' ');
		md.update(Constants.encodeASCII(bin.length));
		md.update((byte) 0);
		md.update(bin);
		assertEquals(id, ObjectId.fromRaw(md.digest()));
	}

	/**
	 * Pack all reachable objects in the repository into a single pack file.
	 * <p>
	 * All loose objects are automatically pruned. Existing packs however are
	 * not removed.
	 *
	 * @throws Exception
	 *             if an error occurred
	 */
	public void packAndPrune() throws Exception {
		if (db.getObjectDatabase() instanceof ObjectDirectory) {
			ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
			NullProgressMonitor m = NullProgressMonitor.INSTANCE;

			final PackFile pack, idx;
			try (PackWriter pw = new PackWriter(db)) {
				Set<ObjectId> all = new HashSet<>();
				for (Ref r : db.getRefDatabase().getRefs())
					all.add(r.getObjectId());
				pw.preparePack(m, all, PackWriter.NONE);

				pack = new PackFile(odb.getPackDirectory(), pw.computeName(),
						PackExt.PACK);
				try (OutputStream out =
						new BufferedOutputStream(new FileOutputStream(pack))) {
					pw.writePack(m, m, out);
				}
				pack.setReadOnly();

				idx = pack.create(PackExt.INDEX);
				try (OutputStream out =
						new BufferedOutputStream(new FileOutputStream(idx))) {
					pw.writeIndex(out);
				}
				idx.setReadOnly();
			}

			odb.openPack(pack);
			updateServerInfo();
			prunePacked(odb);
		}
	}

	/**
	 * Closes the underlying {@link Repository} object and any other internal
	 * resources.
	 * <p>
	 * {@link AutoCloseable} resources that may escape this object, such as
	 * those returned by the {@link #git} and {@link #getRevWalk()} methods are
	 * not closed.
	 */
	@Override
	public void close() {
		try {
			inserter.close();
		} finally {
			db.close();
		}
	}

	private static void prunePacked(ObjectDirectory odb) throws IOException {
		for (Pack p : odb.getPacks()) {
			for (MutableEntry e : p)
				FileUtils.delete(odb.fileFor(e.toObjectId()));
		}
	}

	private void writeFile(File p, byte[] bin) throws IOException,
			ObjectWritingException {
		final LockFile lck = new LockFile(p);
		if (!lck.lock())
			throw new ObjectWritingException("Can't write " + p);
		try {
			lck.write(bin);
		} catch (IOException ioe) {
			throw new ObjectWritingException("Can't write " + p, ioe);
		}
		if (!lck.commit())
			throw new ObjectWritingException("Can't write " + p);
	}

	/** Helper to build a branch with one or more commits */
	public class BranchBuilder {
		private final String ref;

		BranchBuilder(String ref) {
			this.ref = ref;
		}

		/**
		 * Create commit builder
		 *
		 * @return construct a new commit builder that updates this branch. If
		 *         the branch already exists, the commit builder will have its
		 *         first parent as the current commit and its tree will be
		 *         initialized to the current files.
		 * @throws Exception
		 *             the commit builder can't read the current branch state
		 */
		public CommitBuilder commit() throws Exception {
			return new CommitBuilder(this);
		}

		/**
		 * Forcefully update this branch to a particular commit.
		 *
		 * @param to
		 *            the commit to update to.
		 * @return {@code to}.
		 * @throws Exception
		 *             if an error occurred
		 */
		public RevCommit update(CommitBuilder to) throws Exception {
			return update(to.create());
		}

		/**
		 * Forcefully update this branch to a particular commit.
		 *
		 * @param to
		 *            the commit to update to.
		 * @return {@code to}.
		 * @throws Exception
		 *             if an error occurred
		 */
		public RevCommit update(RevCommit to) throws Exception {
			return TestRepository.this.update(ref, to);
		}

		/**
		 * Delete this branch.
		 *
		 * @throws Exception
		 *             if an error occurred
		 * @since 4.4
		 */
		public void delete() throws Exception {
			TestRepository.this.delete(ref);
		}
	}

	/** Helper to generate a commit. */
	public class CommitBuilder {
		private final BranchBuilder branch;

		private final DirCache tree = DirCache.newInCore();

		private ObjectId topLevelTree;

		private final List<RevCommit> parents = new ArrayList<>(2);

		private int tick = 1;

		private String message = "";

		private RevCommit self;

		private PersonIdent author;
		private PersonIdent committer;

		private String changeId;

		private boolean updateCommitterTime;

		CommitBuilder() {
			branch = null;
		}

		CommitBuilder(BranchBuilder b) throws Exception {
			branch = b;

			Ref ref = db.exactRef(branch.ref);
			if (ref != null && ref.getObjectId() != null)
				parent(pool.parseCommit(ref.getObjectId()));
		}

		CommitBuilder(CommitBuilder prior) throws Exception {
			branch = prior.branch;

			DirCacheBuilder b = tree.builder();
			for (int i = 0; i < prior.tree.getEntryCount(); i++)
				b.add(prior.tree.getEntry(i));
			b.finish();

			parents.add(prior.create());
		}

		/**
		 * set parent commit
		 *
		 * @param p
		 *            parent commit
		 * @return this commit builder
		 * @throws Exception
		 *             if an error occurred
		 */
		public CommitBuilder parent(RevCommit p) throws Exception {
			if (parents.isEmpty()) {
				DirCacheBuilder b = tree.builder();
				parseBody(p);
				b.addTree(new byte[0], DirCacheEntry.STAGE_0, pool
						.getObjectReader(), p.getTree());
				b.finish();
			}
			parents.add(p);
			return this;
		}

		/**
		 * Get parent commits
		 *
		 * @return parent commits
		 */
		public List<RevCommit> parents() {
			return Collections.unmodifiableList(parents);
		}

		/**
		 * Remove parent commits
		 *
		 * @return this commit builder
		 */
		public CommitBuilder noParents() {
			parents.clear();
			return this;
		}

		/**
		 * Remove files
		 *
		 * @return this commit builder
		 */
		public CommitBuilder noFiles() {
			tree.clear();
			return this;
		}

		/**
		 * Set top level tree
		 *
		 * @param treeId
		 *            the top level tree
		 * @return this commit builder
		 */
		public CommitBuilder setTopLevelTree(ObjectId treeId) {
			topLevelTree = treeId;
			return this;
		}

		/**
		 * Add file with given content
		 *
		 * @param path
		 *            path of the file
		 * @param content
		 *            the file content
		 * @return this commit builder
		 * @throws Exception
		 *             if an error occurred
		 */
		public CommitBuilder add(String path, String content) throws Exception {
			return add(path, blob(content));
		}

		/**
		 * Add file with given path and blob
		 *
		 * @param path
		 *            path of the file
		 * @param id
		 *            blob for this file
		 * @return this commit builder
		 * @throws Exception
		 *             if an error occurred
		 */
		public CommitBuilder add(String path, RevBlob id)
				throws Exception {
			return edit(new PathEdit(path) {
				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.REGULAR_FILE);
					ent.setObjectId(id);
				}
			});
		}

		/**
		 * Edit the index
		 *
		 * @param edit
		 *            the index record update
		 * @return this commit builder
		 */
		public CommitBuilder edit(PathEdit edit) {
			DirCacheEditor e = tree.editor();
			e.add(edit);
			e.finish();
			return this;
		}

		/**
		 * Remove a file
		 *
		 * @param path
		 *            path of the file
		 * @return this commit builder
		 */
		public CommitBuilder rm(String path) {
			DirCacheEditor e = tree.editor();
			e.add(new DeletePath(path));
			e.add(new DeleteTree(path));
			e.finish();
			return this;
		}

		/**
		 * Set commit message
		 *
		 * @param m
		 *            the message
		 * @return this commit builder
		 */
		public CommitBuilder message(String m) {
			message = m;
			return this;
		}

		/**
		 * Get the commit message
		 *
		 * @return the commit message
		 */
		public String message() {
			return message;
		}

		/**
		 * Tick the clock
		 *
		 * @param secs
		 *            number of seconds
		 * @return this commit builder
		 */
		public CommitBuilder tick(int secs) {
			tick = secs;
			return this;
		}

		/**
		 * Set author and committer identity
		 *
		 * @param ident
		 *            identity to set
		 * @return this commit builder
		 */
		public CommitBuilder ident(PersonIdent ident) {
			author = ident;
			committer = ident;
			return this;
		}

		/**
		 * Set the author identity
		 *
		 * @param a
		 *            the author's identity
		 * @return this commit builder
		 */
		public CommitBuilder author(PersonIdent a) {
			author = a;
			return this;
		}

		/**
		 * Get the author identity
		 *
		 * @return the author identity
		 */
		public PersonIdent author() {
			return author;
		}

		/**
		 * Set the committer identity
		 *
		 * @param c
		 *            the committer identity
		 * @return this commit builder
		 */
		public CommitBuilder committer(PersonIdent c) {
			committer = c;
			return this;
		}

		/**
		 * Get the committer identity
		 *
		 * @return the committer identity
		 */
		public PersonIdent committer() {
			return committer;
		}

		/**
		 * Insert changeId
		 *
		 * @return this commit builder
		 */
		public CommitBuilder insertChangeId() {
			changeId = "";
			return this;
		}

		/**
		 * Insert given changeId
		 *
		 * @param c
		 *            changeId
		 * @return this commit builder
		 */
		public CommitBuilder insertChangeId(String c) {
			// Validate, but store as a string so we can use "" as a sentinel.
			ObjectId.fromString(c);
			changeId = c;
			return this;
		}

		/**
		 * Create the commit
		 *
		 * @return the new commit
		 * @throws Exception
		 *             if creation failed
		 */
		public RevCommit create() throws Exception {
			if (self == null) {
				TestRepository.this.tick(tick);

				final org.eclipse.jgit.lib.CommitBuilder c;

				c = new org.eclipse.jgit.lib.CommitBuilder();
				c.setParentIds(parents);
				setAuthorAndCommitter(c);
				if (author != null)
					c.setAuthor(author);
				if (committer != null) {
					if (updateCommitterTime)
						committer = new PersonIdent(committer, getDate());
					c.setCommitter(committer);
				}

				ObjectId commitId;
				try (ObjectInserter ins = inserter) {
					if (topLevelTree != null)
						c.setTreeId(topLevelTree);
					else
						c.setTreeId(tree.writeTree(ins));
					insertChangeId(c);
					c.setMessage(message);
					commitId = ins.insert(c);
					ins.flush();
				}
				self = pool.parseCommit(commitId);

				if (branch != null)
					branch.update(self);
			}
			return self;
		}

		private void insertChangeId(org.eclipse.jgit.lib.CommitBuilder c) {
			if (changeId == null)
				return;
			int idx = ChangeIdUtil.indexOfChangeId(message, "\n");
			if (idx >= 0)
				return;

			ObjectId firstParentId = null;
			if (!parents.isEmpty())
				firstParentId = parents.get(0);

			ObjectId cid;
			if (changeId.isEmpty())
				cid = ChangeIdUtil.computeChangeId(c.getTreeId(), firstParentId,
						c.getAuthor(), c.getCommitter(), message);
			else
				cid = ObjectId.fromString(changeId);
			message = ChangeIdUtil.insertId(message, cid);
			if (cid != null)
				message = message.replaceAll("\nChange-Id: I" //$NON-NLS-1$
						+ ObjectId.zeroId().getName() + "\n", "\nChange-Id: I" //$NON-NLS-1$ //$NON-NLS-2$
						+ cid.getName() + "\n"); //$NON-NLS-1$
		}

		/**
		 * Create child commit builder
		 *
		 * @return child commit builder
		 * @throws Exception
		 *             if an error occurred
		 */
		public CommitBuilder child() throws Exception {
			return new CommitBuilder(this);
		}
	}
}
