James Moger
2013-11-17 db4f6b5740c6ea45d9e2209dc569bc18904a8b4d
Define manager interfaces and update all of Gitblit to use managers

These manager interfaces define how the GitBlit singleton will
eventually be split into smaller component managers. The Wicket app and
all servlets have been updated to request the needed managers. There
are _very_ few method signature changes - although there are a handful.

This is a surgical sharding of responsibility based on a proof of
concept refactor. Instead of random references to GittBlit.self()
there are now precise references to the manager interface required to
accomplish some task. Some tasks may require references to multiple
managers.

The code is now littered with calls to GitBlit.getManager(class) and
those familiar with the code-base will no doubt notice the duplication
of methods from IUserService in IUserManager and the addition of
implementation methods in the GitBlit context class. When the
GitBlit class is broken apart and the existing external authentication
user service classes are refactored to AuthenticationService classes,
this will again simplify and flatten. But in order to safely and
cleanly modularize the stable code-base we will have to live with a
little duplication for a short while.

Change-Id: I7314ec8acaab2dcc6092785ed4434cc09fdbbe16
9 files added
88 files modified
2851 ■■■■ changed files
src/main/java/com/gitblit/AccessRestrictionFilter.java 17 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/AuthenticationFilter.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/BranchGraphServlet.java 12 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/DownloadZipServlet.java 10 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/EnforceAuthenticationFilter.java 41 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/FederationClient.java 3 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/FederationPullExecutor.java 44 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/FederationServlet.java 56 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/GCExecutor.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/GitBlit.java 518 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/GitBlitServer.java 6 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/GitFilter.java 21 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/GitblitUserService.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/HtpasswdUserService.java 7 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/IStoredSettings.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/LdapUserService.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/LogoServlet.java 10 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/LuceneExecutor.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/MirrorExecutor.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/PAMUserService.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/PagesFilter.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/PagesServlet.java 11 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/RedmineUserService.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/RobotsTxtServlet.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/RpcFilter.java 18 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/RpcServlet.java 104 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/SalesforceUserService.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/SparkleShareInviteServlet.java 19 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/SyndicationFilter.java 17 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/SyndicationServlet.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/WindowsUserService.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/git/GitServlet.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/git/GitblitReceivePack.java 21 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/git/GitblitReceivePackFactory.java 14 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/git/GitblitUploadPackFactory.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/git/RepositoryResolver.java 8 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/IFederationManager.java 177 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/IGitblitManager.java 83 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/INotificationManager.java 66 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/IProjectManager.java 63 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/IRepositoryManager.java 396 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/IRuntimeManager.java 103 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/ISessionManager.java 64 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/IUserManager.java 280 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/utils/ActivityUtils.java 21 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/GitBlitWebApp.java 50 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/GitblitWicketFilter.java 23 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/ActivityPage.java 9 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/ChangePasswordPage.java 4 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/EditTeamPage.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/EditUserPage.java 4 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/LogoutPage.java 3 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/RepositoryPage.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/RootPage.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/SessionPage.java 2 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/ActivityTest.java 4 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/ArrayUtilsTest.java 5 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/Base64Test.java 4 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/ByteFormatTest.java 4 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/DiffUtilsTest.java 5 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/FanoutServiceTest.java 4 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/FederationTests.java 6 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/FileUtilsTest.java 5 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/GitBlitSuite.java 11 ●●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/GitBlitTest.java 54 ●●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/GitDaemonStopTest.java 3 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/GitDaemonTest.java 30 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/GitServletTest.java 65 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/GitblitUnitTest.java 67 ●●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/GroovyScriptTest.java 15 ●●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/HtpasswdUserServiceTest.java 8 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/Issue0259Test.java 3 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/Issue0271Test.java 3 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/JGitUtilsTest.java 8 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/JnaUtilsTest.java 6 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/JsonUtilsTest.java 4 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/LdapUserServiceTest.java 7 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/LuceneExecutorTest.java 6 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/MailTest.java 4 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/MarkdownUtilsTest.java 4 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/MetricUtilsTest.java 5 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/ModelUtilsTest.java 6 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/ObjectCacheTest.java 6 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/PermissionsTest.java 3 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/PushLogTest.java 2 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/RedmineUserServiceTest.java 6 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/RepositoryModelTest.java 13 ●●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/RpcTests.java 7 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/StringUtilsTest.java 6 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/SyndicationUtilsTest.java 5 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/TimeUtilsTest.java 5 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/UserServiceTest.java 6 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/X509UtilsTest.java 3 ●●●● patch | view | raw | blame | history
src/test/java/de/akquinet/devops/GitBlit4UITests.java 3 ●●●● patch | view | raw | blame | history
src/test/java/de/akquinet/devops/GitBlitServer4UITests.java 13 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/AccessRestrictionFilter.java
@@ -25,6 +25,8 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
@@ -126,7 +128,10 @@
        String fullUrl = getFullUrl(httpRequest);
        String repository = extractRepositoryName(fullUrl);
        if (GitBlit.self().isCollectingGarbage(repository)) {
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        if (repositoryManager.isCollectingGarbage(repository)) {
            logger.info(MessageFormat.format("ARF: Rejecting request for {0}, busy collecting garbage!", repository));
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
@@ -139,12 +144,12 @@
        UserModel user = getUser(httpRequest);
        // Load the repository model
        RepositoryModel model = GitBlit.self().getRepositoryModel(repository);
        RepositoryModel model = repositoryManager.getRepositoryModel(repository);
        if (model == null) {
            if (isCreationAllowed()) {
                if (user == null) {
                    // challenge client to provide credentials for creation. send 401.
                    if (GitBlit.isDebugMode()) {
                    if (runtimeManager.isDebugMode()) {
                        logger.info(MessageFormat.format("ARF: CREATE CHALLENGE {0}", fullUrl));
                    }
                    httpResponse.setHeader("WWW-Authenticate", CHALLENGE);
@@ -191,7 +196,7 @@
        if (!StringUtils.isEmpty(urlRequestType) && requiresAuthentication(model, urlRequestType)) {
            if (user == null) {
                // challenge client to provide credentials. send 401.
                if (GitBlit.isDebugMode()) {
                if (runtimeManager.isDebugMode()) {
                    logger.info(MessageFormat.format("ARF: CHALLENGE {0}", fullUrl));
                }
                httpResponse.setHeader("WWW-Authenticate", CHALLENGE);
@@ -209,7 +214,7 @@
                    return;
                }
                // valid user, but not for requested access. send 403.
                if (GitBlit.isDebugMode()) {
                if (runtimeManager.isDebugMode()) {
                    logger.info(MessageFormat.format("ARF: {0} forbidden to access {1}",
                            user.username, fullUrl));
                }
@@ -218,7 +223,7 @@
            }
        }
        if (GitBlit.isDebugMode()) {
        if (runtimeManager.isDebugMode()) {
            logger.info(MessageFormat.format("ARF: {0} ({1}) unauthenticated", fullUrl,
                    HttpServletResponse.SC_CONTINUE));
        }
src/main/java/com/gitblit/AuthenticationFilter.java
@@ -35,6 +35,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.manager.ISessionManager;
import com.gitblit.models.UserModel;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.StringUtils;
@@ -100,7 +101,8 @@
     * @return user
     */
    protected UserModel getUser(HttpServletRequest httpRequest) {
        UserModel user = GitBlit.self().authenticate(httpRequest, requiresClientCertificate());
        ISessionManager sessionManager = GitBlit.getManager(ISessionManager.class);
        UserModel user = sessionManager.authenticate(httpRequest, requiresClientCertificate());
        return user;
    }
src/main/java/com/gitblit/BranchGraphServlet.java
@@ -50,6 +50,8 @@
import org.eclipse.jgit.revplot.PlotWalk;
import org.eclipse.jgit.revwalk.RevCommit;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
@@ -102,9 +104,10 @@
    protected long getLastModified(HttpServletRequest req) {
        String repository = req.getParameter("r");
        String objectId = req.getParameter("h");
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        Repository r = null;
        try {
            r = GitBlit.self().getRepository(repository);
            r = repositoryManager.getRepository(repository);
            if (StringUtils.isEmpty(objectId)) {
                objectId = JGitUtils.getHEADRef(r);
            }
@@ -128,7 +131,10 @@
            String objectId = request.getParameter("h");
            String length = request.getParameter("l");
            r = GitBlit.self().getRepository(repository);
            IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
            IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
            r = repositoryManager.getRepository(repository);
            rw = new PlotWalk(r);
            if (StringUtils.isEmpty(objectId)) {
@@ -138,7 +144,7 @@
            rw.markStart(rw.lookupCommit(r.resolve(objectId)));
            // default to the items-per-page setting, unless specified
            int maxCommits = GitBlit.getInteger(Keys.web.itemsPerPage, 50);
            int maxCommits = settings.getInteger(Keys.web.itemsPerPage, 50);
            int requestedCommits = maxCommits;
            if (!StringUtils.isEmpty(length)) {
                int l = Integer.parseInt(length);
src/main/java/com/gitblit/DownloadZipServlet.java
@@ -29,6 +29,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.utils.CompressionUtils;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.MarkdownUtils;
@@ -101,7 +103,8 @@
    private void processRequest(javax.servlet.http.HttpServletRequest request,
            javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
            java.io.IOException {
        if (!GitBlit.getBoolean(Keys.web.allowZipDownloads, true)) {
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        if (!settings.getBoolean(Keys.web.allowZipDownloads, true)) {
            logger.warn("Zip downloads are disabled");
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
@@ -130,9 +133,10 @@
                name += "-" + objectId;
            }
            Repository r = GitBlit.self().getRepository(repository);
            IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
            Repository r = repositoryManager.getRepository(repository);
            if (r == null) {
                if (GitBlit.self().isCollectingGarbage(repository)) {
                if (repositoryManager.isCollectingGarbage(repository)) {
                    error(response, MessageFormat.format("# Error\nGitblit is busy collecting garbage in {0}", repository));
                    return;
                } else {
src/main/java/com/gitblit/EnforceAuthenticationFilter.java
@@ -30,6 +30,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.ISessionManager;
import com.gitblit.models.UserModel;
/**
@@ -49,9 +51,7 @@
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // nothing to be done
    } //init
    }
    /*
@@ -62,32 +62,28 @@
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /*
         * Determine whether to enforce the BASIC authentication:
         */
        @SuppressWarnings("static-access")
        Boolean mustForceAuth = GitBlit.self().getBoolean(Keys.web.authenticateViewPages, false)
                                && GitBlit.self().getBoolean(Keys.web.enforceHttpBasicAuthentication, false);
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        ISessionManager sessionManager = GitBlit.getManager(ISessionManager.class);
        Boolean mustForceAuth = settings.getBoolean(Keys.web.authenticateViewPages, false)
                                && settings.getBoolean(Keys.web.enforceHttpBasicAuthentication, false);
        HttpServletRequest  HttpRequest  = (HttpServletRequest)request;
        HttpServletResponse HttpResponse = (HttpServletResponse)response;
        UserModel user = GitBlit.self().authenticate(HttpRequest);
        HttpServletRequest  httpRequest  = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        UserModel user = sessionManager.authenticate(httpRequest);
        if (mustForceAuth && (user == null)) {
            // not authenticated, enforce now:
            logger.debug(MessageFormat.format("EnforceAuthFilter: user not authenticated for URL {0}!", request.toString()));
            @SuppressWarnings("static-access")
            String CHALLENGE = MessageFormat.format("Basic realm=\"{0}\"", GitBlit.self().getString("web.siteName",""));
            HttpResponse.setHeader("WWW-Authenticate", CHALLENGE);
            HttpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            String challenge = MessageFormat.format("Basic realm=\"{0}\"", settings.getString(Keys.web.siteName, ""));
            httpResponse.setHeader("WWW-Authenticate", challenge);
            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        } else {
            // user is authenticated, or don't care, continue handling
            chain.doFilter( request, response );
        } // authenticated
    } // doFilter
            chain.doFilter(request, response);
        }
    }
    /*
@@ -95,8 +91,5 @@
     */
    @Override
    public void destroy() {
        // Nothing to be done
    } // destroy
    }
}
src/main/java/com/gitblit/FederationClient.java
@@ -83,7 +83,8 @@
        }
        // configure the Gitblit singleton for minimal, non-server operation
        GitBlit.self().configureContext(settings, baseFolder, false);
        GitBlit gitblit = new GitBlit(settings, baseFolder);
        gitblit.configureContext(settings, baseFolder, false);
        FederationPullExecutor executor = new FederationPullExecutor(registrations, params.isDaemon);
        executor.run();
        if (!params.isDaemon) {
src/main/java/com/gitblit/FederationPullExecutor.java
@@ -46,6 +46,11 @@
import com.gitblit.Constants.FederationPullStatus;
import com.gitblit.Constants.FederationStrategy;
import com.gitblit.GitBlitException.ForbiddenException;
import com.gitblit.manager.IGitblitManager;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.FederationModel;
import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryModel;
@@ -116,7 +121,8 @@
                    if (registration.notifyOnError) {
                        String message = "Federation pull of " + registration.name + " @ "
                                + registration.url + " is now at " + is.name();
                        GitBlit.self()
                        INotificationManager mailManager = GitBlit.getManager(INotificationManager.class);
                        mailManager
                                .sendMailToAdministrators(
                                        "Pull Status of " + registration.name + " is " + is.name(),
                                        message);
@@ -153,7 +159,8 @@
                            c, registrationFolder, registration.name));
            return;
        }
        File repositoriesFolder = GitBlit.getRepositoriesFolder();
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        File repositoriesFolder = repositoryManager.getRepositoriesFolder();
        File registrationFolderFile = new File(repositoriesFolder, registrationFolder);
        registrationFolderFile.mkdirs();
@@ -193,9 +200,9 @@
            // confirm that the origin of any pre-existing repository matches
            // the clone url
            String fetchHead = null;
            Repository existingRepository = GitBlit.self().getRepository(repositoryName);
            Repository existingRepository = repositoryManager.getRepository(repositoryName);
            if (existingRepository == null && GitBlit.self().isCollectingGarbage(repositoryName)) {
            if (existingRepository == null && repositoryManager.isCollectingGarbage(repositoryName)) {
                logger.warn(MessageFormat.format("Skipping local repository {0}, busy collecting garbage", repositoryName));
                continue;
            }
@@ -227,8 +234,8 @@
            CloneResult result = JGitUtils.cloneRepository(registrationFolderFile, repository.name,
                    cloneUrl, registration.bare, credentials);
            Repository r = GitBlit.self().getRepository(repositoryName);
            RepositoryModel rm = GitBlit.self().getRepositoryModel(repositoryName);
            Repository r = repositoryManager.getRepository(repositoryName);
            RepositoryModel rm = repositoryManager.getRepositoryModel(repositoryName);
            repository.isFrozen = registration.mirror;
            if (result.createdRepository) {
                // default local settings
@@ -316,10 +323,12 @@
            // "federated" repositories.
            repository.isFederated = cloneUrl.startsWith(registration.url);
            GitBlit.self().updateConfiguration(r, repository);
            repositoryManager.updateConfiguration(r, repository);
            r.close();
        }
        IUserManager userManager = GitBlit.getManager(IUserManager.class);
        IGitblitManager gitblitManager = GitBlit.getManager(IGitblitManager.class);
        IUserService userService = null;
        try {
@@ -359,10 +368,10 @@
                        }
                        // insert new user or update local user
                        UserModel localUser = GitBlit.self().getUserModel(user.username);
                        UserModel localUser = userManager.getUserModel(user.username);
                        if (localUser == null) {
                            // create new local user
                            GitBlit.self().updateUserModel(user.username, user, true);
                            gitblitManager.updateUserModel(user.username, user, true);
                        } else {
                            // update repository permissions of local user
                            if (user.permissions != null) {
@@ -379,19 +388,19 @@
                            }
                            localUser.password = user.password;
                            localUser.canAdmin = user.canAdmin;
                            GitBlit.self().updateUserModel(localUser.username, localUser, false);
                            gitblitManager.updateUserModel(localUser.username, localUser, false);
                        }
                        for (String teamname : GitBlit.self().getAllTeamnames()) {
                            TeamModel team = GitBlit.self().getTeamModel(teamname);
                        for (String teamname : userManager.getAllTeamNames()) {
                            TeamModel team = userManager.getTeamModel(teamname);
                            if (user.isTeamMember(teamname) && !team.hasUser(user.username)) {
                                // new team member
                                team.addUser(user.username);
                                GitBlit.self().updateTeamModel(teamname, team, false);
                                userManager.updateTeamModel(teamname, team);
                            } else if (!user.isTeamMember(teamname) && team.hasUser(user.username)) {
                                // remove team member
                                team.removeUser(user.username);
                                GitBlit.self().updateTeamModel(teamname, team, false);
                                userManager.updateTeamModel(teamname, team);
                            }
                            // update team repositories
@@ -402,11 +411,11 @@
                                    for (Map.Entry<String, AccessPermission> entry : remoteTeam.permissions.entrySet()){
                                        team.setRepositoryPermission(entry.getKey(), entry.getValue());
                                    }
                                    GitBlit.self().updateTeamModel(teamname, team, false);
                                    userManager.updateTeamModel(teamname, team);
                                } else if(!ArrayUtils.isEmpty(remoteTeam.repositories)) {
                                    // pulling from <= 1.1
                                    team.addRepositoryPermissions(remoteTeam.repositories);
                                    GitBlit.self().updateTeamModel(teamname, team, false);
                                    userManager.updateTeamModel(teamname, team);
                                }
                            }
                        }
@@ -497,7 +506,8 @@
            return;
        }
        InetAddress addr = InetAddress.getLocalHost();
        String federationName = GitBlit.getString(Keys.federation.name, null);
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        String federationName = settings.getString(Keys.federation.name, null);
        if (StringUtils.isEmpty(federationName)) {
            federationName = addr.getHostName();
        }
src/main/java/com/gitblit/FederationServlet.java
@@ -28,6 +28,10 @@
import javax.servlet.http.HttpServletResponse;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.TeamModel;
@@ -65,6 +69,12 @@
    protected void processRequest(javax.servlet.http.HttpServletRequest request,
            javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
            java.io.IOException {
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        IUserManager userManager = GitBlit.getManager(IUserManager.class);
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        IFederationManager federationManager = GitBlit.getManager(IFederationManager.class);
        FederationRequest reqType = FederationRequest.fromName(request.getParameter("req"));
        logger.info(MessageFormat.format("Federation {0} request from {1}", reqType,
                request.getRemoteAddr()));
@@ -75,13 +85,13 @@
            return;
        }
        if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {
        if (!settings.getBoolean(Keys.git.enableGitServlet, true)) {
            logger.warn(Keys.git.enableGitServlet + " must be set TRUE for federation requests.");
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
        String uuid = GitBlit.getString(Keys.federation.passphrase, "");
        String uuid = settings.getString(Keys.federation.passphrase, "");
        if (StringUtils.isEmpty(uuid)) {
            logger.warn(Keys.federation.passphrase
                    + " is not properly set!  Federation request denied.");
@@ -97,7 +107,7 @@
            }
            // reject proposal, if not receipt prohibited
            if (!GitBlit.getBoolean(Keys.federation.allowProposals, false)) {
            if (!settings.getBoolean(Keys.federation.allowProposals, false)) {
                logger.error(MessageFormat.format("Rejected {0} federation proposal from {1}",
                        proposal.tokenType.name(), proposal.url));
                response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
@@ -119,7 +129,7 @@
            }
            String url = HttpUtils.getGitblitURL(request);
            GitBlit.self().submitFederationProposal(proposal, url);
            federationManager.submitFederationProposal(proposal, url);
            logger.info(MessageFormat.format(
                    "Submitted {0} federation proposal to pull {1} repositories from {2}",
                    proposal.tokenType.name(), proposal.repositories.size(), proposal.url));
@@ -145,7 +155,7 @@
            results.nextPull = new Date(System.currentTimeMillis() + (mins * 60 * 1000L));
            // acknowledge the receipt of status
            GitBlit.self().acknowledgeFederationStatus(identification, results);
            federationManager.acknowledgeFederationStatus(identification, results);
            logger.info(MessageFormat.format(
                    "Received status of {0} federated repositories from {1}", results
                            .getStatusList().size(), identification));
@@ -155,7 +165,7 @@
        // Determine the federation tokens for this gitblit instance
        String token = request.getParameter("token");
        List<String> tokens = GitBlit.self().getFederationTokens();
        List<String> tokens = federationManager.getFederationTokens();
        if (!tokens.contains(token)) {
            logger.warn(MessageFormat.format(
                    "Received Federation token ''{0}'' does not match the server tokens", token));
@@ -166,11 +176,11 @@
        Object result = null;
        if (FederationRequest.PULL_REPOSITORIES.equals(reqType)) {
            String gitblitUrl = HttpUtils.getGitblitURL(request);
            result = GitBlit.self().getRepositories(gitblitUrl, token);
            result = federationManager.getRepositories(gitblitUrl, token);
        } else {
            if (FederationRequest.PULL_SETTINGS.equals(reqType)) {
                // pull settings
                if (!GitBlit.self().validateFederationRequest(reqType, token)) {
                if (!federationManager.validateFederationRequest(reqType, token)) {
                    // invalid token to pull users or settings
                    logger.warn(MessageFormat.format(
                            "Federation token from {0} not authorized to pull SETTINGS",
@@ -178,15 +188,15 @@
                    response.sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }
                Map<String, String> settings = new HashMap<String, String>();
                List<String> keys = GitBlit.getAllKeys(null);
                Map<String, String> map = new HashMap<String, String>();
                List<String> keys = settings.getAllKeys(null);
                for (String key : keys) {
                    settings.put(key, GitBlit.getString(key, ""));
                    map.put(key, settings.getString(key, ""));
                }
                result = settings;
                result = map;
            } else if (FederationRequest.PULL_USERS.equals(reqType)) {
                // pull users
                if (!GitBlit.self().validateFederationRequest(reqType, token)) {
                if (!federationManager.validateFederationRequest(reqType, token)) {
                    // invalid token to pull users or settings
                    logger.warn(MessageFormat.format(
                            "Federation token from {0} not authorized to pull USERS",
@@ -194,10 +204,10 @@
                    response.sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }
                List<String> usernames = GitBlit.self().getAllUsernames();
                List<String> usernames = userManager.getAllUsernames();
                List<UserModel> users = new ArrayList<UserModel>();
                for (String username : usernames) {
                    UserModel user = GitBlit.self().getUserModel(username);
                    UserModel user = userManager.getUserModel(username);
                    if (!user.excludeFromFederation) {
                        users.add(user);
                    }
@@ -205,7 +215,7 @@
                result = users;
            } else if (FederationRequest.PULL_TEAMS.equals(reqType)) {
                // pull teams
                if (!GitBlit.self().validateFederationRequest(reqType, token)) {
                if (!federationManager.validateFederationRequest(reqType, token)) {
                    // invalid token to pull teams
                    logger.warn(MessageFormat.format(
                            "Federation token from {0} not authorized to pull TEAMS",
@@ -213,16 +223,16 @@
                    response.sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }
                List<String> teamnames = GitBlit.self().getAllTeamnames();
                List<String> teamnames = userManager.getAllTeamNames();
                List<TeamModel> teams = new ArrayList<TeamModel>();
                for (String teamname : teamnames) {
                    TeamModel user = GitBlit.self().getTeamModel(teamname);
                    TeamModel user = userManager.getTeamModel(teamname);
                    teams.add(user);
                }
                result = teams;
            } else if (FederationRequest.PULL_SCRIPTS.equals(reqType)) {
                // pull scripts
                if (!GitBlit.self().validateFederationRequest(reqType, token)) {
                if (!federationManager.validateFederationRequest(reqType, token)) {
                    // invalid token to pull script
                    logger.warn(MessageFormat.format(
                            "Federation token from {0} not authorized to pull SCRIPTS",
@@ -233,13 +243,13 @@
                Map<String, String> scripts = new HashMap<String, String>();
                Set<String> names = new HashSet<String>();
                names.addAll(GitBlit.getStrings(Keys.groovy.preReceiveScripts));
                names.addAll(GitBlit.getStrings(Keys.groovy.postReceiveScripts));
                for (TeamModel team :  GitBlit.self().getAllTeams()) {
                names.addAll(settings.getStrings(Keys.groovy.preReceiveScripts));
                names.addAll(settings.getStrings(Keys.groovy.postReceiveScripts));
                for (TeamModel team :  userManager.getAllTeams()) {
                    names.addAll(team.preReceiveScripts);
                    names.addAll(team.postReceiveScripts);
                }
                File scriptsFolder = GitBlit.getFileOrFolder(Keys.groovy.scriptsFolder, "groovy");
                File scriptsFolder = repositoryManager.getHooksFolder();
                for (String name : names) {
                    File file = new File(scriptsFolder, name);
                    if (!file.exists() && !file.getName().endsWith(".groovy")) {
src/main/java/com/gitblit/GCExecutor.java
@@ -31,6 +31,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.FileUtils;
@@ -131,7 +132,9 @@
        running.set(true);
        Date now = new Date();
        for (String repositoryName : GitBlit.self().getRepositoryList()) {
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        for (String repositoryName : repositoryManager.getRepositoryList()) {
            if (forceClose.get()) {
                break;
            }
@@ -143,8 +146,8 @@
            RepositoryModel model = null;
            Repository repository = null;
            try {
                model = GitBlit.self().getRepositoryModel(repositoryName);
                repository = GitBlit.self().getRepository(repositoryName);
                model = repositoryManager.getRepositoryModel(repositoryName);
                repository = repositoryManager.getRepository(repositoryName);
                if (repository == null) {
                    logger.warn(MessageFormat.format("GCExecutor is missing repository {0}?!?", repositoryName));
                    continue;
@@ -204,7 +207,7 @@
                    if (garbageCollected) {
                        // update the last GC date
                        model.lastGC = new Date();
                        GitBlit.self().updateConfiguration(repository, model);
                        repositoryManager.updateConfiguration(repository, model);
                    }
                    repository.close();
src/main/java/com/gitblit/GitBlit.java
@@ -69,9 +69,9 @@
import javax.servlet.ServletContextListener;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.protocol.http.WebResponse;
import org.apache.wicket.resource.ContextRelativeResource;
import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
import org.eclipse.jgit.lib.Repository;
@@ -100,6 +100,14 @@
import com.gitblit.fanout.FanoutService;
import com.gitblit.fanout.FanoutSocketService;
import com.gitblit.git.GitDaemon;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IGitblitManager;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.ISessionManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
@@ -158,9 +166,19 @@
 * @author James Moger
 *
 */
public class GitBlit implements ServletContextListener {
public class GitBlit implements ServletContextListener,
                                IRuntimeManager,
                                INotificationManager,
                                IUserManager,
                                ISessionManager,
                                IRepositoryManager,
                                IProjectManager,
                                IFederationManager,
                                IGitblitManager {
    private static GitBlit gitblit;
    private final IStoredSettings goSettings;
    private final Logger logger = LoggerFactory.getLogger(GitBlit.class);
@@ -218,14 +236,18 @@
    private GitDaemon gitDaemon;
    public GitBlit() {
        if (gitblit == null) {
            // set the static singleton reference
            gitblit = this;
        }
        this.goSettings = null;
    }
    public GitBlit(final IUserService userService) {
    protected GitBlit(final IUserService userService) {
        this.goSettings = null;
        this.userService = userService;
        gitblit = this;
    }
    public GitBlit(IStoredSettings settings, File baseFolder) {
        this.goSettings = settings;
        this.baseFolder = baseFolder;
        gitblit = this;
    }
@@ -235,10 +257,25 @@
     * @return gitblit singleton
     */
    public static GitBlit self() {
        if (gitblit == null) {
            new GitBlit();
        }
        return gitblit;
    }
    @SuppressWarnings("unchecked")
    public static <X> X getManager(Class<X> managerClass) {
        if (managerClass.isAssignableFrom(GitBlit.class)) {
            return (X) gitblit;
        }
        return null;
    }
    @Override
    public File getBaseFolder() {
        return baseFolder;
    }
    @Override
    public void setBaseFolder(File folder) {
        this.baseFolder = folder;
    }
    /**
@@ -246,8 +283,9 @@
     *
     * @return the boot date of Gitblit
     */
    public static Date getBootDate() {
        return self().serverStatus.bootDate;
    @Override
    public Date getBootDate() {
        return serverStatus.bootDate;
    }
    /**
@@ -255,10 +293,11 @@
     *
     * @return a date
     */
    public static Date getLastActivityDate() {
    @Override
    public Date getLastActivityDate() {
        Date date = null;
        for (String name : self().getRepositoryList()) {
            Repository r = self().getRepository(name);
        for (String name : getRepositoryList()) {
            Repository r = getRepository(name);
            Date lastChange = JGitUtils.getLastChange(r).when;
            r.close();
            if (lastChange != null && (date == null || lastChange.after(date))) {
@@ -269,32 +308,14 @@
    }
    /**
     * Determine if this is the GO variant of Gitblit.
     *
     * @return true if this is the GO variant of Gitblit.
     */
    public static boolean isGO() {
        return self().settings instanceof FileSettings;
    }
    /**
     * Determine if this Gitblit instance is actively serving git repositories
     * or if it is merely a repository viewer.
     *
     * @return true if Gitblit is serving repositories
     */
    public static boolean isServingRepositories() {
        return getBoolean(Keys.git.enableGitServlet, true) || (getInteger(Keys.git.daemonPort, 0) > 0);
    }
    /**
     * Determine if this Gitblit instance is actively serving git repositories
     * or if it is merely a repository viewer.
     *
     * @return true if Gitblit is serving repositories
     */
    public static boolean isSendingMail() {
        return self().mailExecutor.isReady();
    @Override
    public boolean isServingRepositories() {
        return settings.getBoolean(Keys.git.enableGitServlet, true) || (settings.getInteger(Keys.git.daemonPort, 0) > 0);
    }
    /**
@@ -302,167 +323,17 @@
     *
     * @return a timezone
     */
    public static TimeZone getTimezone() {
        if (self().timezone == null) {
            String tzid = getString("web.timezone", null);
    @Override
    public TimeZone getTimezone() {
        if (timezone == null) {
            String tzid = settings.getString("web.timezone", null);
            if (StringUtils.isEmpty(tzid)) {
                self().timezone = TimeZone.getDefault();
                return self().timezone;
                timezone = TimeZone.getDefault();
                return timezone;
            }
            self().timezone = TimeZone.getTimeZone(tzid);
            timezone = TimeZone.getTimeZone(tzid);
        }
        return self().timezone;
    }
    /**
     * Returns the active settings.
     *
     * @return the active settings
     */
    public static IStoredSettings getSettings() {
        return self().settings;
    }
    /**
     * Returns the user-defined blob encodings.
     *
     * @return an array of encodings, may be empty
     */
    public static String [] getEncodings() {
        return getStrings(Keys.web.blobEncodings).toArray(new String[0]);
    }
    /**
     * Returns the boolean value for the specified key. If the key does not
     * exist or the value for the key can not be interpreted as a boolean, the
     * defaultValue is returned.
     *
     * @see IStoredSettings.getBoolean(String, boolean)
     * @param key
     * @param defaultValue
     * @return key value or defaultValue
     */
    public static boolean getBoolean(String key, boolean defaultValue) {
        return self().settings.getBoolean(key, defaultValue);
    }
    /**
     * Returns the integer value for the specified key. If the key does not
     * exist or the value for the key can not be interpreted as an integer, the
     * defaultValue is returned.
     *
     * @see IStoredSettings.getInteger(String key, int defaultValue)
     * @param key
     * @param defaultValue
     * @return key value or defaultValue
     */
    public static int getInteger(String key, int defaultValue) {
        return self().settings.getInteger(key, defaultValue);
    }
    /**
     * Returns the integer list for the specified key. If the key does not
     * exist or the value for the key can not be interpreted as an integer, an
     * empty list is returned.
     *
     * @see IStoredSettings.getIntegers(String key)
     * @param key
     * @return key value or defaultValue
     */
    public static List<Integer> getIntegers(String key) {
        return self().settings.getIntegers(key);
    }
    /**
     * Returns the value in bytes for the specified key. If the key does not
     * exist or the value for the key can not be interpreted as an integer, the
     * defaultValue is returned.
     *
     * @see IStoredSettings.getFilesize(String key, int defaultValue)
     * @param key
     * @param defaultValue
     * @return key value or defaultValue
     */
    public static int getFilesize(String key, int defaultValue) {
        return self().settings.getFilesize(key, defaultValue);
    }
    /**
     * Returns the value in bytes for the specified key. If the key does not
     * exist or the value for the key can not be interpreted as a long, the
     * defaultValue is returned.
     *
     * @see IStoredSettings.getFilesize(String key, long defaultValue)
     * @param key
     * @param defaultValue
     * @return key value or defaultValue
     */
    public static long getFilesize(String key, long defaultValue) {
        return self().settings.getFilesize(key, defaultValue);
    }
    /**
     * Returns the char value for the specified key. If the key does not exist
     * or the value for the key can not be interpreted as a character, the
     * defaultValue is returned.
     *
     * @see IStoredSettings.getChar(String key, char defaultValue)
     * @param key
     * @param defaultValue
     * @return key value or defaultValue
     */
    public static char getChar(String key, char defaultValue) {
        return self().settings.getChar(key, defaultValue);
    }
    /**
     * Returns the string value for the specified key. If the key does not exist
     * or the value for the key can not be interpreted as a string, the
     * defaultValue is returned.
     *
     * @see IStoredSettings.getString(String key, String defaultValue)
     * @param key
     * @param defaultValue
     * @return key value or defaultValue
     */
    public static String getString(String key, String defaultValue) {
        return self().settings.getString(key, defaultValue);
    }
    /**
     * Returns a list of space-separated strings from the specified key.
     *
     * @see IStoredSettings.getStrings(String key)
     * @param n
     * @return list of strings
     */
    public static List<String> getStrings(String key) {
        return self().settings.getStrings(key);
    }
    /**
     * Returns a map of space-separated key-value pairs from the specified key.
     *
     * @see IStoredSettings.getStrings(String key)
     * @param n
     * @return map of string, string
     */
    public static Map<String, String> getMap(String key) {
        return self().settings.getMap(key);
    }
    /**
     * Returns the list of keys whose name starts with the specified prefix. If
     * the prefix is null or empty, all key names are returned.
     *
     * @see IStoredSettings.getAllKeys(String key)
     * @param startingWith
     * @return list of keys
     */
    public static List<String> getAllKeys(String startingWith) {
        return self().settings.getAllKeys(startingWith);
        return timezone;
    }
    /**
@@ -470,8 +341,9 @@
     *
     * @return true if Gitblit is running in debug mode
     */
    public static boolean isDebugMode() {
        return self().settings.getBoolean(Keys.web.debugMode, false);
    @Override
    public boolean isDebugMode() {
        return settings.getBoolean(Keys.web.debugMode, false);
    }
    /**
@@ -479,8 +351,9 @@
     *
     * @return the file
     */
    public static File getFileOrFolder(String key, String defaultFileOrFolder) {
        String fileOrFolder = GitBlit.getString(key, defaultFileOrFolder);
    @Override
    public File getFileOrFolder(String key, String defaultFileOrFolder) {
        String fileOrFolder = settings.getString(key, defaultFileOrFolder);
        return getFileOrFolder(fileOrFolder);
    }
@@ -493,9 +366,10 @@
     *
     * @return the file
     */
    public static File getFileOrFolder(String fileOrFolder) {
    @Override
    public File getFileOrFolder(String fileOrFolder) {
        return com.gitblit.utils.FileUtils.resolveParameter(Constants.baseFolder$,
                self().baseFolder, fileOrFolder);
                baseFolder, fileOrFolder);
    }
    /**
@@ -504,7 +378,8 @@
     *
     * @return the repositories folder path
     */
    public static File getRepositoriesFolder() {
    @Override
    public File getRepositoriesFolder() {
        return getFileOrFolder(Keys.git.repositoriesFolder, "${baseFolder}/git");
    }
@@ -514,7 +389,8 @@
     *
     * @return the proposals folder path
     */
    public static File getProposalsFolder() {
    @Override
    public File getProposalsFolder() {
        return getFileOrFolder(Keys.federation.proposalsFolder, "${baseFolder}/proposals");
    }
@@ -524,20 +400,44 @@
     *
     * @return the Groovy scripts folder path
     */
    public static File getGroovyScriptsFolder() {
    @Override
    public File getHooksFolder() {
        return getFileOrFolder(Keys.groovy.scriptsFolder, "${baseFolder}/groovy");
    }
    /**
     * Updates the list of server settings.
     * 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 getFileOrFolder(Keys.groovy.grapeFolder, "${baseFolder}/groovy/grape");
    }
    /**
     * Returns the runtime settings.
     *
     * @return runtime settings
     */
    @Override
    public IStoredSettings getSettings() {
        return settings;
    }
    /**
     * Updates the runtime settings.
     *
     * @param settings
     * @return true if the update succeeded
     */
    @Override
    public boolean updateSettings(Map<String, String> updatedSettings) {
        return settings.saveSettings(updatedSettings);
    }
    @Override
    public ServerStatus getStatus() {
        // update heap memory status
        serverStatus.heapAllocated = Runtime.getRuntime().totalMemory();
@@ -553,6 +453,7 @@
     * @param repository
     * @return a list of repository urls
     */
    @Override
    public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) {
        if (user == null) {
            user = UserModel.ANONYMOUS;
@@ -650,6 +551,7 @@
     *
     * @return a collection of client applications
     */
    @Override
    public Collection<GitClientApplication> getClientApplications() {
        // prefer user definitions, if they exist
        File userDefs = new File(baseFolder, "clientapps.json");
@@ -718,6 +620,7 @@
        this.userService.setup(settings);
    }
    @Override
    public boolean supportsAddUser() {
        return supportsCredentialChanges(new UserModel(""));
    }
@@ -728,6 +631,7 @@
     * @param user
     * @return true if the user service supports credential changes
     */
    @Override
    public boolean supportsCredentialChanges(UserModel user) {
        if (user == null) {
            return false;
@@ -746,6 +650,7 @@
     * @param user
     * @return true if the user service supports display name changes
     */
    @Override
    public boolean supportsDisplayNameChanges(UserModel user) {
        return (user != null && user.isLocalAccount()) || userService.supportsDisplayNameChanges();
    }
@@ -756,6 +661,7 @@
     * @param user
     * @return true if the user service supports email address changes
     */
    @Override
    public boolean supportsEmailAddressChanges(UserModel user) {
        return (user != null && user.isLocalAccount()) || userService.supportsEmailAddressChanges();
    }
@@ -766,6 +672,7 @@
     * @param user
     * @return true if the user service supports team membership changes
     */
    @Override
    public boolean supportsTeamMembershipChanges(UserModel user) {
        return (user != null && user.isLocalAccount()) || userService.supportsTeamMembershipChanges();
    }
@@ -790,6 +697,7 @@
     * @param password
     * @return a user object or null
     */
    @Override
    public UserModel authenticate(String username, char[] password) {
        if (StringUtils.isEmpty(username)) {
            // can not authenticate empty username
@@ -850,6 +758,7 @@
     * @param httpRequest
     * @return a user object or null
     */
    @Override
    public UserModel authenticate(HttpServletRequest httpRequest) {
        return authenticate(httpRequest, false);
    }
@@ -864,10 +773,11 @@
     * @param requiresCertificate
     * @return a user object or null
     */
    @Override
    public UserModel authenticate(HttpServletRequest httpRequest, boolean requiresCertificate) {
        // try to authenticate by certificate
        boolean checkValidity = settings.getBoolean(Keys.git.enforceCertificateValidity, true);
        String [] oids = getStrings(Keys.git.certificateUsernameOIDs).toArray(new String[0]);
        String [] oids = settings.getStrings(Keys.git.certificateUsernameOIDs).toArray(new String[0]);
        UserModel model = HttpUtils.getUserModelFromCertificate(httpRequest, checkValidity, oids);
        if (model != null) {
            // grab real user model and preserve certificate serial number
@@ -921,7 +831,7 @@
        }
        // try to authenticate by cookie
        if (allowCookieAuthentication()) {
        if (supportsCookies()) {
            UserModel user = authenticate(httpRequest.getCookies());
            if (user != null) {
                flagWicketSession(AuthenticationType.COOKIE);
@@ -985,7 +895,8 @@
     * @param response
     * @param user
     */
    public void setCookie(WebResponse response, UserModel user) {
    @Override
    public void setCookie(HttpServletResponse response, UserModel user) {
        if (userService == null) {
            return;
        }
@@ -1019,6 +930,7 @@
     *
     * @param user
     */
    @Override
    public void logout(UserModel user) {
        if (userService == null) {
            return;
@@ -1052,6 +964,7 @@
     * @see IUserService.getAllUsernames()
     * @return list of all usernames
     */
    @Override
    public List<String> getAllUsernames() {
        List<String> names = new ArrayList<String>(userService.getAllUsernames());
        return names;
@@ -1063,6 +976,7 @@
     * @see IUserService.getAllUsernames()
     * @return list of all usernames
     */
    @Override
    public List<UserModel> getAllUsers() {
        List<UserModel> users = userService.getAllUsers();
        return users;
@@ -1075,6 +989,7 @@
     * @param username
     * @return true if successful
     */
    @Override
    public boolean deleteUser(String username) {
        if (StringUtils.isEmpty(username)) {
            return false;
@@ -1083,7 +998,8 @@
        return userService.deleteUser(usernameDecoded);
    }
    protected UserModel getFederationUser() {
    @Override
    public UserModel getFederationUser() {
        // the federation user is an administrator
        UserModel federationUser = new UserModel(Constants.FEDERATION_USER);
        federationUser.canAdmin = true;
@@ -1097,6 +1013,7 @@
     * @param username
     * @return a user object or null
     */
    @Override
    public UserModel getUserModel(String username) {
        if (StringUtils.isEmpty(username)) {
            return null;
@@ -1113,6 +1030,7 @@
     * @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
@@ -1123,7 +1041,7 @@
        // Flag missing repositories
        for (RegistrantAccessPermission permission : set) {
            if (permission.mutable && PermissionType.EXPLICIT.equals(permission.permissionType)) {
                RepositoryModel rm = GitBlit.self().getRepositoryModel(permission.registrant);
                RepositoryModel rm = getRepositoryModel(permission.registrant);
                if (rm == null) {
                    permission.permissionType = PermissionType.MISSING;
                    permission.mutable = false;
@@ -1158,6 +1076,7 @@
     * @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)) {
@@ -1185,6 +1104,7 @@
     * @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) {
@@ -1206,6 +1126,7 @@
     * @param repository
     * @return list of all usernames that have an access permission for the repository
     */
    @Override
    public List<String> getRepositoryUsers(RepositoryModel repository) {
        return userService.getUsernamesForRepositoryRole(repository.name);
    }
@@ -1236,6 +1157,7 @@
     * @param isCreate
     * @throws GitBlitException
     */
    @Override
    public void updateUserModel(String username, UserModel user, boolean isCreate)
            throws GitBlitException {
        if (!username.equalsIgnoreCase(user.username)) {
@@ -1283,6 +1205,7 @@
     *
     * @return the list of teams
     */
    @Override
    public List<TeamModel> getAllTeams() {
        List<TeamModel> teams = userService.getAllTeams();
        return teams;
@@ -1294,6 +1217,7 @@
     * @param teamname
     * @return a TeamModel object or null
     */
    @Override
    public TeamModel getTeamModel(String teamname) {
        return userService.getTeamModel(teamname);
    }
@@ -1306,6 +1230,7 @@
     * @param repository
     * @return a list of RegistrantAccessPermissions
     */
    @Override
    public List<RegistrantAccessPermission> getTeamAccessPermissions(RepositoryModel repository) {
        List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
        for (TeamModel team : userService.getAllTeams()) {
@@ -1325,6 +1250,7 @@
     * @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) {
@@ -1346,6 +1272,7 @@
     * @param repository
     * @return list of all teamnames with explicit access permissions to the repository
     */
    @Override
    public List<String> getRepositoryTeams(RepositoryModel repository) {
        return userService.getTeamnamesForRepositoryRole(repository.name);
    }
@@ -1373,6 +1300,7 @@
     * @param team
     * @param isCreate
     */
    @Override
    public void updateTeamModel(String teamname, TeamModel team, boolean isCreate)
            throws GitBlitException {
        if (!teamname.equalsIgnoreCase(team.name)) {
@@ -1394,6 +1322,7 @@
     * @param teamname
     * @return true if successful
     */
    @Override
    public boolean deleteTeam(String teamname) {
        return userService.deleteTeam(teamname);
    }
@@ -1404,7 +1333,8 @@
     *
     * @param model
     */
    private void addToCachedRepositoryList(RepositoryModel model) {
    @Override
    public void addToCachedRepositoryList(RepositoryModel model) {
        if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
            repositoryListCache.put(model.name.toLowerCase(), model);
@@ -1445,6 +1375,7 @@
     * Resets the repository list cache.
     *
     */
    @Override
    public void resetRepositoryListCache() {
        logger.info("Repository cache manually reset");
        repositoryListCache.clear();
@@ -1488,6 +1419,7 @@
     *
     * @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
@@ -1505,7 +1437,7 @@
            } else {
                // we are caching this list
                String msg = "{0} repositories identified in {1} msecs";
                if (getBoolean(Keys.web.showRepositorySizes, true)) {
                if (settings.getBoolean(Keys.web.showRepositorySizes, true)) {
                    // optionally (re)calculate repository sizes
                    msg = "{0} repositories identified with calculated folder sizes in {1} msecs";
                }
@@ -1544,6 +1476,7 @@
     * @param repositoryName
     * @return repository or null
     */
    @Override
    public Repository getRepository(String repositoryName) {
        return getRepository(repositoryName, true);
    }
@@ -1555,6 +1488,7 @@
     * @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
@@ -1588,6 +1522,7 @@
     * @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();
@@ -1620,6 +1555,7 @@
     * @param repositoryName
     * @return repository model or null
     */
    @Override
    public RepositoryModel getRepositoryModel(UserModel user, String repositoryName) {
        RepositoryModel model = getRepositoryModel(repositoryName);
        if (model == null) {
@@ -1641,6 +1577,7 @@
     * @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
@@ -1702,6 +1639,7 @@
     * @param repository
     * @return the star count
     */
    @Override
    public long getStarCount(RepositoryModel repository) {
        long count = 0;
        for (UserModel user : getAllUsers()) {
@@ -1752,7 +1690,7 @@
            }
            // project configs
            String rootName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main");
            String rootName = settings.getString(Keys.web.repositoryRootGroupName, "main");
            ProjectModel rootProject = new ProjectModel(rootName, true);
            Map<String, ProjectModel> configs = new HashMap<String, ProjectModel>();
@@ -1787,6 +1725,7 @@
     * @param includeUsers
     * @return list of projects that are accessible to the user
     */
    @Override
    public List<ProjectModel> getProjectModels(UserModel user, boolean includeUsers) {
        Map<String, ProjectModel> configs = getProjectConfigs();
@@ -1841,6 +1780,7 @@
     * @param user
     * @return a project model, or null if it does not exist
     */
    @Override
    public ProjectModel getProjectModel(String name, UserModel user) {
        for (ProjectModel project : getProjectModels(user, true)) {
            if (project.name.equalsIgnoreCase(name)) {
@@ -1856,6 +1796,7 @@
     * @param name a project name
     * @return a project model or null if the project does not exist
     */
    @Override
    public ProjectModel getProjectModel(String name) {
        Map<String, ProjectModel> configs = getProjectConfigs();
        ProjectModel project = configs.get(name.toLowerCase());
@@ -1906,6 +1847,7 @@
     * @param includeUsers
     * @return a list of project models
     */
    @Override
    public List<ProjectModel> getProjectModels(List<RepositoryModel> repositoryModels, boolean includeUsers) {
        Map<String, ProjectModel> projects = new LinkedHashMap<String, ProjectModel>();
        for (RepositoryModel repository : repositoryModels) {
@@ -2090,6 +2032,7 @@
     * @param n
     * @return true if the repository exists
     */
    @Override
    public boolean hasRepository(String repositoryName) {
        return hasRepository(repositoryName, false);
    }
@@ -2101,6 +2044,7 @@
     * @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
@@ -2123,6 +2067,7 @@
     * @param origin
     * @return true the if the user has a fork
     */
    @Override
    public boolean hasFork(String username, String origin) {
        return getFork(username, origin) != null;
    }
@@ -2135,6 +2080,7 @@
     * @param origin
     * @return the name of the user's fork, null otherwise
     */
    @Override
    public String getFork(String username, String origin) {
        String userProject = ModelUtils.getPersonalPath(username);
        if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
@@ -2200,6 +2146,7 @@
     * @param repository
     * @return a ForkModel
     */
    @Override
    public ForkModel getForkNetwork(String repository) {
        if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
            // find the root, cached
@@ -2263,12 +2210,13 @@
     * @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 (!getBoolean(Keys.web.showRepositorySizes, true) || model.skipSizeCalculation) {
        if (!settings.getBoolean(Keys.web.showRepositorySizes, true) || model.skipSizeCalculation) {
            model.size = null;
            return 0L;
        }
@@ -2336,6 +2284,7 @@
     * @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));
@@ -2410,6 +2359,7 @@
     * @param isCreate
     * @throws GitBlitException
     */
    @Override
    public void updateRepositoryModel(String repositoryName, RepositoryModel repository,
            boolean isCreate) throws GitBlitException {
        if (gcExecutor.isCollectingGarbage(repositoryName)) {
@@ -2419,7 +2369,7 @@
        Repository r = null;
        String projectPath = StringUtils.getFirstPathElement(repository.name);
        if (!StringUtils.isEmpty(projectPath)) {
            if (projectPath.equalsIgnoreCase(getString(Keys.web.repositoryRootGroupName, "main"))) {
            if (projectPath.equalsIgnoreCase(settings.getString(Keys.web.repositoryRootGroupName, "main"))) {
                // strip leading group name
                repository.name = repository.name.substring(projectPath.length() + 1);
            }
@@ -2436,7 +2386,7 @@
            }
            // create repository
            logger.info("create repository " + repository.name);
            String shared = getString(Keys.git.createRepositoriesShared, "FALSE");
            String shared = settings.getString(Keys.git.createRepositoriesShared, "FALSE");
            r = JGitUtils.createRepository(repositoriesFolder, repository.name, shared);
        } else {
            // rename repository
@@ -2538,9 +2488,9 @@
            // Adjust permissions in case we updated the config files
            JGitUtils.adjustSharedPerm(new File(r.getDirectory().getAbsolutePath(), "config"),
                    getString(Keys.git.createRepositoriesShared, "FALSE"));
                    settings.getString(Keys.git.createRepositoriesShared, "FALSE"));
            JGitUtils.adjustSharedPerm(new File(r.getDirectory().getAbsolutePath(), "HEAD"),
                    getString(Keys.git.createRepositoriesShared, "FALSE"));
                    settings.getString(Keys.git.createRepositoriesShared, "FALSE"));
            // close the repository object
            r.close();
@@ -2560,6 +2510,7 @@
     * @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);
@@ -2659,6 +2610,7 @@
     * @param model
     * @return true if successful
     */
    @Override
    public boolean deleteRepositoryModel(RepositoryModel model) {
        return deleteRepository(model.name);
    }
@@ -2670,6 +2622,7 @@
     * @param repositoryName
     * @return true if successful
     */
    @Override
    public boolean deleteRepository(String repositoryName) {
        try {
            closeRepository(repositoryName);
@@ -2791,8 +2744,9 @@
        return scheduledExecutor;
    }
    public static boolean canFederate() {
        String passphrase = getString(Keys.federation.passphrase, "");
    @Override
    public boolean canFederate() {
        String passphrase = settings.getString(Keys.federation.passphrase, "");
        return !StringUtils.isEmpty(passphrase);
    }
@@ -2835,6 +2789,7 @@
     *
     * @return list of registered gitblit instances
     */
    @Override
    public List<FederationModel> getFederationRegistrations() {
        if (federationRegistrations.isEmpty()) {
            federationRegistrations.addAll(FederationUtils.getFederationRegistrations(settings));
@@ -2849,6 +2804,7 @@
     *            the name of the registration
     * @return a federation registration
     */
    @Override
    public FederationModel getFederationRegistration(String url, String name) {
        // check registrations
        for (FederationModel r : getFederationRegistrations()) {
@@ -2871,6 +2827,7 @@
     *
     * @return list of federation sets
     */
    @Override
    public List<FederationSet> getFederationSets(String gitblitUrl) {
        List<FederationSet> list = new ArrayList<FederationSet>();
        // generate standard tokens
@@ -2894,6 +2851,7 @@
     *
     * @return list of federation tokens
     */
    @Override
    public List<String> getFederationTokens() {
        List<String> tokens = new ArrayList<String>();
        // generate standard tokens
@@ -2913,6 +2871,7 @@
     * @param type
     * @return a federation token
     */
    @Override
    public String getFederationToken(FederationToken type) {
        return getFederationToken(type.name());
    }
@@ -2923,6 +2882,7 @@
     * @param value
     * @return a federation token
     */
    @Override
    public String getFederationToken(String value) {
        String passphrase = settings.getString(Keys.federation.passphrase, "");
        return StringUtils.getSHA1(passphrase + "-" + value);
@@ -2936,6 +2896,7 @@
     * @param token
     * @return true if the request can be executed
     */
    @Override
    public boolean validateFederationRequest(FederationRequest req, String token) {
        String all = getFederationToken(FederationToken.ALL);
        String unr = getFederationToken(FederationToken.USERS_AND_REPOSITORIES);
@@ -2964,6 +2925,7 @@
     *            the registration from the pulling Gitblit instance
     * @return true if acknowledged
     */
    @Override
    public boolean acknowledgeFederationStatus(String identification, FederationModel registration) {
        // reset the url to the identification of the pulling Gitblit instance
        registration.url = identification;
@@ -2980,6 +2942,7 @@
     *
     * @return the list of registration results
     */
    @Override
    public List<FederationModel> getFederationResultRegistrations() {
        return new ArrayList<FederationModel>(federationPullResults.values());
    }
@@ -2995,6 +2958,7 @@
     *            administrators
     * @return true if the proposal was submitted
     */
    @Override
    public boolean submitFederationProposal(FederationProposal proposal, String gitblitUrl) {
        // convert proposal to json
        String json = JsonUtils.toJsonString(proposal);
@@ -3022,6 +2986,7 @@
     *
     * @return list of federation proposals
     */
    @Override
    public List<FederationProposal> getPendingFederationProposals() {
        List<FederationProposal> list = new ArrayList<FederationProposal>();
        File folder = getProposalsFolder();
@@ -3052,9 +3017,10 @@
     *            the federation token
     * @return a map of <cloneurl, RepositoryModel>
     */
    @Override
    public Map<String, RepositoryModel> getRepositories(String gitblitUrl, String token) {
        Map<String, String> federationSets = new HashMap<String, String>();
        for (String set : getStrings(Keys.federation.sets)) {
        for (String set : settings.getStrings(Keys.federation.sets)) {
            federationSets.put(getFederationToken(set), set);
        }
@@ -3110,6 +3076,7 @@
     * @param token
     * @return a potential proposal
     */
    @Override
    public FederationProposal createFederationProposal(String gitblitUrl, String token) {
        FederationToken tokenType = FederationToken.REPOSITORIES;
        for (FederationToken type : FederationToken.values()) {
@@ -3130,6 +3097,7 @@
     * @param token
     * @return the specified proposal or null
     */
    @Override
    public FederationProposal getPendingFederationProposal(String token) {
        List<FederationProposal> list = getPendingFederationProposals();
        for (FederationProposal proposal : list) {
@@ -3147,6 +3115,7 @@
     *            proposal
     * @return true if the proposal was deleted
     */
    @Override
    public boolean deletePendingFederationProposal(FederationProposal proposal) {
        File folder = getProposalsFolder();
        File file = new File(folder, proposal.token + Constants.PROPOSAL_EXT);
@@ -3159,8 +3128,9 @@
     *
     * @return list of available hook scripts
     */
    @Override
    public List<String> getAllScripts() {
        File groovyFolder = getGroovyScriptsFolder();
        File groovyFolder = getHooksFolder();
        File[] files = groovyFolder.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
@@ -3185,10 +3155,11 @@
     *            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 : getStrings(Keys.groovy.preReceiveScripts)) {
        for (String script : settings.getStrings(Keys.groovy.preReceiveScripts)) {
            if (script.endsWith(".groovy")) {
                scripts.add(script.substring(0, script.lastIndexOf('.')));
            } else {
@@ -3217,6 +3188,7 @@
     *            optional parameter
     * @return list of available hook scripts
     */
    @Override
    public List<String> getPreReceiveScriptsUnused(RepositoryModel repository) {
        Set<String> inherited = new TreeSet<String>(getPreReceiveScriptsInherited(repository));
@@ -3238,10 +3210,11 @@
     *            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 : getStrings(Keys.groovy.postReceiveScripts)) {
        for (String script : settings.getStrings(Keys.groovy.postReceiveScripts)) {
            if (script.endsWith(".groovy")) {
                scripts.add(script.substring(0, script.lastIndexOf('.')));
            } else {
@@ -3269,6 +3242,7 @@
     *            optional parameter
     * @return list of available hook scripts
     */
    @Override
    public List<String> getPostReceiveScriptsUnused(RepositoryModel repository) {
        Set<String> inherited = new TreeSet<String>(getPostReceiveScriptsInherited(repository));
@@ -3291,6 +3265,7 @@
     * @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;
@@ -3302,6 +3277,7 @@
     * @param subject
     * @param message
     */
    @Override
    public void sendMailToAdministrators(String subject, String message) {
        List<String> toAddresses = settings.getStrings(Keys.mail.adminAddresses);
        sendMail(subject, message, toAddresses);
@@ -3314,6 +3290,7 @@
     * @param message
     * @param toAddresses
     */
    @Override
    public void sendMail(String subject, String message, Collection<String> toAddresses) {
        this.sendMail(subject, message, toAddresses.toArray(new String[0]));
    }
@@ -3325,6 +3302,7 @@
     * @param message
     * @param toAddresses
     */
    @Override
    public void sendMail(String subject, String message, String... toAddresses) {
        if (toAddresses == null || toAddresses.length == 0) {
            logger.debug(MessageFormat.format("Dropping message {0} because there are no recipients", subject));
@@ -3358,6 +3336,7 @@
     * @param message
     * @param toAddresses
     */
    @Override
    public void sendHtmlMail(String subject, String message, Collection<String> toAddresses) {
        this.sendHtmlMail(subject, message, toAddresses.toArray(new String[0]));
    }
@@ -3369,6 +3348,7 @@
     * @param message
     * @param toAddresses
     */
    @Override
    public void sendHtmlMail(String subject, String message, String... toAddresses) {
        if (toAddresses == null || toAddresses.length == 0) {
            logger.debug(MessageFormat.format("Dropping message {0} because there are no recipients", subject));
@@ -3400,6 +3380,7 @@
     *
     * @return SettingsModel
     */
    @Override
    public ServerSettings getSettingsModel() {
        // ensure that the current values are updated in the setting models
        for (String key : settings.getAllKeys(null)) {
@@ -3524,7 +3505,7 @@
        logTimezone("JVM", TimeZone.getDefault());
        logTimezone(Constants.NAME, getTimezone());
        serverStatus = new ServerStatus(isGO());
        serverStatus = new ServerStatus(goSettings != null);
        if (this.userService == null) {
            String realm = settings.getString(Keys.realm.userService, "${baseFolder}/users.properties");
@@ -3899,6 +3880,7 @@
     *
     * @return true if we are running the gc executor
     */
    @Override
    public boolean isCollectingGarbage() {
        return gcExecutor.isRunning();
    }
@@ -3909,6 +3891,7 @@
     * @param repositoryName
     * @return true if actively collecting garbage
     */
    @Override
    public boolean isCollectingGarbage(String repositoryName) {
        return gcExecutor.isCollectingGarbage(repositoryName);
    }
@@ -3923,6 +3906,7 @@
     * @return the repository model of the fork, if successful
     * @throws GitBlitException
     */
    @Override
    public RepositoryModel fork(RepositoryModel repository, UserModel user) throws GitBlitException {
        String cloneName = MessageFormat.format("{0}/{1}.git", user.getPersonalPath(), StringUtils.stripDotGit(StringUtils.getLastPathElement(repository.name)));
        String fromUrl = MessageFormat.format("file://{0}/{1}", repositoriesFolder.getAbsolutePath(), repository.name);
@@ -3990,7 +3974,89 @@
     *
     * @return status of Cookie authentication enablement.
     */
    public boolean allowCookieAuthentication() {
        return GitBlit.getBoolean(Keys.web.allowCookieAuthentication, true) && userService.supportsCookies();
    @Override
    public boolean supportsCookies() {
        return settings.getBoolean(Keys.web.allowCookieAuthentication, true) && userService.supportsCookies();
    }
    @Override
    public String getCookie(UserModel model) {
        return userService.getCookie(model);
    }
    @Override
    public UserModel authenticate(char[] cookie) {
        return userService.authenticate(cookie);
    }
    @Override
    public boolean updateUserModel(UserModel model) {
        return userService.updateUserModel(model);
    }
    @Override
    public boolean updateUserModels(Collection<UserModel> models) {
        return userService.updateUserModels(models);
    }
    @Override
    public boolean updateUserModel(String username, UserModel model) {
        return userService.updateUserModel(username, model);
    }
    @Override
    public boolean deleteUserModel(UserModel model) {
        return userService.deleteUserModel(model);
    }
    @Override
    public List<String> getAllTeamNames() {
        return userService.getAllTeamNames();
    }
    @Override
    public List<String> getTeamnamesForRepositoryRole(String role) {
        return userService.getTeamnamesForRepositoryRole(role);
    }
    @Override
    public boolean updateTeamModel(TeamModel model) {
        return userService.updateTeamModel(model);
    }
    @Override
    public boolean updateTeamModels(Collection<TeamModel> models) {
        return userService.updateTeamModels(models);
    }
    @Override
    public boolean updateTeamModel(String teamname, TeamModel model) {
        return userService.updateTeamModel(teamname, model);
    }
    @Override
    public boolean deleteTeamModel(TeamModel model) {
        return userService.deleteTeamModel(model);
    }
    @Override
    public List<String> getUsernamesForRepositoryRole(String role) {
        return userService.getUsernamesForRepositoryRole(role);
    }
    @Override
    public boolean renameRepositoryRole(String oldRole, String newRole) {
        return userService.renameRepositoryRole(oldRole, newRole);
    }
    @Override
    public boolean deleteRepositoryRole(String role) {
        return userService.deleteRepositoryRole(role);
    }
    @Override
    public void logout(HttpServletResponse response, UserModel user) {
        setCookie(response,  null);
        userService.logout(user);
    }
}
src/main/java/com/gitblit/GitBlitServer.java
@@ -410,7 +410,7 @@
        }
        // Setup the GitBlit context
        GitBlit gitblit = getGitBlitInstance();
        GitBlit gitblit = newGitblit(settings, baseFolder);
        gitblit.configureContext(settings, baseFolder, true);
        rootContext.addEventListener(gitblit);
@@ -430,8 +430,8 @@
        }
    }
    protected GitBlit getGitBlitInstance() {
        return GitBlit.self();
    protected GitBlit newGitblit(IStoredSettings settings, File baseFolder) {
        return new GitBlit(settings, baseFolder);
    }
    /**
src/main/java/com/gitblit/GitFilter.java
@@ -19,6 +19,8 @@
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
@@ -100,7 +102,8 @@
     */
    @Override
    protected boolean isCreationAllowed() {
        return GitBlit.getBoolean(Keys.git.allowCreateOnPush, true);
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        return settings.getBoolean(Keys.git.allowCreateOnPush, true);
    }
    /**
@@ -119,7 +122,8 @@
    @Override
    protected boolean requiresClientCertificate() {
        return GitBlit.getBoolean(Keys.git.requiresClientCertificate, false);
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        return settings.getBoolean(Keys.git.requiresClientCertificate, false);
    }
    /**
@@ -152,7 +156,8 @@
     */
    @Override
    protected boolean canAccess(RepositoryModel repository, UserModel user, String action) {
        if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        if (!settings.getBoolean(Keys.git.enableGitServlet, true)) {
            // Git Servlet disabled
            return false;
        }
@@ -223,15 +228,17 @@
                    model.accessRestriction = AccessRestrictionType.VIEW;
                } else {
                    // common repository, user default server settings
                    model.authorizationControl = AuthorizationControl.fromName(GitBlit.getString(Keys.git.defaultAuthorizationControl, ""));
                    model.accessRestriction = AccessRestrictionType.fromName(GitBlit.getString(Keys.git.defaultAccessRestriction, "PUSH"));
                    IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
                    model.authorizationControl = AuthorizationControl.fromName(settings.getString(Keys.git.defaultAuthorizationControl, ""));
                    model.accessRestriction = AccessRestrictionType.fromName(settings.getString(Keys.git.defaultAccessRestriction, "PUSH"));
                }
                // create the repository
                try {
                    GitBlit.self().updateRepositoryModel(model.name, model, true);
                    IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
                    repositoryManager.updateRepositoryModel(model.name, model, true);
                    logger.info(MessageFormat.format("{0} created {1} ON-PUSH", user.username, model.name));
                    return GitBlit.self().getRepositoryModel(model.name);
                    return repositoryManager.getRepositoryModel(model.name);
                } catch (GitBlitException e) {
                    logger.error(MessageFormat.format("{0} failed to create repository {1} ON-PUSH!", user.username, model.name), e);
                }
src/main/java/com/gitblit/GitblitUserService.java
@@ -25,6 +25,7 @@
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.AccountType;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.DeepCopier;
@@ -59,7 +60,8 @@
    @Override
    public void setup(IStoredSettings settings) {
        File realmFile = GitBlit.getFileOrFolder(Keys.realm.userService, "${baseFolder}/users.conf");
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        File realmFile = runtimeManager.getFileOrFolder(Keys.realm.userService, "${baseFolder}/users.conf");
        serviceImpl = createUserService(realmFile);
        logger.info("GUS delegating to " + serviceImpl.toString());
    }
src/main/java/com/gitblit/HtpasswdUserService.java
@@ -33,6 +33,7 @@
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.AccountType;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.StringUtils;
@@ -125,8 +126,9 @@
        this.settings = settings;
        // This is done in two steps in order to avoid calling GitBlit.getFileOrFolder(String, String) which will segfault for unit tests.
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        String file = settings.getString(KEY_BACKING_US, DEFAULT_BACKING_US);
        File realmFile = GitBlit.getFileOrFolder(file);
        File realmFile = runtimeManager.getFileOrFolder(file);
        serviceImpl = createUserService(realmFile);
        logger.info("Htpasswd User Service backed by " + serviceImpl.toString());
@@ -291,7 +293,8 @@
        if ( !file.equals(htpasswdFilePath) ) {
            // The htpasswd file setting changed. Rediscover the file.
            this.htpasswdFilePath = file;
            this.htpasswdFile = GitBlit.getFileOrFolder(file);
            IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
            this.htpasswdFile = runtimeManager.getFileOrFolder(file);
            this.htUsers.clear();
            this.forceReload = true;
        }
src/main/java/com/gitblit/IStoredSettings.java
@@ -333,6 +333,16 @@
    }
    /**
     * Override the specified key with the specified value.
     *
     * @param key
     * @param value
     */
    public void overrideSetting(String key, boolean value) {
        overrides.put(key, "" + value);
    }
    /**
     * Updates the values for the specified keys and persists the entire
     * configuration file.
     *
src/main/java/com/gitblit/LdapUserService.java
@@ -31,6 +31,7 @@
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.AccountType;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
@@ -83,7 +84,8 @@
    public void setup(IStoredSettings settings) {
        this.settings = settings;
        String file = settings.getString(Keys.realm.ldap.backingUserService, "${baseFolder}/users.conf");
        File realmFile = GitBlit.getFileOrFolder(file);
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        File realmFile = runtimeManager.getFileOrFolder(file);
        serviceImpl = createUserService(realmFile);
        logger.info("LDAP User Service backed by " + serviceImpl.toString());
src/main/java/com/gitblit/LogoServlet.java
@@ -27,6 +27,8 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.gitblit.manager.IRuntimeManager;
/**
 * Handles requests for logo.png
 *
@@ -45,7 +47,8 @@
    @Override
    protected long getLastModified(HttpServletRequest req) {
        File file = GitBlit.getFileOrFolder(Keys.web.headerLogo, "${baseFolder}/logo.png");
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        File file = runtimeManager.getFileOrFolder(Keys.web.headerLogo, "${baseFolder}/logo.png");
        if (file.exists()) {
            return Math.max(lastModified, file.lastModified());
        } else {
@@ -59,7 +62,8 @@
        InputStream is = null;
        try {
            String contentType = null;
            File file = GitBlit.getFileOrFolder(Keys.web.headerLogo, "${baseFolder}/logo.png");
            IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
            File file = runtimeManager.getFileOrFolder(Keys.web.headerLogo, "${baseFolder}/logo.png");
            if (file.exists()) {
                // custom logo
                ServletContext context = request.getSession().getServletContext();
@@ -88,7 +92,7 @@
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(is != null) {
            if (is != null) {
                is.close();
            }
        }
src/main/java/com/gitblit/LuceneExecutor.java
@@ -85,6 +85,7 @@
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.SearchObjectType;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryModel;
@@ -160,17 +161,18 @@
        String exts = storedSettings.getString(Keys.web.luceneIgnoreExtensions, luceneIgnoreExtensions);
        excludedExtensions = new TreeSet<String>(StringUtils.getStringsFromValue(exts));
        if (GitBlit.self().isCollectingGarbage()) {
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        if (repositoryManager.isCollectingGarbage()) {
            // busy collecting garbage, try again later
            return;
        }
        for (String repositoryName: GitBlit.self().getRepositoryList()) {
            RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
        for (String repositoryName: repositoryManager.getRepositoryList()) {
            RepositoryModel model = repositoryManager.getRepositoryModel(repositoryName);
            if (model.hasCommits && !ArrayUtils.isEmpty(model.indexedBranches)) {
                Repository repository = GitBlit.self().getRepository(model.name);
                Repository repository = repositoryManager.getRepository(model.name);
                if (repository == null) {
                    if (GitBlit.self().isCollectingGarbage(model.name)) {
                    if (repositoryManager.isCollectingGarbage(model.name)) {
                        logger.info(MessageFormat.format("Skipping Lucene index of {0}, busy garbage collecting", repositoryName));
                    }
                    continue;
src/main/java/com/gitblit/MirrorExecutor.java
@@ -33,6 +33,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.JGitUtils;
@@ -83,25 +84,27 @@
        running.set(true);
        for (String repositoryName : GitBlit.self().getRepositoryList()) {
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        for (String repositoryName : repositoryManager.getRepositoryList()) {
            if (forceClose.get()) {
                break;
            }
            if (GitBlit.self().isCollectingGarbage(repositoryName)) {
            if (repositoryManager.isCollectingGarbage(repositoryName)) {
                logger.debug("mirror is skipping {} garbagecollection", repositoryName);
                continue;
            }
            RepositoryModel model = null;
            Repository repository = null;
            try {
                model = GitBlit.self().getRepositoryModel(repositoryName);
                model = repositoryManager.getRepositoryModel(repositoryName);
                if (!model.isMirror && !model.isBare) {
                    // repository must be a valid bare git mirror
                    logger.debug("mirror is skipping {} !mirror !bare", repositoryName);
                    continue;
                }
                repository = GitBlit.self().getRepository(repositoryName);
                repository = repositoryManager.getRepository(repositoryName);
                if (repository == null) {
                    logger.warn(MessageFormat.format("MirrorExecutor is missing repository {0}?!?", repositoryName));
                    continue;
src/main/java/com/gitblit/PAMUserService.java
@@ -24,6 +24,7 @@
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.AccountType;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.StringUtils;
@@ -48,7 +49,8 @@
        this.settings = settings;
        String file = settings.getString(Keys.realm.pam.backingUserService, "${baseFolder}/users.conf");
        File realmFile = GitBlit.getFileOrFolder(file);
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        File realmFile = runtimeManager.getFileOrFolder(file);
        serviceImpl = createUserService(realmFile);
        logger.info("PAM User Service backed by " + serviceImpl.toString());
src/main/java/com/gitblit/PagesFilter.java
@@ -18,6 +18,7 @@
import org.eclipse.jgit.lib.Repository;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
@@ -49,7 +50,8 @@
            } else {
                repository = url.substring(0, slash);
            }
            r = GitBlit.self().getRepository(repository, false);
            IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
            r = repositoryManager.getRepository(repository, false);
            if (r == null) {
                // try again
                offset = slash + 1;
src/main/java/com/gitblit/PagesServlet.java
@@ -35,6 +35,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.PathModel;
import com.gitblit.models.RefModel;
import com.gitblit.utils.ArrayUtils;
@@ -99,6 +101,9 @@
            path = path.substring(1);
        }
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        // determine repository and resource from url
        String repository = "";
        String resource = "";
@@ -111,7 +116,7 @@
            } else {
                repository = path.substring(0, slash);
            }
            r = GitBlit.self().getRepository(repository, false);
            r = repositoryManager.getRepository(repository, false);
            offset = slash + 1;
            if (offset > 0) {
                resource = path.substring(offset);
@@ -148,8 +153,8 @@
                return;
            }
            MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());
            String [] encodings = GitBlit.getEncodings();
            MarkupProcessor processor = new MarkupProcessor(settings);
            String [] encodings = settings.getStrings(Keys.web.blobEncodings).toArray(new String[0]);
            RevTree tree = commit.getTree();
src/main/java/com/gitblit/RedmineUserService.java
@@ -25,6 +25,7 @@
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.AccountType;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.ConnectionUtils;
@@ -63,7 +64,8 @@
        this.settings = settings;
        String file = settings.getString(Keys.realm.redmine.backingUserService, "${baseFolder}/users.conf");
        File realmFile = GitBlit.getFileOrFolder(file);
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        File realmFile = runtimeManager.getFileOrFolder(file);
        serviceImpl = createUserService(realmFile);
        logger.info("Redmine User Service backed by " + serviceImpl.toString());
src/main/java/com/gitblit/RobotsTxtServlet.java
@@ -23,6 +23,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.utils.FileUtils;
/**
@@ -54,7 +55,8 @@
    protected void processRequest(javax.servlet.http.HttpServletRequest request,
            javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
            java.io.IOException {
        File file = GitBlit.getFileOrFolder(Keys.web.robots.txt, null);
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        File file = runtimeManager.getFileOrFolder(Keys.web.robots.txt, null);
        String content = "";
        if (file.exists()) {
            content = FileUtils.readContent(file, "\n");
src/main/java/com/gitblit/RpcFilter.java
@@ -26,6 +26,7 @@
import javax.servlet.http.HttpServletResponse;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.UserModel;
/**
@@ -64,17 +65,20 @@
            return;
        }
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        IStoredSettings settings = runtimeManager.getSettings();
        boolean adminRequest = requestType.exceeds(RpcRequest.LIST_SETTINGS);
        // conditionally reject all rpc requests
        if (!GitBlit.getBoolean(Keys.web.enableRpcServlet, true)) {
        if (!settings.getBoolean(Keys.web.enableRpcServlet, true)) {
            logger.warn(Keys.web.enableRpcServlet + " must be set TRUE for rpc requests.");
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
        boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, false);
        boolean authenticateAdmin = GitBlit.getBoolean(Keys.web.authenticateAdminPages, true);
        boolean authenticateView = settings.getBoolean(Keys.web.authenticateViewPages, false);
        boolean authenticateAdmin = settings.getBoolean(Keys.web.authenticateAdminPages, true);
        // Wrap the HttpServletRequest with the RpcServletRequest which
        // overrides the servlet container user principal methods.
@@ -85,7 +89,7 @@
        }
        // conditionally reject rpc management/administration requests
        if (adminRequest && !GitBlit.getBoolean(Keys.web.enableRpcManagement, false)) {
        if (adminRequest && !settings.getBoolean(Keys.web.enableRpcManagement, false)) {
            logger.warn(MessageFormat.format("{0} must be set TRUE for {1} rpc requests.",
                    Keys.web.enableRpcManagement, requestType.toString()));
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
@@ -96,7 +100,7 @@
        if ((adminRequest && authenticateAdmin) || (!adminRequest && authenticateView)) {
            if (user == null) {
                // challenge client to provide credentials. send 401.
                if (GitBlit.isDebugMode()) {
                if (runtimeManager.isDebugMode()) {
                    logger.info(MessageFormat.format("RPC: CHALLENGE {0}", fullUrl));
                }
@@ -115,7 +119,7 @@
                    return;
                }
                // valid user, but not for requested access. send 403.
                if (GitBlit.isDebugMode()) {
                if (runtimeManager.isDebugMode()) {
                    logger.info(MessageFormat.format("RPC: {0} forbidden to access {1}",
                            user.username, fullUrl));
                }
@@ -124,7 +128,7 @@
            }
        }
        if (GitBlit.isDebugMode()) {
        if (runtimeManager.isDebugMode()) {
            logger.info(MessageFormat.format("RPC: {0} ({1}) unauthenticated", fullUrl,
                    HttpServletResponse.SC_CONTINUE));
        }
src/main/java/com/gitblit/RpcServlet.java
@@ -30,6 +30,11 @@
import org.eclipse.jgit.lib.Repository;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IGitblitManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.RefModel;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
@@ -74,13 +79,20 @@
        logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType,
                request.getRemoteAddr()));
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        IUserManager userManager = GitBlit.getManager(IUserManager.class);
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        IGitblitManager gitblitManager = GitBlit.getManager(IGitblitManager.class);
        IFederationManager federationManager = GitBlit.getManager(IFederationManager.class);
        IStoredSettings settings = runtimeManager.getSettings();
        UserModel user = (UserModel) request.getUserPrincipal();
        boolean allowManagement = user != null && user.canAdmin()
                && GitBlit.getBoolean(Keys.web.enableRpcManagement, false);
                && settings.getBoolean(Keys.web.enableRpcManagement, false);
        boolean allowAdmin = user != null && user.canAdmin()
                && GitBlit.getBoolean(Keys.web.enableRpcAdministration, false);
                && settings.getBoolean(Keys.web.enableRpcAdministration, false);
        Object result = null;
        if (RpcRequest.GET_PROTOCOL.equals(reqType)) {
@@ -96,7 +108,7 @@
            String cloneUrl = sb.toString();
            // list repositories
            List<RepositoryModel> list = GitBlit.self().getRepositoryModels(user);
            List<RepositoryModel> list = repositoryManager.getRepositoryModels(user);
            Map<String, RepositoryModel> repositories = new HashMap<String, RepositoryModel>();
            for (RepositoryModel model : list) {
                String url = MessageFormat.format(cloneUrl, model.name);
@@ -106,7 +118,7 @@
        } else if (RpcRequest.LIST_BRANCHES.equals(reqType)) {
            // list all local branches in all repositories accessible to user
            Map<String, List<String>> localBranches = new HashMap<String, List<String>>();
            List<RepositoryModel> models = GitBlit.self().getRepositoryModels(user);
            List<RepositoryModel> models = repositoryManager.getRepositoryModels(user);
            for (RepositoryModel model : models) {
                if (!model.hasCommits) {
                    // skip empty repository
@@ -118,7 +130,7 @@
                    continue;
                }
                // get local branches
                Repository repository = GitBlit.self().getRepository(model.name);
                Repository repository = repositoryManager.getRepository(model.name);
                List<RefModel> refs = JGitUtils.getLocalBranches(repository, false, -1);
                if (model.showRemoteBranches) {
                    // add remote branches if repository displays them
@@ -146,7 +158,7 @@
            } else {
                if (user.canAdmin() || objectName.equals(user.username)) {
                    // return the specified user
                    UserModel requestedUser = GitBlit.self().getUserModel(objectName);
                    UserModel requestedUser = userManager.getUserModel(objectName);
                    if (requestedUser == null) {
                        response.setStatus(failureCode);
                    } else {
@@ -158,25 +170,25 @@
            }
        } else if (RpcRequest.LIST_USERS.equals(reqType)) {
            // list users
            List<String> names = GitBlit.self().getAllUsernames();
            List<String> names = userManager.getAllUsernames();
            List<UserModel> users = new ArrayList<UserModel>();
            for (String name : names) {
                users.add(GitBlit.self().getUserModel(name));
                users.add(userManager.getUserModel(name));
            }
            result = users;
        } else if (RpcRequest.LIST_TEAMS.equals(reqType)) {
            // list teams
            List<String> names = GitBlit.self().getAllTeamnames();
            List<String> names = userManager.getAllTeamNames();
            List<TeamModel> teams = new ArrayList<TeamModel>();
            for (String name : names) {
                teams.add(GitBlit.self().getTeamModel(name));
                teams.add(userManager.getTeamModel(name));
            }
            result = teams;
        } else if (RpcRequest.CREATE_REPOSITORY.equals(reqType)) {
            // create repository
            RepositoryModel model = deserialize(request, response, RepositoryModel.class);
            try {
                GitBlit.self().updateRepositoryModel(model.name, model, true);
                repositoryManager.updateRepositoryModel(model.name, model, true);
            } catch (GitBlitException e) {
                response.setStatus(failureCode);
            }
@@ -189,19 +201,19 @@
                repoName = model.name;
            }
            try {
                GitBlit.self().updateRepositoryModel(repoName, model, false);
                repositoryManager.updateRepositoryModel(repoName, model, false);
            } catch (GitBlitException e) {
                response.setStatus(failureCode);
            }
        } else if (RpcRequest.DELETE_REPOSITORY.equals(reqType)) {
            // delete repository
            RepositoryModel model = deserialize(request, response, RepositoryModel.class);
            GitBlit.self().deleteRepositoryModel(model);
            repositoryManager.deleteRepositoryModel(model);
        } else if (RpcRequest.CREATE_USER.equals(reqType)) {
            // create user
            UserModel model = deserialize(request, response, UserModel.class);
            try {
                GitBlit.self().updateUserModel(model.username, model, true);
                gitblitManager.updateUserModel(model.username, model, true);
            } catch (GitBlitException e) {
                response.setStatus(failureCode);
            }
@@ -214,21 +226,21 @@
                username = model.username;
            }
            try {
                GitBlit.self().updateUserModel(username, model, false);
                gitblitManager.updateUserModel(username, model, false);
            } catch (GitBlitException e) {
                response.setStatus(failureCode);
            }
        } else if (RpcRequest.DELETE_USER.equals(reqType)) {
            // delete user
            UserModel model = deserialize(request, response, UserModel.class);
            if (!GitBlit.self().deleteUser(model.username)) {
            if (!userManager.deleteUser(model.username)) {
                response.setStatus(failureCode);
            }
        } else if (RpcRequest.CREATE_TEAM.equals(reqType)) {
            // create team
            TeamModel model = deserialize(request, response, TeamModel.class);
            try {
                GitBlit.self().updateTeamModel(model.name, model, true);
                gitblitManager.updateTeamModel(model.name, model, true);
            } catch (GitBlitException e) {
                response.setStatus(failureCode);
            }
@@ -241,83 +253,83 @@
                teamname = model.name;
            }
            try {
                GitBlit.self().updateTeamModel(teamname, model, false);
                gitblitManager.updateTeamModel(teamname, model, false);
            } catch (GitBlitException e) {
                response.setStatus(failureCode);
            }
        } else if (RpcRequest.DELETE_TEAM.equals(reqType)) {
            // delete team
            TeamModel model = deserialize(request, response, TeamModel.class);
            if (!GitBlit.self().deleteTeam(model.name)) {
            if (!userManager.deleteTeam(model.name)) {
                response.setStatus(failureCode);
            }
        } else if (RpcRequest.LIST_REPOSITORY_MEMBERS.equals(reqType)) {
            // get repository members
            RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
            result = GitBlit.self().getRepositoryUsers(model);
            RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
            result = repositoryManager.getRepositoryUsers(model);
        } else if (RpcRequest.SET_REPOSITORY_MEMBERS.equals(reqType)) {
            // rejected since 1.2.0
            response.setStatus(failureCode);
        } else if (RpcRequest.LIST_REPOSITORY_MEMBER_PERMISSIONS.equals(reqType)) {
            // get repository member permissions
            RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
            result = GitBlit.self().getUserAccessPermissions(model);
            RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
            result = repositoryManager.getUserAccessPermissions(model);
        } else if (RpcRequest.SET_REPOSITORY_MEMBER_PERMISSIONS.equals(reqType)) {
            // set the repository permissions for the specified users
            RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
            RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
            Collection<RegistrantAccessPermission> permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE);
            result = GitBlit.self().setUserAccessPermissions(model, permissions);
            result = repositoryManager.setUserAccessPermissions(model, permissions);
        } else if (RpcRequest.LIST_REPOSITORY_TEAMS.equals(reqType)) {
            // get repository teams
            RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
            result = GitBlit.self().getRepositoryTeams(model);
            RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
            result = repositoryManager.getRepositoryTeams(model);
        } else if (RpcRequest.SET_REPOSITORY_TEAMS.equals(reqType)) {
            // rejected since 1.2.0
            response.setStatus(failureCode);
        } else if (RpcRequest.LIST_REPOSITORY_TEAM_PERMISSIONS.equals(reqType)) {
            // get repository team permissions
            RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
            result = GitBlit.self().getTeamAccessPermissions(model);
            RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
            result = repositoryManager.getTeamAccessPermissions(model);
        } else if (RpcRequest.SET_REPOSITORY_TEAM_PERMISSIONS.equals(reqType)) {
            // set the repository permissions for the specified teams
            RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
            RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
            Collection<RegistrantAccessPermission> permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE);
            result = GitBlit.self().setTeamAccessPermissions(model, permissions);
            result = repositoryManager.setTeamAccessPermissions(model, permissions);
        } else if (RpcRequest.LIST_FEDERATION_REGISTRATIONS.equals(reqType)) {
            // return the list of federation registrations
            if (allowAdmin) {
                result = GitBlit.self().getFederationRegistrations();
                result = federationManager.getFederationRegistrations();
            } else {
                response.sendError(notAllowedCode);
            }
        } else if (RpcRequest.LIST_FEDERATION_RESULTS.equals(reqType)) {
            // return the list of federation result registrations
            if (allowAdmin && GitBlit.canFederate()) {
                result = GitBlit.self().getFederationResultRegistrations();
            if (allowAdmin && federationManager.canFederate()) {
                result = federationManager.getFederationResultRegistrations();
            } else {
                response.sendError(notAllowedCode);
            }
        } else if (RpcRequest.LIST_FEDERATION_PROPOSALS.equals(reqType)) {
            // return the list of federation proposals
            if (allowAdmin && GitBlit.canFederate()) {
                result = GitBlit.self().getPendingFederationProposals();
            if (allowAdmin && federationManager.canFederate()) {
                result = federationManager.getPendingFederationProposals();
            } else {
                response.sendError(notAllowedCode);
            }
        } else if (RpcRequest.LIST_FEDERATION_SETS.equals(reqType)) {
            // return the list of federation sets
            if (allowAdmin && GitBlit.canFederate()) {
            if (allowAdmin && federationManager.canFederate()) {
                String gitblitUrl = HttpUtils.getGitblitURL(request);
                result = GitBlit.self().getFederationSets(gitblitUrl);
                result = federationManager.getFederationSets(gitblitUrl);
            } else {
                response.sendError(notAllowedCode);
            }
        } else if (RpcRequest.LIST_SETTINGS.equals(reqType)) {
            // return the server's settings
            ServerSettings settings = GitBlit.self().getSettingsModel();
            ServerSettings serverSettings = runtimeManager.getSettingsModel();
            if (allowAdmin) {
                // return all settings
                result = settings;
                result = serverSettings;
            } else {
                // anonymous users get a few settings to allow browser launching
                List<String> keys = new ArrayList<String>();
@@ -334,33 +346,33 @@
                // build the settings
                ServerSettings managementSettings = new ServerSettings();
                for (String key : keys) {
                    managementSettings.add(settings.get(key));
                    managementSettings.add(serverSettings.get(key));
                }
                if (allowManagement) {
                    managementSettings.pushScripts = settings.pushScripts;
                    managementSettings.pushScripts = serverSettings.pushScripts;
                }
                result = managementSettings;
            }
        } else if (RpcRequest.EDIT_SETTINGS.equals(reqType)) {
            // update settings on the server
            if (allowAdmin) {
                Map<String, String> settings = deserialize(request, response,
                Map<String, String> map = deserialize(request, response,
                        RpcUtils.SETTINGS_TYPE);
                GitBlit.self().updateSettings(settings);
                runtimeManager.updateSettings(map);
            } else {
                response.sendError(notAllowedCode);
            }
        } else if (RpcRequest.LIST_STATUS.equals(reqType)) {
            // return the server's status information
            if (allowAdmin) {
                result = GitBlit.self().getStatus();
                result = runtimeManager.getStatus();
            } else {
                response.sendError(notAllowedCode);
            }
        } else if (RpcRequest.CLEAR_REPOSITORY_CACHE.equals(reqType)) {
            // clear the repository list cache
            if (allowManagement) {
                GitBlit.self().resetRepositoryListCache();
                repositoryManager.resetRepositoryListCache();
            } else {
                response.sendError(notAllowedCode);
            }
src/main/java/com/gitblit/SalesforceUserService.java
@@ -6,6 +6,7 @@
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.AccountType;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.StringUtils;
@@ -31,7 +32,8 @@
        String file = settings.getString(
                Keys.realm.salesforce.backingUserService,
                "${baseFolder}/users.conf");
        File realmFile = GitBlit.getFileOrFolder(file);
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        File realmFile = runtimeManager.getFileOrFolder(file);
        serviceImpl = createUserService(realmFile);
src/main/java/com/gitblit/SparkleShareInviteServlet.java
@@ -23,6 +23,10 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.ISessionManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
@@ -57,6 +61,11 @@
            javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
            java.io.IOException {
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        IUserManager userManager = GitBlit.getManager(IUserManager.class);
        ISessionManager sessionManager = GitBlit.getManager(ISessionManager.class);
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        // extract repo name from request
        String repoUrl = request.getPathInfo().substring(1);
@@ -77,9 +86,9 @@
        }
        UserModel user;
        if (StringUtils.isEmpty(username)) {
            user = GitBlit.self().authenticate(request);
            user = sessionManager.authenticate(request);
        } else {
            user = GitBlit.self().getUserModel(username);
            user = userManager.getUserModel(username);
        }
        if (user == null) {
            user = UserModel.ANONYMOUS;
@@ -87,7 +96,7 @@
        }
        // ensure that the requested repository exists
        RepositoryModel model = GitBlit.self().getRepositoryModel(path);
        RepositoryModel model = repositoryManager.getRepositoryModel(path);
        if (model == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            response.getWriter().append(MessageFormat.format("Repository \"{0}\" not found!", path));
@@ -99,9 +108,9 @@
        sb.append("<sparkleshare><invite>\n");
        sb.append(MessageFormat.format("<address>{0}</address>\n", host));
        sb.append(MessageFormat.format("<remote_path>{0}{1}</remote_path>\n", servletPath, model.name));
        if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) {
        if (settings.getInteger(Keys.fanout.port, 0) > 0) {
            // Gitblit is running it's own fanout service for pubsub notifications
            sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, "")));
            sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), settings.getString(Keys.fanout.port, "")));
        }
        sb.append("</invite></sparkleshare>\n");
src/main/java/com/gitblit/SyndicationFilter.java
@@ -26,6 +26,9 @@
import javax.servlet.http.HttpServletResponse;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
@@ -70,12 +73,16 @@
        String fullUrl = getFullUrl(httpRequest);
        String name = extractRequestedName(fullUrl);
        ProjectModel project = GitBlit.self().getProjectModel(name);
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        IProjectManager projectManager = GitBlit.getManager(IProjectManager.class);
        ProjectModel project = projectManager.getProjectModel(name);
        RepositoryModel model = null;
        if (project == null) {
            // try loading a repository model
            model = GitBlit.self().getRepositoryModel(name);
            model = repositoryManager.getRepositoryModel(name);
            if (model == null) {
                // repository not found. send 404.
                logger.info(MessageFormat.format("ARF: {0} ({1})", fullUrl,
@@ -105,7 +112,7 @@
            if (model.accessRestriction.atLeast(AccessRestrictionType.VIEW)) {
                if (user == null) {
                    // challenge client to provide credentials. send 401.
                    if (GitBlit.isDebugMode()) {
                    if (runtimeManager.isDebugMode()) {
                        logger.info(MessageFormat.format("ARF: CHALLENGE {0}", fullUrl));
                    }
                    httpResponse.setHeader("WWW-Authenticate", CHALLENGE);
@@ -123,7 +130,7 @@
                        return;
                    }
                    // valid user, but not for requested access. send 403.
                    if (GitBlit.isDebugMode()) {
                    if (runtimeManager.isDebugMode()) {
                        logger.info(MessageFormat.format("ARF: {0} forbidden to access {1}",
                                user.username, fullUrl));
                    }
@@ -133,7 +140,7 @@
            }
        }
        if (GitBlit.isDebugMode()) {
        if (runtimeManager.isDebugMode()) {
            logger.info(MessageFormat.format("ARF: {0} ({1}) unauthenticated", fullUrl,
                    HttpServletResponse.SC_CONTINUE));
        }
src/main/java/com/gitblit/SyndicationServlet.java
@@ -31,6 +31,9 @@
import org.slf4j.LoggerFactory;
import com.gitblit.AuthenticationFilter.AuthenticatedRequest;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.FeedEntryModel;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RefModel;
@@ -38,6 +41,7 @@
import com.gitblit.models.UserModel;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.MessageProcessor;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.SyndicationUtils;
@@ -126,6 +130,10 @@
            javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
            java.io.IOException {
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        IProjectManager projectManager = GitBlit.getManager(IProjectManager.class);
        String servletUrl = request.getContextPath() + request.getServletPath();
        String url = request.getRequestURI().substring(servletUrl.length());
        if (url.charAt(0) == '/' && url.length() > 1) {
@@ -143,7 +151,7 @@
                searchType = type;
            }
        }
        int length = GitBlit.getInteger(Keys.web.syndicationEntries, 25);
        int length = settings.getInteger(Keys.web.syndicationEntries, 25);
        if (StringUtils.isEmpty(objectId)) {
            objectId = org.eclipse.jgit.lib.Constants.HEAD;
        }
@@ -175,7 +183,7 @@
            if (request instanceof AuthenticatedRequest) {
                user = ((AuthenticatedRequest) request).getUser();
            }
            ProjectModel project = GitBlit.self().getProjectModel(repositoryName, user);
            ProjectModel project = projectManager.getProjectModel(repositoryName, user);
            if (project != null) {
                isProjectFeed = true;
                repositories = new ArrayList<String>(project.repositories);
@@ -193,7 +201,7 @@
        }
        boolean mountParameters = GitBlit.getBoolean(Keys.web.mountParameters, true);
        boolean mountParameters = settings.getBoolean(Keys.web.mountParameters, true);
        String urlPattern;
        if (mountParameters) {
            // mounted parameters
@@ -203,13 +211,13 @@
            urlPattern = "{0}/commit/?r={1}&h={2}";
        }
        String gitblitUrl = HttpUtils.getGitblitURL(request);
        char fsc = GitBlit.getChar(Keys.web.forwardSlashCharacter, '/');
        char fsc = settings.getChar(Keys.web.forwardSlashCharacter, '/');
        List<FeedEntryModel> entries = new ArrayList<FeedEntryModel>();
        for (String name : repositories) {
            Repository repository = GitBlit.self().getRepository(name);
            RepositoryModel model = GitBlit.self().getRepositoryModel(name);
            Repository repository = repositoryManager.getRepository(name);
            RepositoryModel model = repositoryManager.getRepositoryModel(name);
            if (repository == null) {
                if (model.isCollectingGarbage) {
@@ -234,6 +242,7 @@
                        offset, length);
            }
            Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches);
            MessageProcessor processor = new MessageProcessor(settings);
            // convert RevCommit to SyndicatedEntryModel
            for (RevCommit commit : commits) {
@@ -244,8 +253,7 @@
                        StringUtils.encodeURL(model.name.replace('/', fsc)), commit.getName());
                entry.published = commit.getCommitterIdent().getWhen();
                entry.contentType = "text/html";
                String message = GitBlit.self().processCommitMessage(model,
                        commit.getFullMessage());
                String message = processor.processCommitMessage(model, commit.getFullMessage());
                entry.content = message;
                entry.repository = model.name;
                entry.branch = objectId;
src/main/java/com/gitblit/WindowsUserService.java
@@ -29,6 +29,7 @@
import waffle.windows.auth.impl.WindowsAuthProviderImpl;
import com.gitblit.Constants.AccountType;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.StringUtils;
@@ -56,7 +57,8 @@
        this.settings = settings;
        String file = settings.getString(Keys.realm.windows.backingUserService, "${baseFolder}/users.conf");
        File realmFile = GitBlit.getFileOrFolder(file);
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        File realmFile = runtimeManager.getFileOrFolder(file);
        serviceImpl = createUserService(realmFile);
        logger.info("Windows User Service backed by " + serviceImpl.toString());
src/main/java/com/gitblit/git/GitServlet.java
@@ -20,6 +20,7 @@
import javax.servlet.http.HttpServletRequest;
import com.gitblit.GitBlit;
import com.gitblit.manager.IRepositoryManager;
/**
 * The GitServlet provides http/https access to Git repositories.
@@ -34,7 +35,8 @@
    @Override
    public void init(ServletConfig config) throws ServletException {
        setRepositoryResolver(new RepositoryResolver<HttpServletRequest>(GitBlit.getRepositoriesFolder()));
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        setRepositoryResolver(new RepositoryResolver<HttpServletRequest>(repositoryManager.getRepositoriesFolder()));
        setUploadPackFactory(new GitblitUploadPackFactory<HttpServletRequest>());
        setReceivePackFactory(new GitblitReceivePackFactory<HttpServletRequest>());
        super.init(config);
src/main/java/com/gitblit/git/GitblitReceivePack.java
@@ -45,8 +45,11 @@
import com.gitblit.Constants;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.GitBlit;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.client.Translation;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
@@ -90,12 +93,15 @@
    public GitblitReceivePack(Repository db, RepositoryModel repository, UserModel user) {
        super(db);
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        this.repository = repository;
        this.user = user == null ? UserModel.ANONYMOUS : user;
        this.groovyDir = GitBlit.getGroovyScriptsFolder();
        this.groovyDir = repositoryManager.getHooksFolder();
        try {
            // set Grape root
            File grapeRoot = GitBlit.getFileOrFolder(Keys.groovy.grapeFolder, "${baseFolder}/groovy/grape").getAbsoluteFile();
            File grapeRoot = repositoryManager.getGrapesFolder();
            grapeRoot.mkdirs();
            System.setProperty("grape.root", grapeRoot.getAbsolutePath());
            this.gse = new GroovyScriptEngine(groovyDir.getAbsolutePath());
@@ -233,8 +239,9 @@
            }
        }
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        Set<String> scripts = new LinkedHashSet<String>();
        scripts.addAll(GitBlit.self().getPreReceiveScriptsInherited(repository));
        scripts.addAll(repositoryManager.getPreReceiveScriptsInherited(repository));
        if (!ArrayUtils.isEmpty(repository.preReceiveScripts)) {
            scripts.addAll(repository.preReceiveScripts);
        }
@@ -258,6 +265,8 @@
            LOGGER.debug("skipping post-receive hooks, no refs created, updated, or removed");
            return;
        }
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        // log ref changes
        for (ReceiveCommand cmd : commands) {
@@ -303,7 +312,7 @@
                    String msg = MessageFormat.format(template, branch);
                    String prefix;
                    if (StringUtils.isEmpty(repository.incrementalPushTagPrefix)) {
                        prefix = GitBlit.getString(Keys.git.defaultIncrementalPushTagPrefix, "r");
                        prefix = settings.getString(Keys.git.defaultIncrementalPushTagPrefix, "r");
                    } else {
                        prefix = repository.incrementalPushTagPrefix;
                    }
@@ -327,9 +336,11 @@
            LOGGER.error(MessageFormat.format("Failed to update {0} pushlog", repository.name), e);
        }
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        // run Groovy hook scripts
        Set<String> scripts = new LinkedHashSet<String>();
        scripts.addAll(GitBlit.self().getPostReceiveScriptsInherited(repository));
        scripts.addAll(repositoryManager.getPostReceiveScriptsInherited(repository));
        if (!ArrayUtils.isEmpty(repository.postReceiveScripts)) {
            scripts.addAll(repository.postReceiveScripts);
        }
src/main/java/com/gitblit/git/GitblitReceivePackFactory.java
@@ -27,7 +27,11 @@
import org.slf4j.LoggerFactory;
import com.gitblit.GitBlit;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.HttpUtils;
@@ -48,6 +52,10 @@
    public ReceivePack create(X req, Repository db)
            throws ServiceNotEnabledException, ServiceNotAuthorizedException {
        IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
        IUserManager userManager = GitBlit.getManager(IUserManager.class);
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        UserModel user = UserModel.ANONYMOUS;
        String repositoryName = "";
        String origin = "";
@@ -66,7 +74,7 @@
            // determine pushing user
            String username = request.getRemoteUser();
            if (!StringUtils.isEmpty(username)) {
                UserModel u = GitBlit.self().getUserModel(username);
                UserModel u = userManager.getUserModel(username);
                if (u != null) {
                    user = u;
                }
@@ -81,13 +89,13 @@
            timeout = client.getDaemon().getTimeout();
        }
        boolean allowAnonymousPushes = GitBlit.getBoolean(Keys.git.allowAnonymousPushes, false);
        boolean allowAnonymousPushes = settings.getBoolean(Keys.git.allowAnonymousPushes, false);
        if (!allowAnonymousPushes && UserModel.ANONYMOUS.equals(user)) {
            // prohibit anonymous pushes
            throw new ServiceNotEnabledException();
        }
        final RepositoryModel repository = GitBlit.self().getRepositoryModel(repositoryName);
        final RepositoryModel repository = repositoryManager.getRepositoryModel(repositoryName);
        final GitblitReceivePack rp = new GitblitReceivePack(db, repository, user);
        rp.setGitblitUrl(gitblitUrl);
src/main/java/com/gitblit/git/GitblitUploadPackFactory.java
@@ -24,6 +24,7 @@
import org.eclipse.jgit.transport.resolver.UploadPackFactory;
import com.gitblit.GitBlit;
import com.gitblit.manager.ISessionManager;
import com.gitblit.models.UserModel;
/**
@@ -40,12 +41,13 @@
    public UploadPack create(X req, Repository db)
            throws ServiceNotEnabledException, ServiceNotAuthorizedException {
        ISessionManager sessionManager = GitBlit.getManager(ISessionManager.class);
        UserModel user = UserModel.ANONYMOUS;
        int timeout = 0;
        if (req instanceof HttpServletRequest) {
            // http/https request may or may not be authenticated
            user = GitBlit.self().authenticate((HttpServletRequest) req);
            user = sessionManager.authenticate((HttpServletRequest) req);
            if (user == null) {
                user = UserModel.ANONYMOUS;
            }
src/main/java/com/gitblit/git/RepositoryResolver.java
@@ -29,6 +29,8 @@
import org.slf4j.LoggerFactory;
import com.gitblit.GitBlit;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.ISessionManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
@@ -74,7 +76,9 @@
     */
    @Override
    protected boolean isExportOk(X req, String repositoryName, Repository db) throws IOException {
        RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        ISessionManager sessionManager = GitBlit.getManager(ISessionManager.class);
        RepositoryModel model = repositoryManager.getRepositoryModel(repositoryName);
        String scheme = null;
        UserModel user = null;
@@ -92,7 +96,7 @@
            HttpServletRequest httpRequest = (HttpServletRequest) req;
            scheme = httpRequest.getScheme();
            origin = httpRequest.getRemoteAddr();
            user = GitBlit.self().authenticate(httpRequest);
            user = sessionManager.authenticate(httpRequest);
            if (user == null) {
                user = UserModel.ANONYMOUS;
            }
src/main/java/com/gitblit/manager/IFederationManager.java
New file
@@ -0,0 +1,177 @@
/*
 * 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.util.List;
import java.util.Map;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.Constants.FederationToken;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
public interface IFederationManager {
    /**
     * Returns the path of the proposals folder. This method checks to see if
     * Gitblit is running on a cloud service and may return an adjusted path.
     *
     * @return the proposals folder path
     */
    File getProposalsFolder();
    UserModel getFederationUser();
    boolean canFederate();
    /**
     * Returns the list of federated gitblit instances that this instance will
     * try to pull.
     *
     * @return list of registered gitblit instances
     */
    List<FederationModel> getFederationRegistrations();
    /**
     * Retrieve the specified federation registration.
     *
     * @param name
     *            the name of the registration
     * @return a federation registration
     */
    FederationModel getFederationRegistration(String url, String name);
    /**
     * Returns the list of federation sets.
     *
     * @return list of federation sets
     */
    List<FederationSet> getFederationSets(String gitblitUrl);
    /**
     * Returns the list of possible federation tokens for this Gitblit instance.
     *
     * @return list of federation tokens
     */
    List<String> getFederationTokens();
    /**
     * Returns the specified federation token for this Gitblit instance.
     *
     * @param type
     * @return a federation token
     */
    String getFederationToken(FederationToken type);
    /**
     * Returns the specified federation token for this Gitblit instance.
     *
     * @param value
     * @return a federation token
     */
    String getFederationToken(String value);
    /**
     * Compares the provided token with this Gitblit instance's tokens and
     * determines if the requested permission may be granted to the token.
     *
     * @param req
     * @param token
     * @return true if the request can be executed
     */
    boolean validateFederationRequest(FederationRequest req, String token);
    /**
     * Acknowledge and cache the status of a remote Gitblit instance.
     *
     * @param identification
     *            the identification of the pulling Gitblit instance
     * @param registration
     *            the registration from the pulling Gitblit instance
     * @return true if acknowledged
     */
    boolean acknowledgeFederationStatus(String identification, FederationModel registration);
    /**
     * Returns the list of registration results.
     *
     * @return the list of registration results
     */
    List<FederationModel> getFederationResultRegistrations();
    /**
     * Submit a federation proposal. The proposal is cached locally and the
     * Gitblit administrator(s) are notified via email.
     *
     * @param proposal
     *            the proposal
     * @param gitblitUrl
     *            the url of your gitblit instance to send an email to
     *            administrators
     * @return true if the proposal was submitted
     */
    boolean submitFederationProposal(FederationProposal proposal, String gitblitUrl);
    /**
     * Returns the list of pending federation proposals
     *
     * @return list of federation proposals
     */
    List<FederationProposal> getPendingFederationProposals();
    /**
     * Get repositories for the specified token.
     *
     * @param gitblitUrl
     *            the base url of this gitblit instance
     * @param token
     *            the federation token
     * @return a map of <cloneurl, RepositoryModel>
     */
    Map<String, RepositoryModel> getRepositories(String gitblitUrl, String token);
    /**
     * Creates a proposal from the token.
     *
     * @param gitblitUrl
     *            the url of this Gitblit instance
     * @param token
     * @return a potential proposal
     */
    FederationProposal createFederationProposal(String gitblitUrl, String token);
    /**
     * Returns the proposal identified by the supplied token.
     *
     * @param token
     * @return the specified proposal or null
     */
    FederationProposal getPendingFederationProposal(String token);
    /**
     * Deletes a pending federation proposal.
     *
     * @param a
     *            proposal
     * @return true if the proposal was deleted
     */
    boolean deletePendingFederationProposal(FederationProposal proposal);
}
src/main/java/com/gitblit/manager/IGitblitManager.java
New file
@@ -0,0 +1,83 @@
/*
 * 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.util.Collection;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.gitblit.GitBlitException;
import com.gitblit.models.GitClientApplication;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.RepositoryUrl;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
public interface IGitblitManager {
    /**
     * Returns a list of repository URLs and the user access permission.
     *
     * @param request
     * @param user
     * @param repository
     * @return a list of repository urls
     */
    List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository);
    /**
     * Adds/updates a complete user object keyed by username. This method allows
     * for renaming a user.
     *
     * @see IUserService.updateUserModel(String, UserModel)
     * @param username
     * @param user
     * @param isCreate
     * @throws GitBlitException
     */
    void updateUserModel(String username, UserModel user, boolean isCreate) throws GitBlitException;
    /**
     * Updates the TeamModel object for the specified name.
     *
     * @param teamname
     * @param team
     * @param isCreate
     */
    void updateTeamModel(String teamname, TeamModel team, boolean isCreate) throws GitBlitException;
    /**
     * Creates a personal fork of the specified repository. The clone is view
     * restricted by default and the owner of the source repository is given
     * access to the clone.
     *
     * @param repository
     * @param user
     * @return the repository model of the fork, if successful
     * @throws GitBlitException
     */
    RepositoryModel fork(RepositoryModel repository, UserModel user) throws GitBlitException;
    /**
     * Returns the list of custom client applications to be used for the
     * repository url panel;
     *
     * @return a collection of client applications
     */
    Collection<GitClientApplication> getClientApplications();
}
src/main/java/com/gitblit/manager/INotificationManager.java
New file
@@ -0,0 +1,66 @@
/*
 * 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.util.Collection;
public interface INotificationManager {
    /**
     * Notify the administrators by email.
     *
     * @param subject
     * @param message
     */
    void sendMailToAdministrators(String subject, String message);
    /**
     * Notify users by email of something.
     *
     * @param subject
     * @param message
     * @param toAddresses
     */
    void sendMail(String subject, String message, Collection<String> toAddresses);
    /**
     * Notify users by email of something.
     *
     * @param subject
     * @param message
     * @param toAddresses
     */
    void sendMail(String subject, String message, String... toAddresses);
    /**
     * Notify users by email of something.
     *
     * @param subject
     * @param message
     * @param toAddresses
     */
    void sendHtmlMail(String subject, String message, Collection<String> toAddresses);
    /**
     * Notify users by email of something.
     *
     * @param subject
     * @param message
     * @param toAddresses
     */
    void sendHtmlMail(String subject, String message, String... toAddresses);
}
src/main/java/com/gitblit/manager/IProjectManager.java
New file
@@ -0,0 +1,63 @@
/*
 * 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.util.List;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
public interface IProjectManager {
    /**
     * Returns a list of project models for the user.
     *
     * @param user
     * @param includeUsers
     * @return list of projects that are accessible to the user
     */
    List<ProjectModel> getProjectModels(UserModel user, boolean includeUsers);
    /**
     * Returns the project model for the specified user.
     *
     * @param name
     * @param user
     * @return a project model, or null if it does not exist
     */
    ProjectModel getProjectModel(String name, UserModel user);
    /**
     * Returns a project model for the Gitblit/system user.
     *
     * @param name a project name
     * @return a project model or null if the project does not exist
     */
    ProjectModel getProjectModel(String name);
    /**
     * Returns the list of project models that are referenced by the supplied
     * repository model    list.  This is an alternative method exists to ensure
     * Gitblit does not call getRepositoryModels(UserModel) twice in a request.
     *
     * @param repositoryModels
     * @param includeUsers
     * @return a list of project models
     */
    List<ProjectModel> getProjectModels(List<RepositoryModel> repositoryModels, boolean includeUsers);
}
src/main/java/com/gitblit/manager/IRepositoryManager.java
New file
@@ -0,0 +1,396 @@
/*
 * 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.util.Collection;
import java.util.Date;
import java.util.List;
import org.eclipse.jgit.lib.Repository;
import com.gitblit.GitBlitException;
import com.gitblit.models.ForkModel;
import com.gitblit.models.Metric;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.SearchResult;
import com.gitblit.models.UserModel;
public interface IRepositoryManager {
    /**
     * 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
     */
    File getRepositoriesFolder();
    /**
     * Returns the path of the hooks folder. This method checks to see if
     * Gitblit is running on a cloud service and may return an adjusted path.
     *
     * @return the Groovy hook scripts folder path
     */
    File getHooksFolder();
    /**
     * Returns the path of the grapes folder. This method checks to see if
     * Gitblit is running on a cloud service and may return an adjusted path.
     *
     * @return the Groovy grapes folder path
     */
    File getGrapesFolder();
    /**
     * Returns the most recent change date of any repository served by Gitblit.
     *
     * @return a date
     */
    Date getLastActivityDate();
    /**
     * 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
     */
    List<RegistrantAccessPermission> getUserAccessPermissions(UserModel user);
    /**
     * 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
     */
    List<RegistrantAccessPermission> getUserAccessPermissions(RepositoryModel repository);
    /**
     * 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
     */
    boolean setUserAccessPermissions(RepositoryModel repository, Collection<RegistrantAccessPermission> permissions);
    /**
     * 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
     */
    List<String> getRepositoryUsers(RepositoryModel repository);
    /**
     * 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
     */
    List<RegistrantAccessPermission> getTeamAccessPermissions(RepositoryModel repository);
    /**
     * 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
     */
    boolean setTeamAccessPermissions(RepositoryModel repository, Collection<RegistrantAccessPermission> permissions);
    /**
     * 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
     */
    List<String> getRepositoryTeams(RepositoryModel repository);
    /**
     * Adds the repository to the list of cached repositories if Gitblit is
     * configured to cache the repository list.
     *
     * @param model
     */
    void addToCachedRepositoryList(RepositoryModel model);
    /**
     * Resets the repository list cache.
     *
     */
    void resetRepositoryListCache();
    /**
     * Returns the list of all repositories available to Gitblit. This method
     * does not consider user access permissions.
     *
     * @return list of all repositories
     */
    List<String> getRepositoryList();
    /**
     * Returns the JGit repository for the specified name.
     *
     * @param repositoryName
     * @return repository or null
     */
    Repository getRepository(String repositoryName);
    /**
     * Returns the JGit repository for the specified name.
     *
     * @param repositoryName
     * @param logError
     * @return repository or null
     */
    Repository getRepository(String repositoryName, boolean logError);
    /**
     * Returns the list of repository models that are accessible to the user.
     *
     * @param user
     * @return list of repository models accessible to user
     */
    List<RepositoryModel> getRepositoryModels(UserModel user);
    /**
     * Returns a repository model if the repository exists and the user may
     * access the repository.
     *
     * @param user
     * @param repositoryName
     * @return repository model or null
     */
    RepositoryModel getRepositoryModel(UserModel user, String repositoryName);
    /**
     * Returns the repository model for the specified repository. This method
     * does not consider user access permissions.
     *
     * @param repositoryName
     * @return repository model or null
     */
    RepositoryModel getRepositoryModel(String repositoryName);
    /**
     * Returns the star count of the repository.
     *
     * @param repository
     * @return the star count
     */
    long getStarCount(RepositoryModel repository);
    /**
     * Determines if this server has the requested repository.
     *
     * @param n
     * @return true if the repository exists
     */
    boolean hasRepository(String repositoryName);
    /**
     * Determines if this server has the requested repository.
     *
     * @param n
     * @param caseInsensitive
     * @return true if the repository exists
     */
    boolean hasRepository(String repositoryName, boolean caseSensitiveCheck);
    /**
     * 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
     */
    boolean hasFork(String username, String origin);
    /**
     * 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
     */
    String getFork(String username, String origin);
    /**
     * 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
     */
    ForkModel getForkNetwork(String repository);
    /**
     * 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
     */
    long updateLastChangeFields(Repository r, RepositoryModel model);
    /**
     * 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
     */
    List<Metric> getRepositoryDefaultMetrics(RepositoryModel model, Repository repository);
    /**
     * 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
     */
    void updateRepositoryModel(String repositoryName, RepositoryModel repository, boolean isCreate)
            throws GitBlitException;
    /**
     * Updates the Gitblit configuration for the specified repository.
     *
     * @param r
     *            the Git repository
     * @param repository
     *            the Gitblit repository model
     */
    void updateConfiguration(Repository r, RepositoryModel repository);
    /**
     * Deletes the repository from the file system and removes the repository
     * permission from all repository users.
     *
     * @param model
     * @return true if successful
     */
    boolean deleteRepositoryModel(RepositoryModel model);
    /**
     * Deletes the repository from the file system and removes the repository
     * permission from all repository users.
     *
     * @param repositoryName
     * @return true if successful
     */
    boolean deleteRepository(String repositoryName);
    /**
     * Returns the list of all Groovy push hook scripts. Script files must have
     * .groovy extension
     *
     * @return list of available hook scripts
     */
    List<String> getAllScripts();
    /**
     * 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
     */
    List<String> getPreReceiveScriptsInherited(RepositoryModel repository);
    /**
     * 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
     */
    List<String> getPreReceiveScriptsUnused(RepositoryModel repository);
    /**
     * 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
     */
    List<String> getPostReceiveScriptsInherited(RepositoryModel repository);
    /**
     * 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
     */
    List<String> getPostReceiveScriptsUnused(RepositoryModel repository);
    /**
     * Search the specified repositories using the Lucene query.
     *
     * @param query
     * @param page
     * @param pageSize
     * @param repositories
     * @return
     */
    List<SearchResult> search(String query, int page, int pageSize, List<String> repositories);
    /**
     *
     * @return true if we are running the gc executor
     */
    boolean isCollectingGarbage();
    /**
     * Returns true if Gitblit is actively collecting garbage in this repository.
     *
     * @param repositoryName
     * @return true if actively collecting garbage
     */
    boolean isCollectingGarbage(String repositoryName);
}
src/main/java/com/gitblit/manager/IRuntimeManager.java
New file
@@ -0,0 +1,103 @@
/*
 * 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.util.Date;
import java.util.Map;
import java.util.TimeZone;
import com.gitblit.IStoredSettings;
import com.gitblit.models.ServerSettings;
import com.gitblit.models.ServerStatus;
public interface IRuntimeManager {
    void setBaseFolder(File folder);
    File getBaseFolder();
    /**
     * Returns the preferred timezone for the Gitblit instance.
     *
     * @return a timezone
     */
    TimeZone getTimezone();
    /**
     * Determine if this Gitblit instance is actively serving git repositories
     * or if it is merely a repository viewer.
     *
     * @return true if Gitblit is serving repositories
     */
    boolean isServingRepositories();
    /**
     * Determine if this Gitblit instance is running in debug mode
     *
     * @return true if Gitblit is running in debug mode
     */
    boolean isDebugMode();
    /**
     * Returns the boot date of the Gitblit server.
     *
     * @return the boot date of Gitblit
     */
    Date getBootDate();
    ServerStatus getStatus();
    /**
     * Returns the descriptions/comments of the Gitblit config settings.
     *
     * @return SettingsModel
     */
    ServerSettings getSettingsModel();
    /**
     * Returns the file object for the specified configuration key.
     *
     * @return the file
     */
    File getFileOrFolder(String key, String defaultFileOrFolder);
    /**
     * Returns the file object which may have it's base-path determined by
     * environment variables for running on a cloud hosting service. All Gitblit
     * file or folder retrievals are (at least initially) funneled through this
     * method so it is the correct point to globally override/alter filesystem
     * access based on environment or some other indicator.
     *
     * @return the file
     */
    File getFileOrFolder(String fileOrFolder);
    /**
     * Returns the runtime settings.
     *
     * @return settings
     */
    IStoredSettings getSettings();
    /**
     * Updates the runtime settings.
     *
     * @param settings
     * @return true if the update succeeded
     */
    boolean updateSettings(Map<String, String> updatedSettings);
}
src/main/java/com/gitblit/manager/ISessionManager.java
New file
@@ -0,0 +1,64 @@
/*
 * 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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.gitblit.models.UserModel;
public interface ISessionManager {
    /**
     * Authenticate a user based on HTTP request parameters.
     *
     * Authentication by X509Certificate is tried first and then by cookie.
     *
     * @param httpRequest
     * @return a user object or null
     */
    UserModel authenticate(HttpServletRequest httpRequest);
    /**
     * Authenticate a user based on HTTP request parameters.
     *
     * Authentication by X509Certificate, servlet container principal, cookie,
     * and BASIC header.
     *
     * @param httpRequest
     * @param requiresCertificate
     * @return a user object or null
     */
    UserModel authenticate(HttpServletRequest httpRequest, boolean requiresCertificate);
    UserModel authenticate(String username, char[] password);
    /**
     * Sets a cookie for the specified user.
     *
     * @param response
     * @param user
     */
    void setCookie(HttpServletResponse response, UserModel user);
    /**
     * Logout a user.
     *
     * @param user
     */
    void logout(HttpServletResponse response, UserModel user);
}
src/main/java/com/gitblit/manager/IUserManager.java
New file
@@ -0,0 +1,280 @@
/*
 * 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.util.Collection;
import java.util.List;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
public interface IUserManager {
    boolean supportsAddUser();
    /**
     * Does the user service support changes to credentials?
     *
     * @return true or false
     * @since 1.0.0
     */
    boolean supportsCredentialChanges(UserModel user);
    /**
     * Returns true if the user's display name can be changed.
     *
     * @param user
     * @return true if the user service supports display name changes
     */
    boolean supportsDisplayNameChanges(UserModel user);
    /**
     * Returns true if the user's email address can be changed.
     *
     * @param user
     * @return true if the user service supports email address changes
     */
    boolean supportsEmailAddressChanges(UserModel user);
    /**
     * Returns true if the user's team memberships can be changed.
     *
     * @param user
     * @return true if the user service supports team membership changes
     */
    boolean supportsTeamMembershipChanges(UserModel user);
    /**
     * Does the user service support cookie authentication?
     *
     * @return true or false
     */
    boolean supportsCookies();
    /**
     * Returns the cookie value for the specified user.
     *
     * @param model
     * @return cookie value
     */
    String getCookie(UserModel model);
    /**
     * Authenticate a user based on their cookie.
     *
     * @param cookie
     * @return a user object or null
     */
    UserModel authenticate(char[] cookie);
    /**
     * Authenticate a user based on a username and password.
     *
     * @param username
     * @param password
     * @return a user object or null
     */
    UserModel authenticate(String username, char[] password);
    /**
     * Logout a user.
     *
     * @param user
     */
    void logout(UserModel user);
    /**
     * Retrieve the user object for the specified username.
     *
     * @param username
     * @return a user object or null
     */
    UserModel getUserModel(String username);
    /**
     * Updates/writes a complete user object.
     *
     * @param model
     * @return true if update is successful
     */
    boolean updateUserModel(UserModel model);
    /**
     * Updates/writes all specified user objects.
     *
     * @param models a list of user models
     * @return true if update is successful
     * @since 1.2.0
     */
    boolean updateUserModels(Collection<UserModel> models);
    /**
     * Adds/updates a user object keyed by username. This method allows for
     * renaming a user.
     *
     * @param username
     *            the old username
     * @param model
     *            the user object to use for username
     * @return true if update is successful
     */
    boolean updateUserModel(String username, UserModel model);
    /**
     * Deletes the user object from the user service.
     *
     * @param model
     * @return true if successful
     */
    boolean deleteUserModel(UserModel model);
    /**
     * Delete the user object with the specified username
     *
     * @param username
     * @return true if successful
     */
    boolean deleteUser(String username);
    /**
     * Returns the list of all users available to the login service.
     *
     * @return list of all usernames
     */
    List<String> getAllUsernames();
    /**
     * Returns the list of all users available to the login service.
     *
     * @return list of all users
     * @since 0.8.0
     */
    List<UserModel> getAllUsers();
    /**
     * Returns the list of all teams available to the login service.
     *
     * @return list of all teams
     * @since 0.8.0
     */
    List<String> getAllTeamNames();
    /**
     * Returns the list of all teams available to the login service.
     *
     * @return list of all teams
     * @since 0.8.0
     */
    List<TeamModel> getAllTeams();
    /**
     * Returns the list of all users who are allowed to bypass the access
     * restriction placed on the specified repository.
     *
     * @param role
     *            the repository name
     * @return list of all usernames that can bypass the access restriction
     * @since 0.8.0
     */
    List<String> getTeamnamesForRepositoryRole(String role);
    /**
     * Retrieve the team object for the specified team name.
     *
     * @param teamname
     * @return a team object or null
     * @since 0.8.0
     */
    TeamModel getTeamModel(String teamname);
    /**
     * Updates/writes a complete team object.
     *
     * @param model
     * @return true if update is successful
     * @since 0.8.0
     */
    boolean updateTeamModel(TeamModel model);
    /**
     * Updates/writes all specified team objects.
     *
     * @param models a list of team models
     * @return true if update is successful
     * @since 1.2.0
     */
    boolean updateTeamModels(Collection<TeamModel> models);
    /**
     * Updates/writes and replaces a complete team object keyed by teamname.
     * This method allows for renaming a team.
     *
     * @param teamname
     *            the old teamname
     * @param model
     *            the team object to use for teamname
     * @return true if update is successful
     * @since 0.8.0
     */
    boolean updateTeamModel(String teamname, TeamModel model);
    /**
     * Deletes the team object from the user service.
     *
     * @param model
     * @return true if successful
     * @since 0.8.0
     */
    boolean deleteTeamModel(TeamModel model);
    /**
     * Delete the team object with the specified teamname
     *
     * @param teamname
     * @return true if successful
     * @since 0.8.0
     */
    boolean deleteTeam(String teamname);
    /**
     * Returns the list of all users who are allowed to bypass the access
     * restriction placed on the specified repository.
     *
     * @param role
     *            the repository name
     * @return list of all usernames that can bypass the access restriction
     * @since 0.8.0
     */
    List<String> getUsernamesForRepositoryRole(String role);
    /**
     * Renames a repository role.
     *
     * @param oldRole
     * @param newRole
     * @return true if successful
     */
    boolean renameRepositoryRole(String oldRole, String newRole);
    /**
     * Removes a repository role from all users.
     *
     * @param role
     * @return true if successful
     */
    boolean deleteRepositoryRole(String role);
}
src/main/java/com/gitblit/utils/ActivityUtils.java
@@ -34,8 +34,9 @@
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import com.gitblit.GitBlit;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.Activity;
import com.gitblit.models.GravatarProfile;
import com.gitblit.models.RefModel;
@@ -55,6 +56,10 @@
     * Gets the recent activity from the repositories for the last daysBack days
     * on the specified branch.
     *
     * @param settings
     *            the runtime settings
     * @param repositoryManager
     *            the repository manager
     * @param models
     *            the list of repositories to query
     * @param daysBack
@@ -66,8 +71,13 @@
     *            the timezone for aggregating commits
     * @return
     */
    public static List<Activity> getRecentActivity(List<RepositoryModel> models, int daysBack,
            String objectId, TimeZone timezone) {
    public static List<Activity> getRecentActivity(
                    IStoredSettings settings,
                    IRepositoryManager repositoryManager,
                    List<RepositoryModel> models,
                    int daysBack,
                    String objectId,
                    TimeZone timezone) {
        // Activity panel shows last daysBack of activity across all
        // repositories.
@@ -82,7 +92,7 @@
        // aggregate author exclusions
        Set<String> authorExclusions = new TreeSet<String>();
        authorExclusions.addAll(GitBlit.getStrings(Keys.web.metricAuthorExclusions));
        authorExclusions.addAll(settings.getStrings(Keys.web.metricAuthorExclusions));
        for (RepositoryModel model : models) {
            if (!ArrayUtils.isEmpty(model.metricAuthorExclusions)) {
                authorExclusions.addAll(model.metricAuthorExclusions);
@@ -99,8 +109,7 @@
                if (model.isCollectingGarbage) {
                    continue;
                }
                Repository repository = GitBlit.self()
                        .getRepository(model.name);
                Repository repository = repositoryManager.getRepository(model.name);
                List<String> branches = new ArrayList<String>();
                if (StringUtils.isEmpty(objectId)) {
                    for (RefModel local : JGitUtils.getLocalBranches(
src/main/java/com/gitblit/wicket/GitBlitWebApp.java
@@ -31,6 +31,14 @@
import com.gitblit.GitBlit;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IGitblitManager;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.ISessionManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.pages.ActivityPage;
import com.gitblit.wicket.pages.BlamePage;
@@ -80,7 +88,7 @@
    public void init() {
        super.init();
        settings = GitBlit.getSettings();
        settings = runtime().getSettings();
        // Setup page authorization mechanism
        boolean useAuthentication = settings.getBoolean(Keys.web.authenticateViewPages, false)
@@ -197,7 +205,7 @@
     * @return true if Gitblit is running in debug mode
     */
    public boolean isDebugMode() {
        return GitBlit.isDebugMode();
        return runtime().isDebugMode();
    }
    /*
@@ -205,47 +213,47 @@
     * step towards modularization across multiple commits.
     */
    public Date getBootDate() {
        return GitBlit.getBootDate();
        return runtime().getBootDate();
    }
    public Date getLastActivityDate() {
        return GitBlit.getLastActivityDate();
        return repositories().getLastActivityDate();
    }
    public GitBlit runtime() {
        return GitBlit.self();
    public IRuntimeManager runtime() {
        return GitBlit.getManager(IRuntimeManager.class);
    }
    public GitBlit mail() {
        return GitBlit.self();
    public INotificationManager notifier() {
        return GitBlit.getManager(INotificationManager.class);
    }
    public GitBlit users() {
        return GitBlit.self();
    public IUserManager users() {
        return GitBlit.getManager(IUserManager.class);
    }
    public GitBlit session() {
        return GitBlit.self();
    public ISessionManager session() {
        return GitBlit.getManager(ISessionManager.class);
    }
    public GitBlit repositories() {
        return GitBlit.self();
    public IRepositoryManager repositories() {
        return GitBlit.getManager(IRepositoryManager.class);
    }
    public GitBlit projects() {
        return GitBlit.self();
    public IProjectManager projects() {
        return GitBlit.getManager(IProjectManager.class);
    }
    public GitBlit federation() {
        return GitBlit.self();
    public IFederationManager federation() {
        return GitBlit.getManager(IFederationManager.class);
    }
    public GitBlit gitblit() {
        return GitBlit.self();
    public IGitblitManager gitblit() {
        return GitBlit.getManager(IGitblitManager.class);
    }
    public TimeZone getTimezone() {
        return GitBlit.getTimezone();
        return runtime().getTimezone();
    }
    @Override
src/main/java/com/gitblit/wicket/GitblitWicketFilter.java
@@ -25,7 +25,11 @@
import org.eclipse.jgit.revwalk.RevCommit;
import com.gitblit.GitBlit;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.JGitUtils;
@@ -77,18 +81,23 @@
            commitId = servletRequest.getParameter("h");
        }
        repo = repo.replace("%2f", "/").replace("%2F", "/").replace(GitBlit.getChar(Keys.web.forwardSlashCharacter, '/'), '/');
        IRuntimeManager runtimeManager = GitBlit.getManager(IRuntimeManager.class);
        IStoredSettings settings = runtimeManager.getSettings();
        IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
        IProjectManager projectManager = GitBlit.getManager(IProjectManager.class);
        repo = repo.replace("%2f", "/").replace("%2F", "/").replace(settings.getChar(Keys.web.forwardSlashCharacter, '/'), '/');
        GitBlitWebApp app = (GitBlitWebApp) getWebApplication();
        int expires = GitBlit.getInteger(Keys.web.pageCacheExpires, 0);
        int expires = settings.getInteger(Keys.web.pageCacheExpires, 0);
        if (!StringUtils.isEmpty(page) && app.isCacheablePage(page) && expires > 0) {
            // page can be cached by the browser
            CacheControl cacheControl = app.getCacheControl(page);
            Date bootDate = GitBlit.getBootDate();
            Date bootDate = runtimeManager.getBootDate();
            switch (cacheControl.value()) {
            case ACTIVITY:
                // returns the last activity date of the server
                Date activityDate = GitBlit.getLastActivityDate();
                Date activityDate = repositoryManager.getLastActivityDate();
                if (activityDate != null) {
                    return activityDate.after(bootDate) ? activityDate.getTime() : bootDate.getTime();
                }
@@ -98,7 +107,7 @@
                return bootDate.getTime();
            case PROJECT:
                // return the latest change date for the project OR the boot date
                ProjectModel project = GitBlit.self().getProjectModel(StringUtils.getRootPath(repo));
                ProjectModel project = projectManager.getProjectModel(StringUtils.getRootPath(repo));
                if (project != null) {
                    return project.lastChange.after(bootDate) ? project.lastChange.getTime() : bootDate.getTime();
                }
@@ -106,7 +115,7 @@
            case REPOSITORY:
                // return the lastest change date for the repository OR the boot
                // date, whichever is latest
                RepositoryModel repository = GitBlit.self().getRepositoryModel(repo);
                RepositoryModel repository = repositoryManager.getRepositoryModel(repo);
                if (repository != null && repository.lastChange != null) {
                    return repository.lastChange.after(bootDate) ? repository.lastChange.getTime() : bootDate.getTime();
                }
@@ -121,7 +130,7 @@
                    Repository r = null;
                    try {
                        // return the timestamp of the associated commit
                        r = GitBlit.self().getRepository(repo);
                        r = repositoryManager.getRepository(repo);
                        if (r != null) {
                            RevCommit commit = JGitUtils.getCommit(r, commitId);
                            if (commit != null) {
src/main/java/com/gitblit/wicket/pages/ActivityPage.java
@@ -71,8 +71,13 @@
        // determine repositories to view and retrieve the activity
        List<RepositoryModel> models = getRepositories(params);
        List<Activity> recentActivity = ActivityUtils.getRecentActivity(models,
                daysBack, objectId, getTimeZone());
        List<Activity> recentActivity = ActivityUtils.getRecentActivity(
                app().settings(),
                app().repositories(),
                models,
                daysBack,
                objectId,
                getTimeZone());
        String headerPattern;
        if (daysBack == 1) {
src/main/java/com/gitblit/wicket/pages/ChangePasswordPage.java
@@ -97,10 +97,10 @@
                user.password = password;
                try {
                    app().users().updateUserModel(user.username, user, false);
                    app().gitblit().updateUserModel(user.username, user, false);
                    if (app().settings().getBoolean(Keys.web.allowCookieAuthentication, false)) {
                        WebResponse response = (WebResponse) getRequestCycle().getResponse();
                        app().session().setCookie(response, user);
                        app().session().setCookie(response.getHttpServletResponse(), user);
                    }
                } catch (GitBlitException e) {
                    error(e.getMessage());
src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java
@@ -169,7 +169,7 @@
        final RegistrantPermissionsPanel usersPalette = new RegistrantPermissionsPanel("users",
                RegistrantType.USER, app().users().getAllUsernames(), repositoryUsers, getAccessPermissions());
        final RegistrantPermissionsPanel teamsPalette = new RegistrantPermissionsPanel("teams",
                RegistrantType.TEAM, app().users().getAllTeamnames(), repositoryTeams, getAccessPermissions());
                RegistrantType.TEAM, app().users().getAllTeamNames(), repositoryTeams, getAccessPermissions());
        // owners palette
        List<String> owners = new ArrayList<String>(repositoryModel.owners);
src/main/java/com/gitblit/wicket/pages/EditTeamPage.java
@@ -196,7 +196,7 @@
                teamModel.postReceiveScripts.addAll(postReceiveScripts);
                try {
                    app().users().updateTeamModel(oldName, teamModel, isCreate);
                    app().gitblit().updateTeamModel(oldName, teamModel, isCreate);
                } catch (GitBlitException e) {
                    error(e.getMessage());
                    return;
src/main/java/com/gitblit/wicket/pages/EditUserPage.java
@@ -110,7 +110,7 @@
        final Palette<String> teams = new Palette<String>("teams", new ListModel<String>(
                new ArrayList<String>(userTeams)), new CollectionModel<String>(app().users()
                .getAllTeamnames()), new StringChoiceRenderer(), 10, false);
                .getAllTeamNames()), new StringChoiceRenderer(), 10, false);
        Form<UserModel> form = new Form<UserModel>("editForm", model) {
            private static final long serialVersionUID = 1L;
@@ -192,7 +192,7 @@
                }
                try {
                    app().users().updateUserModel(oldName, userModel, isCreate);
                    app().gitblit().updateUserModel(oldName, userModel, isCreate);
                } catch (GitBlitException e) {
                    error(e.getMessage());
                    return;
src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java
@@ -58,7 +58,7 @@
        }
        HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest();
        List<RepositoryUrl> repositoryUrls = app().repositories().getRepositoryUrls(req, user, repository);
        List<RepositoryUrl> repositoryUrls = app().gitblit().getRepositoryUrls(req, user, repository);
        RepositoryUrl primaryUrl = repositoryUrls.size() == 0 ? null : repositoryUrls.get(0);
        String url = primaryUrl != null ? primaryUrl.url : "";
src/main/java/com/gitblit/wicket/pages/LogoutPage.java
@@ -27,8 +27,7 @@
        super();
        GitBlitWebSession session = GitBlitWebSession.get();
        UserModel user = session.getUser();
        app().session().setCookie((WebResponse) getResponse(), null);
        app().session().logout(user);
        app().session().logout(((WebResponse) getResponse()).getHttpServletResponse(), user);
        session.invalidate();
        /*
src/main/java/com/gitblit/wicket/pages/RepositoryPage.java
@@ -139,7 +139,7 @@
                UserRepositoryPreferences prefs = user.getPreferences().getRepositoryPreferences(getRepositoryModel().name);
                prefs.starred = star;
                try {
                    app().users().updateUserModel(user.username, user, false);
                    app().gitblit().updateUserModel(user.username, user, false);
                } catch (GitBlitException e) {
                    logger.error("Failed to update user " + user.username, e);
                    error(getString("gb.failedToUpdateUser"), false);
src/main/java/com/gitblit/wicket/pages/RootPage.java
@@ -252,7 +252,7 @@
            // Set Cookie
            if (app().settings().getBoolean(Keys.web.allowCookieAuthentication, false)) {
                WebResponse response = (WebResponse) getRequestCycle().getResponse();
                app().session().setCookie(response, user);
                app().session().setCookie(response.getHttpServletResponse(), user);
            }
            if (!session.continueRequest()) {
src/main/java/com/gitblit/wicket/pages/SessionPage.java
@@ -70,7 +70,7 @@
            // Set Cookie
            WebResponse response = (WebResponse) getRequestCycle().getResponse();
            app().session().setCookie(response, user);
            app().session().setCookie(response.getHttpServletResponse(), user);
            session.continueRequest();
        }
src/test/java/com/gitblit/tests/ActivityTest.java
@@ -15,8 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import org.junit.Test;
@@ -24,7 +22,7 @@
import com.gitblit.models.GravatarProfile;
import com.gitblit.utils.ActivityUtils;
public class ActivityTest {
public class ActivityTest extends GitblitUnitTest {
    @Test
    public void testGravatarProfile() throws IOException {
src/test/java/com/gitblit/tests/ArrayUtilsTest.java
@@ -15,9 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -28,7 +25,7 @@
import com.gitblit.utils.ArrayUtils;
public class ArrayUtilsTest {
public class ArrayUtilsTest extends GitblitUnitTest {
    @Test
    public void testArrays() {
src/test/java/com/gitblit/tests/Base64Test.java
@@ -15,13 +15,11 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.gitblit.utils.Base64;
public class Base64Test {
public class Base64Test extends GitblitUnitTest {
    @Test
    public void testBase64() {
src/test/java/com/gitblit/tests/ByteFormatTest.java
@@ -15,15 +15,13 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import java.util.Locale;
import org.junit.Test;
import com.gitblit.utils.ByteFormat;
public class ByteFormatTest {
public class ByteFormatTest extends GitblitUnitTest {
    @Test
    public void testByteFormat() throws Exception {
src/test/java/com/gitblit/tests/DiffUtilsTest.java
@@ -15,9 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.eclipse.jgit.lib.Repository;
@@ -29,7 +26,7 @@
import com.gitblit.utils.DiffUtils.DiffOutputType;
import com.gitblit.utils.JGitUtils;
public class DiffUtilsTest {
public class DiffUtilsTest extends GitblitUnitTest {
    @Test
    public void testDiffOutputTypes() throws Exception {
src/test/java/com/gitblit/tests/FanoutServiceTest.java
@@ -15,8 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Map;
@@ -31,7 +29,7 @@
import com.gitblit.fanout.FanoutService;
import com.gitblit.fanout.FanoutSocketService;
public class FanoutServiceTest {
public class FanoutServiceTest extends GitblitUnitTest {
    int fanoutPort = FanoutService.DEFAULT_PORT;
src/test/java/com/gitblit/tests/FederationTests.java
@@ -15,10 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -42,7 +38,7 @@
import com.gitblit.utils.JsonUtils;
import com.gitblit.utils.RpcUtils;
public class FederationTests {
public class FederationTests extends GitblitUnitTest {
    String url = GitBlitSuite.url;
    String account = GitBlitSuite.account;
src/test/java/com/gitblit/tests/FileUtilsTest.java
@@ -15,16 +15,13 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.junit.Test;
import com.gitblit.utils.FileUtils;
public class FileUtilsTest {
public class FileUtilsTest extends GitblitUnitTest {
    @Test
    public void testReadContent() throws Exception {
src/test/java/com/gitblit/tests/GitBlitSuite.java
@@ -36,6 +36,7 @@
import com.gitblit.GitBlit;
import com.gitblit.GitBlitException;
import com.gitblit.GitBlitServer;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.JGitUtils;
@@ -179,9 +180,10 @@
    private static void showRemoteBranches(String repositoryName) {
        try {
            RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
            IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
            RepositoryModel model = repositoryManager.getRepositoryModel(repositoryName);
            model.showRemoteBranches = true;
            GitBlit.self().updateRepositoryModel(model.name, model, false);
            repositoryManager.updateRepositoryModel(model.name, model, false);
        } catch (GitBlitException g) {
            g.printStackTrace();
        }
@@ -189,9 +191,10 @@
    private static void automaticallyTagBranchTips(String repositoryName) {
        try {
            RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
            IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
            RepositoryModel model = repositoryManager.getRepositoryModel(repositoryName);
            model.useIncrementalPushTags = true;
            GitBlit.self().updateRepositoryModel(model.name, model, false);
            repositoryManager.updateRepositoryModel(model.name, model, false);
        } catch (GitBlitException g) {
            g.printStackTrace();
        }
src/test/java/com/gitblit/tests/GitBlitTest.java
@@ -15,11 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.eclipse.jgit.lib.Repository;
@@ -27,48 +22,47 @@
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.FileSettings;
import com.gitblit.GitBlit;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
public class GitBlitTest {
public class GitBlitTest extends GitblitUnitTest {
    @Test
    public void testRepositoryModel() throws Exception {
        List<String> repositories = GitBlit.self().getRepositoryList();
        List<String> repositories = repositories().getRepositoryList();
        assertTrue("Repository list is empty!", repositories.size() > 0);
        assertTrue(
                "Missing Helloworld repository!",
                repositories.contains(GitBlitSuite.getHelloworldRepository().getDirectory()
                        .getName()));
        Repository r = GitBlitSuite.getHelloworldRepository();
        RepositoryModel model = GitBlit.self().getRepositoryModel(r.getDirectory().getName());
        RepositoryModel model = repositories().getRepositoryModel(r.getDirectory().getName());
        assertTrue("Helloworld model is null!", model != null);
        assertEquals(GitBlitSuite.getHelloworldRepository().getDirectory().getName(), model.name);
        assertTrue(GitBlit.self().updateLastChangeFields(r, model) > 22000L);
        assertTrue(repositories().updateLastChangeFields(r, model) > 22000L);
        r.close();
    }
    @Test
    public void testUserModel() throws Exception {
        List<String> users = GitBlit.self().getAllUsernames();
        List<String> users = users().getAllUsernames();
        assertTrue("No users found!", users.size() > 0);
        assertTrue("Admin not found", users.contains("admin"));
        UserModel user = GitBlit.self().getUserModel("admin");
        UserModel user = users().getUserModel("admin");
        assertEquals("admin", user.toString());
        assertTrue("Admin missing #admin role!", user.canAdmin);
        user.canAdmin = false;
        assertFalse("Admin should not have #admin!", user.canAdmin);
        String repository = GitBlitSuite.getHelloworldRepository().getDirectory().getName();
        RepositoryModel repositoryModel = GitBlit.self().getRepositoryModel(repository);
        RepositoryModel repositoryModel = repositories().getRepositoryModel(repository);
        repositoryModel.accessRestriction = AccessRestrictionType.VIEW;
        assertFalse("Admin can still access repository!",
                user.canView(repositoryModel));
        user.addRepositoryPermission(repository);
        assertTrue("Admin can't access repository!", user.canView(repositoryModel));
        assertEquals(GitBlit.self().getRepositoryModel(user, "pretend"), null);
        assertNotNull(GitBlit.self().getRepositoryModel(user, repository));
        assertTrue(GitBlit.self().getRepositoryModels(user).size() > 0);
        assertEquals(repositories().getRepositoryModel(user, "pretend"), null);
        assertNotNull(repositories().getRepositoryModel(user, repository));
        assertTrue(repositories().getRepositoryModels(user).size() > 0);
    }
    @Test
@@ -156,34 +150,34 @@
    @Test
    public void testGitblitSettings() throws Exception {
        // These are already tested by above test method.
        assertTrue(GitBlit.getBoolean("missing", true));
        assertEquals("default", GitBlit.getString("missing", "default"));
        assertEquals(10, GitBlit.getInteger("missing", 10));
        assertEquals(5, GitBlit.getInteger("realm.userService", 5));
        assertTrue(settings().getBoolean("missing", true));
        assertEquals("default", settings().getString("missing", "default"));
        assertEquals(10, settings().getInteger("missing", 10));
        assertEquals(5, settings().getInteger("realm.userService", 5));
        assertTrue(GitBlit.getBoolean("git.enableGitServlet", false));
        assertEquals(GitBlitSuite.USERSCONF.getAbsolutePath(), GitBlit.getString("realm.userService", null));
        assertEquals(5, GitBlit.getInteger("realm.minPasswordLength", 0));
        List<String> mdExtensions = GitBlit.getStrings("web.markdownExtensions");
        assertTrue(settings().getBoolean("git.enableGitServlet", false));
        assertEquals(GitBlitSuite.USERSCONF.getAbsolutePath(), settings().getString("realm.userService", null));
        assertEquals(5, settings().getInteger("realm.minPasswordLength", 0));
        List<String> mdExtensions = settings().getStrings("web.markdownExtensions");
        assertTrue(mdExtensions.size() > 0);
        assertTrue(mdExtensions.contains("md"));
        List<String> keys = GitBlit.getAllKeys("server");
        List<String> keys = settings().getAllKeys("server");
        assertTrue(keys.size() > 0);
        assertTrue(keys.contains("server.httpsPort"));
        assertTrue(GitBlit.getChar("web.forwardSlashCharacter", ' ') == '/');
        assertFalse(GitBlit.isDebugMode());
        assertTrue(settings().getChar("web.forwardSlashCharacter", ' ') == '/');
        assertFalse(runtime().isDebugMode());
    }
    @Test
    public void testAuthentication() throws Exception {
        assertTrue(GitBlit.self().authenticate("admin", "admin".toCharArray()) != null);
        assertTrue(session().authenticate("admin", "admin".toCharArray()) != null);
    }
    @Test
    public void testRepositories() throws Exception {
        assertTrue(GitBlit.self().getRepository("missing") == null);
        assertTrue(GitBlit.self().getRepositoryModel("missing") == null);
        assertTrue(repositories().getRepository("missing") == null);
        assertTrue(repositories().getRepositoryModel("missing") == null);
    }
}
src/test/java/com/gitblit/tests/GitDaemonStopTest.java
@@ -15,12 +15,11 @@
 */
package com.gitblit.tests;
import org.junit.Assert;
import org.junit.Test;
import com.gitblit.git.GitDaemon;
public class GitDaemonStopTest extends Assert {
public class GitDaemonStopTest extends GitblitUnitTest {
    @Test
    public void testGitDaemonStop() throws Exception {
src/test/java/com/gitblit/tests/GitDaemonTest.java
@@ -31,16 +31,14 @@
import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
import org.eclipse.jgit.util.FileUtils;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.GitBlit;
import com.gitblit.models.RepositoryModel;
public class GitDaemonTest extends Assert {
public class GitDaemonTest extends GitblitUnitTest {
    static File ticgitFolder = new File(GitBlitSuite.REPOSITORIES, "working/ticgit");
@@ -94,10 +92,10 @@
        }
        // set push restriction
        RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git");
        RepositoryModel model = repositories().getRepositoryModel("ticgit.git");
        model.accessRestriction = AccessRestrictionType.PUSH;
        model.authorizationControl = AuthorizationControl.NAMED;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        CloneCommand clone = Git.cloneRepository();
        clone.setURI(MessageFormat.format("{0}/ticgit.git", url));
@@ -110,7 +108,7 @@
        // restore anonymous repository access
        model.accessRestriction = AccessRestrictionType.NONE;
        model.authorizationControl = AuthorizationControl.NAMED;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
    }
    @Test
@@ -121,10 +119,10 @@
        }
        // restrict repository access
        RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git");
        RepositoryModel model = repositories().getRepositoryModel("ticgit.git");
        model.accessRestriction = AccessRestrictionType.CLONE;
        model.authorizationControl = AuthorizationControl.NAMED;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        // delete any existing working folder
        boolean cloned = false;
@@ -147,7 +145,7 @@
        // restore anonymous repository access
        model.accessRestriction = AccessRestrictionType.NONE;
        model.authorizationControl = AuthorizationControl.NAMED;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
    }
    @Test
@@ -158,10 +156,10 @@
        }
        // restore anonymous repository access
        RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git");
        RepositoryModel model = repositories().getRepositoryModel("ticgit.git");
        model.accessRestriction = AccessRestrictionType.NONE;
        model.authorizationControl = AuthorizationControl.NAMED;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        CloneCommand clone = Git.cloneRepository();
        clone.setURI(MessageFormat.format("{0}/ticgit.git", url));
@@ -196,10 +194,10 @@
        }
        // restore anonymous repository access
        RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git");
        RepositoryModel model = repositories().getRepositoryModel("ticgit.git");
        model.accessRestriction = AccessRestrictionType.PUSH;
        model.authorizationControl = AuthorizationControl.NAMED;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        CloneCommand clone = Git.cloneRepository();
        clone.setURI(MessageFormat.format("{0}/ticgit.git", url));
@@ -242,9 +240,9 @@
        assertTrue(true);
        // freeze repo
        RepositoryModel model = GitBlit.self().getRepositoryModel("test/jgit.git");
        RepositoryModel model = repositories().getRepositoryModel("test/jgit.git");
        model.isFrozen = true;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        Git git = Git.open(jgitFolder);
        File file = new File(jgitFolder, "TODO");
@@ -264,7 +262,7 @@
        // unfreeze repo
        model.isFrozen = false;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        results = git.push().setPushAll().call();
        GitBlitSuite.close(git);
src/test/java/com/gitblit/tests/GitServletTest.java
@@ -15,10 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
@@ -53,7 +49,6 @@
import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.models.RefLogEntry;
import com.gitblit.models.RepositoryModel;
@@ -62,7 +57,7 @@
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.RefLogUtils;
public class GitServletTest {
public class GitServletTest extends GitblitUnitTest {
    static File ticgitFolder = new File(GitBlitSuite.REPOSITORIES, "working/ticgit");
@@ -87,8 +82,8 @@
    }
    private static void delete(UserModel user) {
        if (GitBlit.self().getUserModel(user.username) != null) {
            GitBlit.self().deleteUser(user.username);
        if (users().getUserModel(user.username) != null) {
            users().deleteUser(user.username);
        }
    }
@@ -148,9 +143,9 @@
    @Test
    public void testBogusLoginClone() throws Exception {
        // restrict repository access
        RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git");
        RepositoryModel model = repositories().getRepositoryModel("ticgit.git");
        model.accessRestriction = AccessRestrictionType.CLONE;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        // delete any existing working folder
        boolean cloned = false;
@@ -169,7 +164,7 @@
        // restore anonymous repository access
        model.accessRestriction = AccessRestrictionType.NONE;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        assertFalse("Bogus login cloned a repository?!", cloned);
    }
@@ -177,13 +172,13 @@
    @Test
    public void testUnauthorizedLoginClone() throws Exception {
        // restrict repository access
        RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git");
        RepositoryModel model = repositories().getRepositoryModel("ticgit.git");
        model.accessRestriction = AccessRestrictionType.CLONE;
        model.authorizationControl = AuthorizationControl.NAMED;
        UserModel user = new UserModel("james");
        user.password = "james";
        GitBlit.self().updateUserModel(user.username, user, true);
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        gitblit().updateUserModel(user.username, user, true);
        repositories().updateRepositoryModel(model.name, model, false);
        FileUtils.delete(ticgit2Folder, FileUtils.RECURSIVE);
@@ -208,7 +203,7 @@
        // switch to authenticated
        model.authorizationControl = AuthorizationControl.AUTHENTICATED;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        // try clone again
        cloned = false;
@@ -228,7 +223,7 @@
        // restore anonymous repository access
        model.accessRestriction = AccessRestrictionType.NONE;
        model.authorizationControl = AuthorizationControl.NAMED;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        delete(user);
    }
@@ -240,9 +235,9 @@
            FileUtils.delete(ticgitFolder, FileUtils.RECURSIVE | FileUtils.RETRY);
        }
        RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git");
        RepositoryModel model = repositories().getRepositoryModel("ticgit.git");
        model.accessRestriction = AccessRestrictionType.NONE;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        CloneCommand clone = Git.cloneRepository();
        clone.setURI(MessageFormat.format("{0}/ticgit.git", url));
@@ -320,9 +315,9 @@
        assertTrue(true);
        // freeze repo
        RepositoryModel model = GitBlit.self().getRepositoryModel("test/jgit.git");
        RepositoryModel model = repositories().getRepositoryModel("test/jgit.git");
        model.isFrozen = true;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        Git git = Git.open(jgitFolder);
        File file = new File(jgitFolder, "TODO");
@@ -342,7 +337,7 @@
        // unfreeze repo
        model.isFrozen = false;
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        results = git.push().setPushAll().setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)).call();
        GitBlitSuite.close(git);
@@ -428,7 +423,7 @@
        GitBlitSuite.close(clone.call());
        // require push permissions and committer verification
        RepositoryModel model = GitBlit.self().getRepositoryModel("refchecks/verify-committer.git");
        RepositoryModel model = repositories().getRepositoryModel("refchecks/verify-committer.git");
        model.authorizationControl = AuthorizationControl.NAMED;
        model.accessRestriction = AccessRestrictionType.PUSH;
        model.verifyCommitter = true;
@@ -436,8 +431,8 @@
        // grant user push permission
        user.setRepositoryPermission(model.name, AccessPermission.PUSH);
        GitBlit.self().updateUserModel(user.username, user, true);
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        gitblit().updateUserModel(user.username, user, true);
        repositories().updateRepositoryModel(model.name, model, false);
        // clone temp bare repo to working copy
        File local = new File(GitBlitSuite.REPOSITORIES, "refchecks/verify-wc");
@@ -513,7 +508,7 @@
        GitBlitSuite.close(clone.call());
        // require push permissions and committer verification
        RepositoryModel model = GitBlit.self().getRepositoryModel("refchecks/verify-committer.git");
        RepositoryModel model = repositories().getRepositoryModel("refchecks/verify-committer.git");
        model.authorizationControl = AuthorizationControl.NAMED;
        model.accessRestriction = AccessRestrictionType.PUSH;
        model.verifyCommitter = true;
@@ -521,8 +516,8 @@
        // grant user push permission
        user.setRepositoryPermission(model.name, AccessPermission.PUSH);
        GitBlit.self().updateUserModel(user.username, user, true);
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        gitblit().updateUserModel(user.username, user, true);
        repositories().updateRepositoryModel(model.name, model, false);
        // clone temp bare repo to working copy
        File local = new File(GitBlitSuite.REPOSITORIES, "refchecks/verify-wc");
@@ -648,7 +643,7 @@
        GitBlitSuite.close(clone.call());
        // elevate repository to clone permission
        RepositoryModel model = GitBlit.self().getRepositoryModel("refchecks/ticgit.git");
        RepositoryModel model = repositories().getRepositoryModel("refchecks/ticgit.git");
        switch (permission) {
            case VIEW:
                model.accessRestriction = AccessRestrictionType.CLONE;
@@ -664,8 +659,8 @@
        // grant user specified
        user.setRepositoryPermission(model.name, permission);
        GitBlit.self().updateUserModel(user.username, user, true);
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        gitblit().updateUserModel(user.username, user, true);
        repositories().updateRepositoryModel(model.name, model, false);
        // clone temp bare repo to working copy
        File local = new File(GitBlitSuite.REPOSITORIES, "refchecks/ticgit-wc");
@@ -834,7 +829,7 @@
        user.canCreate = canCreate;
        user.canAdmin = canAdmin;
        GitBlit.self().updateUserModel(user.username, user, true);
        gitblit().updateUserModel(user.username, user, true);
        CredentialsProvider cp = new UsernamePasswordCredentialsProvider(user.username, user.password);
@@ -885,7 +880,7 @@
            assertTrue("User canAdmin:" + user.canAdmin + " canCreate:" + user.canCreate, user.canAdmin || user.canCreate);
            // confirm default personal repository permissions
            RepositoryModel model = GitBlit.self().getRepositoryModel(MessageFormat.format("~{0}/ticgit.git", user.username));
            RepositoryModel model = repositories().getRepositoryModel(MessageFormat.format("~{0}/ticgit.git", user.username));
            assertEquals("Unexpected owner", user.username, ArrayUtils.toString(model.owners));
            assertEquals("Unexpected authorization control", AuthorizationControl.NAMED, model.authorizationControl);
            assertEquals("Unexpected access restriction", AccessRestrictionType.VIEW, model.accessRestriction);
@@ -909,10 +904,10 @@
            assertTrue("User canAdmin:" + user.canAdmin, user.canAdmin);
            // confirm default project repository permissions
            RepositoryModel model = GitBlit.self().getRepositoryModel("project/ticgit.git");
            RepositoryModel model = repositories().getRepositoryModel("project/ticgit.git");
            assertEquals("Unexpected owner", user.username, ArrayUtils.toString(model.owners));
            assertEquals("Unexpected authorization control", AuthorizationControl.fromName(GitBlit.getString(Keys.git.defaultAuthorizationControl, "NAMED")), model.authorizationControl);
            assertEquals("Unexpected access restriction", AccessRestrictionType.fromName(GitBlit.getString(Keys.git.defaultAccessRestriction, "NONE")), model.accessRestriction);
            assertEquals("Unexpected authorization control", AuthorizationControl.fromName(settings().getString(Keys.git.defaultAuthorizationControl, "NAMED")), model.authorizationControl);
            assertEquals("Unexpected access restriction", AccessRestrictionType.fromName(settings().getString(Keys.git.defaultAccessRestriction, "NONE")), model.accessRestriction);
        } catch (GitAPIException e) {
            assertTrue(e.getMessage(), e.getMessage().contains("git-receive-pack not found"));
src/test/java/com/gitblit/tests/GitblitUnitTest.java
New file
@@ -0,0 +1,67 @@
/*
 * 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.tests;
import com.gitblit.GitBlit;
import com.gitblit.IStoredSettings;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IGitblitManager;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.ISessionManager;
import com.gitblit.manager.IUserManager;
public class GitblitUnitTest extends org.junit.Assert {
    public static IStoredSettings settings() {
        return runtime().getSettings();
    }
    public static IRuntimeManager runtime() {
        return GitBlit.getManager(IRuntimeManager.class);
    }
    public static INotificationManager notifier() {
        return GitBlit.getManager(INotificationManager.class);
    }
    public static IUserManager users() {
        return GitBlit.getManager(IUserManager.class);
    }
    public static ISessionManager session() {
        return GitBlit.getManager(ISessionManager.class);
    }
    public static IRepositoryManager repositories() {
        return GitBlit.getManager(IRepositoryManager.class);
    }
    public static IProjectManager projects() {
        return GitBlit.getManager(IProjectManager.class);
    }
    public static IFederationManager federation() {
        return GitBlit.getManager(IFederationManager.class);
    }
    public static IGitblitManager gitblit() {
        return GitBlit.getManager(IGitblitManager.class);
    }
}
src/test/java/com/gitblit/tests/GroovyScriptTest.java
@@ -15,8 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;
@@ -41,7 +39,6 @@
import org.junit.BeforeClass;
import org.junit.Test;
import com.gitblit.GitBlit;
import com.gitblit.GitBlitException;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TeamModel;
@@ -54,7 +51,7 @@
 * @author James Moger
 *
 */
public class GroovyScriptTest {
public class GroovyScriptTest extends GitblitUnitTest {
    private static final AtomicBoolean started = new AtomicBoolean(false);
@@ -83,7 +80,7 @@
                .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId
                .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master2"));
        RepositoryModel repository = GitBlit.self().getRepositoryModel("helloworld.git");
        RepositoryModel repository = repositories().getRepositoryModel("helloworld.git");
        repository.customFields = new HashMap<String,String>();
        repository.customFields.put( "fogbugzUrl", "http://bugs.test.com" );
        repository.customFields.put( "fogbugzRepositoryId", "1" );
@@ -105,7 +102,7 @@
                .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId
                .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master2"));
        RepositoryModel repository = GitBlit.self().getRepositoryModel("helloworld.git");
        RepositoryModel repository = repositories().getRepositoryModel("helloworld.git");
        repository.mailingLists.add("list@helloworld.git");
        test("sendmail-html.groovy", gitblit, logger, clientLogger, commands, repository);
@@ -130,7 +127,7 @@
                .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId
                .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master2"));
        RepositoryModel repository = GitBlit.self().getRepositoryModel("helloworld.git");
        RepositoryModel repository = repositories().getRepositoryModel("helloworld.git");
        repository.mailingLists.add("list@helloworld.git");
        test("sendmail.groovy", gitblit, logger, clientLogger, commands, repository);
@@ -270,7 +267,7 @@
        RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date());
        File groovyDir = GitBlit.getGroovyScriptsFolder();
        File groovyDir = repositories().getHooksFolder();
        File tempScript = File.createTempFile("testClientLogging", "groovy", groovyDir);
        tempScript.deleteOnExit();
@@ -291,7 +288,7 @@
        String gitblitUrl = GitBlitSuite.url;
        File groovyDir = GitBlit.getGroovyScriptsFolder();
        File groovyDir = repositories().getHooksFolder();
        GroovyScriptEngine gse = new GroovyScriptEngine(groovyDir.getAbsolutePath());
        Binding binding = new Binding();
src/test/java/com/gitblit/tests/HtpasswdUserServiceTest.java
@@ -15,12 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
@@ -40,7 +34,7 @@
 * Test the Htpasswd user service.
 *
 */
public class HtpasswdUserServiceTest {
public class HtpasswdUserServiceTest extends GitblitUnitTest {
    private static final String RESOURCE_DIR = "src/test/resources/htpasswdUSTest/";
    private static final String KEY_SUPPORT_PLAINTEXT_PWD = "realm.htpasswd.supportPlaintextPasswords";
src/test/java/com/gitblit/tests/Issue0259Test.java
@@ -17,7 +17,6 @@
import java.io.File;
import org.junit.Assert;
import org.junit.Test;
import com.gitblit.ConfigUserService;
@@ -40,7 +39,7 @@
 * @author James Moger
 *
 */
public class Issue0259Test extends Assert {
public class Issue0259Test extends GitblitUnitTest {
    RepositoryModel repo(String name, AccessRestrictionType restriction) {
        RepositoryModel repo = new RepositoryModel();
src/test/java/com/gitblit/tests/Issue0271Test.java
@@ -17,7 +17,6 @@
import java.io.File;
import org.junit.Assert;
import org.junit.Test;
import com.gitblit.ConfigUserService;
@@ -37,7 +36,7 @@
 * @author James Moger
 *
 */
public class Issue0271Test extends Assert {
public class Issue0271Test extends GitblitUnitTest {
    RepositoryModel repo(String name, AccessRestrictionType restriction) {
        RepositoryModel repo = new RepositoryModel();
src/test/java/com/gitblit/tests/JGitUtilsTest.java
@@ -15,12 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
@@ -57,7 +51,7 @@
import com.gitblit.utils.JnaUtils;
import com.gitblit.utils.StringUtils;
public class JGitUtilsTest {
public class JGitUtilsTest extends GitblitUnitTest {
    @Test
    public void testDisplayName() throws Exception {
src/test/java/com/gitblit/tests/JnaUtilsTest.java
@@ -15,10 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
@@ -36,7 +32,7 @@
 *
 * @author Florian Zschocke
 */
public class JnaUtilsTest {
public class JnaUtilsTest extends GitblitUnitTest {
    @Test
    public void testGetgid() {
src/test/java/com/gitblit/tests/JsonUtilsTest.java
@@ -15,8 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
@@ -27,7 +25,7 @@
import com.gitblit.utils.JsonUtils;
import com.google.gson.reflect.TypeToken;
public class JsonUtilsTest {
public class JsonUtilsTest extends GitblitUnitTest {
    @Test
    public void testSerialization() {
src/test/java/com/gitblit/tests/LdapUserServiceTest.java
@@ -16,11 +16,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.HashMap;
import java.util.Map;
@@ -44,7 +39,7 @@
 * @author jcrygier
 *
 */
public class LdapUserServiceTest {
public class LdapUserServiceTest extends GitblitUnitTest {
    private LdapUserService ldapUserService;
src/test/java/com/gitblit/tests/LuceneExecutorTest.java
@@ -15,10 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -43,7 +39,7 @@
 * @author James Moger
 *
 */
public class LuceneExecutorTest {
public class LuceneExecutorTest extends GitblitUnitTest {
    LuceneExecutor lucene;
src/test/java/com/gitblit/tests/MailTest.java
@@ -15,8 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertTrue;
import javax.mail.Message;
import org.junit.Test;
@@ -25,7 +23,7 @@
import com.gitblit.Keys;
import com.gitblit.MailExecutor;
public class MailTest {
public class MailTest extends GitblitUnitTest {
    @Test
    public void testSendMail() throws Exception {
src/test/java/com/gitblit/tests/MarkdownUtilsTest.java
@@ -15,13 +15,11 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.gitblit.utils.MarkdownUtils;
public class MarkdownUtilsTest {
public class MarkdownUtilsTest extends GitblitUnitTest {
    @Test
    public void testMarkdown() throws Exception {
src/test/java/com/gitblit/tests/MetricUtilsTest.java
@@ -15,9 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.TimeZone;
@@ -27,7 +24,7 @@
import com.gitblit.models.Metric;
import com.gitblit.utils.MetricUtils;
public class MetricUtilsTest {
public class MetricUtilsTest extends GitblitUnitTest {
    @Test
    public void testMetrics() throws Exception {
src/test/java/com/gitblit/tests/ModelUtilsTest.java
@@ -1,16 +1,12 @@
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Test;
import com.gitblit.Constants;
import com.gitblit.utils.ModelUtils;
public class ModelUtilsTest {
public class ModelUtilsTest extends GitblitUnitTest {
    @After
    public void resetPrefix()
src/test/java/com/gitblit/tests/ObjectCacheTest.java
@@ -15,17 +15,13 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Date;
import org.junit.Test;
import com.gitblit.utils.ObjectCache;
public class ObjectCacheTest {
public class ObjectCacheTest extends GitblitUnitTest {
    @Test
    public void testCache() throws Exception {
src/test/java/com/gitblit/tests/PermissionsTest.java
@@ -17,7 +17,6 @@
import java.util.Date;
import org.junit.Assert;
import org.junit.Test;
import com.gitblit.Constants.AccessPermission;
@@ -33,7 +32,7 @@
 * @author James Moger
 *
 */
public class PermissionsTest extends Assert {
public class PermissionsTest extends GitblitUnitTest {
    /**
     * Admin access rights/permissions
src/test/java/com/gitblit/tests/PushLogTest.java
@@ -28,7 +28,7 @@
import com.gitblit.models.RefLogEntry;
import com.gitblit.utils.RefLogUtils;
public class PushLogTest {
public class PushLogTest extends GitblitUnitTest {
    @Test
    public void testPushLog() throws IOException {
src/test/java/com/gitblit/tests/RedmineUserServiceTest.java
@@ -1,10 +1,6 @@
package com.gitblit.tests;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.HashMap;
@@ -15,7 +11,7 @@
import com.gitblit.tests.mock.MemorySettings;
import com.gitblit.utils.StringUtils;
public class RedmineUserServiceTest {
public class RedmineUserServiceTest extends GitblitUnitTest {
    private static final String JSON = "{\"user\":{\"created_on\":\"2011-03-28T00:41:29Z\",\"lastname\":\"foo\","
        + "\"last_login_on\":\"2012-09-06T23:59:26Z\",\"firstname\":\"baz\","
src/test/java/com/gitblit/tests/RepositoryModelTest.java
@@ -16,8 +16,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.junit.After;
@@ -27,10 +25,9 @@
import org.junit.Test;
import com.gitblit.Constants;
import com.gitblit.GitBlit;
import com.gitblit.models.RepositoryModel;
public class RepositoryModelTest {
public class RepositoryModelTest extends GitblitUnitTest {
    private static boolean wasStarted = false;
@@ -68,7 +65,7 @@
    @Test
    public void testGetCustomProperty() throws Exception {
        RepositoryModel model = GitBlit.self().getRepositoryModel(
        RepositoryModel model = repositories().getRepositoryModel(
                GitBlitSuite.getHelloworldRepository().getDirectory().getName());
        assertEquals("\\d", model.customFields.get("commitMessageRegEx"));
@@ -77,16 +74,16 @@
    @Test
    public void testSetCustomProperty() throws Exception {
        RepositoryModel model = GitBlit.self().getRepositoryModel(
        RepositoryModel model = repositories().getRepositoryModel(
                GitBlitSuite.getHelloworldRepository().getDirectory().getName());
        assertEquals("\\d", model.customFields.get("commitMessageRegEx"));
        assertEquals("Hello", model.customFields.get("anotherProperty"));
        assertEquals("Hello", model.customFields.put("anotherProperty", "GoodBye"));
        GitBlit.self().updateRepositoryModel(model.name, model, false);
        repositories().updateRepositoryModel(model.name, model, false);
        model = GitBlit.self().getRepositoryModel(
        model = repositories().getRepositoryModel(
                GitBlitSuite.getHelloworldRepository().getDirectory().getName());
        assertEquals("\\d", model.customFields.get("commitMessageRegEx"));
src/test/java/com/gitblit/tests/RpcTests.java
@@ -15,11 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@@ -58,7 +53,7 @@
 * @author James Moger
 *
 */
public class RpcTests {
public class RpcTests extends GitblitUnitTest {
    String url = GitBlitSuite.url;
    String account = GitBlitSuite.account;
src/test/java/com/gitblit/tests/StringUtilsTest.java
@@ -15,10 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
@@ -26,7 +22,7 @@
import com.gitblit.utils.StringUtils;
public class StringUtilsTest {
public class StringUtilsTest extends GitblitUnitTest {
    @Test
    public void testIsEmpty() throws Exception {
src/test/java/com/gitblit/tests/SyndicationUtilsTest.java
@@ -15,9 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Date;
@@ -31,7 +28,7 @@
import com.gitblit.models.FeedEntryModel;
import com.gitblit.utils.SyndicationUtils;
public class SyndicationUtilsTest {
public class SyndicationUtilsTest extends GitblitUnitTest {
    @Test
    public void testSyndication() throws Exception {
src/test/java/com/gitblit/tests/TimeUtilsTest.java
@@ -15,16 +15,13 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Date;
import org.junit.Test;
import com.gitblit.utils.TimeUtils;
public class TimeUtilsTest {
public class TimeUtilsTest extends GitblitUnitTest {
    private Date offset(long subtract) {
        return new Date(System.currentTimeMillis() - subtract);
src/test/java/com/gitblit/tests/UserServiceTest.java
@@ -15,10 +15,6 @@
 */
package com.gitblit.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
@@ -31,7 +27,7 @@
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
public class UserServiceTest {
public class UserServiceTest extends GitblitUnitTest {
    @Test
    public void testConfigUserService() throws IOException {
src/test/java/com/gitblit/tests/X509UtilsTest.java
@@ -26,7 +26,6 @@
import org.eclipse.jgit.util.FileUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -43,7 +42,7 @@
 * @author James Moger
 *
 */
public class X509UtilsTest extends Assert {
public class X509UtilsTest extends GitblitUnitTest {
    // passwords are case-sensitive and may be length-limited
    // based on the JCE policy files
src/test/java/de/akquinet/devops/GitBlit4UITests.java
@@ -9,6 +9,7 @@
    private boolean luceneIndexingEnabled;
    public GitBlit4UITests(boolean luceneIndexingEnabled) {
        super(null);
        this.luceneIndexingEnabled = luceneIndexingEnabled;
    }
@@ -21,5 +22,5 @@
                    .info("Lucene executor is scheduled to process indexed branches every 2 minutes.");
        }
    }
}
src/test/java/de/akquinet/devops/GitBlitServer4UITests.java
@@ -1,5 +1,6 @@
package de.akquinet.devops;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@@ -7,6 +8,8 @@
import com.beust.jcommander.ParameterException;
import com.gitblit.GitBlit;
import com.gitblit.GitBlitServer;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
public class GitBlitServer4UITests extends GitBlitServer {
@@ -50,13 +53,9 @@
        }
    }
    private GitBlit4UITests instance;
    @Override
    protected GitBlit getGitBlitInstance() {
        if (instance == null) {
            instance = new GitBlit4UITests(false);
        }
        return instance;
    protected GitBlit newGitblit(IStoredSettings settings, File baseFolder) {
        settings.overrideSetting(Keys.web.allowLuceneIndexing, false);
        return new GitBlit(settings, baseFolder);
    }
}