| | |
| | | import com.gitblit.GitBlitException; |
| | | import com.gitblit.IStoredSettings; |
| | | import com.gitblit.Keys; |
| | | import com.gitblit.extensions.RepositoryLifeCycleListener; |
| | | import com.gitblit.models.ForkModel; |
| | | import com.gitblit.models.Metric; |
| | | import com.gitblit.models.RefModel; |
| | |
| | | |
| | | private final IRuntimeManager runtimeManager; |
| | | |
| | | private final IPluginManager pluginManager; |
| | | |
| | | private final IUserManager userManager; |
| | | |
| | | private final File repositoriesFolder; |
| | |
| | | |
| | | public RepositoryManager( |
| | | IRuntimeManager runtimeManager, |
| | | IPluginManager pluginManager, |
| | | IUserManager userManager) { |
| | | |
| | | this.settings = runtimeManager.getSettings(); |
| | | this.runtimeManager = runtimeManager; |
| | | this.pluginManager = pluginManager; |
| | | this.userManager = userManager; |
| | | this.repositoriesFolder = runtimeManager.getFileOrFolder(Keys.git.repositoriesFolder, "${baseFolder}/git"); |
| | | } |
| | |
| | | |
| | | // update the fork origin repository with this repository clone |
| | | if (!StringUtils.isEmpty(model.originRepository)) { |
| | | if (repositoryListCache.containsKey(model.originRepository)) { |
| | | RepositoryModel origin = repositoryListCache.get(model.originRepository); |
| | | String originKey = model.originRepository.toLowerCase(); |
| | | if (repositoryListCache.containsKey(originKey)) { |
| | | RepositoryModel origin = repositoryListCache.get(originKey); |
| | | origin.addFork(model.name); |
| | | } |
| | | } |
| | |
| | | repositorySizeCache.remove(repositoryName); |
| | | repositoryMetricsCache.remove(repositoryName); |
| | | CommitCache.instance().clear(repositoryName); |
| | | } |
| | | |
| | | /** |
| | | * Reset all caches for this repository. |
| | | * |
| | | * @param repositoryName |
| | | * @since 1.5.1 |
| | | */ |
| | | @Override |
| | | public void resetRepositoryCache(String repositoryName) { |
| | | removeFromCachedRepositoryList(repositoryName); |
| | | clearRepositoryMetadataCache(repositoryName); |
| | | // force a reload of the repository data (ticket-82, issue-433) |
| | | getRepositoryModel(repositoryName); |
| | | } |
| | | |
| | | /** |
| | |
| | | // rebuild fork networks |
| | | for (RepositoryModel model : repositoryListCache.values()) { |
| | | if (!StringUtils.isEmpty(model.originRepository)) { |
| | | if (repositoryListCache.containsKey(model.originRepository)) { |
| | | RepositoryModel origin = repositoryListCache.get(model.originRepository); |
| | | String originKey = model.originRepository.toLowerCase(); |
| | | if (repositoryListCache.containsKey(originKey)) { |
| | | RepositoryModel origin = repositoryListCache.get(originKey); |
| | | origin.addFork(model.name); |
| | | } |
| | | } |
| | |
| | | // http://stackoverflow.com/questions/17183110 |
| | | repositoryName = repositoryName.replace("%7E", "~").replace("%7e", "~"); |
| | | |
| | | if (!repositoryListCache.containsKey(repositoryName)) { |
| | | String repositoryKey = repositoryName.toLowerCase(); |
| | | if (!repositoryListCache.containsKey(repositoryKey)) { |
| | | RepositoryModel model = loadRepositoryModel(repositoryName); |
| | | if (model == null) { |
| | | return null; |
| | |
| | | } |
| | | |
| | | // cached model |
| | | RepositoryModel model = repositoryListCache.get(repositoryName.toLowerCase()); |
| | | RepositoryModel model = repositoryListCache.get(repositoryKey); |
| | | |
| | | if (gcExecutor.isCollectingGarbage(model.name)) { |
| | | // Gitblit is busy collecting garbage, use our cached model |
| | |
| | | */ |
| | | @Override |
| | | public String getFork(String username, String origin) { |
| | | if (StringUtils.isEmpty(origin)) { |
| | | return null; |
| | | } |
| | | String userProject = ModelUtils.getPersonalPath(username); |
| | | if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { |
| | | String originKey = origin.toLowerCase(); |
| | | String userPath = userProject + "/"; |
| | | |
| | | // collect all origin nodes in fork network |
| | | Set<String> roots = new HashSet<String>(); |
| | | roots.add(origin); |
| | | RepositoryModel originModel = repositoryListCache.get(origin); |
| | | roots.add(originKey); |
| | | RepositoryModel originModel = repositoryListCache.get(originKey); |
| | | while (originModel != null) { |
| | | if (!ArrayUtils.isEmpty(originModel.forks)) { |
| | | for (String fork : originModel.forks) { |
| | | if (!fork.startsWith(userPath)) { |
| | | roots.add(fork); |
| | | roots.add(fork.toLowerCase()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (originModel.originRepository != null) { |
| | | roots.add(originModel.originRepository); |
| | | originModel = repositoryListCache.get(originModel.originRepository); |
| | | String ooKey = originModel.originRepository.toLowerCase(); |
| | | roots.add(ooKey); |
| | | originModel = repositoryListCache.get(ooKey); |
| | | } else { |
| | | // break |
| | | originModel = null; |
| | |
| | | if (repository.startsWith(userPath)) { |
| | | RepositoryModel model = repositoryListCache.get(repository); |
| | | if (!StringUtils.isEmpty(model.originRepository)) { |
| | | if (roots.contains(model.originRepository)) { |
| | | if (roots.contains(model.originRepository.toLowerCase())) { |
| | | // user has a fork in this graph |
| | | return model.name; |
| | | } |
| | |
| | | // find the root, cached |
| | | RepositoryModel model = repositoryListCache.get(repository.toLowerCase()); |
| | | while (model.originRepository != null) { |
| | | model = repositoryListCache.get(model.originRepository); |
| | | model = repositoryListCache.get(model.originRepository.toLowerCase()); |
| | | } |
| | | ForkModel root = getForkModelFromCache(model.name); |
| | | return root; |
| | |
| | | |
| | | // update this repository's origin's fork list |
| | | if (!StringUtils.isEmpty(repository.originRepository)) { |
| | | RepositoryModel origin = repositoryListCache.get(repository.originRepository); |
| | | RepositoryModel origin = repositoryListCache.get(repository.originRepository.toLowerCase()); |
| | | if (origin != null && !ArrayUtils.isEmpty(origin.forks)) { |
| | | origin.forks.remove(repositoryName); |
| | | origin.forks.add(repository.name); |
| | |
| | | removeFromCachedRepositoryList(repositoryName); |
| | | // model will actually be replaced on next load because config is stale |
| | | addToCachedRepositoryList(repository); |
| | | |
| | | if (isCreate && pluginManager != null) { |
| | | for (RepositoryLifeCycleListener listener : pluginManager.getExtensions(RepositoryLifeCycleListener.class)) { |
| | | try { |
| | | listener.onCreation(repository); |
| | | } catch (Throwable t) { |
| | | logger.error(String.format("failed to call plugin onCreation %s", repositoryName), t); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns true if the repository can be deleted. |
| | | * |
| | | * @return true if the repository can be deleted |
| | | */ |
| | | @Override |
| | | public boolean canDelete(RepositoryModel repository) { |
| | | return settings.getBoolean(Keys.web.allowDeletingNonEmptyRepositories, true) |
| | | || !repository.hasCommits; |
| | | } |
| | | |
| | | /** |
| | | * Deletes the repository from the file system and removes the repository |
| | | * permission from all repository users. |
| | | * |
| | |
| | | */ |
| | | @Override |
| | | public boolean deleteRepository(String repositoryName) { |
| | | RepositoryModel repository = getRepositoryModel(repositoryName); |
| | | if (!canDelete(repository)) { |
| | | logger.warn("Attempt to delete {} rejected!", repositoryName); |
| | | return false; |
| | | } |
| | | |
| | | try { |
| | | close(repositoryName); |
| | | // clear the repository cache |
| | |
| | | FileUtils.delete(folder, FileUtils.RECURSIVE | FileUtils.RETRY); |
| | | if (userManager.deleteRepositoryRole(repositoryName)) { |
| | | logger.info(MessageFormat.format("Repository \"{0}\" deleted", repositoryName)); |
| | | |
| | | if (pluginManager != null) { |
| | | for (RepositoryLifeCycleListener listener : pluginManager.getExtensions(RepositoryLifeCycleListener.class)) { |
| | | try { |
| | | listener.onDeletion(repository); |
| | | } catch (Throwable t) { |
| | | logger.error(String.format("failed to call plugin onDeletion %s", repositoryName), t); |
| | | } |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | } |