src/main/java/com/gitblit/DaggerModule.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/GitBlit.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/manager/IProjectManager.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/manager/ProjectManager.java | ●●●●● patch | view | raw | blame | history |
src/main/java/com/gitblit/DaggerModule.java
@@ -29,6 +29,7 @@ import com.gitblit.manager.ISessionManager; import com.gitblit.manager.IUserManager; import com.gitblit.manager.NotificationManager; import com.gitblit.manager.ProjectManager; import com.gitblit.manager.RepositoryManager; import com.gitblit.manager.RuntimeManager; import com.gitblit.manager.SessionManager; @@ -125,8 +126,15 @@ userManager); } @Provides @Singleton IProjectManager provideProjectManager() { return gitblit; @Provides @Singleton IProjectManager provideProjectManager( IRuntimeManager runtimeManager, IUserManager userManager, IRepositoryManager repositoryManager) { return new ProjectManager( runtimeManager, userManager, repositoryManager); } @Provides @Singleton IGitblitManager provideGitblitManager() { src/main/java/com/gitblit/GitBlit.java
@@ -32,10 +32,8 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -50,8 +48,6 @@ import org.apache.wicket.resource.ContextRelativeResource; import org.apache.wicket.util.resource.ResourceStreamNotFoundException; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; import org.slf4j.Logger; import com.gitblit.Constants.AccessPermission; @@ -77,7 +73,6 @@ import com.gitblit.models.FederationProposal; import com.gitblit.models.FederationSet; import com.gitblit.models.GitClientApplication; import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.RepositoryUrl; import com.gitblit.models.ServerSettings; @@ -86,12 +81,10 @@ import com.gitblit.models.UserModel; import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.ContainerUtils; import com.gitblit.utils.DeepCopier; import com.gitblit.utils.FederationUtils; import com.gitblit.utils.HttpUtils; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.JsonUtils; import com.gitblit.utils.ModelUtils; import com.gitblit.utils.ObjectCache; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitblitWicketFilter; @@ -117,8 +110,7 @@ */ @WebListener public class GitBlit extends DaggerContextListener implements IProjectManager, IFederationManager, implements IFederationManager, IGitblitManager { private static GitBlit gitblit; @@ -138,15 +130,7 @@ private final Map<String, FederationModel> federationPullResults = new ConcurrentHashMap<String, FederationModel>(); private final Map<String, ProjectModel> projectCache = new ConcurrentHashMap<String, ProjectModel>(); private final ObjectCache<String> projectMarkdownCache = new ObjectCache<String>(); private final ObjectCache<String> projectRepositoriesMarkdownCache = new ObjectCache<String>(); private IStoredSettings settings; private FileBasedConfig projectConfigs; private FanoutService fanoutService; @@ -442,237 +426,6 @@ } } private void reloadProjectMarkdown(ProjectModel project) { // project markdown File pmkd = new File(getManager(IRepositoryManager.class).getRepositoriesFolder(), (project.isRoot ? "" : project.name) + "/project.mkd"); if (pmkd.exists()) { Date lm = new Date(pmkd.lastModified()); if (!projectMarkdownCache.hasCurrent(project.name, lm)) { String mkd = com.gitblit.utils.FileUtils.readContent(pmkd, "\n"); projectMarkdownCache.updateObject(project.name, lm, mkd); } project.projectMarkdown = projectMarkdownCache.getObject(project.name); } // project repositories markdown File rmkd = new File(getManager(IRepositoryManager.class).getRepositoriesFolder(), (project.isRoot ? "" : project.name) + "/repositories.mkd"); if (rmkd.exists()) { Date lm = new Date(rmkd.lastModified()); if (!projectRepositoriesMarkdownCache.hasCurrent(project.name, lm)) { String mkd = com.gitblit.utils.FileUtils.readContent(rmkd, "\n"); projectRepositoriesMarkdownCache.updateObject(project.name, lm, mkd); } project.repositoriesMarkdown = projectRepositoriesMarkdownCache.getObject(project.name); } } /** * Returns the map of project config. This map is cached and reloaded if * the underlying projects.conf file changes. * * @return project config map */ private Map<String, ProjectModel> getProjectConfigs() { if (projectCache.isEmpty() || projectConfigs.isOutdated()) { try { projectConfigs.load(); } catch (Exception e) { } // project configs String rootName = settings.getString(Keys.web.repositoryRootGroupName, "main"); ProjectModel rootProject = new ProjectModel(rootName, true); Map<String, ProjectModel> configs = new HashMap<String, ProjectModel>(); // cache the root project under its alias and an empty path configs.put("", rootProject); configs.put(rootProject.name.toLowerCase(), rootProject); for (String name : projectConfigs.getSubsections("project")) { ProjectModel project; if (name.equalsIgnoreCase(rootName)) { project = rootProject; } else { project = new ProjectModel(name); } project.title = projectConfigs.getString("project", name, "title"); project.description = projectConfigs.getString("project", name, "description"); reloadProjectMarkdown(project); configs.put(name.toLowerCase(), project); } projectCache.clear(); projectCache.putAll(configs); } return projectCache; } /** * Returns a list of project models for the user. * * @param user * @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(); // per-user project lists, this accounts for security and visibility Map<String, ProjectModel> map = new TreeMap<String, ProjectModel>(); // root project map.put("", configs.get("")); for (RepositoryModel model : getManager(IRepositoryManager.class).getRepositoryModels(user)) { String rootPath = StringUtils.getRootPath(model.name).toLowerCase(); if (!map.containsKey(rootPath)) { ProjectModel project; if (configs.containsKey(rootPath)) { // clone the project model because it's repository list will // be tailored for the requesting user project = DeepCopier.copy(configs.get(rootPath)); } else { project = new ProjectModel(rootPath); } map.put(rootPath, project); } map.get(rootPath).addRepository(model); } // sort projects, root project first List<ProjectModel> projects; if (includeUsers) { // all projects projects = new ArrayList<ProjectModel>(map.values()); Collections.sort(projects); projects.remove(map.get("")); projects.add(0, map.get("")); } else { // all non-user projects projects = new ArrayList<ProjectModel>(); ProjectModel root = map.remove(""); for (ProjectModel model : map.values()) { if (!model.isUserProject()) { projects.add(model); } } Collections.sort(projects); projects.add(0, root); } return projects; } /** * Returns the project model for the specified user. * * @param name * @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)) { return project; } } return null; } /** * 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 */ @Override public ProjectModel getProjectModel(String name) { Map<String, ProjectModel> configs = getProjectConfigs(); ProjectModel project = configs.get(name.toLowerCase()); if (project == null) { project = new ProjectModel(name); if (ModelUtils.isPersonalRepository(name)) { UserModel user = getManager(IUserManager.class).getUserModel(ModelUtils.getUserNameFromRepoPath(name)); if (user != null) { project.title = user.getDisplayName(); project.description = "personal repositories"; } } } else { // clone the object project = DeepCopier.copy(project); } if (StringUtils.isEmpty(name)) { // get root repositories for (String repository : getManager(IRepositoryManager.class).getRepositoryList()) { if (repository.indexOf('/') == -1) { project.addRepository(repository); } } } else { // get repositories in subfolder String folder = name.toLowerCase() + "/"; for (String repository : getManager(IRepositoryManager.class).getRepositoryList()) { if (repository.toLowerCase().startsWith(folder)) { project.addRepository(repository); } } } if (project.repositories.size() == 0) { // no repositories == no project return null; } reloadProjectMarkdown(project); return project; } /** * 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 */ @Override public List<ProjectModel> getProjectModels(List<RepositoryModel> repositoryModels, boolean includeUsers) { Map<String, ProjectModel> projects = new LinkedHashMap<String, ProjectModel>(); for (RepositoryModel repository : repositoryModels) { if (!includeUsers && repository.isPersonalRepository()) { // exclude personal repositories continue; } if (!projects.containsKey(repository.projectPath)) { ProjectModel project = getProjectModel(repository.projectPath); if (project == null) { logger.warn(MessageFormat.format("excluding project \"{0}\" from project list because it is empty!", repository.projectPath)); continue; } projects.put(repository.projectPath, project); // clear the repo list in the project because that is the system // list, not the user-accessible list and start building the // user-accessible list project.repositories.clear(); project.repositories.add(repository.name); project.lastChange = repository.lastChange; } else { // update the user-accessible list // this is used for repository count ProjectModel project = projects.get(repository.projectPath); project.repositories.add(repository.name); if (project.lastChange.before(repository.lastChange)) { project.lastChange = repository.lastChange; } } } return new ArrayList<ProjectModel>(projects.values()); } /** * Returns Gitblit's scheduled executor service for scheduling tasks. @@ -1173,7 +926,7 @@ getManager(IUserManager.class), getManager(ISessionManager.class), getManager(IRepositoryManager.class), this, getManager(IProjectManager.class), this, this); gitDaemon = new GitDaemon(gitblit); @@ -1242,14 +995,11 @@ startManager(injector, IUserManager.class); startManager(injector, ISessionManager.class); startManager(injector, IRepositoryManager.class); startManager(injector, IProjectManager.class); logger.info("Gitblit base folder = " + baseFolder.getAbsolutePath()); loadSettingModels(runtime.getSettingsModel()); // load and cache the project metadata projectConfigs = new FileBasedConfig(runtime.getFileOrFolder(Keys.web.projectsFile, "${baseFolder}/projects.conf"), FS.detect()); getProjectConfigs(); if (true/*startFederation*/) { configureFederation(); src/main/java/com/gitblit/manager/IProjectManager.java
@@ -21,7 +21,7 @@ import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; public interface IProjectManager { public interface IProjectManager extends IManager { /** * Returns a list of project models for the user. src/main/java/com/gitblit/manager/ProjectManager.java
New file @@ -0,0 +1,327 @@ /* * 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.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.utils.DeepCopier; import com.gitblit.utils.ModelUtils; import com.gitblit.utils.ObjectCache; import com.gitblit.utils.StringUtils; /** * Project manager handles project-related functions. * * @author James Moger * */ public class ProjectManager implements IProjectManager { private final Logger logger = LoggerFactory.getLogger(getClass()); private final Map<String, ProjectModel> projectCache = new ConcurrentHashMap<String, ProjectModel>(); private final ObjectCache<String> projectMarkdownCache = new ObjectCache<String>(); private final ObjectCache<String> projectRepositoriesMarkdownCache = new ObjectCache<String>(); private final IStoredSettings settings; private final IRuntimeManager runtimeManager; private final IUserManager userManager; private final IRepositoryManager repositoryManager; private FileBasedConfig projectConfigs; public ProjectManager( IRuntimeManager runtimeManager, IUserManager userManager, IRepositoryManager repositoryManager) { this.settings = runtimeManager.getSettings(); this.runtimeManager = runtimeManager; this.userManager = userManager; this.repositoryManager = repositoryManager; } @Override public IManager setup() { // load and cache the project metadata projectConfigs = new FileBasedConfig(runtimeManager.getFileOrFolder(Keys.web.projectsFile, "${baseFolder}/projects.conf"), FS.detect()); getProjectConfigs(); return this; } @Override public IManager stop() { return this; } private void reloadProjectMarkdown(ProjectModel project) { // project markdown File pmkd = new File(repositoryManager.getRepositoriesFolder(), (project.isRoot ? "" : project.name) + "/project.mkd"); if (pmkd.exists()) { Date lm = new Date(pmkd.lastModified()); if (!projectMarkdownCache.hasCurrent(project.name, lm)) { String mkd = com.gitblit.utils.FileUtils.readContent(pmkd, "\n"); projectMarkdownCache.updateObject(project.name, lm, mkd); } project.projectMarkdown = projectMarkdownCache.getObject(project.name); } // project repositories markdown File rmkd = new File(repositoryManager.getRepositoriesFolder(), (project.isRoot ? "" : project.name) + "/repositories.mkd"); if (rmkd.exists()) { Date lm = new Date(rmkd.lastModified()); if (!projectRepositoriesMarkdownCache.hasCurrent(project.name, lm)) { String mkd = com.gitblit.utils.FileUtils.readContent(rmkd, "\n"); projectRepositoriesMarkdownCache.updateObject(project.name, lm, mkd); } project.repositoriesMarkdown = projectRepositoriesMarkdownCache.getObject(project.name); } } /** * Returns the map of project config. This map is cached and reloaded if * the underlying projects.conf file changes. * * @return project config map */ private Map<String, ProjectModel> getProjectConfigs() { if (projectCache.isEmpty() || projectConfigs.isOutdated()) { try { projectConfigs.load(); } catch (Exception e) { } // project configs String rootName = settings.getString(Keys.web.repositoryRootGroupName, "main"); ProjectModel rootProject = new ProjectModel(rootName, true); Map<String, ProjectModel> configs = new HashMap<String, ProjectModel>(); // cache the root project under its alias and an empty path configs.put("", rootProject); configs.put(rootProject.name.toLowerCase(), rootProject); for (String name : projectConfigs.getSubsections("project")) { ProjectModel project; if (name.equalsIgnoreCase(rootName)) { project = rootProject; } else { project = new ProjectModel(name); } project.title = projectConfigs.getString("project", name, "title"); project.description = projectConfigs.getString("project", name, "description"); reloadProjectMarkdown(project); configs.put(name.toLowerCase(), project); } projectCache.clear(); projectCache.putAll(configs); } return projectCache; } /** * Returns a list of project models for the user. * * @param user * @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(); // per-user project lists, this accounts for security and visibility Map<String, ProjectModel> map = new TreeMap<String, ProjectModel>(); // root project map.put("", configs.get("")); for (RepositoryModel model : repositoryManager.getRepositoryModels(user)) { String rootPath = StringUtils.getRootPath(model.name).toLowerCase(); if (!map.containsKey(rootPath)) { ProjectModel project; if (configs.containsKey(rootPath)) { // clone the project model because it's repository list will // be tailored for the requesting user project = DeepCopier.copy(configs.get(rootPath)); } else { project = new ProjectModel(rootPath); } map.put(rootPath, project); } map.get(rootPath).addRepository(model); } // sort projects, root project first List<ProjectModel> projects; if (includeUsers) { // all projects projects = new ArrayList<ProjectModel>(map.values()); Collections.sort(projects); projects.remove(map.get("")); projects.add(0, map.get("")); } else { // all non-user projects projects = new ArrayList<ProjectModel>(); ProjectModel root = map.remove(""); for (ProjectModel model : map.values()) { if (!model.isUserProject()) { projects.add(model); } } Collections.sort(projects); projects.add(0, root); } return projects; } /** * Returns the project model for the specified user. * * @param name * @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)) { return project; } } return null; } /** * 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 */ @Override public ProjectModel getProjectModel(String name) { Map<String, ProjectModel> configs = getProjectConfigs(); ProjectModel project = configs.get(name.toLowerCase()); if (project == null) { project = new ProjectModel(name); if (ModelUtils.isPersonalRepository(name)) { UserModel user = userManager.getUserModel(ModelUtils.getUserNameFromRepoPath(name)); if (user != null) { project.title = user.getDisplayName(); project.description = "personal repositories"; } } } else { // clone the object project = DeepCopier.copy(project); } if (StringUtils.isEmpty(name)) { // get root repositories for (String repository : repositoryManager.getRepositoryList()) { if (repository.indexOf('/') == -1) { project.addRepository(repository); } } } else { // get repositories in subfolder String folder = name.toLowerCase() + "/"; for (String repository : repositoryManager.getRepositoryList()) { if (repository.toLowerCase().startsWith(folder)) { project.addRepository(repository); } } } if (project.repositories.size() == 0) { // no repositories == no project return null; } reloadProjectMarkdown(project); return project; } /** * 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 */ @Override public List<ProjectModel> getProjectModels(List<RepositoryModel> repositoryModels, boolean includeUsers) { Map<String, ProjectModel> projects = new LinkedHashMap<String, ProjectModel>(); for (RepositoryModel repository : repositoryModels) { if (!includeUsers && repository.isPersonalRepository()) { // exclude personal repositories continue; } if (!projects.containsKey(repository.projectPath)) { ProjectModel project = getProjectModel(repository.projectPath); if (project == null) { logger.warn(MessageFormat.format("excluding project \"{0}\" from project list because it is empty!", repository.projectPath)); continue; } projects.put(repository.projectPath, project); // clear the repo list in the project because that is the system // list, not the user-accessible list and start building the // user-accessible list project.repositories.clear(); project.repositories.add(repository.name); project.lastChange = repository.lastChange; } else { // update the user-accessible list // this is used for repository count ProjectModel project = projects.get(repository.projectPath); project.repositories.add(repository.name); if (project.lastChange.before(repository.lastChange)) { project.lastChange = repository.lastChange; } } } return new ArrayList<ProjectModel>(projects.values()); } }