/*
 * 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.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
	 * @return true if we can merge without conflict
	 */
	public static MergeStatus canMerge(Repository repository, String src, String toBranch) {
		RevWalk revWalk = null;
		try {
			revWalk = new RevWalk(repository);
			ObjectId branchId = repository.resolve(toBranch);
			if (branchId == null) {
				return MergeStatus.MISSING_INTEGRATION_BRANCH;
			}
			ObjectId srcId = repository.resolve(src);
			if (srcId == null) {
				return MergeStatus.MISSING_SRC_BRANCH;
			}
			RevCommit branchTip = revWalk.lookupCommit(branchId);
			RevCommit srcTip = revWalk.lookupCommit(srcId);
			if (revWalk.isMergedInto(srcTip, branchTip)) {
				// already merged
				return MergeStatus.ALREADY_MERGED;
			} else 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;
			}
		} 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;
	}


	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 committer
	 * @param message
	 * @return the merge result
	 */
	public static MergeResult merge(Repository repository, String src, String toBranch,
			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;
		}

		RevWalk revWalk = null;
		try {
			revWalk = new RevWalk(repository);
			RevCommit branchTip = revWalk.lookupCommit(repository.resolve(toBranch));
			RevCommit srcTip = revWalk.lookupCommit(repository.resolve(src));
			if (revWalk.isMergedInto(srcTip, branchTip)) {
				// already merged
				return new MergeResult(MergeStatus.ALREADY_MERGED, null);
			}
			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();

					// set the merge ref to the merge commit
					RevCommit mergeCommit = revWalk.parseCommit(mergeCommitId);
					RefUpdate mergeRefUpdate = repository.updateRef(toBranch);
					mergeRefUpdate.setNewObjectId(mergeCommitId);
					mergeRefUpdate.setRefLogMessage("commit: " + mergeCommit.getShortMessage(), false);
					RefUpdate.Result rc = mergeRefUpdate.update();
					switch (rc) {
					case FAST_FORWARD:
						// successful, clean merge
						break;
					default:
						throw new GitBlitException(MessageFormat.format("Unexpected result \"{0}\" when merging commit {1} into {2} in {3}",
								rc.name(), srcTip.getName(), branchTip.getName(), repository.getDirectory()));
					}

					// return the merge commit id
					return new MergeResult(MergeStatus.MERGED, mergeCommitId.getName());
				} finally {
					odi.close();
				}
			}
		} catch (IOException e) {
			LOGGER.error("Failed to merge", e);
		} finally {
			if (revWalk != null) {
				revWalk.close();
			}
		}
		return new MergeResult(MergeStatus.FAILED, 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;
	}
}
