/*
 * Copyright 2013 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.manager;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.storage.file.WindowCacheConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants;
import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.Constants.CommitMessageRenderer;
import com.gitblit.Constants.FederationStrategy;
import com.gitblit.Constants.PermissionType;
import com.gitblit.Constants.RegistrantType;
import com.gitblit.GitBlitException;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.extensions.RepositoryLifeCycleListener;
import com.gitblit.models.ForkModel;
import com.gitblit.models.Metric;
import com.gitblit.models.RefModel;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.SearchResult;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.service.GarbageCollectorService;
import com.gitblit.service.LuceneService;
import com.gitblit.service.MirrorService;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.ByteFormat;
import com.gitblit.utils.CommitCache;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.JGitUtils.LastChange;
import com.gitblit.utils.MetricUtils;
import com.gitblit.utils.ModelUtils;
import com.gitblit.utils.ObjectCache;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TimeUtils;

/**
 * Repository manager creates, updates, deletes and caches git repositories.  It
 * also starts services to mirror, index, and cleanup repositories.
 *
 * @author James Moger
 *
 */
public class RepositoryManager implements IRepositoryManager {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(5);

	private final ObjectCache<Long> repositorySizeCache = new ObjectCache<Long>();

	private final ObjectCache<List<Metric>> repositoryMetricsCache = new ObjectCache<List<Metric>>();

	private final Map<String, RepositoryModel> repositoryListCache = new ConcurrentHashMap<String, RepositoryModel>();

	private final AtomicReference<String> repositoryListSettingsChecksum = new AtomicReference<String>("");

	private final IStoredSettings settings;

	private final IRuntimeManager runtimeManager;

	private final IPluginManager pluginManager;

	private final IUserManager userManager;

	private final File repositoriesFolder;

	private LuceneService luceneExecutor;

	private GarbageCollectorService gcExecutor;

	private MirrorService mirrorExecutor;

	public RepositoryManager(
			IRuntimeManager runtimeManager,
			IPluginManager pluginManager,
			IUserManager userManager) {

		this.settings = runtimeManager.getSettings();
		this.runtimeManager = runtimeManager;
		this.pluginManager = pluginManager;
		this.userManager = userManager;
		this.repositoriesFolder = runtimeManager.getFileOrFolder(Keys.git.repositoriesFolder, "${baseFolder}/git");
	}

	@Override
	public RepositoryManager start() {
		logger.info("Repositories folder : {}", repositoriesFolder.getAbsolutePath());

		// initialize utilities
		String prefix = settings.getString(Keys.git.userRepositoryPrefix, "~");
		ModelUtils.setUserRepoPrefix(prefix);

		// calculate repository list settings checksum for future config changes
		repositoryListSettingsChecksum.set(getRepositoryListSettingsChecksum());

		// build initial repository list
		if (settings.getBoolean(Keys.git.cacheRepositoryList,  true)) {
			logger.info("Identifying repositories...");
			getRepositoryList();
		}

		configureLuceneIndexing();
		configureGarbageCollector();
		configureMirrorExecutor();
		configureJGit();
		configureCommitCache();

		confirmWriteAccess();

		return this;
	}

	@Override
	public RepositoryManager stop() {
		scheduledExecutor.shutdownNow();
		luceneExecutor.close();
		gcExecutor.close();
		mirrorExecutor.close();

		closeAll();
		return this;
	}

	/**
	 * Returns the most recent change date of any repository served by Gitblit.
	 *
	 * @return a date
	 */
	@Override
	public Date getLastActivityDate() {
		Date date = null;
		for (String name : getRepositoryList()) {
			Repository r = getRepository(name);
			Date lastChange = JGitUtils.getLastChange(r).when;
			r.close();
			if (lastChange != null && (date == null || lastChange.after(date))) {
				date = lastChange;
			}
		}
		return date;
	}

	/**
	 * Returns the path of the repositories folder. This method checks to see if
	 * Gitblit is running on a cloud service and may return an adjusted path.
	 *
	 * @return the repositories folder path
	 */
	@Override
	public File getRepositoriesFolder() {
		return repositoriesFolder;
	}

	/**
	 * Returns the path of the Groovy folder. This method checks to see if
	 * Gitblit is running on a cloud service and may return an adjusted path.
	 *
	 * @return the Groovy scripts folder path
	 */
	@Override
	public File getHooksFolder() {
		return runtimeManager.getFileOrFolder(Keys.groovy.scriptsFolder, "${baseFolder}/groovy");
	}

	/**
	 * Returns the path of the Groovy Grape folder. This method checks to see if
	 * Gitblit is running on a cloud service and may return an adjusted path.
	 *
	 * @return the Groovy Grape folder path
	 */
	@Override
	public File getGrapesFolder() {
		return runtimeManager.getFileOrFolder(Keys.groovy.grapeFolder, "${baseFolder}/groovy/grape");
	}

	/**
	 *
	 * @return true if we are running the gc executor
	 */
	@Override
	public boolean isCollectingGarbage() {
		return gcExecutor != null && gcExecutor.isRunning();
	}

	/**
	 * Returns true if Gitblit is actively collecting garbage in this repository.
	 *
	 * @param repositoryName
	 * @return true if actively collecting garbage
	 */
	@Override
	public boolean isCollectingGarbage(String repositoryName) {
		return gcExecutor != null && gcExecutor.isCollectingGarbage(repositoryName);
	}

	/**
	 * Returns the effective list of permissions for this user, taking into account
	 * team memberships, ownerships.
	 *
	 * @param user
	 * @return the effective list of permissions for the user
	 */
	@Override
	public List<RegistrantAccessPermission> getUserAccessPermissions(UserModel user) {
		if (StringUtils.isEmpty(user.username)) {
			// new user
			return new ArrayList<RegistrantAccessPermission>();
		}
		Set<RegistrantAccessPermission> set = new LinkedHashSet<RegistrantAccessPermission>();
		set.addAll(user.getRepositoryPermissions());
		// Flag missing repositories
		for (RegistrantAccessPermission permission : set) {
			if (permission.mutable && PermissionType.EXPLICIT.equals(permission.permissionType)) {
				RepositoryModel rm = getRepositoryModel(permission.registrant);
				if (rm == null) {
					permission.permissionType = PermissionType.MISSING;
					permission.mutable = false;
					continue;
				}
			}
		}

		// manually specify personal repository ownerships
		for (RepositoryModel rm : repositoryListCache.values()) {
			if (user.isOwner(rm)) {
				RegistrantAccessPermission rp = new RegistrantAccessPermission(rm.name, AccessPermission.REWIND,
						PermissionType.OWNER, RegistrantType.REPOSITORY, null, false);
				// user may be owner of a repository to which they've inherited
				// a team permission, replace any existing perm with owner perm
				set.remove(rp);
				set.add(rp);
			}
		}

		List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>(set);
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of users and their access permissions for the specified
	 * repository including permission source information such as the team or
	 * regular expression which sets the permission.
	 *
	 * @param repository
	 * @return a list of RegistrantAccessPermissions
	 */
	@Override
	public List<RegistrantAccessPermission> getUserAccessPermissions(RepositoryModel repository) {
		List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
		if (AccessRestrictionType.NONE.equals(repository.accessRestriction)) {
			// no permissions needed, REWIND for everyone!
			return list;
		}
		if (AuthorizationControl.AUTHENTICATED.equals(repository.authorizationControl)) {
			// no permissions needed, REWIND for authenticated!
			return list;
		}
		// NAMED users and teams
		for (UserModel user : userManager.getAllUsers()) {
			RegistrantAccessPermission ap = user.getRepositoryPermission(repository);
			if (ap.permission.exceeds(AccessPermission.NONE)) {
				list.add(ap);
			}
		}
		return list;
	}

	/**
	 * Sets the access permissions to the specified repository for the specified users.
	 *
	 * @param repository
	 * @param permissions
	 * @return true if the user models have been updated
	 */
	@Override
	public boolean setUserAccessPermissions(RepositoryModel repository, Collection<RegistrantAccessPermission> permissions) {
		List<UserModel> users = new ArrayList<UserModel>();
		for (RegistrantAccessPermission up : permissions) {
			if (up.mutable) {
				// only set editable defined permissions
				UserModel user = userManager.getUserModel(up.registrant);
				user.setRepositoryPermission(repository.name, up.permission);
				users.add(user);
			}
		}
		return userManager.updateUserModels(users);
	}

	/**
	 * Returns the list of all users who have an explicit access permission
	 * for the specified repository.
	 *
	 * @see IUserService.getUsernamesForRepositoryRole(String)
	 * @param repository
	 * @return list of all usernames that have an access permission for the repository
	 */
	@Override
	public List<String> getRepositoryUsers(RepositoryModel repository) {
		return userManager.getUsernamesForRepositoryRole(repository.name);
	}

	/**
	 * Returns the list of teams and their access permissions for the specified
	 * repository including the source of the permission such as the admin flag
	 * or a regular expression.
	 *
	 * @param repository
	 * @return a list of RegistrantAccessPermissions
	 */
	@Override
	public List<RegistrantAccessPermission> getTeamAccessPermissions(RepositoryModel repository) {
		List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
		for (TeamModel team : userManager.getAllTeams()) {
			RegistrantAccessPermission ap = team.getRepositoryPermission(repository);
			if (ap.permission.exceeds(AccessPermission.NONE)) {
				list.add(ap);
			}
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Sets the access permissions to the specified repository for the specified teams.
	 *
	 * @param repository
	 * @param permissions
	 * @return true if the team models have been updated
	 */
	@Override
	public boolean setTeamAccessPermissions(RepositoryModel repository, Collection<RegistrantAccessPermission> permissions) {
		List<TeamModel> teams = new ArrayList<TeamModel>();
		for (RegistrantAccessPermission tp : permissions) {
			if (tp.mutable) {
				// only set explicitly defined access permissions
				TeamModel team = userManager.getTeamModel(tp.registrant);
				team.setRepositoryPermission(repository.name, tp.permission);
				teams.add(team);
			}
		}
		return userManager.updateTeamModels(teams);
	}

	/**
	 * Returns the list of all teams who have an explicit access permission for
	 * the specified repository.
	 *
	 * @see IUserService.getTeamnamesForRepositoryRole(String)
	 * @param repository
	 * @return list of all teamnames with explicit access permissions to the repository
	 */
	@Override
	public List<String> getRepositoryTeams(RepositoryModel repository) {
		return userManager.getTeamNamesForRepositoryRole(repository.name);
	}

	/**
	 * Adds the repository to the list of cached repositories if Gitblit is
	 * configured to cache the repository list.
	 *
	 * @param model
	 */
	@Override
	public void addToCachedRepositoryList(RepositoryModel model) {
		if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
			repositoryListCache.put(model.name.toLowerCase(), model);

			// update the fork origin repository with this repository clone
			if (!StringUtils.isEmpty(model.originRepository)) {
				String originKey = model.originRepository.toLowerCase();
				if (repositoryListCache.containsKey(originKey)) {
					RepositoryModel origin = repositoryListCache.get(originKey);
					origin.addFork(model.name);
				}
			}
		}
	}

	/**
	 * Removes the repository from the list of cached repositories.
	 *
	 * @param name
	 * @return the model being removed
	 */
	private RepositoryModel removeFromCachedRepositoryList(String name) {
		if (StringUtils.isEmpty(name)) {
			return null;
		}
		return repositoryListCache.remove(name.toLowerCase());
	}

	/**
	 * Clears all the cached metadata for the specified repository.
	 *
	 * @param repositoryName
	 */
	private void clearRepositoryMetadataCache(String repositoryName) {
		repositorySizeCache.remove(repositoryName);
		repositoryMetricsCache.remove(repositoryName);
		CommitCache.instance().clear(repositoryName);
	}

	/**
	 * Reset all caches for this repository.
	 *
	 * @param repositoryName
	 * @since 1.5.1
	 */
	@Override
	public void resetRepositoryCache(String repositoryName) {
		removeFromCachedRepositoryList(repositoryName);
		clearRepositoryMetadataCache(repositoryName);
		// force a reload of the repository data (ticket-82, issue-433)
		getRepositoryModel(repositoryName);
	}

	/**
	 * Resets the repository list cache.
	 *
	 */
	@Override
	public void resetRepositoryListCache() {
		logger.info("Repository cache manually reset");
		repositoryListCache.clear();
		repositorySizeCache.clear();
		repositoryMetricsCache.clear();
		CommitCache.instance().clear();
	}

	/**
	 * Calculate the checksum of settings that affect the repository list cache.
	 * @return a checksum
	 */
	private String getRepositoryListSettingsChecksum() {
		StringBuilder ns = new StringBuilder();
		ns.append(settings.getString(Keys.git.cacheRepositoryList, "")).append('\n');
		ns.append(settings.getString(Keys.git.onlyAccessBareRepositories, "")).append('\n');
		ns.append(settings.getString(Keys.git.searchRepositoriesSubfolders, "")).append('\n');
		ns.append(settings.getString(Keys.git.searchRecursionDepth, "")).append('\n');
		ns.append(settings.getString(Keys.git.searchExclusions, "")).append('\n');
		String checksum = StringUtils.getSHA1(ns.toString());
		return checksum;
	}

	/**
	 * Compare the last repository list setting checksum to the current checksum.
	 * If different then clear the cache so that it may be rebuilt.
	 *
	 * @return true if the cached repository list is valid since the last check
	 */
	private boolean isValidRepositoryList() {
		String newChecksum = getRepositoryListSettingsChecksum();
		boolean valid = newChecksum.equals(repositoryListSettingsChecksum.get());
		repositoryListSettingsChecksum.set(newChecksum);
		if (!valid && settings.getBoolean(Keys.git.cacheRepositoryList,  true)) {
			logger.info("Repository list settings have changed. Clearing repository list cache.");
			repositoryListCache.clear();
		}
		return valid;
	}

	/**
	 * Returns the list of all repositories available to Gitblit. This method
	 * does not consider user access permissions.
	 *
	 * @return list of all repositories
	 */
	@Override
	public List<String> getRepositoryList() {
		if (repositoryListCache.size() == 0 || !isValidRepositoryList()) {
			// we are not caching OR we have not yet cached OR the cached list is invalid
			long startTime = System.currentTimeMillis();
			List<String> repositories = JGitUtils.getRepositoryList(repositoriesFolder,
					settings.getBoolean(Keys.git.onlyAccessBareRepositories, false),
					settings.getBoolean(Keys.git.searchRepositoriesSubfolders, true),
					settings.getInteger(Keys.git.searchRecursionDepth, -1),
					settings.getStrings(Keys.git.searchExclusions));

			if (!settings.getBoolean(Keys.git.cacheRepositoryList,  true)) {
				// we are not caching
				StringUtils.sortRepositorynames(repositories);
				return repositories;
			} else {
				// we are caching this list
				String msg = "{0} repositories identified in {1} msecs";
				if (settings.getBoolean(Keys.web.showRepositorySizes, true)) {
					// optionally (re)calculate repository sizes
					msg = "{0} repositories identified with calculated folder sizes in {1} msecs";
				}

				for (String repository : repositories) {
					getRepositoryModel(repository);
				}

				// rebuild fork networks
				for (RepositoryModel model : repositoryListCache.values()) {
					if (!StringUtils.isEmpty(model.originRepository)) {
						String originKey = model.originRepository.toLowerCase();
						if (repositoryListCache.containsKey(originKey)) {
							RepositoryModel origin = repositoryListCache.get(originKey);
							origin.addFork(model.name);
						}
					}
				}

				long duration = System.currentTimeMillis() - startTime;
				logger.info(MessageFormat.format(msg, repositoryListCache.size(), duration));
			}
		}

		// return sorted copy of cached list
		List<String> list = new ArrayList<String>();
		for (RepositoryModel model : repositoryListCache.values()) {
			list.add(model.name);
		}
		StringUtils.sortRepositorynames(list);
		return list;
	}

	/**
	 * Returns the JGit repository for the specified name.
	 *
	 * @param repositoryName
	 * @return repository or null
	 */
	@Override
	public Repository getRepository(String repositoryName) {
		return getRepository(repositoryName, true);
	}

	/**
	 * Returns the JGit repository for the specified name.
	 *
	 * @param repositoryName
	 * @param logError
	 * @return repository or null
	 */
	@Override
	public Repository getRepository(String repositoryName, boolean logError) {
		// Decode url-encoded repository name (issue-278)
		// http://stackoverflow.com/questions/17183110
		repositoryName = repositoryName.replace("%7E", "~").replace("%7e", "~");

		if (isCollectingGarbage(repositoryName)) {
			logger.warn(MessageFormat.format("Rejecting request for {0}, busy collecting garbage!", repositoryName));
			return null;
		}

		File dir = FileKey.resolve(new File(repositoriesFolder, repositoryName), FS.DETECTED);
		if (dir == null)
			return null;

		Repository r = null;
		try {
			FileKey key = FileKey.exact(dir, FS.DETECTED);
			r = RepositoryCache.open(key, true);
		} catch (IOException e) {
			if (logError) {
				logger.error("GitBlit.getRepository(String) failed to find "
						+ new File(repositoriesFolder, repositoryName).getAbsolutePath());
			}
		}
		return r;
	}

	/**
	 * Returns the list of repository models that are accessible to the user.
	 *
	 * @param user
	 * @return list of repository models accessible to user
	 */
	@Override
	public List<RepositoryModel> getRepositoryModels(UserModel user) {
		long methodStart = System.currentTimeMillis();
		List<String> list = getRepositoryList();
		List<RepositoryModel> repositories = new ArrayList<RepositoryModel>();
		for (String repo : list) {
			RepositoryModel model = getRepositoryModel(user, repo);
			if (model != null) {
				if (!model.hasCommits) {
					// only add empty repositories that user can push to
					if (UserModel.ANONYMOUS.canPush(model)
							|| user != null && user.canPush(model)) {
						repositories.add(model);
					}
				} else {
					repositories.add(model);
				}
			}
		}
		long duration = System.currentTimeMillis() - methodStart;
		logger.info(MessageFormat.format("{0} repository models loaded for {1} in {2} msecs",
				repositories.size(), user == null ? "anonymous" : user.username, duration));
		return repositories;
	}

	/**
	 * Returns a repository model if the repository exists and the user may
	 * access the repository.
	 *
	 * @param user
	 * @param repositoryName
	 * @return repository model or null
	 */
	@Override
	public RepositoryModel getRepositoryModel(UserModel user, String repositoryName) {
		RepositoryModel model = getRepositoryModel(repositoryName);
		if (model == null) {
			return null;
		}
		if (user == null) {
			user = UserModel.ANONYMOUS;
		}
		if (user.canView(model)) {
			return model;
		}
		return null;
	}

	/**
	 * Returns the repository model for the specified repository. This method
	 * does not consider user access permissions.
	 *
	 * @param repositoryName
	 * @return repository model or null
	 */
	@Override
	public RepositoryModel getRepositoryModel(String repositoryName) {
		// Decode url-encoded repository name (issue-278)
		// http://stackoverflow.com/questions/17183110
		repositoryName = repositoryName.replace("%7E", "~").replace("%7e", "~");

		String repositoryKey = repositoryName.toLowerCase();
		if (!repositoryListCache.containsKey(repositoryKey)) {
			RepositoryModel model = loadRepositoryModel(repositoryName);
			if (model == null) {
				return null;
			}
			addToCachedRepositoryList(model);
			return DeepCopier.copy(model);
		}

		// cached model
		RepositoryModel model = repositoryListCache.get(repositoryKey);

		if (gcExecutor.isCollectingGarbage(model.name)) {
			// Gitblit is busy collecting garbage, use our cached model
			RepositoryModel rm = DeepCopier.copy(model);
			rm.isCollectingGarbage = true;
			return rm;
		}

		// check for updates
		Repository r = getRepository(model.name);
		if (r == null) {
			// repository is missing
			removeFromCachedRepositoryList(repositoryName);
			logger.error(MessageFormat.format("Repository \"{0}\" is missing! Removing from cache.", repositoryName));
			return null;
		}

		FileBasedConfig config = (FileBasedConfig) getRepositoryConfig(r);
		if (config.isOutdated()) {
			// reload model
			logger.debug(MessageFormat.format("Config for \"{0}\" has changed. Reloading model and updating cache.", repositoryName));
			model = loadRepositoryModel(model.name);
			removeFromCachedRepositoryList(model.name);
			addToCachedRepositoryList(model);
		} else {
			// update a few repository parameters
			if (!model.hasCommits) {
				// update hasCommits, assume a repository only gains commits :)
				model.hasCommits = JGitUtils.hasCommits(r);
			}

			updateLastChangeFields(r, model);
		}
		r.close();

		// return a copy of the cached model
		return DeepCopier.copy(model);
	}

	/**
	 * Returns the star count of the repository.
	 *
	 * @param repository
	 * @return the star count
	 */
	@Override
	public long getStarCount(RepositoryModel repository) {
		long count = 0;
		for (UserModel user : userManager.getAllUsers()) {
			if (user.getPreferences().isStarredRepository(repository.name)) {
				count++;
			}
		}
		return count;
	}

	/**
	 * Workaround JGit.  I need to access the raw config object directly in order
	 * to see if the config is dirty so that I can reload a repository model.
	 * If I use the stock JGit method to get the config it already reloads the
	 * config.  If the config changes are made within Gitblit this is fine as
	 * the returned config will still be flagged as dirty.  BUT... if the config
	 * is manipulated outside Gitblit then it fails to recognize this as dirty.
	 *
	 * @param r
	 * @return a config
	 */
	private StoredConfig getRepositoryConfig(Repository r) {
		try {
			Field f = r.getClass().getDeclaredField("repoConfig");
			f.setAccessible(true);
			StoredConfig config = (StoredConfig) f.get(r);
			return config;
		} catch (Exception e) {
			logger.error("Failed to retrieve \"repoConfig\" via reflection", e);
		}
		return r.getConfig();
	}

	/**
	 * Create a repository model from the configuration and repository data.
	 *
	 * @param repositoryName
	 * @return a repositoryModel or null if the repository does not exist
	 */
	private RepositoryModel loadRepositoryModel(String repositoryName) {
		Repository r = getRepository(repositoryName);
		if (r == null) {
			return null;
		}

		String name;
		File basePath = getRepositoriesFolder();
		if (r.isBare()) {
			name = com.gitblit.utils.FileUtils.getRelativePath(basePath, r.getDirectory());
		} else {
			name = com.gitblit.utils.FileUtils.getRelativePath(basePath, r.getDirectory().getParentFile());
		}

		if (StringUtils.isEmpty(name)) {
			// Repository is NOT located relative to the base folder because it
			// is symlinked.  Use the provided repository name.
			name = repositoryName;
		}

		RepositoryModel model = new RepositoryModel(name);
		model.isBare = r.isBare();

		StoredConfig config = r.getConfig();
		boolean hasOrigin = false;

		if (config != null) {
			// Initialize description from description file
			hasOrigin = !StringUtils.isEmpty(config.getString("remote", "origin", "url"));
			if (getConfig(config,"description", null) == null) {
				File descFile = new File(r.getDirectory(), "description");
				if (descFile.exists()) {
					String desc = com.gitblit.utils.FileUtils.readContent(descFile, System.getProperty("line.separator"));
					if (!desc.toLowerCase().startsWith("unnamed repository")) {
						config.setString(Constants.CONFIG_GITBLIT, null, "description", desc);
					}
				}
			}
			model.description = getConfig(config, "description", "");
			model.originRepository = getConfig(config, "originRepository", null);
//			model.addOwners(ArrayUtils.fromString(getConfig(config, "owner", "")));
			model.acceptNewPatchsets = getConfig(config, "acceptNewPatchsets", true);
			model.acceptNewTickets = getConfig(config, "acceptNewTickets", true);
			model.requireApproval = getConfig(config, "requireApproval", settings.getBoolean(Keys.tickets.requireApproval, false));
			model.mergeTo = getConfig(config, "mergeTo", null);
			model.useIncrementalPushTags = getConfig(config, "useIncrementalPushTags", false);
			model.incrementalPushTagPrefix = getConfig(config, "incrementalPushTagPrefix", null);
			model.allowForks = getConfig(config, "allowForks", true);
			model.accessRestriction = AccessRestrictionType.fromName(getConfig(config,
					"accessRestriction", settings.getString(Keys.git.defaultAccessRestriction, "PUSH")));
			model.authorizationControl = AuthorizationControl.fromName(getConfig(config,
					"authorizationControl", settings.getString(Keys.git.defaultAuthorizationControl, null)));
			model.verifyCommitter = getConfig(config, "verifyCommitter", false);
			model.showRemoteBranches = getConfig(config, "showRemoteBranches", hasOrigin);
			model.isFrozen = getConfig(config, "isFrozen", false);
			model.skipSizeCalculation = getConfig(config, "skipSizeCalculation", false);
			model.skipSummaryMetrics = getConfig(config, "skipSummaryMetrics", false);
			model.commitMessageRenderer = CommitMessageRenderer.fromName(getConfig(config, "commitMessageRenderer",
					settings.getString(Keys.web.commitMessageRenderer, null)));
			model.federationStrategy = FederationStrategy.fromName(getConfig(config,
					"federationStrategy", null));
			model.federationSets = new ArrayList<String>(Arrays.asList(config.getStringList(
					Constants.CONFIG_GITBLIT, null, "federationSets")));
			model.isFederated = getConfig(config, "isFederated", false);
			model.gcThreshold = getConfig(config, "gcThreshold", settings.getString(Keys.git.defaultGarbageCollectionThreshold, "500KB"));
			model.gcPeriod = getConfig(config, "gcPeriod", settings.getInteger(Keys.git.defaultGarbageCollectionPeriod, 7));
			try {
				model.lastGC = new SimpleDateFormat(Constants.ISO8601).parse(getConfig(config, "lastGC", "1970-01-01'T'00:00:00Z"));
			} catch (Exception e) {
				model.lastGC = new Date(0);
			}
			model.maxActivityCommits = getConfig(config, "maxActivityCommits", settings.getInteger(Keys.web.maxActivityCommits, 0));
			model.origin = config.getString("remote", "origin", "url");
			if (model.origin != null) {
				model.origin = model.origin.replace('\\', '/');
				model.isMirror = config.getBoolean("remote", "origin", "mirror", false);
			}
			model.preReceiveScripts = new ArrayList<String>(Arrays.asList(config.getStringList(
					Constants.CONFIG_GITBLIT, null, "preReceiveScript")));
			model.postReceiveScripts = new ArrayList<String>(Arrays.asList(config.getStringList(
					Constants.CONFIG_GITBLIT, null, "postReceiveScript")));
			model.mailingLists = new ArrayList<String>(Arrays.asList(config.getStringList(
					Constants.CONFIG_GITBLIT, null, "mailingList")));
			model.indexedBranches = new ArrayList<String>(Arrays.asList(config.getStringList(
					Constants.CONFIG_GITBLIT, null, "indexBranch")));
			model.metricAuthorExclusions = new ArrayList<String>(Arrays.asList(config.getStringList(
					Constants.CONFIG_GITBLIT, null, "metricAuthorExclusions")));

			// Custom defined properties
			model.customFields = new LinkedHashMap<String, String>();
			for (String aProperty : config.getNames(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS)) {
				model.customFields.put(aProperty, config.getString(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS, aProperty));
			}
		}
		model.HEAD = JGitUtils.getHEADRef(r);
		if (StringUtils.isEmpty(model.mergeTo)) {
			model.mergeTo = model.HEAD;
		}
		model.availableRefs = JGitUtils.getAvailableHeadTargets(r);
		model.sparkleshareId = JGitUtils.getSparkleshareId(r);
		model.hasCommits = JGitUtils.hasCommits(r);
		updateLastChangeFields(r, model);
		r.close();

		if (StringUtils.isEmpty(model.originRepository) && model.origin != null && model.origin.startsWith("file://")) {
			// repository was cloned locally... perhaps as a fork
			try {
				File folder = new File(new URI(model.origin));
				String originRepo = com.gitblit.utils.FileUtils.getRelativePath(getRepositoriesFolder(), folder);
				if (!StringUtils.isEmpty(originRepo)) {
					// ensure origin still exists
					File repoFolder = new File(getRepositoriesFolder(), originRepo);
					if (repoFolder.exists()) {
						model.originRepository = originRepo.toLowerCase();

						// persist the fork origin
						updateConfiguration(r, model);
					}
				}
			} catch (URISyntaxException e) {
				logger.error("Failed to determine fork for " + model, e);
			}
		}
		return model;
	}

	/**
	 * Determines if this server has the requested repository.
	 *
	 * @param n
	 * @return true if the repository exists
	 */
	@Override
	public boolean hasRepository(String repositoryName) {
		return hasRepository(repositoryName, false);
	}

	/**
	 * Determines if this server has the requested repository.
	 *
	 * @param n
	 * @param caseInsensitive
	 * @return true if the repository exists
	 */
	@Override
	public boolean hasRepository(String repositoryName, boolean caseSensitiveCheck) {
		if (!caseSensitiveCheck && settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
			// if we are caching use the cache to determine availability
			// otherwise we end up adding a phantom repository to the cache
			return repositoryListCache.containsKey(repositoryName.toLowerCase());
		}
		Repository r = getRepository(repositoryName, false);
		if (r == null) {
			return false;
		}
		r.close();
		return true;
	}

	/**
	 * Determines if the specified user has a fork of the specified origin
	 * repository.
	 *
	 * @param username
	 * @param origin
	 * @return true the if the user has a fork
	 */
	@Override
	public boolean hasFork(String username, String origin) {
		return getFork(username, origin) != null;
	}

	/**
	 * Gets the name of a user's fork of the specified origin
	 * repository.
	 *
	 * @param username
	 * @param origin
	 * @return the name of the user's fork, null otherwise
	 */
	@Override
	public String getFork(String username, String origin) {
		if (StringUtils.isEmpty(origin)) {
			return null;
		}
		String userPath = ModelUtils.getPersonalPath(username);
		if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
			String originKey = origin.toLowerCase();

			// collect all origin nodes in fork network
			Set<String> roots = new HashSet<String>();
			roots.add(originKey);
			RepositoryModel originModel = repositoryListCache.get(originKey);
			while (originModel != null) {
				if (!ArrayUtils.isEmpty(originModel.forks)) {
					for (String fork : originModel.forks) {
						if (!fork.startsWith(userPath)) {
							roots.add(fork.toLowerCase());
						}
					}
				}

				if (originModel.originRepository != null) {
					String ooKey = originModel.originRepository.toLowerCase();
					roots.add(ooKey);
					originModel = repositoryListCache.get(ooKey);
				} else {
					// break
					originModel = null;
				}
			}

			for (String repository : repositoryListCache.keySet()) {
				if (repository.startsWith(userPath)) {
					RepositoryModel model = repositoryListCache.get(repository);
					if (!StringUtils.isEmpty(model.originRepository)) {
						if (roots.contains(model.originRepository.toLowerCase())) {
							// user has a fork in this graph
							return model.name;
						}
					}
				}
			}
		} else {
			// not caching
			String userProject = ModelUtils.getPersonalProject(username);
			File subfolder = new File(getRepositoriesFolder(), userProject);
			List<String> repositories = JGitUtils.getRepositoryList(subfolder,
					settings.getBoolean(Keys.git.onlyAccessBareRepositories, false),
					settings.getBoolean(Keys.git.searchRepositoriesSubfolders, true),
					settings.getInteger(Keys.git.searchRecursionDepth, -1),
					settings.getStrings(Keys.git.searchExclusions));
			for (String repository : repositories) {
				RepositoryModel model = getRepositoryModel(userPath + repository);
				if (model.originRepository != null && model.originRepository.equalsIgnoreCase(origin)) {
					// user has a fork
					return model.name;
				}
			}
		}
		// user does not have a fork
		return null;
	}

	/**
	 * Returns the fork network for a repository by traversing up the fork graph
	 * to discover the root and then down through all children of the root node.
	 *
	 * @param repository
	 * @return a ForkModel
	 */
	@Override
	public ForkModel getForkNetwork(String repository) {
		if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
			// find the root, cached
			RepositoryModel model = repositoryListCache.get(repository.toLowerCase());
			while (model.originRepository != null) {
				model = repositoryListCache.get(model.originRepository.toLowerCase());
			}
			ForkModel root = getForkModelFromCache(model.name);
			return root;
		} else {
			// find the root, non-cached
			RepositoryModel model = getRepositoryModel(repository.toLowerCase());
			while (model.originRepository != null) {
				model = getRepositoryModel(model.originRepository);
			}
			ForkModel root = getForkModel(model.name);
			return root;
		}
	}

	private ForkModel getForkModelFromCache(String repository) {
		RepositoryModel model = repositoryListCache.get(repository.toLowerCase());
		if (model == null) {
			return null;
		}
		ForkModel fork = new ForkModel(model);
		if (!ArrayUtils.isEmpty(model.forks)) {
			for (String aFork : model.forks) {
				ForkModel fm = getForkModelFromCache(aFork);
				if (fm != null) {
					fork.forks.add(fm);
				}
			}
		}
		return fork;
	}

	private ForkModel getForkModel(String repository) {
		RepositoryModel model = getRepositoryModel(repository.toLowerCase());
		if (model == null) {
			return null;
		}
		ForkModel fork = new ForkModel(model);
		if (!ArrayUtils.isEmpty(model.forks)) {
			for (String aFork : model.forks) {
				ForkModel fm = getForkModel(aFork);
				if (fm != null) {
					fork.forks.add(fm);
				}
			}
		}
		return fork;
	}

	/**
	 * Updates the last changed fields and optionally calculates the size of the
	 * repository.  Gitblit caches the repository sizes to reduce the performance
	 * penalty of recursive calculation. The cache is updated if the repository
	 * has been changed since the last calculation.
	 *
	 * @param model
	 * @return size in bytes of the repository
	 */
	@Override
	public long updateLastChangeFields(Repository r, RepositoryModel model) {
		LastChange lc = JGitUtils.getLastChange(r);
		model.lastChange = lc.when;
		model.lastChangeAuthor = lc.who;

		if (!settings.getBoolean(Keys.web.showRepositorySizes, true) || model.skipSizeCalculation) {
			model.size = null;
			return 0L;
		}
		if (!repositorySizeCache.hasCurrent(model.name, model.lastChange)) {
			File gitDir = r.getDirectory();
			long sz = com.gitblit.utils.FileUtils.folderSize(gitDir);
			repositorySizeCache.updateObject(model.name, model.lastChange, sz);
		}
		long size = repositorySizeCache.getObject(model.name);
		ByteFormat byteFormat = new ByteFormat();
		model.size = byteFormat.format(size);
		return size;
	}

	/**
	 * Returns true if the repository is idle (not being accessed).
	 *
	 * @param repository
	 * @return true if the repository is idle
	 */
	@Override
	public boolean isIdle(Repository repository) {
		try {
			// Read the use count.
			// An idle use count is 2:
			// +1 for being in the cache
			// +1 for the repository parameter in this method
			Field useCnt = Repository.class.getDeclaredField("useCnt");
			useCnt.setAccessible(true);
			int useCount = ((AtomicInteger) useCnt.get(repository)).get();
			return useCount == 2;
		} catch (Exception e) {
			logger.warn(MessageFormat
					.format("Failed to reflectively determine use count for repository {0}",
							repository.getDirectory().getPath()), e);
		}
		return false;
	}

	/**
	 * Ensures that all cached repository are completely closed and their resources
	 * are properly released.
	 */
	@Override
	public void closeAll() {
		for (String repository : getRepositoryList()) {
			close(repository);
		}
	}

	/**
	 * Ensure that a cached repository is completely closed and its resources
	 * are properly released.
	 *
	 * @param repositoryName
	 */
	@Override
	public void close(String repositoryName) {
		Repository repository = getRepository(repositoryName);
		if (repository == null) {
			return;
		}
		RepositoryCache.close(repository);

		// assume 2 uses in case reflection fails
		int uses = 2;
		try {
			// The FileResolver caches repositories which is very useful
			// for performance until you want to delete a repository.
			// I have to use reflection to call close() the correct
			// number of times to ensure that the object and ref databases
			// are properly closed before I can delete the repository from
			// the filesystem.
			Field useCnt = Repository.class.getDeclaredField("useCnt");
			useCnt.setAccessible(true);
			uses = ((AtomicInteger) useCnt.get(repository)).get();
		} catch (Exception e) {
			logger.warn(MessageFormat
					.format("Failed to reflectively determine use count for repository {0}",
							repositoryName), e);
		}
		if (uses > 0) {
			logger.debug(MessageFormat
					.format("{0}.useCnt={1}, calling close() {2} time(s) to close object and ref databases",
							repositoryName, uses, uses));
			for (int i = 0; i < uses; i++) {
				repository.close();
			}
		}

		// close any open index writer/searcher in the Lucene executor
		luceneExecutor.close(repositoryName);
	}

	/**
	 * Returns the metrics for the default branch of the specified repository.
	 * This method builds a metrics cache. The cache is updated if the
	 * repository is updated. A new copy of the metrics list is returned on each
	 * call so that modifications to the list are non-destructive.
	 *
	 * @param model
	 * @param repository
	 * @return a new array list of metrics
	 */
	@Override
	public List<Metric> getRepositoryDefaultMetrics(RepositoryModel model, Repository repository) {
		if (repositoryMetricsCache.hasCurrent(model.name, model.lastChange)) {
			return new ArrayList<Metric>(repositoryMetricsCache.getObject(model.name));
		}
		List<Metric> metrics = MetricUtils.getDateMetrics(repository, null, true, null, runtimeManager.getTimezone());
		repositoryMetricsCache.updateObject(model.name, model.lastChange, metrics);
		return new ArrayList<Metric>(metrics);
	}

	/**
	 * Returns the gitblit string value for the specified key. If key is not
	 * set, returns defaultValue.
	 *
	 * @param config
	 * @param field
	 * @param defaultValue
	 * @return field value or defaultValue
	 */
	private String getConfig(StoredConfig config, String field, String defaultValue) {
		String value = config.getString(Constants.CONFIG_GITBLIT, null, field);
		if (StringUtils.isEmpty(value)) {
			return defaultValue;
		}
		return value;
	}

	/**
	 * Returns the gitblit boolean value for the specified key. If key is not
	 * set, returns defaultValue.
	 *
	 * @param config
	 * @param field
	 * @param defaultValue
	 * @return field value or defaultValue
	 */
	private boolean getConfig(StoredConfig config, String field, boolean defaultValue) {
		return config.getBoolean(Constants.CONFIG_GITBLIT, field, defaultValue);
	}

	/**
	 * Returns the gitblit string value for the specified key. If key is not
	 * set, returns defaultValue.
	 *
	 * @param config
	 * @param field
	 * @param defaultValue
	 * @return field value or defaultValue
	 */
	private int getConfig(StoredConfig config, String field, int defaultValue) {
		String value = config.getString(Constants.CONFIG_GITBLIT, null, field);
		if (StringUtils.isEmpty(value)) {
			return defaultValue;
		}
		try {
			return Integer.parseInt(value);
		} catch (Exception e) {
		}
		return defaultValue;
	}

	/**
	 * Creates/updates the repository model keyed by reopsitoryName. Saves all
	 * repository settings in .git/config. This method allows for renaming
	 * repositories and will update user access permissions accordingly.
	 *
	 * All repositories created by this method are bare and automatically have
	 * .git appended to their names, which is the standard convention for bare
	 * repositories.
	 *
	 * @param repositoryName
	 * @param repository
	 * @param isCreate
	 * @throws GitBlitException
	 */
	@Override
	public void updateRepositoryModel(String repositoryName, RepositoryModel repository,
			boolean isCreate) throws GitBlitException {
		if (gcExecutor.isCollectingGarbage(repositoryName)) {
			throw new GitBlitException(MessageFormat.format("sorry, Gitblit is busy collecting garbage in {0}",
					repositoryName));
		}
		Repository r = null;
		String projectPath = StringUtils.getFirstPathElement(repository.name);
		if (!StringUtils.isEmpty(projectPath)) {
			if (projectPath.equalsIgnoreCase(settings.getString(Keys.web.repositoryRootGroupName, "main"))) {
				// strip leading group name
				repository.name = repository.name.substring(projectPath.length() + 1);
			}
		}
		if (isCreate) {
			// ensure created repository name ends with .git
			if (!repository.name.toLowerCase().endsWith(org.eclipse.jgit.lib.Constants.DOT_GIT_EXT)) {
				repository.name += org.eclipse.jgit.lib.Constants.DOT_GIT_EXT;
			}
			if (hasRepository(repository.name)) {
				throw new GitBlitException(MessageFormat.format(
						"Can not create repository ''{0}'' because it already exists.",
						repository.name));
			}
			// create repository
			logger.info("create repository " + repository.name);
			String shared = settings.getString(Keys.git.createRepositoriesShared, "FALSE");
			r = JGitUtils.createRepository(repositoriesFolder, repository.name, shared);
		} else {
			// rename repository
			if (!repositoryName.equalsIgnoreCase(repository.name)) {
				if (!repository.name.toLowerCase().endsWith(
						org.eclipse.jgit.lib.Constants.DOT_GIT_EXT)) {
					repository.name += org.eclipse.jgit.lib.Constants.DOT_GIT_EXT;
				}
				if (new File(repositoriesFolder, repository.name).exists()) {
					throw new GitBlitException(MessageFormat.format(
							"Failed to rename ''{0}'' because ''{1}'' already exists.",
							repositoryName, repository.name));
				}
				close(repositoryName);
				File folder = new File(repositoriesFolder, repositoryName);
				File destFolder = new File(repositoriesFolder, repository.name);
				if (destFolder.exists()) {
					throw new GitBlitException(
							MessageFormat
									.format("Can not rename repository ''{0}'' to ''{1}'' because ''{1}'' already exists.",
											repositoryName, repository.name));
				}
				File parentFile = destFolder.getParentFile();
				if (!parentFile.exists() && !parentFile.mkdirs()) {
					throw new GitBlitException(MessageFormat.format(
							"Failed to create folder ''{0}''", parentFile.getAbsolutePath()));
				}
				if (!folder.renameTo(destFolder)) {
					throw new GitBlitException(MessageFormat.format(
							"Failed to rename repository ''{0}'' to ''{1}''.", repositoryName,
							repository.name));
				}
				// rename the roles
				if (!userManager.renameRepositoryRole(repositoryName, repository.name)) {
					throw new GitBlitException(MessageFormat.format(
							"Failed to rename repository permissions ''{0}'' to ''{1}''.",
							repositoryName, repository.name));
				}

				// rename fork origins in their configs
				if (!ArrayUtils.isEmpty(repository.forks)) {
					for (String fork : repository.forks) {
						Repository rf = getRepository(fork);
						try {
							StoredConfig config = rf.getConfig();
							String origin = config.getString("remote", "origin", "url");
							origin = origin.replace(repositoryName, repository.name);
							config.setString("remote", "origin", "url", origin);
							config.setString(Constants.CONFIG_GITBLIT, null, "originRepository", repository.name);
							config.save();
						} catch (Exception e) {
							logger.error("Failed to update repository fork config for " + fork, e);
						}
						rf.close();
					}
				}

				// update this repository's origin's fork list
				if (!StringUtils.isEmpty(repository.originRepository)) {
					RepositoryModel origin = repositoryListCache.get(repository.originRepository.toLowerCase());
					if (origin != null && !ArrayUtils.isEmpty(origin.forks)) {
						origin.forks.remove(repositoryName);
						origin.forks.add(repository.name);
					}
				}

				// clear the cache
				clearRepositoryMetadataCache(repositoryName);
				repository.resetDisplayName();
			}

			// load repository
			logger.info("edit repository " + repository.name);
			r = getRepository(repository.name);
		}

		// update settings
		if (r != null) {
			updateConfiguration(r, repository);
			// Update the description file
			File descFile = new File(r.getDirectory(), "description");
			if (repository.description != null)
			{
				com.gitblit.utils.FileUtils.writeContent(descFile, repository.description);
			}
			else if (descFile.exists() && !descFile.isDirectory()) {
				descFile.delete();
			}
			// only update symbolic head if it changes
			String currentRef = JGitUtils.getHEADRef(r);
			if (!StringUtils.isEmpty(repository.HEAD) && !repository.HEAD.equals(currentRef)) {
				logger.info(MessageFormat.format("Relinking {0} HEAD from {1} to {2}",
						repository.name, currentRef, repository.HEAD));
				if (JGitUtils.setHEADtoRef(r, repository.HEAD)) {
					// clear the cache
					clearRepositoryMetadataCache(repository.name);
				}
			}

			// Adjust permissions in case we updated the config files
			JGitUtils.adjustSharedPerm(new File(r.getDirectory().getAbsolutePath(), "config"),
					settings.getString(Keys.git.createRepositoriesShared, "FALSE"));
			JGitUtils.adjustSharedPerm(new File(r.getDirectory().getAbsolutePath(), "HEAD"),
					settings.getString(Keys.git.createRepositoriesShared, "FALSE"));

			// close the repository object
			r.close();
		}

		// update repository cache
		removeFromCachedRepositoryList(repositoryName);
		// model will actually be replaced on next load because config is stale
		addToCachedRepositoryList(repository);

		if (isCreate && pluginManager != null) {
			for (RepositoryLifeCycleListener listener : pluginManager.getExtensions(RepositoryLifeCycleListener.class)) {
				try {
					listener.onCreation(repository);
				} catch (Throwable t) {
					logger.error(String.format("failed to call plugin onCreation %s", repositoryName), t);
				}
			}
		}
	}

	/**
	 * Updates the Gitblit configuration for the specified repository.
	 *
	 * @param r
	 *            the Git repository
	 * @param repository
	 *            the Gitblit repository model
	 */
	@Override
	public void updateConfiguration(Repository r, RepositoryModel repository) {
		StoredConfig config = r.getConfig();
		config.setString(Constants.CONFIG_GITBLIT, null, "description", repository.description);
		config.setString(Constants.CONFIG_GITBLIT, null, "originRepository", repository.originRepository);
//		config.setString(Constants.CONFIG_GITBLIT, null, "owner", ArrayUtils.toString(repository.owners));
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "acceptNewPatchsets", repository.acceptNewPatchsets);
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "acceptNewTickets", repository.acceptNewTickets);
		if (settings.getBoolean(Keys.tickets.requireApproval, false) == repository.requireApproval) {
			// use default
			config.unset(Constants.CONFIG_GITBLIT, null, "requireApproval");
		} else {
			// override default
			config.setBoolean(Constants.CONFIG_GITBLIT, null, "requireApproval", repository.requireApproval);
		}
		if (!StringUtils.isEmpty(repository.mergeTo)) {
			config.setString(Constants.CONFIG_GITBLIT, null, "mergeTo", repository.mergeTo);
		}
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "useIncrementalPushTags", repository.useIncrementalPushTags);
		if (StringUtils.isEmpty(repository.incrementalPushTagPrefix) ||
				repository.incrementalPushTagPrefix.equals(settings.getString(Keys.git.defaultIncrementalPushTagPrefix, "r"))) {
			config.unset(Constants.CONFIG_GITBLIT, null, "incrementalPushTagPrefix");
		} else {
			config.setString(Constants.CONFIG_GITBLIT, null, "incrementalPushTagPrefix", repository.incrementalPushTagPrefix);
		}
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "allowForks", repository.allowForks);
		config.setString(Constants.CONFIG_GITBLIT, null, "accessRestriction", repository.accessRestriction.name());
		config.setString(Constants.CONFIG_GITBLIT, null, "authorizationControl", repository.authorizationControl.name());
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "verifyCommitter", repository.verifyCommitter);
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "showRemoteBranches", repository.showRemoteBranches);
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "isFrozen", repository.isFrozen);
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "skipSizeCalculation", repository.skipSizeCalculation);
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "skipSummaryMetrics", repository.skipSummaryMetrics);
		config.setString(Constants.CONFIG_GITBLIT, null, "federationStrategy",
				repository.federationStrategy.name());
		config.setBoolean(Constants.CONFIG_GITBLIT, null, "isFederated", repository.isFederated);
		config.setString(Constants.CONFIG_GITBLIT, null, "gcThreshold", repository.gcThreshold);
		if (repository.gcPeriod == settings.getInteger(Keys.git.defaultGarbageCollectionPeriod, 7)) {
			// use default from config
			config.unset(Constants.CONFIG_GITBLIT, null, "gcPeriod");
		} else {
			config.setInt(Constants.CONFIG_GITBLIT, null, "gcPeriod", repository.gcPeriod);
		}
		if (repository.lastGC != null) {
			config.setString(Constants.CONFIG_GITBLIT, null, "lastGC", new SimpleDateFormat(Constants.ISO8601).format(repository.lastGC));
		}
		if (repository.maxActivityCommits == settings.getInteger(Keys.web.maxActivityCommits, 0)) {
			// use default from config
			config.unset(Constants.CONFIG_GITBLIT, null, "maxActivityCommits");
		} else {
			config.setInt(Constants.CONFIG_GITBLIT, null, "maxActivityCommits", repository.maxActivityCommits);
		}

		CommitMessageRenderer defaultRenderer = CommitMessageRenderer.fromName(settings.getString(Keys.web.commitMessageRenderer, null));
		if (repository.commitMessageRenderer == null || repository.commitMessageRenderer == defaultRenderer) {
			// use default from config
			config.unset(Constants.CONFIG_GITBLIT, null, "commitMessageRenderer");
		} else {
			// repository overrides default
			config.setString(Constants.CONFIG_GITBLIT, null, "commitMessageRenderer",
					repository.commitMessageRenderer.name());
		}

		updateList(config, "federationSets", repository.federationSets);
		updateList(config, "preReceiveScript", repository.preReceiveScripts);
		updateList(config, "postReceiveScript", repository.postReceiveScripts);
		updateList(config, "mailingList", repository.mailingLists);
		updateList(config, "indexBranch", repository.indexedBranches);
		updateList(config, "metricAuthorExclusions", repository.metricAuthorExclusions);

		// User Defined Properties
		if (repository.customFields != null) {
			if (repository.customFields.size() == 0) {
				// clear section
				config.unsetSection(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS);
			} else {
				for (Entry<String, String> property : repository.customFields.entrySet()) {
					// set field
					String key = property.getKey();
					String value = property.getValue();
					config.setString(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS, key, value);
				}
			}
		}

		try {
			config.save();
		} catch (IOException e) {
			logger.error("Failed to save repository config!", e);
		}
	}

	private void updateList(StoredConfig config, String field, List<String> list) {
		// a null list is skipped, not cleared
		// this is for RPC administration where an older manager might be used
		if (list == null) {
			return;
		}
		if (ArrayUtils.isEmpty(list)) {
			config.unset(Constants.CONFIG_GITBLIT, null, field);
		} else {
			config.setStringList(Constants.CONFIG_GITBLIT, null, field, list);
		}
	}

	/**
	 * Returns true if the repository can be deleted.
	 *
	 * @return true if the repository can be deleted
	 */
	@Override
	public boolean canDelete(RepositoryModel repository) {
		return settings.getBoolean(Keys.web.allowDeletingNonEmptyRepositories, true)
					|| !repository.hasCommits;
	}

	/**
	 * Deletes the repository from the file system and removes the repository
	 * permission from all repository users.
	 *
	 * @param model
	 * @return true if successful
	 */
	@Override
	public boolean deleteRepositoryModel(RepositoryModel model) {
		return deleteRepository(model.name);
	}

	/**
	 * Deletes the repository from the file system and removes the repository
	 * permission from all repository users.
	 *
	 * @param repositoryName
	 * @return true if successful
	 */
	@Override
	public boolean deleteRepository(String repositoryName) {
		RepositoryModel repository = getRepositoryModel(repositoryName);
		if (!canDelete(repository)) {
			logger.warn("Attempt to delete {} rejected!", repositoryName);
			return false;
		}

		try {
			close(repositoryName);
			// clear the repository cache
			clearRepositoryMetadataCache(repositoryName);

			RepositoryModel model = removeFromCachedRepositoryList(repositoryName);
			if (model != null && !ArrayUtils.isEmpty(model.forks)) {
				resetRepositoryListCache();
			}

			File folder = new File(repositoriesFolder, repositoryName);
			if (folder.exists() && folder.isDirectory()) {
				FileUtils.delete(folder, FileUtils.RECURSIVE | FileUtils.RETRY);
				if (userManager.deleteRepositoryRole(repositoryName)) {
					logger.info(MessageFormat.format("Repository \"{0}\" deleted", repositoryName));

					if (pluginManager != null) {
						for (RepositoryLifeCycleListener listener : pluginManager.getExtensions(RepositoryLifeCycleListener.class)) {
							try {
								listener.onDeletion(repository);
							} catch (Throwable t) {
								logger.error(String.format("failed to call plugin onDeletion %s", repositoryName), t);
							}
						}
					}
					return true;
				}
			}
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to delete repository {0}", repositoryName), t);
		}
		return false;
	}

	/**
	 * Returns the list of all Groovy push hook scripts. Script files must have
	 * .groovy extension
	 *
	 * @return list of available hook scripts
	 */
	@Override
	public List<String> getAllScripts() {
		File groovyFolder = getHooksFolder();
		File[] files = groovyFolder.listFiles(new FileFilter() {
			@Override
			public boolean accept(File pathname) {
				return pathname.isFile() && pathname.getName().endsWith(".groovy");
			}
		});
		List<String> scripts = new ArrayList<String>();
		if (files != null) {
			for (File file : files) {
				String script = file.getName().substring(0, file.getName().lastIndexOf('.'));
				scripts.add(script);
			}
		}
		return scripts;
	}

	/**
	 * Returns the list of pre-receive scripts the repository inherited from the
	 * global settings and team affiliations.
	 *
	 * @param repository
	 *            if null only the globally specified scripts are returned
	 * @return a list of scripts
	 */
	@Override
	public List<String> getPreReceiveScriptsInherited(RepositoryModel repository) {
		Set<String> scripts = new LinkedHashSet<String>();
		// Globals
		for (String script : settings.getStrings(Keys.groovy.preReceiveScripts)) {
			if (script.endsWith(".groovy")) {
				scripts.add(script.substring(0, script.lastIndexOf('.')));
			} else {
				scripts.add(script);
			}
		}

		// Team Scripts
		if (repository != null) {
			for (String teamname : userManager.getTeamNamesForRepositoryRole(repository.name)) {
				TeamModel team = userManager.getTeamModel(teamname);
				if (!ArrayUtils.isEmpty(team.preReceiveScripts)) {
					scripts.addAll(team.preReceiveScripts);
				}
			}
		}
		return new ArrayList<String>(scripts);
	}

	/**
	 * Returns the list of all available Groovy pre-receive push hook scripts
	 * that are not already inherited by the repository. Script files must have
	 * .groovy extension
	 *
	 * @param repository
	 *            optional parameter
	 * @return list of available hook scripts
	 */
	@Override
	public List<String> getPreReceiveScriptsUnused(RepositoryModel repository) {
		Set<String> inherited = new TreeSet<String>(getPreReceiveScriptsInherited(repository));

		// create list of available scripts by excluding inherited scripts
		List<String> scripts = new ArrayList<String>();
		for (String script : getAllScripts()) {
			if (!inherited.contains(script)) {
				scripts.add(script);
			}
		}
		return scripts;
	}

	/**
	 * Returns the list of post-receive scripts the repository inherited from
	 * the global settings and team affiliations.
	 *
	 * @param repository
	 *            if null only the globally specified scripts are returned
	 * @return a list of scripts
	 */
	@Override
	public List<String> getPostReceiveScriptsInherited(RepositoryModel repository) {
		Set<String> scripts = new LinkedHashSet<String>();
		// Global Scripts
		for (String script : settings.getStrings(Keys.groovy.postReceiveScripts)) {
			if (script.endsWith(".groovy")) {
				scripts.add(script.substring(0, script.lastIndexOf('.')));
			} else {
				scripts.add(script);
			}
		}
		// Team Scripts
		if (repository != null) {
			for (String teamname : userManager.getTeamNamesForRepositoryRole(repository.name)) {
				TeamModel team = userManager.getTeamModel(teamname);
				if (!ArrayUtils.isEmpty(team.postReceiveScripts)) {
					scripts.addAll(team.postReceiveScripts);
				}
			}
		}
		return new ArrayList<String>(scripts);
	}

	/**
	 * Returns the list of unused Groovy post-receive push hook scripts that are
	 * not already inherited by the repository. Script files must have .groovy
	 * extension
	 *
	 * @param repository
	 *            optional parameter
	 * @return list of available hook scripts
	 */
	@Override
	public List<String> getPostReceiveScriptsUnused(RepositoryModel repository) {
		Set<String> inherited = new TreeSet<String>(getPostReceiveScriptsInherited(repository));

		// create list of available scripts by excluding inherited scripts
		List<String> scripts = new ArrayList<String>();
		for (String script : getAllScripts()) {
			if (!inherited.contains(script)) {
				scripts.add(script);
			}
		}
		return scripts;
	}

	/**
	 * Search the specified repositories using the Lucene query.
	 *
	 * @param query
	 * @param page
	 * @param pageSize
	 * @param repositories
	 * @return
	 */
	@Override
	public List<SearchResult> search(String query, int page, int pageSize, List<String> repositories) {
		List<SearchResult> srs = luceneExecutor.search(query, page, pageSize, repositories);
		return srs;
	}

	protected void configureLuceneIndexing() {
		luceneExecutor = new LuceneService(settings, this);
		int period = 2;
		scheduledExecutor.scheduleAtFixedRate(luceneExecutor, 1, period,  TimeUnit.MINUTES);
		logger.info("Lucene will process indexed branches every {} minutes.", period);
	}

	protected void configureGarbageCollector() {
		// schedule gc engine
		gcExecutor = new GarbageCollectorService(settings, this);
		if (gcExecutor.isReady()) {
			logger.info("Garbage Collector (GC) will scan repositories every 24 hours.");
			Calendar c = Calendar.getInstance();
			c.set(Calendar.HOUR_OF_DAY, settings.getInteger(Keys.git.garbageCollectionHour, 0));
			c.set(Calendar.MINUTE, 0);
			c.set(Calendar.SECOND, 0);
			c.set(Calendar.MILLISECOND, 0);
			Date cd = c.getTime();
			Date now = new Date();
			int delay = 0;
			if (cd.before(now)) {
				c.add(Calendar.DATE, 1);
				cd = c.getTime();
			}
			delay = (int) ((cd.getTime() - now.getTime())/TimeUtils.MIN);
			String when = delay + " mins";
			if (delay > 60) {
				when = MessageFormat.format("{0,number,0.0} hours", delay / 60f);
			}
			logger.info(MessageFormat.format("Next scheculed GC scan is in {0}", when));
			scheduledExecutor.scheduleAtFixedRate(gcExecutor, delay, 60 * 24, TimeUnit.MINUTES);
		} else {
			logger.info("Garbage Collector (GC) is disabled.");
		}
	}

	protected void configureMirrorExecutor() {
		mirrorExecutor = new MirrorService(settings, this);
		if (mirrorExecutor.isReady()) {
			int mins = TimeUtils.convertFrequencyToMinutes(settings.getString(Keys.git.mirrorPeriod, "30 mins"));
			if (mins < 5) {
				mins = 5;
			}
			int delay = 1;
			scheduledExecutor.scheduleAtFixedRate(mirrorExecutor, delay, mins,  TimeUnit.MINUTES);
			logger.info("Mirror service will fetch updates every {} minutes.", mins);
			logger.info("Next scheduled mirror fetch is in {} minutes", delay);
		} else {
			logger.info("Mirror service is disabled.");
		}
	}

	protected void configureJGit() {
		// Configure JGit
		WindowCacheConfig cfg = new WindowCacheConfig();

		cfg.setPackedGitWindowSize(settings.getFilesize(Keys.git.packedGitWindowSize, cfg.getPackedGitWindowSize()));
		cfg.setPackedGitLimit(settings.getFilesize(Keys.git.packedGitLimit, cfg.getPackedGitLimit()));
		cfg.setDeltaBaseCacheLimit(settings.getFilesize(Keys.git.deltaBaseCacheLimit, cfg.getDeltaBaseCacheLimit()));
		cfg.setPackedGitOpenFiles(settings.getFilesize(Keys.git.packedGitOpenFiles, cfg.getPackedGitOpenFiles()));
		cfg.setStreamFileThreshold(settings.getFilesize(Keys.git.streamFileThreshold, cfg.getStreamFileThreshold()));
		cfg.setPackedGitMMAP(settings.getBoolean(Keys.git.packedGitMmap, cfg.isPackedGitMMAP()));

		try {
			cfg.install();
			logger.debug(MessageFormat.format("{0} = {1,number,0}", Keys.git.packedGitWindowSize, cfg.getPackedGitWindowSize()));
			logger.debug(MessageFormat.format("{0} = {1,number,0}", Keys.git.packedGitLimit, cfg.getPackedGitLimit()));
			logger.debug(MessageFormat.format("{0} = {1,number,0}", Keys.git.deltaBaseCacheLimit, cfg.getDeltaBaseCacheLimit()));
			logger.debug(MessageFormat.format("{0} = {1,number,0}", Keys.git.packedGitOpenFiles, cfg.getPackedGitOpenFiles()));
			logger.debug(MessageFormat.format("{0} = {1,number,0}", Keys.git.streamFileThreshold, cfg.getStreamFileThreshold()));
			logger.debug(MessageFormat.format("{0} = {1}", Keys.git.packedGitMmap, cfg.isPackedGitMMAP()));
		} catch (IllegalArgumentException e) {
			logger.error("Failed to configure JGit parameters!", e);
		}
	}

	protected void configureCommitCache() {
		int daysToCache = settings.getInteger(Keys.web.activityCacheDays, 14);
		if (daysToCache <= 0) {
			logger.info("Commit cache is disabled");
		} else {
			long start = System.nanoTime();
			long repoCount = 0;
			long commitCount = 0;
			logger.info(MessageFormat.format("Preparing {0} day commit cache. please wait...", daysToCache));
			CommitCache.instance().setCacheDays(daysToCache);
			Date cutoff = CommitCache.instance().getCutoffDate();
			for (String repositoryName : getRepositoryList()) {
				RepositoryModel model = getRepositoryModel(repositoryName);
				if (model != null && model.hasCommits && model.lastChange.after(cutoff)) {
					repoCount++;
					Repository repository = getRepository(repositoryName);
					for (RefModel ref : JGitUtils.getLocalBranches(repository, true, -1)) {
						if (!ref.getDate().after(cutoff)) {
							// branch not recently updated
							continue;
						}
						List<?> commits = CommitCache.instance().getCommits(repositoryName, repository, ref.getName());
						if (commits.size() > 0) {
							logger.info(MessageFormat.format("  cached {0} commits for {1}:{2}",
									commits.size(), repositoryName, ref.getName()));
							commitCount += commits.size();
						}
					}
					repository.close();
				}
			}
			logger.info(MessageFormat.format("built {0} day commit cache of {1} commits across {2} repositories in {3} msecs",
					daysToCache, commitCount, repoCount, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start)));
		}
	}

	protected void confirmWriteAccess() {
		if (runtimeManager.isServingRepositories()) {
			try {
				if (!getRepositoriesFolder().exists()) {
					getRepositoriesFolder().mkdirs();
				}
				File file = File.createTempFile(".test-", ".txt", getRepositoriesFolder());
				file.delete();
			} catch (Exception e) {
				logger.error("");
				logger.error(Constants.BORDER2);
				logger.error("Please check filesystem permissions!");
				logger.error("FAILED TO WRITE TO REPOSITORIES FOLDER!!", e);
				logger.error(Constants.BORDER2);
				logger.error("");
			}
		}
	}
}
