/*
 * Copyright 2011 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit.utils;

import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.filefilter.TrueFileFilter;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RevisionSyntaxException;
import org.eclipse.jgit.errors.StopWalkException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.BlobBasedConfig;
import org.eclipse.jgit.lib.CommitBuilder;
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.ObjectLoader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.lib.TreeFormatter;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.RecursiveMerger;
import org.eclipse.jgit.merge.ThreeWayMerger;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.filter.CommitTimeRevFilter;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.OrTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.PathSuffixFilter;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.jgit.util.FS;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants.MergeType;
import com.gitblit.GitBlitException;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.git.PatchsetCommand;
import com.gitblit.models.FilestoreModel;
import com.gitblit.models.GitNote;
import com.gitblit.models.PathModel;
import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.TicketModel.TicketAction;
import com.gitblit.models.TicketModel.TicketLink;
import com.gitblit.models.RefModel;
import com.gitblit.models.SubmoduleModel;
import com.google.common.base.Strings;

/**
 * Collection of static methods for retrieving information from a repository.
 *
 * @author James Moger
 *
 */
public class JGitUtils {

	static final Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);

	/**
	 * Log an error message and exception.
	 *
	 * @param t
	 * @param repository
	 *            if repository is not null it MUST be the {0} parameter in the
	 *            pattern.
	 * @param pattern
	 * @param objects
	 */
	private static void error(Throwable t, Repository repository, String pattern, Object... objects) {
		List<Object> parameters = new ArrayList<Object>();
		if (objects != null && objects.length > 0) {
			for (Object o : objects) {
				parameters.add(o);
			}
		}
		if (repository != null) {
			parameters.add(0, repository.getDirectory().getAbsolutePath());
		}
		LOGGER.error(MessageFormat.format(pattern, parameters.toArray()), t);
	}

	/**
	 * Returns the displayable name of the person in the form "Real Name <email
	 * address>".  If the email address is empty, just "Real Name" is returned.
	 *
	 * @param person
	 * @return "Real Name <email address>" or "Real Name"
	 */
	public static String getDisplayName(PersonIdent person) {
		if (StringUtils.isEmpty(person.getEmailAddress())) {
			return person.getName();
		}
		final StringBuilder r = new StringBuilder();
		r.append(person.getName());
		r.append(" <");
		r.append(person.getEmailAddress());
		r.append('>');
		return r.toString().trim();
	}

	/**
	 * Encapsulates the result of cloning or pulling from a repository.
	 */
	public static class CloneResult {
		public String name;
		public FetchResult fetchResult;
		public boolean createdRepository;
	}

	/**
	 * Clone or Fetch a repository. If the local repository does not exist,
	 * clone is called. If the repository does exist, fetch is called. By
	 * default the clone/fetch retrieves the remote heads, tags, and notes.
	 *
	 * @param repositoriesFolder
	 * @param name
	 * @param fromUrl
	 * @return CloneResult
	 * @throws Exception
	 */
	public static CloneResult cloneRepository(File repositoriesFolder, String name, String fromUrl)
			throws Exception {
		return cloneRepository(repositoriesFolder, name, fromUrl, true, null);
	}

	/**
	 * Clone or Fetch a repository. If the local repository does not exist,
	 * clone is called. If the repository does exist, fetch is called. By
	 * default the clone/fetch retrieves the remote heads, tags, and notes.
	 *
	 * @param repositoriesFolder
	 * @param name
	 * @param fromUrl
	 * @param bare
	 * @param credentialsProvider
	 * @return CloneResult
	 * @throws Exception
	 */
	public static CloneResult cloneRepository(File repositoriesFolder, String name, String fromUrl,
			boolean bare, CredentialsProvider credentialsProvider) throws Exception {
		CloneResult result = new CloneResult();
		if (bare) {
			// bare repository, ensure .git suffix
			if (!name.toLowerCase().endsWith(Constants.DOT_GIT_EXT)) {
				name += Constants.DOT_GIT_EXT;
			}
		} else {
			// normal repository, strip .git suffix
			if (name.toLowerCase().endsWith(Constants.DOT_GIT_EXT)) {
				name = name.substring(0, name.indexOf(Constants.DOT_GIT_EXT));
			}
		}
		result.name = name;

		File folder = new File(repositoriesFolder, name);
		if (folder.exists()) {
			File gitDir = FileKey.resolve(new File(repositoriesFolder, name), FS.DETECTED);
			Repository repository = new FileRepositoryBuilder().setGitDir(gitDir).build();
			result.fetchResult = fetchRepository(credentialsProvider, repository);
			repository.close();
		} else {
			CloneCommand clone = new CloneCommand();
			clone.setBare(bare);
			clone.setCloneAllBranches(true);
			clone.setURI(fromUrl);
			clone.setDirectory(folder);
			if (credentialsProvider != null) {
				clone.setCredentialsProvider(credentialsProvider);
			}
			Repository repository = clone.call().getRepository();

			// Now we have to fetch because CloneCommand doesn't fetch
			// refs/notes nor does it allow manual RefSpec.
			result.createdRepository = true;
			result.fetchResult = fetchRepository(credentialsProvider, repository);
			repository.close();
		}
		return result;
	}

	/**
	 * Fetch updates from the remote repository. If refSpecs is unspecifed,
	 * remote heads, tags, and notes are retrieved.
	 *
	 * @param credentialsProvider
	 * @param repository
	 * @param refSpecs
	 * @return FetchResult
	 * @throws Exception
	 */
	public static FetchResult fetchRepository(CredentialsProvider credentialsProvider,
			Repository repository, RefSpec... refSpecs) throws Exception {
		Git git = new Git(repository);
		FetchCommand fetch = git.fetch();
		List<RefSpec> specs = new ArrayList<RefSpec>();
		if (refSpecs == null || refSpecs.length == 0) {
			specs.add(new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
			specs.add(new RefSpec("+refs/tags/*:refs/tags/*"));
			specs.add(new RefSpec("+refs/notes/*:refs/notes/*"));
		} else {
			specs.addAll(Arrays.asList(refSpecs));
		}
		if (credentialsProvider != null) {
			fetch.setCredentialsProvider(credentialsProvider);
		}
		fetch.setRefSpecs(specs);
		FetchResult fetchRes = fetch.call();
		return fetchRes;
	}

	/**
	 * Creates a bare repository.
	 *
	 * @param repositoriesFolder
	 * @param name
	 * @return Repository
	 */
	public static Repository createRepository(File repositoriesFolder, String name) {
		return createRepository(repositoriesFolder, name, "FALSE");
	}

	/**
	 * Creates a bare, shared repository.
	 *
	 * @param repositoriesFolder
	 * @param name
	 * @param shared
	 *          the setting for the --shared option of "git init".
	 * @return Repository
	 */
	public static Repository createRepository(File repositoriesFolder, String name, String shared) {
		try {
			Repository repo = null;
			try {
				Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(true).call();
				repo = git.getRepository();
			} catch (GitAPIException e) {
				throw new RuntimeException(e);
			}

			GitConfigSharedRepository sharedRepository = new GitConfigSharedRepository(shared);
			if (sharedRepository.isShared()) {
				StoredConfig config = repo.getConfig();
				config.setString("core", null, "sharedRepository", sharedRepository.getValue());
				config.setBoolean("receive", null, "denyNonFastforwards", true);
				config.save();

				if (! JnaUtils.isWindows()) {
					Iterator<File> iter = org.apache.commons.io.FileUtils.iterateFilesAndDirs(repo.getDirectory(),
							TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
					// Adjust permissions on file/directory
					while (iter.hasNext()) {
						adjustSharedPerm(iter.next(), sharedRepository);
					}
				}
			}

			return repo;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	private enum GitConfigSharedRepositoryValue
	{
		UMASK("0", 0), FALSE("0", 0), OFF("0", 0), NO("0", 0),
		GROUP("1", 0660), TRUE("1", 0660), ON("1", 0660), YES("1", 0660),
		ALL("2", 0664), WORLD("2", 0664), EVERYBODY("2", 0664),
		Oxxx(null, -1);

		private String configValue;
		private int permValue;
		private GitConfigSharedRepositoryValue(String config, int perm) { configValue = config; permValue = perm; };

		public String getConfigValue() { return configValue; };
		public int getPerm() { return permValue; };

	}

	private static class GitConfigSharedRepository
	{
		private int intValue;
		private GitConfigSharedRepositoryValue enumValue;

		GitConfigSharedRepository(String s) {
			if ( s == null || s.trim().isEmpty() ) {
				enumValue = GitConfigSharedRepositoryValue.GROUP;
			}
			else {
				try {
					// Try one of the string values
					enumValue = GitConfigSharedRepositoryValue.valueOf(s.trim().toUpperCase());
				} catch (IllegalArgumentException  iae) {
					try {
						// Try if this is an octal number
						int i = Integer.parseInt(s, 8);
						if ( (i & 0600) != 0600 ) {
							String msg = String.format("Problem with core.sharedRepository filemode value (0%03o).\nThe owner of files must always have read and write permissions.", i);
							throw new IllegalArgumentException(msg);
						}
						intValue = i & 0666;
						enumValue = GitConfigSharedRepositoryValue.Oxxx;
					} catch (NumberFormatException nfe) {
						throw new IllegalArgumentException("Bad configuration value for 'shared': '" + s + "'");
					}
				}
			}
		}

		String getValue() {
			if ( enumValue == GitConfigSharedRepositoryValue.Oxxx ) {
				if (intValue == 0) return "0";
				return String.format("0%o", intValue);
			}
			return enumValue.getConfigValue();
		}

		int getPerm() {
			if ( enumValue == GitConfigSharedRepositoryValue.Oxxx ) return intValue;
			return enumValue.getPerm();
		}

		boolean isCustom() {
			return enumValue == GitConfigSharedRepositoryValue.Oxxx;
		}

		boolean isShared() {
			return (enumValue.getPerm() > 0) || enumValue == GitConfigSharedRepositoryValue.Oxxx;
		}
	}


	/**
	 * Adjust file permissions of a file/directory for shared repositories
	 *
	 * @param path
	 * 			File that should get its permissions changed.
	 * @param configShared
	 * 			Configuration string value for the shared mode.
	 * @return Upon successful completion, a value of 0 is returned. Otherwise, a value of -1 is returned.
	 */
	public static int adjustSharedPerm(File path, String configShared) {
		return adjustSharedPerm(path, new GitConfigSharedRepository(configShared));
	}


	/**
	 * Adjust file permissions of a file/directory for shared repositories
	 *
	 * @param path
	 * 			File that should get its permissions changed.
	 * @param configShared
	 * 			Configuration setting for the shared mode.
	 * @return Upon successful completion, a value of 0 is returned. Otherwise, a value of -1 is returned.
	 */
	public static int adjustSharedPerm(File path, GitConfigSharedRepository configShared) {
		if (! configShared.isShared()) return 0;
		if (! path.exists()) return -1;

		int perm = configShared.getPerm();
		JnaUtils.Filestat stat = JnaUtils.getFilestat(path);
		if (stat == null) return -1;
		int mode = stat.mode;
		if (mode < 0) return -1;

		// Now, here is the kicker: Under Linux, chmod'ing a sgid file whose guid is different from the process'
		// effective guid will reset the sgid flag of the file. Since there is no way to get the sgid flag back in
		// that case, we decide to rather not touch is and getting the right permissions will have to be achieved
		// in a different way, e.g. by using an appropriate umask for the Gitblit process.
		if (System.getProperty("os.name").toLowerCase().startsWith("linux")) {
			if ( ((mode & (JnaUtils.S_ISGID | JnaUtils.S_ISUID)) != 0)
				&& stat.gid != JnaUtils.getegid() ) {
				LOGGER.debug("Not adjusting permissions to prevent clearing suid/sgid bits for '" + path + "'" );
				return 0;
			}
		}

		// If the owner has no write access, delete it from group and other, too.
		if ((mode & JnaUtils.S_IWUSR) == 0) perm &= ~0222;
		// If the owner has execute access, set it for all blocks that have read access.
		if ((mode & JnaUtils.S_IXUSR) == JnaUtils.S_IXUSR) perm |= (perm & 0444) >> 2;

		if (configShared.isCustom()) {
			// Use the custom value for access permissions.
			mode = (mode & ~0777) | perm;
		}
		else {
			// Just add necessary bits to existing permissions.
			mode |= perm;
		}

		if (path.isDirectory()) {
			mode |= (mode & 0444) >> 2;
			mode |= JnaUtils.S_ISGID;
		}

		return JnaUtils.setFilemode(path, mode);
	}


	/**
	 * Returns a list of repository names in the specified folder.
	 *
	 * @param repositoriesFolder
	 * @param onlyBare
	 *            if true, only bare repositories repositories are listed. If
	 *            false all repositories are included.
	 * @param searchSubfolders
	 *            recurse into subfolders to find grouped repositories
	 * @param depth
	 *            optional recursion depth, -1 = infinite recursion
	 * @param exclusions
	 *            list of regex exclusions for matching to folder names
	 * @return list of repository names
	 */
	public static List<String> getRepositoryList(File repositoriesFolder, boolean onlyBare,
			boolean searchSubfolders, int depth, List<String> exclusions) {
		List<String> list = new ArrayList<String>();
		if (repositoriesFolder == null || !repositoriesFolder.exists()) {
			return list;
		}
		List<Pattern> patterns = new ArrayList<Pattern>();
		if (!ArrayUtils.isEmpty(exclusions)) {
			for (String regex : exclusions) {
				patterns.add(Pattern.compile(regex));
			}
		}
		list.addAll(getRepositoryList(repositoriesFolder.getAbsolutePath(), repositoriesFolder,
				onlyBare, searchSubfolders, depth, patterns));
		StringUtils.sortRepositorynames(list);
		list.remove(".git"); // issue-256
		return list;
	}

	/**
	 * Recursive function to find git repositories.
	 *
	 * @param basePath
	 *            basePath is stripped from the repository name as repositories
	 *            are relative to this path
	 * @param searchFolder
	 * @param onlyBare
	 *            if true only bare repositories will be listed. if false all
	 *            repositories are included.
	 * @param searchSubfolders
	 *            recurse into subfolders to find grouped repositories
	 * @param depth
	 *            recursion depth, -1 = infinite recursion
	 * @param patterns
	 *            list of regex patterns for matching to folder names
	 * @return
	 */
	private static List<String> getRepositoryList(String basePath, File searchFolder,
			boolean onlyBare, boolean searchSubfolders, int depth, List<Pattern> patterns) {
		File baseFile = new File(basePath);
		List<String> list = new ArrayList<String>();
		if (depth == 0) {
			return list;
		}

		int nextDepth = (depth == -1) ? -1 : depth - 1;
		for (File file : searchFolder.listFiles()) {
			if (file.isDirectory()) {
				boolean exclude = false;
				for (Pattern pattern : patterns) {
					String path = FileUtils.getRelativePath(baseFile, file).replace('\\',  '/');
					if (pattern.matcher(path).matches()) {
						LOGGER.debug(MessageFormat.format("excluding {0} because of rule {1}", path, pattern.pattern()));
						exclude = true;
						break;
					}
				}
				if (exclude) {
					// skip to next file
					continue;
				}

				File gitDir = FileKey.resolve(new File(searchFolder, file.getName()), FS.DETECTED);
				if (gitDir != null) {
					if (onlyBare && gitDir.getName().equals(".git")) {
						continue;
					}
					if (gitDir.equals(file) || gitDir.getParentFile().equals(file)) {
						// determine repository name relative to base path
						String repository = FileUtils.getRelativePath(baseFile, file);
						list.add(repository);
					} else if (searchSubfolders && file.canRead()) {
						// look for repositories in subfolders
						list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders,
								nextDepth, patterns));
					}
				} else if (searchSubfolders && file.canRead()) {
					// look for repositories in subfolders
					list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders,
							nextDepth, patterns));
				}
			}
		}
		return list;
	}

	/**
	 * Returns the first commit on a branch. If the repository does not exist or
	 * is empty, null is returned.
	 *
	 * @param repository
	 * @param branch
	 *            if unspecified, HEAD is assumed.
	 * @return RevCommit
	 */
	public static RevCommit getFirstCommit(Repository repository, String branch) {
		if (!hasCommits(repository)) {
			return null;
		}
		RevCommit commit = null;
		try {
			// resolve branch
			ObjectId branchObject;
			if (StringUtils.isEmpty(branch)) {
				branchObject = getDefaultBranch(repository);
			} else {
				branchObject = repository.resolve(branch);
			}

			RevWalk walk = new RevWalk(repository);
			walk.sort(RevSort.REVERSE);
			RevCommit head = walk.parseCommit(branchObject);
			walk.markStart(head);
			commit = walk.next();
			walk.dispose();
		} catch (Throwable t) {
			error(t, repository, "{0} failed to determine first commit");
		}
		return commit;
	}

	/**
	 * Returns the date of the first commit on a branch. If the repository does
	 * not exist, Date(0) is returned. If the repository does exist bit is
	 * empty, the last modified date of the repository folder is returned.
	 *
	 * @param repository
	 * @param branch
	 *            if unspecified, HEAD is assumed.
	 * @return Date of the first commit on a branch
	 */
	public static Date getFirstChange(Repository repository, String branch) {
		RevCommit commit = getFirstCommit(repository, branch);
		if (commit == null) {
			if (repository == null || !repository.getDirectory().exists()) {
				return new Date(0);
			}
			// fresh repository
			return new Date(repository.getDirectory().lastModified());
		}
		return getCommitDate(commit);
	}

	/**
	 * Determine if a repository has any commits. This is determined by checking
	 * the for loose and packed objects.
	 *
	 * @param repository
	 * @return true if the repository has commits
	 */
	public static boolean hasCommits(Repository repository) {
		if (repository != null && repository.getDirectory().exists()) {
			return (new File(repository.getDirectory(), "objects").list().length > 2)
					|| (new File(repository.getDirectory(), "objects/pack").list().length > 0);
		}
		return false;
	}

	/**
	 * Encapsulates the result of cloning or pulling from a repository.
	 */
	public static class LastChange {
		public Date when;
		public String who;

		LastChange() {
			when = new Date(0);
		}

		LastChange(long lastModified) {
			this.when = new Date(lastModified);
		}
	}

	/**
	 * Returns the date and author of the most recent commit on a branch. If the
	 * repository does not exist Date(0) is returned. If it does exist but is
	 * empty, the last modified date of the repository folder is returned.
	 *
	 * @param repository
	 * @return a LastChange object
	 */
	public static LastChange getLastChange(Repository repository) {
		if (!hasCommits(repository)) {
			// null repository
			if (repository == null) {
				return new LastChange();
			}
			// fresh repository
			return new LastChange(repository.getDirectory().lastModified());
		}

		List<RefModel> branchModels = getLocalBranches(repository, true, -1);
		if (branchModels.size() > 0) {
			// find most recent branch update
			LastChange lastChange = new LastChange();
			for (RefModel branchModel : branchModels) {
				if (branchModel.getDate().after(lastChange.when)) {
					lastChange.when = branchModel.getDate();
					lastChange.who = branchModel.getAuthorIdent().getName();
				}
			}
			return lastChange;
		}

		// default to the repository folder modification date
		return new LastChange(repository.getDirectory().lastModified());
	}

	/**
	 * Retrieves a Java Date from a Git commit.
	 *
	 * @param commit
	 * @return date of the commit or Date(0) if the commit is null
	 */
	public static Date getCommitDate(RevCommit commit) {
		if (commit == null) {
			return new Date(0);
		}
		return new Date(commit.getCommitTime() * 1000L);
	}

	/**
	 * Retrieves a Java Date from a Git commit.
	 *
	 * @param commit
	 * @return date of the commit or Date(0) if the commit is null
	 */
	public static Date getAuthorDate(RevCommit commit) {
		if (commit == null) {
			return new Date(0);
		}
		if (commit.getAuthorIdent() != null) {
			return commit.getAuthorIdent().getWhen();
		}
		return getCommitDate(commit);
	}

	/**
	 * Returns the specified commit from the repository. If the repository does
	 * not exist or is empty, null is returned.
	 *
	 * @param repository
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @return RevCommit
	 */
	public static RevCommit getCommit(Repository repository, String objectId) {
		if (!hasCommits(repository)) {
			return null;
		}
		RevCommit commit = null;
		RevWalk walk = null;
		try {
			// resolve object id
			ObjectId branchObject;
			if (StringUtils.isEmpty(objectId) || "HEAD".equalsIgnoreCase(objectId)) {
				branchObject = getDefaultBranch(repository);
			} else {
				branchObject = repository.resolve(objectId);
			}
			if (branchObject == null) {
				return null;
			}
			walk = new RevWalk(repository);
			RevCommit rev = walk.parseCommit(branchObject);
			commit = rev;
		} catch (Throwable t) {
			error(t, repository, "{0} failed to get commit {1}", objectId);
		} finally {
			if (walk != null) {
				walk.dispose();
			}
		}
		return commit;
	}

	/**
	 * Retrieves the raw byte content of a file in the specified tree.
	 *
	 * @param repository
	 * @param tree
	 *            if null, the RevTree from HEAD is assumed.
	 * @param path
	 * @return content as a byte []
	 */
	public static byte[] getByteContent(Repository repository, RevTree tree, final String path, boolean throwError) {
		RevWalk rw = new RevWalk(repository);
		TreeWalk tw = new TreeWalk(repository);
		tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
		byte[] content = null;
		try {
			if (tree == null) {
				ObjectId object = getDefaultBranch(repository);
				if (object == null)
					return null;
				RevCommit commit = rw.parseCommit(object);
				tree = commit.getTree();
			}
			tw.reset(tree);
			while (tw.next()) {
				if (tw.isSubtree() && !path.equals(tw.getPathString())) {
					tw.enterSubtree();
					continue;
				}
				ObjectId entid = tw.getObjectId(0);
				FileMode entmode = tw.getFileMode(0);
				if (entmode != FileMode.GITLINK) {
					ObjectLoader ldr = repository.open(entid, Constants.OBJ_BLOB);
					content = ldr.getCachedBytes();
				}
			}
		} catch (Throwable t) {
			if (throwError) {
				error(t, repository, "{0} can't find {1} in tree {2}", path, tree.name());
			}
		} finally {
			rw.dispose();
			tw.close();
		}
		return content;
	}

	/**
	 * Returns the UTF-8 string content of a file in the specified tree.
	 *
	 * @param repository
	 * @param tree
	 *            if null, the RevTree from HEAD is assumed.
	 * @param blobPath
	 * @param charsets optional
	 * @return UTF-8 string content
	 */
	public static String getStringContent(Repository repository, RevTree tree, String blobPath, String... charsets) {
		byte[] content = getByteContent(repository, tree, blobPath, true);
		if (content == null) {
			return null;
		}
		return StringUtils.decodeString(content, charsets);
	}

	/**
	 * Gets the raw byte content of the specified blob object.
	 *
	 * @param repository
	 * @param objectId
	 * @return byte [] blob content
	 */
	public static byte[] getByteContent(Repository repository, String objectId) {
		RevWalk rw = new RevWalk(repository);
		byte[] content = null;
		try {
			RevBlob blob = rw.lookupBlob(ObjectId.fromString(objectId));
			ObjectLoader ldr = repository.open(blob.getId(), Constants.OBJ_BLOB);
			content = ldr.getCachedBytes();
		} catch (Throwable t) {
			error(t, repository, "{0} can't find blob {1}", objectId);
		} finally {
			rw.dispose();
		}
		return content;
	}

	/**
	 * Gets the UTF-8 string content of the blob specified by objectId.
	 *
	 * @param repository
	 * @param objectId
	 * @param charsets optional
	 * @return UTF-8 string content
	 */
	public static String getStringContent(Repository repository, String objectId, String... charsets) {
		byte[] content = getByteContent(repository, objectId);
		if (content == null) {
			return null;
		}
		return StringUtils.decodeString(content, charsets);
	}

	/**
	 * Returns the list of files in the specified folder at the specified
	 * commit. If the repository does not exist or is empty, an empty list is
	 * returned.
	 *
	 * @param repository
	 * @param path
	 *            if unspecified, root folder is assumed.
	 * @param commit
	 *            if null, HEAD is assumed.
	 * @return list of files in specified path
	 */
	public static List<PathModel> getFilesInPath(Repository repository, String path,
			RevCommit commit) {
		List<PathModel> list = new ArrayList<PathModel>();
		if (!hasCommits(repository)) {
			return list;
		}
		if (commit == null) {
			commit = getCommit(repository, null);
		}
		final TreeWalk tw = new TreeWalk(repository);
		try {
			tw.addTree(commit.getTree());
			if (!StringUtils.isEmpty(path)) {
				PathFilter f = PathFilter.create(path);
				tw.setFilter(f);
				tw.setRecursive(false);
				boolean foundFolder = false;
				while (tw.next()) {
					if (!foundFolder && tw.isSubtree()) {
						tw.enterSubtree();
					}
					if (tw.getPathString().equals(path)) {
						foundFolder = true;
						continue;
					}
					if (foundFolder) {
						list.add(getPathModel(tw, path, commit));
					}
				}
			} else {
				tw.setRecursive(false);
				while (tw.next()) {
					list.add(getPathModel(tw, null, commit));
				}
			}
		} catch (IOException e) {
			error(e, repository, "{0} failed to get files for commit {1}", commit.getName());
		} finally {
			tw.close();
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of files in the specified folder at the specified
	 * commit. If the repository does not exist or is empty, an empty list is
	 * returned.
	 *
	 * This is modified version that implements path compression feature.
	 *
	 * @param repository
	 * @param path
	 *            if unspecified, root folder is assumed.
	 * @param commit
	 *            if null, HEAD is assumed.
	 * @return list of files in specified path
	 */
	public static List<PathModel> getFilesInPath2(Repository repository, String path, RevCommit commit) {

		List<PathModel> list = new ArrayList<PathModel>();
		if (!hasCommits(repository)) {
			return list;
		}
		if (commit == null) {
			commit = getCommit(repository, null);
		}
		final TreeWalk tw = new TreeWalk(repository);
		try {

			tw.addTree(commit.getTree());
			final boolean isPathEmpty = Strings.isNullOrEmpty(path);

			if (!isPathEmpty) {
				PathFilter f = PathFilter.create(path);
				tw.setFilter(f);
			}

			tw.setRecursive(true);
			List<String> paths = new ArrayList<>();

			while (tw.next()) {
					String child = isPathEmpty ? tw.getPathString()
							: tw.getPathString().replaceFirst(String.format("%s/", path), "");
					paths.add(child);
			}

			for(String p: PathUtils.compressPaths(paths)) {
				String pathString = isPathEmpty ? p : String.format("%s/%s", path, p);
				list.add(getPathModel(repository, pathString, path, commit));
			}

		} catch (IOException e) {
			error(e, repository, "{0} failed to get files for commit {1}", commit.getName());
		} finally {
			tw.close();
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of files changed in a specified commit. If the
	 * repository does not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param commit
	 *            if null, HEAD is assumed.
	 * @return list of files changed in a commit
	 */
	public static List<PathChangeModel> getFilesInCommit(Repository repository, RevCommit commit) {
		return getFilesInCommit(repository, commit, true);
	}

	/**
	 * Returns the list of files changed in a specified commit. If the
	 * repository does not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param commit
	 *            if null, HEAD is assumed.
	 * @param calculateDiffStat
	 *            if true, each PathChangeModel will have insertions/deletions
	 * @return list of files changed in a commit
	 */
	public static List<PathChangeModel> getFilesInCommit(Repository repository, RevCommit commit, boolean calculateDiffStat) {
		List<PathChangeModel> list = new ArrayList<PathChangeModel>();
		if (!hasCommits(repository)) {
			return list;
		}
		RevWalk rw = new RevWalk(repository);
		try {
			if (commit == null) {
				ObjectId object = getDefaultBranch(repository);
				commit = rw.parseCommit(object);
			}

			if (commit.getParentCount() == 0) {
				TreeWalk tw = new TreeWalk(repository);
				tw.reset();
				tw.setRecursive(true);
				tw.addTree(commit.getTree());
				while (tw.next()) {
					long size = 0;
					FilestoreModel filestoreItem = null;
					ObjectId objectId = tw.getObjectId(0);
					
					try {
						if (!tw.isSubtree() && (tw.getFileMode(0) != FileMode.GITLINK)) {

							size = tw.getObjectReader().getObjectSize(objectId, Constants.OBJ_BLOB);

							if (isPossibleFilestoreItem(size)) {
								filestoreItem = getFilestoreItem(tw.getObjectReader().open(objectId));
							}
						}
					} catch (Throwable t) {
						error(t, null, "failed to retrieve blob size for " + tw.getPathString());
					}
					
					list.add(new PathChangeModel(tw.getPathString(), tw.getPathString(),filestoreItem, size, tw
							.getRawMode(0), objectId.getName(), commit.getId().getName(),
							ChangeType.ADD));
				}
				tw.close();
			} else {
				RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
				DiffStatFormatter df = new DiffStatFormatter(commit.getName(), repository);
				df.setRepository(repository);
				df.setDiffComparator(RawTextComparator.DEFAULT);
				df.setDetectRenames(true);
				List<DiffEntry> diffs = df.scan(parent.getTree(), commit.getTree());
				for (DiffEntry diff : diffs) {
					// create the path change model
					PathChangeModel pcm = PathChangeModel.from(diff, commit.getName(), repository);
						
						if (calculateDiffStat) {
						// update file diffstats
						df.format(diff);
						PathChangeModel pathStat = df.getDiffStat().getPath(pcm.path);
						if (pathStat != null) {
							pcm.insertions = pathStat.insertions;
							pcm.deletions = pathStat.deletions;
						}
					}
					list.add(pcm);
				}
			}
		} catch (Throwable t) {
			error(t, repository, "{0} failed to determine files in commit!");
		} finally {
			rw.dispose();
		}
		return list;
	}

	/**
	 * Returns the list of files changed in a specified commit. If the
	 * repository does not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param startCommit
	 *            earliest commit
	 * @param endCommit
	 *            most recent commit. if null, HEAD is assumed.
	 * @return list of files changed in a commit range
	 */
	public static List<PathChangeModel> getFilesInRange(Repository repository, String startCommit, String endCommit) {
		List<PathChangeModel> list = new ArrayList<PathChangeModel>();
		if (!hasCommits(repository)) {
			return list;
		}
		try {
			ObjectId startRange = repository.resolve(startCommit);
			ObjectId endRange = repository.resolve(endCommit);
			RevWalk rw = new RevWalk(repository);
			RevCommit start = rw.parseCommit(startRange);
			RevCommit end = rw.parseCommit(endRange);
			list.addAll(getFilesInRange(repository, start, end));
			rw.close();
		} catch (Throwable t) {
			error(t, repository, "{0} failed to determine files in range {1}..{2}!", startCommit, endCommit);
		}
		return list;
	}

	/**
	 * Returns the list of files changed in a specified commit. If the
	 * repository does not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param startCommit
	 *            earliest commit
	 * @param endCommit
	 *            most recent commit. if null, HEAD is assumed.
	 * @return list of files changed in a commit range
	 */
	public static List<PathChangeModel> getFilesInRange(Repository repository, RevCommit startCommit, RevCommit endCommit) {
		List<PathChangeModel> list = new ArrayList<PathChangeModel>();
		if (!hasCommits(repository)) {
			return list;
		}
		try {
			DiffFormatter df = new DiffFormatter(null);
			df.setRepository(repository);
			df.setDiffComparator(RawTextComparator.DEFAULT);
			df.setDetectRenames(true);

			List<DiffEntry> diffEntries = df.scan(startCommit.getTree(), endCommit.getTree());
			for (DiffEntry diff : diffEntries) {
				PathChangeModel pcm = PathChangeModel.from(diff,  endCommit.getName(), repository);
				list.add(pcm);
			}
			Collections.sort(list);
		} catch (Throwable t) {
			error(t, repository, "{0} failed to determine files in range {1}..{2}!", startCommit, endCommit);
		}
		return list;
	}
	/**
	 * Returns the list of files in the repository on the default branch that
	 * match one of the specified extensions. This is a CASE-SENSITIVE search.
	 * If the repository does not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param extensions
	 * @return list of files in repository with a matching extension
	 */
	public static List<PathModel> getDocuments(Repository repository, List<String> extensions) {
		return getDocuments(repository, extensions, null);
	}

	/**
	 * Returns the list of files in the repository in the specified commit that
	 * match one of the specified extensions. This is a CASE-SENSITIVE search.
	 * If the repository does not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param extensions
	 * @param objectId
	 * @return list of files in repository with a matching extension
	 */
	public static List<PathModel> getDocuments(Repository repository, List<String> extensions,
			String objectId) {
		List<PathModel> list = new ArrayList<PathModel>();
		if (!hasCommits(repository)) {
			return list;
		}
		RevCommit commit = getCommit(repository, objectId);
		final TreeWalk tw = new TreeWalk(repository);
		try {
			tw.addTree(commit.getTree());
			if (extensions != null && extensions.size() > 0) {
				List<TreeFilter> suffixFilters = new ArrayList<TreeFilter>();
				for (String extension : extensions) {
					if (extension.charAt(0) == '.') {
						suffixFilters.add(PathSuffixFilter.create(extension));
					} else {
						// escape the . since this is a regexp filter
						suffixFilters.add(PathSuffixFilter.create("." + extension));
					}
				}
				TreeFilter filter;
				if (suffixFilters.size() == 1) {
					filter = suffixFilters.get(0);
				} else {
					filter = OrTreeFilter.create(suffixFilters);
				}
				tw.setFilter(filter);
				tw.setRecursive(true);
			}
			while (tw.next()) {
				list.add(getPathModel(tw, null, commit));
			}
		} catch (IOException e) {
			error(e, repository, "{0} failed to get documents for commit {1}", commit.getName());
		} finally {
			tw.close();
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns a path model of the current file in the treewalk.
	 *
	 * @param tw
	 * @param basePath
	 * @param commit
	 * @return a path model of the current file in the treewalk
	 */
	private static PathModel getPathModel(TreeWalk tw, String basePath, RevCommit commit) {
		String name;
		long size = 0;
		
		if (StringUtils.isEmpty(basePath)) {
			name = tw.getPathString();
		} else {
			name = tw.getPathString().substring(basePath.length() + 1);
		}
		ObjectId objectId = tw.getObjectId(0);
		FilestoreModel filestoreItem = null;
		
		try {
			if (!tw.isSubtree() && (tw.getFileMode(0) != FileMode.GITLINK)) {

				size = tw.getObjectReader().getObjectSize(objectId, Constants.OBJ_BLOB);

				if (isPossibleFilestoreItem(size)) {
					filestoreItem = getFilestoreItem(tw.getObjectReader().open(objectId));
				}
			}
		} catch (Throwable t) {
			error(t, null, "failed to retrieve blob size for " + tw.getPathString());
		}
		return new PathModel(name, tw.getPathString(), filestoreItem, size, tw.getFileMode(0).getBits(),
				objectId.getName(), commit.getName());
	}
	
	public static boolean isPossibleFilestoreItem(long size) {
		return (   (size >= com.gitblit.Constants.LEN_FILESTORE_META_MIN) 
				&& (size <= com.gitblit.Constants.LEN_FILESTORE_META_MAX));
	}
	
	/**
	 * 
	 * @return Representative FilestoreModel if valid, otherwise null
	 */
	public static FilestoreModel getFilestoreItem(ObjectLoader obj){
		try {
			final byte[] blob = obj.getCachedBytes(com.gitblit.Constants.LEN_FILESTORE_META_MAX);
			final String meta = new String(blob, "UTF-8");
		
			return FilestoreModel.fromMetaString(meta);

		} catch (LargeObjectException e) {
			//Intentionally failing silent
		} catch (Exception e) {
			error(e, null, "failed to retrieve filestoreItem " + obj.toString());
		}
		
		return null;
	}

	/**
	 * Returns a path model by path string
	 *
	 * @param repo
	 * @param path
	 * @param filter
	 * @param commit
	 * @return a path model of the specified object
	 */
	private static PathModel getPathModel(Repository repo, String path, String filter, RevCommit commit)
			throws IOException {

		long size = 0;
		FilestoreModel filestoreItem = null;
		TreeWalk tw = TreeWalk.forPath(repo, path, commit.getTree());
		String pathString = path;

		if (!tw.isSubtree() && (tw.getFileMode(0) != FileMode.GITLINK)) {

			pathString = PathUtils.getLastPathComponent(pathString);
			
			size = tw.getObjectReader().getObjectSize(tw.getObjectId(0), Constants.OBJ_BLOB);
			
			if (isPossibleFilestoreItem(size)) {
				filestoreItem = getFilestoreItem(tw.getObjectReader().open(tw.getObjectId(0)));
			}
		} else if (tw.isSubtree()) {

			// do not display dirs that are behind in the path
			if (!Strings.isNullOrEmpty(filter)) {
				pathString = path.replaceFirst(filter + "/", "");
			}

			// remove the last slash from path in displayed link
			if (pathString != null && pathString.charAt(pathString.length()-1) == '/') {
				pathString = pathString.substring(0, pathString.length()-1);
			}
		}

		return new PathModel(pathString, tw.getPathString(), filestoreItem, size, tw.getFileMode(0).getBits(),
				tw.getObjectId(0).getName(), commit.getName());

	}


	/**
	 * Returns a permissions representation of the mode bits.
	 *
	 * @param mode
	 * @return string representation of the mode bits
	 */
	public static String getPermissionsFromMode(int mode) {
		if (FileMode.TREE.equals(mode)) {
			return "drwxr-xr-x";
		} else if (FileMode.REGULAR_FILE.equals(mode)) {
			return "-rw-r--r--";
		} else if (FileMode.EXECUTABLE_FILE.equals(mode)) {
			return "-rwxr-xr-x";
		} else if (FileMode.SYMLINK.equals(mode)) {
			return "symlink";
		} else if (FileMode.GITLINK.equals(mode)) {
			return "submodule";
		}
		return "missing";
	}

	/**
	 * Returns a list of commits since the minimum date starting from the
	 * specified object id.
	 *
	 * @param repository
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param minimumDate
	 * @return list of commits
	 */
	public static List<RevCommit> getRevLog(Repository repository, String objectId, Date minimumDate) {
		List<RevCommit> list = new ArrayList<RevCommit>();
		if (!hasCommits(repository)) {
			return list;
		}
		try {
			// resolve branch
			ObjectId branchObject;
			if (StringUtils.isEmpty(objectId)) {
				branchObject = getDefaultBranch(repository);
			} else {
				branchObject = repository.resolve(objectId);
			}

			RevWalk rw = new RevWalk(repository);
			rw.markStart(rw.parseCommit(branchObject));
			rw.setRevFilter(CommitTimeRevFilter.after(minimumDate));
			Iterable<RevCommit> revlog = rw;
			for (RevCommit rev : revlog) {
				list.add(rev);
			}
			rw.dispose();
		} catch (Throwable t) {
			error(t, repository, "{0} failed to get {1} revlog for minimum date {2}", objectId,
					minimumDate);
		}
		return list;
	}

	/**
	 * Returns a list of commits starting from HEAD and working backwards.
	 *
	 * @param repository
	 * @param maxCount
	 *            if < 0, all commits for the repository are returned.
	 * @return list of commits
	 */
	public static List<RevCommit> getRevLog(Repository repository, int maxCount) {
		return getRevLog(repository, null, 0, maxCount);
	}

	/**
	 * Returns a list of commits starting from the specified objectId using an
	 * offset and maxCount for paging. This is similar to LIMIT n OFFSET p in
	 * SQL. If the repository does not exist or is empty, an empty list is
	 * returned.
	 *
	 * @param repository
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param offset
	 * @param maxCount
	 *            if < 0, all commits are returned.
	 * @return a paged list of commits
	 */
	public static List<RevCommit> getRevLog(Repository repository, String objectId, int offset,
			int maxCount) {
		return getRevLog(repository, objectId, null, offset, maxCount);
	}

	/**
	 * Returns a list of commits for the repository or a path within the
	 * repository. Caller may specify ending revision with objectId. Caller may
	 * specify offset and maxCount to achieve pagination of results. If the
	 * repository does not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param path
	 *            if unspecified, commits for repository are returned. If
	 *            specified, commits for the path are returned.
	 * @param offset
	 * @param maxCount
	 *            if < 0, all commits are returned.
	 * @return a paged list of commits
	 */
	public static List<RevCommit> getRevLog(Repository repository, String objectId, String path,
			int offset, int maxCount) {
		List<RevCommit> list = new ArrayList<RevCommit>();
		if (maxCount == 0) {
			return list;
		}
		if (!hasCommits(repository)) {
			return list;
		}
		try {
			// resolve branch
			ObjectId startRange = null;
			ObjectId endRange;
			if (StringUtils.isEmpty(objectId)) {
				endRange = getDefaultBranch(repository);
			} else {
				if( objectId.contains("..") ) {
					// range expression
					String[] parts = objectId.split("\\.\\.");
					startRange = repository.resolve(parts[0]);
					endRange = repository.resolve(parts[1]);
				} else {
					// objectid
					endRange= repository.resolve(objectId);
				}
			}
			if (endRange == null) {
				return list;
			}

			RevWalk rw = new RevWalk(repository);
			rw.markStart(rw.parseCommit(endRange));
			if (startRange != null) {
				rw.markUninteresting(rw.parseCommit(startRange));
			}
			if (!StringUtils.isEmpty(path)) {
				TreeFilter filter = AndTreeFilter.create(
						PathFilterGroup.createFromStrings(Collections.singleton(path)),
						TreeFilter.ANY_DIFF);
				rw.setTreeFilter(filter);
			}
			Iterable<RevCommit> revlog = rw;
			if (offset > 0) {
				int count = 0;
				for (RevCommit rev : revlog) {
					count++;
					if (count > offset) {
						list.add(rev);
						if (maxCount > 0 && list.size() == maxCount) {
							break;
						}
					}
				}
			} else {
				for (RevCommit rev : revlog) {
					list.add(rev);
					if (maxCount > 0 && list.size() == maxCount) {
						break;
					}
				}
			}
			rw.dispose();
		} catch (Throwable t) {
			error(t, repository, "{0} failed to get {1} revlog for path {2}", objectId, path);
		}
		return list;
	}

	/**
	 * Returns a list of commits for the repository within the range specified
	 * by startRangeId and endRangeId. If the repository does not exist or is
	 * empty, an empty list is returned.
	 *
	 * @param repository
	 * @param startRangeId
	 *            the first commit (not included in results)
	 * @param endRangeId
	 *            the end commit (included in results)
	 * @return a list of commits
	 */
	public static List<RevCommit> getRevLog(Repository repository, String startRangeId,
			String endRangeId) {
		List<RevCommit> list = new ArrayList<RevCommit>();
		if (!hasCommits(repository)) {
			return list;
		}
		try {
			ObjectId endRange = repository.resolve(endRangeId);
			ObjectId startRange = repository.resolve(startRangeId);

			RevWalk rw = new RevWalk(repository);
			rw.markStart(rw.parseCommit(endRange));
			if (startRange.equals(ObjectId.zeroId())) {
				// maybe this is a tag or an orphan branch
				list.add(rw.parseCommit(endRange));
				rw.dispose();
				return list;
			} else {
				rw.markUninteresting(rw.parseCommit(startRange));
			}

			Iterable<RevCommit> revlog = rw;
			for (RevCommit rev : revlog) {
				list.add(rev);
			}
			rw.dispose();
		} catch (Throwable t) {
			error(t, repository, "{0} failed to get revlog for {1}..{2}", startRangeId, endRangeId);
		}
		return list;
	}

	/**
	 * Search the commit history for a case-insensitive match to the value.
	 * Search results require a specified SearchType of AUTHOR, COMMITTER, or
	 * COMMIT. Results may be paginated using offset and maxCount. If the
	 * repository does not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param objectId
	 *            if unspecified, HEAD is assumed.
	 * @param value
	 * @param type
	 *            AUTHOR, COMMITTER, COMMIT
	 * @param offset
	 * @param maxCount
	 *            if < 0, all matches are returned
	 * @return matching list of commits
	 */
	public static List<RevCommit> searchRevlogs(Repository repository, String objectId,
			String value, final com.gitblit.Constants.SearchType type, int offset, int maxCount) {
		List<RevCommit> list = new ArrayList<RevCommit>();
		if (StringUtils.isEmpty(value)) {
			return list;
		}
		if (maxCount == 0) {
			return list;
		}
		if (!hasCommits(repository)) {
			return list;
		}
		final String lcValue = value.toLowerCase();
		try {
			// resolve branch
			ObjectId branchObject;
			if (StringUtils.isEmpty(objectId)) {
				branchObject = getDefaultBranch(repository);
			} else {
				branchObject = repository.resolve(objectId);
			}

			RevWalk rw = new RevWalk(repository);
			rw.setRevFilter(new RevFilter() {

				@Override
				public RevFilter clone() {
					// FindBugs complains about this method name.
					// This is part of JGit design and unrelated to Cloneable.
					return this;
				}

				@Override
				public boolean include(RevWalk walker, RevCommit commit) throws StopWalkException,
						MissingObjectException, IncorrectObjectTypeException, IOException {
					boolean include = false;
					switch (type) {
					case AUTHOR:
						include = (commit.getAuthorIdent().getName().toLowerCase().indexOf(lcValue) > -1)
								|| (commit.getAuthorIdent().getEmailAddress().toLowerCase()
										.indexOf(lcValue) > -1);
						break;
					case COMMITTER:
						include = (commit.getCommitterIdent().getName().toLowerCase()
								.indexOf(lcValue) > -1)
								|| (commit.getCommitterIdent().getEmailAddress().toLowerCase()
										.indexOf(lcValue) > -1);
						break;
					case COMMIT:
						include = commit.getFullMessage().toLowerCase().indexOf(lcValue) > -1;
						break;
					}
					return include;
				}

			});
			rw.markStart(rw.parseCommit(branchObject));
			Iterable<RevCommit> revlog = rw;
			if (offset > 0) {
				int count = 0;
				for (RevCommit rev : revlog) {
					count++;
					if (count > offset) {
						list.add(rev);
						if (maxCount > 0 && list.size() == maxCount) {
							break;
						}
					}
				}
			} else {
				for (RevCommit rev : revlog) {
					list.add(rev);
					if (maxCount > 0 && list.size() == maxCount) {
						break;
					}
				}
			}
			rw.dispose();
		} catch (Throwable t) {
			error(t, repository, "{0} failed to {1} search revlogs for {2}", type.name(), value);
		}
		return list;
	}

	/**
	 * Returns the default branch to use for a repository. Normally returns
	 * whatever branch HEAD points to, but if HEAD points to nothing it returns
	 * the most recently updated branch.
	 *
	 * @param repository
	 * @return the objectid of a branch
	 * @throws Exception
	 */
	public static ObjectId getDefaultBranch(Repository repository) throws Exception {
		ObjectId object = repository.resolve(Constants.HEAD);
		if (object == null) {
			// no HEAD
			// perhaps non-standard repository, try local branches
			List<RefModel> branchModels = getLocalBranches(repository, true, -1);
			if (branchModels.size() > 0) {
				// use most recently updated branch
				RefModel branch = null;
				Date lastDate = new Date(0);
				for (RefModel branchModel : branchModels) {
					if (branchModel.getDate().after(lastDate)) {
						branch = branchModel;
						lastDate = branch.getDate();
					}
				}
				object = branch.getReferencedObjectId();
			}
		}
		return object;
	}

	/**
	 * Returns the target of the symbolic HEAD reference for a repository.
	 * Normally returns a branch reference name, but when HEAD is detached,
	 * the commit is matched against the known tags. The most recent matching
	 * tag ref name will be returned if it references the HEAD commit. If
	 * no match is found, the SHA1 is returned.
	 *
	 * @param repository
	 * @return the ref name or the SHA1 for a detached HEAD
	 */
	public static String getHEADRef(Repository repository) {
		String target = null;
		try {
			target = repository.getFullBranch();
		} catch (Throwable t) {
			error(t, repository, "{0} failed to get symbolic HEAD target");
		}
		return target;
	}

	/**
	 * Sets the symbolic ref HEAD to the specified target ref. The
	 * HEAD will be detached if the target ref is not a branch.
	 *
	 * @param repository
	 * @param targetRef
	 * @return true if successful
	 */
	public static boolean setHEADtoRef(Repository repository, String targetRef) {
		try {
			 // detach HEAD if target ref is not a branch
			boolean detach = !targetRef.startsWith(Constants.R_HEADS);
			RefUpdate.Result result;
			RefUpdate head = repository.updateRef(Constants.HEAD, detach);
			if (detach) { // Tag
				RevCommit commit = getCommit(repository, targetRef);
				head.setNewObjectId(commit.getId());
				result = head.forceUpdate();
			} else {
				result = head.link(targetRef);
			}
			switch (result) {
			case NEW:
			case FORCED:
			case NO_CHANGE:
			case FAST_FORWARD:
				return true;
			default:
				LOGGER.error(MessageFormat.format("{0} HEAD update to {1} returned result {2}",
						repository.getDirectory().getAbsolutePath(), targetRef, result));
			}
		} catch (Throwable t) {
			error(t, repository, "{0} failed to set HEAD to {1}", targetRef);
		}
		return false;
	}

	/**
	 * Sets the local branch ref to point to the specified commit id.
	 *
	 * @param repository
	 * @param branch
	 * @param commitId
	 * @return true if successful
	 */
	public static boolean setBranchRef(Repository repository, String branch, String commitId) {
		String branchName = branch;
		if (!branchName.startsWith(Constants.R_REFS)) {
			branchName = Constants.R_HEADS + branch;
		}

		try {
			RefUpdate refUpdate = repository.updateRef(branchName, false);
			refUpdate.setNewObjectId(ObjectId.fromString(commitId));
			RefUpdate.Result result = refUpdate.forceUpdate();

			switch (result) {
			case NEW:
			case FORCED:
			case NO_CHANGE:
			case FAST_FORWARD:
				return true;
			default:
				LOGGER.error(MessageFormat.format("{0} {1} update to {2} returned result {3}",
						repository.getDirectory().getAbsolutePath(), branchName, commitId, result));
			}
		} catch (Throwable t) {
			error(t, repository, "{0} failed to set {1} to {2}", branchName, commitId);
		}
		return false;
	}

	/**
	 * Deletes the specified branch ref.
	 *
	 * @param repository
	 * @param branch
	 * @return true if successful
	 */
	public static boolean deleteBranchRef(Repository repository, String branch) {

		try {
			RefUpdate refUpdate = repository.updateRef(branch, false);
			refUpdate.setForceUpdate(true);
			RefUpdate.Result result = refUpdate.delete();
			switch (result) {
			case NEW:
			case FORCED:
			case NO_CHANGE:
			case FAST_FORWARD:
				return true;
			default:
				LOGGER.error(MessageFormat.format("{0} failed to delete to {1} returned result {2}",
						repository.getDirectory().getAbsolutePath(), branch, result));
			}
		} catch (Throwable t) {
			error(t, repository, "{0} failed to delete {1}", branch);
		}
		return false;
	}

	/**
	 * Get the full branch and tag ref names for any potential HEAD targets.
	 *
	 * @param repository
	 * @return a list of ref names
	 */
	public static List<String> getAvailableHeadTargets(Repository repository) {
		List<String> targets = new ArrayList<String>();
		for (RefModel branchModel : JGitUtils.getLocalBranches(repository, true, -1)) {
			targets.add(branchModel.getName());
		}

		for (RefModel tagModel : JGitUtils.getTags(repository, true, -1)) {
			targets.add(tagModel.getName());
		}
		return targets;
	}

	/**
	 * Returns all refs grouped by their associated object id.
	 *
	 * @param repository
	 * @return all refs grouped by their referenced object id
	 */
	public static Map<ObjectId, List<RefModel>> getAllRefs(Repository repository) {
		return getAllRefs(repository, true);
	}

	/**
	 * Returns all refs grouped by their associated object id.
	 *
	 * @param repository
	 * @param includeRemoteRefs
	 * @return all refs grouped by their referenced object id
	 */
	public static Map<ObjectId, List<RefModel>> getAllRefs(Repository repository, boolean includeRemoteRefs) {
		List<RefModel> list = getRefs(repository, org.eclipse.jgit.lib.RefDatabase.ALL, true, -1);
		Map<ObjectId, List<RefModel>> refs = new HashMap<ObjectId, List<RefModel>>();
		for (RefModel ref : list) {
			if (!includeRemoteRefs && ref.getName().startsWith(Constants.R_REMOTES)) {
				continue;
			}
			ObjectId objectid = ref.getReferencedObjectId();
			if (!refs.containsKey(objectid)) {
				refs.put(objectid, new ArrayList<RefModel>());
			}
			refs.get(objectid).add(ref);
		}
		return refs;
	}

	/**
	 * Returns the list of tags in the repository. If repository does not exist
	 * or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param fullName
	 *            if true, /refs/tags/yadayadayada is returned. If false,
	 *            yadayadayada is returned.
	 * @param maxCount
	 *            if < 0, all tags are returned
	 * @return list of tags
	 */
	public static List<RefModel> getTags(Repository repository, boolean fullName, int maxCount) {
		return getRefs(repository, Constants.R_TAGS, fullName, maxCount);
	}

	/**
	 * Returns the list of tags in the repository. If repository does not exist
	 * or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param fullName
	 *            if true, /refs/tags/yadayadayada is returned. If false,
	 *            yadayadayada is returned.
	 * @param maxCount
	 *            if < 0, all tags are returned
	 * @param offset
	 *            if maxCount provided sets the starting point of the records to return
	 * @return list of tags
	 */
	public static List<RefModel> getTags(Repository repository, boolean fullName, int maxCount, int offset) {
		return getRefs(repository, Constants.R_TAGS, fullName, maxCount, offset);
	}

	/**
	 * Returns the list of local branches in the repository. If repository does
	 * not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param fullName
	 *            if true, /refs/heads/yadayadayada is returned. If false,
	 *            yadayadayada is returned.
	 * @param maxCount
	 *            if < 0, all local branches are returned
	 * @return list of local branches
	 */
	public static List<RefModel> getLocalBranches(Repository repository, boolean fullName,
			int maxCount) {
		return getRefs(repository, Constants.R_HEADS, fullName, maxCount);
	}

	/**
	 * Returns the list of remote branches in the repository. If repository does
	 * not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param fullName
	 *            if true, /refs/remotes/yadayadayada is returned. If false,
	 *            yadayadayada is returned.
	 * @param maxCount
	 *            if < 0, all remote branches are returned
	 * @return list of remote branches
	 */
	public static List<RefModel> getRemoteBranches(Repository repository, boolean fullName,
			int maxCount) {
		return getRefs(repository, Constants.R_REMOTES, fullName, maxCount);
	}

	/**
	 * Returns the list of note branches. If repository does not exist or is
	 * empty, an empty list is returned.
	 *
	 * @param repository
	 * @param fullName
	 *            if true, /refs/notes/yadayadayada is returned. If false,
	 *            yadayadayada is returned.
	 * @param maxCount
	 *            if < 0, all note branches are returned
	 * @return list of note branches
	 */
	public static List<RefModel> getNoteBranches(Repository repository, boolean fullName,
			int maxCount) {
		return getRefs(repository, Constants.R_NOTES, fullName, maxCount);
	}

	/**
	 * Returns the list of refs in the specified base ref. If repository does
	 * not exist or is empty, an empty list is returned.
	 *
	 * @param repository
	 * @param fullName
	 *            if true, /refs/yadayadayada is returned. If false,
	 *            yadayadayada is returned.
	 * @return list of refs
	 */
	public static List<RefModel> getRefs(Repository repository, String baseRef) {
		return getRefs(repository, baseRef, true, -1);
	}

	/**
	 * Returns a list of references in the repository matching "refs". If the
	 * repository is null or empty, an empty list is returned.
	 *
	 * @param repository
	 * @param refs
	 *            if unspecified, all refs are returned
	 * @param fullName
	 *            if true, /refs/something/yadayadayada is returned. If false,
	 *            yadayadayada is returned.
	 * @param maxCount
	 *            if < 0, all references are returned
	 * @return list of references
	 */
	private static List<RefModel> getRefs(Repository repository, String refs, boolean fullName,
			int maxCount) {
		return getRefs(repository, refs, fullName, maxCount, 0);
	}

	/**
	 * Returns a list of references in the repository matching "refs". If the
	 * repository is null or empty, an empty list is returned.
	 *
	 * @param repository
	 * @param refs
	 *            if unspecified, all refs are returned
	 * @param fullName
	 *            if true, /refs/something/yadayadayada is returned. If false,
	 *            yadayadayada is returned.
	 * @param maxCount
	 *            if < 0, all references are returned
	 * @param offset
	 *            if maxCount provided sets the starting point of the records to return
	 * @return list of references
	 */
	private static List<RefModel> getRefs(Repository repository, String refs, boolean fullName,
			int maxCount, int offset) {
		List<RefModel> list = new ArrayList<RefModel>();
		if (maxCount == 0) {
			return list;
		}
		if (!hasCommits(repository)) {
			return list;
		}
		try {
			Map<String, Ref> map = repository.getRefDatabase().getRefs(refs);
			RevWalk rw = new RevWalk(repository);
			for (Entry<String, Ref> entry : map.entrySet()) {
				Ref ref = entry.getValue();
				RevObject object = rw.parseAny(ref.getObjectId());
				String name = entry.getKey();
				if (fullName && !StringUtils.isEmpty(refs)) {
					name = refs + name;
				}
				list.add(new RefModel(name, ref, object));
			}
			rw.dispose();
			Collections.sort(list);
			Collections.reverse(list);
			if (maxCount > 0 && list.size() > maxCount) {
				if (offset < 0) {
					offset = 0;
				}
				int endIndex = offset + maxCount;
				if (endIndex > list.size()) {
					endIndex = list.size();
				}
				list = new ArrayList<RefModel>(list.subList(offset, endIndex));
			}
		} catch (IOException e) {
			error(e, repository, "{0} failed to retrieve {1}", refs);
		}
		return list;
	}

	/**
	 * Returns a RefModel for the gh-pages branch in the repository. If the
	 * branch can not be found, null is returned.
	 *
	 * @param repository
	 * @return a refmodel for the gh-pages branch or null
	 */
	public static RefModel getPagesBranch(Repository repository) {
		return getBranch(repository, "gh-pages");
	}

	/**
	 * Returns a RefModel for a specific branch name in the repository. If the
	 * branch can not be found, null is returned.
	 *
	 * @param repository
	 * @return a refmodel for the branch or null
	 */
	public static RefModel getBranch(Repository repository, String name) {
		RefModel branch = null;
		try {
			// search for the branch in local heads
			for (RefModel ref : JGitUtils.getLocalBranches(repository, false, -1)) {
				if (ref.reference.getName().endsWith(name)) {
					branch = ref;
					break;
				}
			}

			// search for the branch in remote heads
			if (branch == null) {
				for (RefModel ref : JGitUtils.getRemoteBranches(repository, false, -1)) {
					if (ref.reference.getName().endsWith(name)) {
						branch = ref;
						break;
					}
				}
			}
		} catch (Throwable t) {
			LOGGER.error(MessageFormat.format("Failed to find {0} branch!", name), t);
		}
		return branch;
	}

	/**
	 * Returns the list of submodules for this repository.
	 *
	 * @param repository
	 * @param commit
	 * @return list of submodules
	 */
	public static List<SubmoduleModel> getSubmodules(Repository repository, String commitId) {
		RevCommit commit = getCommit(repository, commitId);
		return getSubmodules(repository, commit.getTree());
	}

	/**
	 * Returns the list of submodules for this repository.
	 *
	 * @param repository
	 * @param commit
	 * @return list of submodules
	 */
	public static List<SubmoduleModel> getSubmodules(Repository repository, RevTree tree) {
		List<SubmoduleModel> list = new ArrayList<SubmoduleModel>();
		byte [] blob = getByteContent(repository, tree, ".gitmodules", false);
		if (blob == null) {
			return list;
		}
		try {
			BlobBasedConfig config = new BlobBasedConfig(repository.getConfig(), blob);
			for (String module : config.getSubsections("submodule")) {
				String path = config.getString("submodule", module, "path");
				String url = config.getString("submodule", module, "url");
				list.add(new SubmoduleModel(module, path, url));
			}
		} catch (ConfigInvalidException e) {
			LOGGER.error("Failed to load .gitmodules file for " + repository.getDirectory(), e);
		}
		return list;
	}

	/**
	 * Returns the submodule definition for the specified path at the specified
	 * commit.  If no module is defined for the path, null is returned.
	 *
	 * @param repository
	 * @param commit
	 * @param path
	 * @return a submodule definition or null if there is no submodule
	 */
	public static SubmoduleModel getSubmoduleModel(Repository repository, String commitId, String path) {
		for (SubmoduleModel model : getSubmodules(repository, commitId)) {
			if (model.path.equals(path)) {
				return model;
			}
		}
		return null;
	}

	public static String getSubmoduleCommitId(Repository repository, String path, RevCommit commit) {
		String commitId = null;
		RevWalk rw = new RevWalk(repository);
		TreeWalk tw = new TreeWalk(repository);
		tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
		try {
			tw.reset(commit.getTree());
			while (tw.next()) {
				if (tw.isSubtree() && !path.equals(tw.getPathString())) {
					tw.enterSubtree();
					continue;
				}
				if (FileMode.GITLINK == tw.getFileMode(0)) {
					commitId = tw.getObjectId(0).getName();
					break;
				}
			}
		} catch (Throwable t) {
			error(t, repository, "{0} can't find {1} in commit {2}", path, commit.name());
		} finally {
			rw.dispose();
			tw.close();
		}
		return commitId;
	}

	/**
	 * Returns the list of notes entered about the commit from the refs/notes
	 * namespace. If the repository does not exist or is empty, an empty list is
	 * returned.
	 *
	 * @param repository
	 * @param commit
	 * @return list of notes
	 */
	public static List<GitNote> getNotesOnCommit(Repository repository, RevCommit commit) {
		List<GitNote> list = new ArrayList<GitNote>();
		if (!hasCommits(repository)) {
			return list;
		}
		List<RefModel> noteBranches = getNoteBranches(repository, true, -1);
		for (RefModel notesRef : noteBranches) {
			RevTree notesTree = JGitUtils.getCommit(repository, notesRef.getName()).getTree();
			// flat notes list
			String notePath = commit.getName();
			String text = getStringContent(repository, notesTree, notePath);
			if (!StringUtils.isEmpty(text)) {
				List<RevCommit> history = getRevLog(repository, notesRef.getName(), notePath, 0, -1);
				RefModel noteRef = new RefModel(notesRef.displayName, null, history.get(history
						.size() - 1));
				GitNote gitNote = new GitNote(noteRef, text);
				list.add(gitNote);
				continue;
			}

			// folder structure
			StringBuilder sb = new StringBuilder(commit.getName());
			sb.insert(2, '/');
			notePath = sb.toString();
			text = getStringContent(repository, notesTree, notePath);
			if (!StringUtils.isEmpty(text)) {
				List<RevCommit> history = getRevLog(repository, notesRef.getName(), notePath, 0, -1);
				RefModel noteRef = new RefModel(notesRef.displayName, null, history.get(history
						.size() - 1));
				GitNote gitNote = new GitNote(noteRef, text);
				list.add(gitNote);
			}
		}
		return list;
	}

	/**
	 * this method creates an incremental revision number as a tag according to
	 * the amount of already existing tags, which start with a defined prefix.
	 *
	 * @param repository
	 * @param objectId
	 * @param tagger
	 * @param prefix
	 * @param intPattern
	 * @param message
	 * @return true if operation was successful, otherwise false
	 */
	public static boolean createIncrementalRevisionTag(Repository repository,
			String objectId, PersonIdent tagger, String prefix, String intPattern, String message) {
		boolean result = false;
		Iterator<Entry<String, Ref>> iterator = repository.getTags().entrySet().iterator();
		long lastRev = 0;
		while (iterator.hasNext()) {
			Entry<String, Ref> entry = iterator.next();
			if (entry.getKey().startsWith(prefix)) {
				try {
					long val = Long.parseLong(entry.getKey().substring(prefix.length()));
					if (val > lastRev) {
						lastRev = val;
					}
				} catch (Exception e) {
					// this tag is NOT an incremental revision tag
				}
			}
		}
		DecimalFormat df = new DecimalFormat(intPattern);
		result = createTag(repository, objectId, tagger, prefix + df.format((lastRev + 1)), message);
		return result;
	}

	/**
	 * creates a tag in a repository
	 *
	 * @param repository
	 * @param objectId, the ref the tag points towards
	 * @param tagger, the person tagging the object
	 * @param tag, the string label
	 * @param message, the string message
	 * @return boolean, true if operation was successful, otherwise false
	 */
	public static boolean createTag(Repository repository, String objectId, PersonIdent tagger, String tag, String message) {
		try {
			Git gitClient = Git.open(repository.getDirectory());
			TagCommand tagCommand = gitClient.tag();
			tagCommand.setTagger(tagger);
			tagCommand.setMessage(message);
			if (objectId != null) {
				RevObject revObj = getCommit(repository, objectId);
				tagCommand.setObjectId(revObj);
			}
			tagCommand.setName(tag);
			Ref call = tagCommand.call();
			return call != null ? true : false;
		} catch (Exception e) {
			error(e, repository, "Failed to create tag {1} in repository {0}", objectId, tag);
		}
		return false;
	}

	/**
	 * Create an orphaned branch in a repository.
	 *
	 * @param repository
	 * @param branchName
	 * @param author
	 *            if unspecified, Gitblit will be the author of this new branch
	 * @return true if successful
	 */
	public static boolean createOrphanBranch(Repository repository, String branchName,
			PersonIdent author) {
		boolean success = false;
		String message = "Created branch " + branchName;
		if (author == null) {
			author = new PersonIdent("Gitblit", "gitblit@localhost");
		}
		try {
			ObjectInserter odi = repository.newObjectInserter();
			try {
				// Create a blob object to insert into a tree
				ObjectId blobId = odi.insert(Constants.OBJ_BLOB,
						message.getBytes(Constants.CHARACTER_ENCODING));

				// Create a tree object to reference from a commit
				TreeFormatter tree = new TreeFormatter();
				tree.append(".branch", FileMode.REGULAR_FILE, blobId);
				ObjectId treeId = odi.insert(tree);

				// Create a commit object
				CommitBuilder commit = new CommitBuilder();
				commit.setAuthor(author);
				commit.setCommitter(author);
				commit.setEncoding(Constants.CHARACTER_ENCODING);
				commit.setMessage(message);
				commit.setTreeId(treeId);

				// Insert the commit into the repository
				ObjectId commitId = odi.insert(commit);
				odi.flush();

				RevWalk revWalk = new RevWalk(repository);
				try {
					RevCommit revCommit = revWalk.parseCommit(commitId);
					if (!branchName.startsWith("refs/")) {
						branchName = "refs/heads/" + branchName;
					}
					RefUpdate ru = repository.updateRef(branchName);
					ru.setNewObjectId(commitId);
					ru.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
					Result rc = ru.forceUpdate();
					switch (rc) {
					case NEW:
					case FORCED:
					case FAST_FORWARD:
						success = true;
						break;
					default:
						success = false;
					}
				} finally {
					revWalk.close();
				}
			} finally {
				odi.close();
			}
		} catch (Throwable t) {
			error(t, repository, "Failed to create orphan branch {1} in repository {0}", branchName);
		}
		return success;
	}

	/**
	 * Reads the sparkleshare id, if present, from the repository.
	 *
	 * @param repository
	 * @return an id or null
	 */
	public static String getSparkleshareId(Repository repository) {
		byte[] content = getByteContent(repository, null, ".sparkleshare", false);
		if (content == null) {
			return null;
		}
		return StringUtils.decodeString(content);
	}

	/**
	 * Automatic repair of (some) invalid refspecs.  These are the result of a
	 * bug in JGit cloning where a double forward-slash was injected.  :(
	 *
	 * @param repository
	 * @return true, if the refspecs were repaired
	 */
	public static boolean repairFetchSpecs(Repository repository) {
		StoredConfig rc = repository.getConfig();

		// auto-repair broken fetch ref specs
		for (String name : rc.getSubsections("remote")) {
			int invalidSpecs = 0;
			int repairedSpecs = 0;
			List<String> specs = new ArrayList<String>();
			for (String spec : rc.getStringList("remote", name, "fetch")) {
				try {
					RefSpec rs = new RefSpec(spec);
					// valid spec
					specs.add(spec);
				} catch (IllegalArgumentException e) {
					// invalid spec
					invalidSpecs++;
					if (spec.contains("//")) {
						// auto-repair this known spec bug
						spec = spec.replace("//", "/");
						specs.add(spec);
						repairedSpecs++;
					}
				}
			}

			if (invalidSpecs == repairedSpecs && repairedSpecs > 0) {
				// the fetch specs were automatically repaired
				rc.setStringList("remote", name, "fetch", specs);
				try {
					rc.save();
					rc.load();
					LOGGER.debug("repaired {} invalid fetch refspecs for {}", repairedSpecs, repository.getDirectory());
					return true;
				} catch (Exception e) {
					LOGGER.error(null, e);
				}
			} else if (invalidSpecs > 0) {
				LOGGER.error("mirror executor found {} invalid fetch refspecs for {}", invalidSpecs, repository.getDirectory());
			}
		}
		return false;
	}

	/**
	 * Returns true if the commit identified by commitId is an ancestor or the
	 * the commit identified by tipId.
	 *
	 * @param repository
	 * @param commitId
	 * @param tipId
	 * @return true if there is the commit is an ancestor of the tip
	 */
	public static boolean isMergedInto(Repository repository, String commitId, String tipId) {
		try {
			return isMergedInto(repository, repository.resolve(commitId), repository.resolve(tipId));
		} catch (Exception e) {
			LOGGER.error("Failed to determine isMergedInto", e);
		}
		return false;
	}

	/**
	 * Returns true if the commit identified by commitId is an ancestor or the
	 * the commit identified by tipId.
	 *
	 * @param repository
	 * @param commitId
	 * @param tipId
	 * @return true if there is the commit is an ancestor of the tip
	 */
	public static boolean isMergedInto(Repository repository, ObjectId commitId, ObjectId tipCommitId) {
		// traverse the revlog looking for a commit chain between the endpoints
		RevWalk rw = new RevWalk(repository);
		try {
			// must re-lookup RevCommits to workaround undocumented RevWalk bug
			RevCommit tip = rw.lookupCommit(tipCommitId);
			RevCommit commit = rw.lookupCommit(commitId);
			return rw.isMergedInto(commit, tip);
		} catch (Exception e) {
			LOGGER.error("Failed to determine isMergedInto", e);
		} finally {
			rw.dispose();
		}
		return false;
	}

	/**
	 * Returns the merge base of two commits or null if there is no common
	 * ancestry.
	 *
	 * @param repository
	 * @param commitIdA
	 * @param commitIdB
	 * @return the commit id of the merge base or null if there is no common base
	 */
	public static String getMergeBase(Repository repository, ObjectId commitIdA, ObjectId commitIdB) {
		RevWalk rw = new RevWalk(repository);
		try {
			RevCommit a = rw.lookupCommit(commitIdA);
			RevCommit b = rw.lookupCommit(commitIdB);

			rw.setRevFilter(RevFilter.MERGE_BASE);
			rw.markStart(a);
			rw.markStart(b);
			RevCommit mergeBase = rw.next();
			if (mergeBase == null) {
				return null;
			}
			return mergeBase.getName();
		} catch (Exception e) {
			LOGGER.error("Failed to determine merge base", e);
		} finally {
			rw.dispose();
		}
		return null;
	}

	public static enum MergeStatus {
		MISSING_INTEGRATION_BRANCH, MISSING_SRC_BRANCH, NOT_MERGEABLE, FAILED, ALREADY_MERGED, MERGEABLE, MERGED;
	}

	/**
	 * Determines if we can cleanly merge one branch into another.  Returns true
	 * if we can merge without conflict, otherwise returns false.
	 *
	 * @param repository
	 * @param src
	 * @param toBranch
	 * @param mergeType
	 *            Defines the integration strategy to use for merging.
	 * @return true if we can merge without conflict
	 */
	public static MergeStatus canMerge(Repository repository, String src, String toBranch, MergeType mergeType) {
		IntegrationStrategy strategy = IntegrationStrategyFactory.create(mergeType, repository, src, toBranch);
		return strategy.canMerge();
	}


	public static class MergeResult {
		public final MergeStatus status;
		public final String sha;

		MergeResult(MergeStatus status, String sha) {
			this.status = status;
			this.sha = sha;
		}
	}

	/**
	 * Tries to merge a commit into a branch.  If there are conflicts, the merge
	 * will fail.
	 *
	 * @param repository
	 * @param src
	 * @param toBranch
	 * @param mergeType
	 *            Defines the integration strategy to use for merging.
	 * @param committer
	 * @param message
	 * @return the merge result
	 */
	public static MergeResult merge(Repository repository, String src, String toBranch, MergeType mergeType,
			PersonIdent committer, String message) {

		if (!toBranch.startsWith(Constants.R_REFS)) {
			// branch ref doesn't start with ref, assume this is a branch head
			toBranch = Constants.R_HEADS + toBranch;
		}

		IntegrationStrategy strategy = IntegrationStrategyFactory.create(mergeType, repository, src, toBranch);
		MergeResult mergeResult = strategy.merge(committer, message);

		if (mergeResult.status != MergeStatus.MERGED) {
			return mergeResult;
		}

		try {
			// Update the integration branch ref
			RefUpdate mergeRefUpdate = repository.updateRef(toBranch);
			mergeRefUpdate.setNewObjectId(strategy.getMergeCommit());
			mergeRefUpdate.setRefLogMessage(strategy.getRefLogMessage(), false);
			mergeRefUpdate.setExpectedOldObjectId(strategy.branchTip);
			RefUpdate.Result rc = mergeRefUpdate.update();
			switch (rc) {
			case FAST_FORWARD:
				// successful, clean merge
				break;
			default:
				mergeResult = new MergeResult(MergeStatus.FAILED, null);
				throw new GitBlitException(MessageFormat.format("Unexpected result \"{0}\" when {1} in {2}",
						rc.name(), strategy.getOperationMessage(), repository.getDirectory()));
			}
		} catch (IOException e) {
			LOGGER.error("Failed to merge", e);
		}

		return mergeResult;
	}


	private static abstract class IntegrationStrategy {
		Repository repository;
		String src;
		String toBranch;

		RevWalk revWalk;
		RevCommit branchTip;
		RevCommit srcTip;

		RevCommit mergeCommit;
		String refLogMessage;
		String operationMessage;

		RevCommit getMergeCommit() {
			return mergeCommit;
		}

		String getRefLogMessage() {
			return refLogMessage;
		}

		String getOperationMessage() {
			return operationMessage;
		}

		IntegrationStrategy(Repository repository, String src, String toBranch) {
			this.repository = repository;
			this.src = src;
			this.toBranch = toBranch;
		}

		void prepare() throws IOException {
			if (revWalk == null) revWalk = new RevWalk(repository);
			ObjectId branchId = repository.resolve(toBranch);
			if (branchId != null) {
				branchTip = revWalk.lookupCommit(branchId);
			}
			ObjectId srcId = repository.resolve(src);
			if (srcId != null) {
				srcTip = revWalk.lookupCommit(srcId);
			}
		}


		abstract MergeStatus _canMerge() throws IOException;


		MergeStatus canMerge() {
			try {
				prepare();
				if (branchTip == null) {
					return MergeStatus.MISSING_INTEGRATION_BRANCH;
				}
				if (srcTip == null) {
					return MergeStatus.MISSING_SRC_BRANCH;
				}
				if (revWalk.isMergedInto(srcTip, branchTip)) {
					// already merged
					return MergeStatus.ALREADY_MERGED;
				}
				// determined by specific integration strategy
				return _canMerge();

			} catch (NullPointerException e) {
				LOGGER.error("Failed to determine canMerge", e);
			} catch (IOException e) {
				LOGGER.error("Failed to determine canMerge", e);
			} finally {
				if (revWalk != null) {
					revWalk.close();
				}
			}

			return MergeStatus.NOT_MERGEABLE;
		}


		abstract MergeResult _merge(PersonIdent committer, String message) throws IOException;


		MergeResult merge(PersonIdent committer, String message) {
			try {
				prepare();
				if (revWalk.isMergedInto(srcTip, branchTip)) {
					// already merged
					return new MergeResult(MergeStatus.ALREADY_MERGED, null);
				}
				// determined by specific integration strategy
				return _merge(committer, message);

			} catch (IOException e) {
				LOGGER.error("Failed to merge", e);
			} finally {
				if (revWalk != null) {
					revWalk.close();
				}
			}

			return new MergeResult(MergeStatus.FAILED, null);
		}
	}


	private static class FastForwardOnly extends IntegrationStrategy {
		FastForwardOnly(Repository repository, String src, String toBranch) {
			super(repository, src, toBranch);
		}

		@Override
		MergeStatus _canMerge() throws IOException {
			if (revWalk.isMergedInto(branchTip, srcTip)) {
				// fast-forward
				return MergeStatus.MERGEABLE;
			}

			return MergeStatus.NOT_MERGEABLE;
		}

		@Override
		MergeResult _merge(PersonIdent committer, String message) throws IOException {
			if (! revWalk.isMergedInto(branchTip, srcTip)) {
				// is not fast-forward
				return new MergeResult(MergeStatus.FAILED, null);
			}

			mergeCommit = srcTip;
			refLogMessage = "merge " + src + ": Fast-forward";
			operationMessage = MessageFormat.format("fast-forwarding {0} to commit {1}", srcTip.getName(), branchTip.getName());

			return new MergeResult(MergeStatus.MERGED, srcTip.getName());
		}
	}

	private static class MergeIfNecessary extends IntegrationStrategy {
		MergeIfNecessary(Repository repository, String src, String toBranch) {
			super(repository, src, toBranch);
		}

		@Override
		MergeStatus _canMerge() throws IOException {
			if (revWalk.isMergedInto(branchTip, srcTip)) {
				// fast-forward
				return MergeStatus.MERGEABLE;
			}

			RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
			boolean canMerge = merger.merge(branchTip, srcTip);
			if (canMerge) {
				return MergeStatus.MERGEABLE;
			}

			return MergeStatus.NOT_MERGEABLE;
		}

		@Override
		MergeResult _merge(PersonIdent committer, String message) throws IOException {
			if (revWalk.isMergedInto(branchTip, srcTip)) {
				// fast-forward
				mergeCommit = srcTip;
				refLogMessage = "merge " + src + ": Fast-forward";
				operationMessage = MessageFormat.format("fast-forwarding {0} to commit {1}", branchTip.getName(), srcTip.getName());

				return new MergeResult(MergeStatus.MERGED, srcTip.getName());
			}

			RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
			boolean merged = merger.merge(branchTip, srcTip);
			if (merged) {
				// create a merge commit and a reference to track the merge commit
				ObjectId treeId = merger.getResultTreeId();
				ObjectInserter odi = repository.newObjectInserter();
				try {
					// Create a commit object
					CommitBuilder commitBuilder = new CommitBuilder();
					commitBuilder.setCommitter(committer);
					commitBuilder.setAuthor(committer);
					commitBuilder.setEncoding(Constants.CHARSET);
					if (StringUtils.isEmpty(message)) {
						message = MessageFormat.format("merge {0} into {1}", srcTip.getName(), branchTip.getName());
					}
					commitBuilder.setMessage(message);
					commitBuilder.setParentIds(branchTip.getId(), srcTip.getId());
					commitBuilder.setTreeId(treeId);

					// Insert the merge commit into the repository
					ObjectId mergeCommitId = odi.insert(commitBuilder);
					odi.flush();

					mergeCommit = revWalk.parseCommit(mergeCommitId);
					refLogMessage = "commit: " + mergeCommit.getShortMessage();
					operationMessage = MessageFormat.format("merging commit {0} into {1}", srcTip.getName(), branchTip.getName());

					// return the merge commit id
					return new MergeResult(MergeStatus.MERGED, mergeCommitId.getName());
				} finally {
					odi.close();
				}
			}
			return new MergeResult(MergeStatus.FAILED, null);
		}
	}

	private static class MergeAlways extends IntegrationStrategy {
		MergeAlways(Repository repository, String src, String toBranch) {
			super(repository, src, toBranch);
		}

		@Override
		MergeStatus _canMerge() throws IOException {
			RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
			boolean canMerge = merger.merge(branchTip, srcTip);
			if (canMerge) {
				return MergeStatus.MERGEABLE;
			}

			return MergeStatus.NOT_MERGEABLE;
		}

		@Override
		MergeResult _merge(PersonIdent committer, String message) throws IOException {
			RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
			boolean merged = merger.merge(branchTip, srcTip);
			if (merged) {
				// create a merge commit and a reference to track the merge commit
				ObjectId treeId = merger.getResultTreeId();
				ObjectInserter odi = repository.newObjectInserter();
				try {
					// Create a commit object
					CommitBuilder commitBuilder = new CommitBuilder();
					commitBuilder.setCommitter(committer);
					commitBuilder.setAuthor(committer);
					commitBuilder.setEncoding(Constants.CHARSET);
					if (StringUtils.isEmpty(message)) {
						message = MessageFormat.format("merge {0} into {1}", srcTip.getName(), branchTip.getName());
					}
					commitBuilder.setMessage(message);
					commitBuilder.setParentIds(branchTip.getId(), srcTip.getId());
					commitBuilder.setTreeId(treeId);

					// Insert the merge commit into the repository
					ObjectId mergeCommitId = odi.insert(commitBuilder);
					odi.flush();

					mergeCommit = revWalk.parseCommit(mergeCommitId);
					refLogMessage = "commit: " + mergeCommit.getShortMessage();
					operationMessage = MessageFormat.format("merging commit {0} into {1}", srcTip.getName(), branchTip.getName());

					// return the merge commit id
					return new MergeResult(MergeStatus.MERGED, mergeCommitId.getName());
				} finally {
					odi.close();
				}
			}

			return new MergeResult(MergeStatus.FAILED, null);
		}
	}


	private static class IntegrationStrategyFactory {
		static IntegrationStrategy create(MergeType mergeType, Repository repository, String src, String toBranch) {
			switch(mergeType) {
			case FAST_FORWARD_ONLY:
				return new FastForwardOnly(repository, src, toBranch);
			case MERGE_IF_NECESSARY:
				return new MergeIfNecessary(repository, src, toBranch);
			case MERGE_ALWAYS:
				return new MergeAlways(repository, src, toBranch);
			}
			return null;
		}
	}


	/**
	 * Returns the LFS URL for the given oid 
	 * Currently assumes that the Gitblit Filestore is used 
	 *
	 * @param baseURL
	 * @param repository name
	 * @param oid of lfs item
	 * @return the lfs item URL
	 */
	public static String getLfsRepositoryUrl(String baseURL, String repositoryName, String oid) {
		
		if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
			baseURL = baseURL.substring(0, baseURL.length() - 1);
		}
		
		return baseURL + com.gitblit.Constants.R_PATH 
					   + repositoryName + "/" 
					   + com.gitblit.Constants.R_LFS 
					   + "objects/" + oid;
		
	}
	
	/**
	 * Returns all tree entries that do not match the ignore paths.
	 *
	 * @param db
	 * @param ignorePaths
	 * @param dcBuilder
	 * @throws IOException
	 */
	public static List<DirCacheEntry> getTreeEntries(Repository db, String branch, Collection<String> ignorePaths) throws IOException {
		List<DirCacheEntry> list = new ArrayList<DirCacheEntry>();
		TreeWalk tw = null;
		try {
			ObjectId treeId = db.resolve(branch + "^{tree}");
			if (treeId == null) {
				// branch does not exist yet
				return list;
			}
			tw = new TreeWalk(db);
			int hIdx = tw.addTree(treeId);
			tw.setRecursive(true);

			while (tw.next()) {
				String path = tw.getPathString();
				CanonicalTreeParser hTree = null;
				if (hIdx != -1) {
					hTree = tw.getTree(hIdx, CanonicalTreeParser.class);
				}
				if (!ignorePaths.contains(path)) {
					// add all other tree entries
					if (hTree != null) {
						final DirCacheEntry entry = new DirCacheEntry(path);
						entry.setObjectId(hTree.getEntryObjectId());
						entry.setFileMode(hTree.getEntryFileMode());
						list.add(entry);
					}
				}
			}
		} finally {
			if (tw != null) {
				tw.close();
			}
		}
		return list;
	}
	
	public static boolean commitIndex(Repository db, String branch, DirCache index,
									  ObjectId parentId, boolean forceCommit,
									  String author, String authorEmail, String message) throws IOException, ConcurrentRefUpdateException {
		boolean success = false;

		ObjectId headId = db.resolve(branch + "^{commit}");
		ObjectId baseId = parentId;
		if (baseId == null || headId == null) { return false; }
		
		ObjectInserter odi = db.newObjectInserter();
		try {
			// Create the in-memory index of the new/updated ticket
			ObjectId indexTreeId = index.writeTree(odi);

			// Create a commit object
			PersonIdent ident = new PersonIdent(author, authorEmail);
			
			if (forceCommit == false) {
				ThreeWayMerger merger = MergeStrategy.RECURSIVE.newMerger(db, true);
				merger.setObjectInserter(odi);
				merger.setBase(baseId);
				boolean mergeSuccess = merger.merge(indexTreeId, headId);
				
				if (mergeSuccess) {
					indexTreeId = merger.getResultTreeId();
				 } else {
					//Manual merge required
					return false; 
				 }
			}
			
			CommitBuilder commit = new CommitBuilder();
			commit.setAuthor(ident);
			commit.setCommitter(ident);
			commit.setEncoding(com.gitblit.Constants.ENCODING);
			commit.setMessage(message);
			commit.setParentId(headId);
			commit.setTreeId(indexTreeId);

			// Insert the commit into the repository
			ObjectId commitId = odi.insert(commit);
			odi.flush();

			RevWalk revWalk = new RevWalk(db);
			try {
				RevCommit revCommit = revWalk.parseCommit(commitId);
				RefUpdate ru = db.updateRef(branch);
				ru.setForceUpdate(forceCommit);
				ru.setNewObjectId(commitId);
				ru.setExpectedOldObjectId(headId);
				ru.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
				Result rc = ru.update();

				switch (rc) {
				case NEW:
				case FORCED:
				case FAST_FORWARD:
					success = true;
					break;
				case REJECTED:
				case LOCK_FAILURE:
					throw new ConcurrentRefUpdateException(JGitText.get().couldNotLockHEAD,
							ru.getRef(), rc);
				default:
					throw new JGitInternalException(MessageFormat.format(
							JGitText.get().updatingRefFailed, branch, commitId.toString(),
							rc));
				}
			} finally {
				revWalk.close();
			}
		} finally {
			odi.close();
		}
		return success;
	}
	
	/**
	 * Returns true if the commit identified by commitId is at the tip of it's branch.
	 *
	 * @param repository
	 * @param commitId
	 * @return true if the given commit is the tip
	 */
	public static boolean isTip(Repository repository, String commitId) {
		try {
			RefModel tip = getBranch(repository, commitId);
			return (tip != null);	
		} catch (Exception e) {
			LOGGER.error("Failed to determine isTip", e);
		}
		return false;
	}
	
	/*
	 * Identify ticket by considering the branch the commit is on
	 * 
	 * @param repository
	 * @param commit 
	 * @return ticket number, or 0 if no ticket
	 */
	public static long getTicketNumberFromCommitBranch(Repository repository, RevCommit commit) {
		// try lookup by change ref
		Map<AnyObjectId, Set<Ref>> map = repository.getAllRefsByPeeledObjectId();
		Set<Ref> refs = map.get(commit.getId());
		if (!ArrayUtils.isEmpty(refs)) {
			for (Ref ref : refs) {
				long number = PatchsetCommand.getTicketNumber(ref.getName());
				
				if (number > 0) {
					return number;
				}
			}
		}
		
		return 0;
	}
	
	
	/**
	 * Try to identify all referenced tickets from the commit.
	 *
	 * @param commit
	 * @return a collection of TicketLinks
	 */
	@NotNull
	public static List<TicketLink> identifyTicketsFromCommitMessage(Repository repository, IStoredSettings settings,
			RevCommit commit) {
		List<TicketLink> ticketLinks = new ArrayList<TicketLink>();
		List<Long> linkedTickets = new ArrayList<Long>();

		// parse commit message looking for fixes/closes #n
		final String xFixDefault = "(?:fixes|closes)[\\s-]+#?(\\d+)";
		String xFix = settings.getString(Keys.tickets.closeOnPushCommitMessageRegex, xFixDefault);
		if (StringUtils.isEmpty(xFix)) {
			xFix = xFixDefault;
		}
		try {
			Pattern p = Pattern.compile(xFix, Pattern.CASE_INSENSITIVE);
			Matcher m = p.matcher(commit.getFullMessage());
			while (m.find()) {
				String val = m.group(1);
				long number = Long.parseLong(val); 
				
				if (number > 0) {
					ticketLinks.add(new TicketLink(number, TicketAction.Close));
					linkedTickets.add(number);
				}
			}
		} catch (Exception e) {
			LOGGER.error(String.format("Failed to parse \"%s\" in commit %s", xFix, commit.getName()), e);
		}
		
		// parse commit message looking for ref #n
		final String xRefDefault = "(?:ref|task|issue|bug)?[\\s-]*#(\\d+)";
		String xRef = settings.getString(Keys.tickets.linkOnPushCommitMessageRegex, xRefDefault);
		if (StringUtils.isEmpty(xRef)) {
			xRef = xRefDefault;
		}
		try {
			Pattern p = Pattern.compile(xRef, Pattern.CASE_INSENSITIVE);
			Matcher m = p.matcher(commit.getFullMessage());
			while (m.find()) {
				String val = m.group(1);
				long number = Long.parseLong(val); 
				//Most generic case so don't included tickets more precisely linked
				if ((number > 0) && (!linkedTickets.contains(number))) {
					ticketLinks.add( new TicketLink(number, TicketAction.Commit, commit.getName()));
					linkedTickets.add(number);
				}
			}
		} catch (Exception e) {
			LOGGER.error(String.format("Failed to parse \"%s\" in commit %s", xRef, commit.getName()), e);
		}

		return ticketLinks;
	}
	
	/**
	 * Try to identify all referenced tickets between two commits
	 *
	 * @param commit
	 * @param parseMessage
	 * @param currentTicketId, or 0 if not on a ticket branch
	 * @return a collection of TicketLink, or null if commit is already linked
	 */
	public static List<TicketLink> identifyTicketsBetweenCommits(Repository repository, IStoredSettings settings,
			String baseSha, String tipSha) {
		List<TicketLink> links = new ArrayList<TicketLink>();
		if (repository == null) { return links; }
		
		RevWalk walk = new RevWalk(repository);
		walk.sort(RevSort.TOPO);
		walk.sort(RevSort.REVERSE, true);
		try {
			RevCommit tip = walk.parseCommit(repository.resolve(tipSha));
			RevCommit base = walk.parseCommit(repository.resolve(baseSha));
			walk.markStart(tip);
			walk.markUninteresting(base);
			for (;;) {
				RevCommit commit = walk.next();
				if (commit == null) {
					break;
				}
				links.addAll(JGitUtils.identifyTicketsFromCommitMessage(repository, settings, commit));
			}
		} catch (IOException e) {
			LOGGER.error("failed to identify tickets between commits.", e);
		} finally {
			walk.dispose();
		}
		
		return links;
	}
	
	public static int countCommits(Repository repository, RevWalk walk, ObjectId baseId, ObjectId tipId) {
		int count = 0;
		walk.reset();
		walk.sort(RevSort.TOPO);
		walk.sort(RevSort.REVERSE, true);
		try {
			RevCommit tip = walk.parseCommit(tipId);
			RevCommit base = walk.parseCommit(baseId);
			walk.markStart(tip);
			walk.markUninteresting(base);
			for (;;) {
				RevCommit c = walk.next();
				if (c == null) {
					break;
				}
				count++;
			}
		} catch (IOException e) {
			// Should never happen, the core receive process would have
			// identified the missing object earlier before we got control.
			LOGGER.error("failed to get commit count", e);
			return 0;
		} finally {
			walk.close();
		}
		return count;
	}

	public static int countCommits(Repository repository, RevWalk walk, String baseId, String tipId) {
		int count = 0;
		try {
			count = countCommits(repository, walk, repository.resolve(baseId),repository.resolve(tipId));
		} catch (IOException e) {
			LOGGER.error("failed to get commit count", e);
		}
		return count;
	}
}
