| | |
| | | |
| | | import com.gitblit.Constants.AccessPermission; |
| | | import com.gitblit.Constants.AccessRestrictionType; |
| | | import com.gitblit.Constants.AccountType; |
| | | import com.gitblit.Constants.AuthenticationType; |
| | | import com.gitblit.Constants.AuthorizationControl; |
| | | import com.gitblit.Constants.FederationRequest; |
| | |
| | | import com.gitblit.utils.FederationUtils; |
| | | import com.gitblit.utils.HttpUtils; |
| | | import com.gitblit.utils.JGitUtils; |
| | | import com.gitblit.utils.JGitUtils.LastChange; |
| | | import com.gitblit.utils.JsonUtils; |
| | | import com.gitblit.utils.MetricUtils; |
| | | import com.gitblit.utils.ModelUtils; |
| | | import com.gitblit.utils.ObjectCache; |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.utils.TimeUtils; |
| | |
| | | new GitBlit(); |
| | | } |
| | | return gitblit; |
| | | } |
| | | |
| | | /** |
| | | * Returns the boot date of the Gitblit server. |
| | | * |
| | | * @return the boot date of Gitblit |
| | | */ |
| | | public static Date getBootDate() { |
| | | return self().serverStatus.bootDate; |
| | | } |
| | | |
| | | /** |
| | | * Returns the most recent change date of any repository served by Gitblit. |
| | | * |
| | | * @return a date |
| | | */ |
| | | public static Date getLastActivityDate() { |
| | | Date date = null; |
| | | for (String name : self().getRepositoryList()) { |
| | | Repository r = self().getRepository(name); |
| | | Date lastChange = JGitUtils.getLastChange(r).when; |
| | | r.close(); |
| | | if (lastChange != null && (date == null || lastChange.after(date))) { |
| | | date = lastChange; |
| | | } |
| | | } |
| | | return date; |
| | | } |
| | | |
| | | /** |
| | |
| | | public boolean supportsCredentialChanges(UserModel user) { |
| | | if (user == null) { |
| | | return false; |
| | | } else if (!Constants.EXTERNAL_ACCOUNT.equals(user.password)) { |
| | | // credentials likely maintained by Gitblit |
| | | return userService.supportsCredentialChanges(); |
| | | } else if (AccountType.LOCAL.equals(user.accountType)) { |
| | | // local account, we can change credentials |
| | | return true; |
| | | } else { |
| | | // credentials are externally maintained |
| | | return false; |
| | | // external account, ask user service |
| | | return userService.supportsCredentialChanges(); |
| | | } |
| | | } |
| | | |
| | |
| | | // personal repository |
| | | model.addOwner(user.username); |
| | | String oldRepositoryName = model.name; |
| | | model.name = "~" + user.username + model.name.substring(model.projectPath.length()); |
| | | model.projectPath = "~" + user.username; |
| | | model.name = user.getPersonalPath() + model.name.substring(model.projectPath.length()); |
| | | model.projectPath = user.getPersonalPath(); |
| | | updateRepositoryModel(oldRepositoryName, model, false); |
| | | } else if (model.isOwner(username)) { |
| | | // common/shared repo |
| | |
| | | } else { |
| | | // we are caching this list |
| | | String msg = "{0} repositories identified in {1} msecs"; |
| | | |
| | | // optionally (re)calculate repository sizes |
| | | if (getBoolean(Keys.web.showRepositorySizes, true)) { |
| | | ByteFormat byteFormat = new ByteFormat(); |
| | | // optionally (re)calculate repository sizes |
| | | msg = "{0} repositories identified with calculated folder sizes in {1} msecs"; |
| | | for (String repository : repositories) { |
| | | RepositoryModel model = getRepositoryModel(repository); |
| | | if (!model.skipSizeCalculation) { |
| | | model.size = byteFormat.format(calculateSize(model)); |
| | | } |
| | | } |
| | | } else { |
| | | // update cache |
| | | for (String repository : repositories) { |
| | | getRepositoryModel(repository); |
| | | } |
| | | } |
| | | |
| | | for (String repository : repositories) { |
| | | getRepositoryModel(repository); |
| | | } |
| | | |
| | | // rebuild fork networks |
| | |
| | | * @return repository or null |
| | | */ |
| | | public Repository getRepository(String repositoryName, boolean logError) { |
| | | // Decode url-encoded repository name (issue-278) |
| | | // http://stackoverflow.com/questions/17183110 |
| | | repositoryName = repositoryName.replace("%7E", "~").replace("%7e", "~"); |
| | | |
| | | if (isCollectingGarbage(repositoryName)) { |
| | | logger.warn(MessageFormat.format("Rejecting request for {0}, busy collecting garbage!", repositoryName)); |
| | | return null; |
| | |
| | | } |
| | | } |
| | | } |
| | | if (getBoolean(Keys.web.showRepositorySizes, true)) { |
| | | int repoCount = 0; |
| | | long startTime = System.currentTimeMillis(); |
| | | ByteFormat byteFormat = new ByteFormat(); |
| | | for (RepositoryModel model : repositories) { |
| | | if (!model.skipSizeCalculation) { |
| | | repoCount++; |
| | | model.size = byteFormat.format(calculateSize(model)); |
| | | } |
| | | } |
| | | long duration = System.currentTimeMillis() - startTime; |
| | | if (duration > 250) { |
| | | // only log calcualtion time if > 250 msecs |
| | | logger.info(MessageFormat.format("{0} repository sizes calculated in {1} msecs", |
| | | repoCount, duration)); |
| | | } |
| | | } |
| | | long duration = System.currentTimeMillis() - methodStart; |
| | | logger.info(MessageFormat.format("{0} repository models loaded for {1} in {2} msecs", |
| | | repositories.size(), user == null ? "anonymous" : user.username, duration)); |
| | |
| | | * @return repository model or null |
| | | */ |
| | | public RepositoryModel getRepositoryModel(String repositoryName) { |
| | | // Decode url-encoded repository name (issue-278) |
| | | // http://stackoverflow.com/questions/17183110 |
| | | repositoryName = repositoryName.replace("%7E", "~").replace("%7e", "~"); |
| | | |
| | | if (!repositoryListCache.containsKey(repositoryName)) { |
| | | RepositoryModel model = loadRepositoryModel(repositoryName); |
| | | if (model == null) { |
| | | return null; |
| | | } |
| | | addToCachedRepositoryList(model); |
| | | return model; |
| | | return DeepCopier.copy(model); |
| | | } |
| | | |
| | | // cached model |
| | |
| | | model.hasCommits = JGitUtils.hasCommits(r); |
| | | } |
| | | |
| | | model.lastChange = JGitUtils.getLastChange(r); |
| | | if (!model.skipSizeCalculation) { |
| | | ByteFormat byteFormat = new ByteFormat(); |
| | | model.size = byteFormat.format(calculateSize(model)); |
| | | } |
| | | updateLastChangeFields(r, model); |
| | | } |
| | | r.close(); |
| | | |
| | |
| | | ProjectModel project = configs.get(name.toLowerCase()); |
| | | if (project == null) { |
| | | project = new ProjectModel(name); |
| | | if (name.length() > 0 && name.charAt(0) == '~') { |
| | | UserModel user = getUserModel(name.substring(1)); |
| | | if (ModelUtils.isPersonalRepository(name)) { |
| | | UserModel user = getUserModel(ModelUtils.getUserNameFromRepoPath(name)); |
| | | if (user != null) { |
| | | project.title = user.getDisplayName(); |
| | | project.description = "personal repositories"; |
| | |
| | | // is symlinked. Use the provided repository name. |
| | | model.name = repositoryName; |
| | | } |
| | | model.hasCommits = JGitUtils.hasCommits(r); |
| | | model.lastChange = JGitUtils.getLastChange(r); |
| | | model.projectPath = StringUtils.getFirstPathElement(repositoryName); |
| | | |
| | | StoredConfig config = r.getConfig(); |
| | | boolean hasOrigin = !StringUtils.isEmpty(config.getString("remote", "origin", "url")); |
| | | |
| | | if (config != null) { |
| | | // Initialize description from description file |
| | | if (getConfig(config,"description", null) == null) { |
| | | File descFile = new File(r.getDirectory(), "description"); |
| | | if (descFile.exists()) { |
| | | config.setString(Constants.CONFIG_GITBLIT, null, "description", |
| | | com.gitblit.utils.FileUtils.readContent(descFile, System.getProperty("line.separator"))); |
| | | } |
| | | } |
| | | model.description = getConfig(config, "description", ""); |
| | | model.originRepository = getConfig(config, "originRepository", null); |
| | | model.addOwners(ArrayUtils.fromString(getConfig(config, "owner", ""))); |
| | |
| | | model.HEAD = JGitUtils.getHEADRef(r); |
| | | model.availableRefs = JGitUtils.getAvailableHeadTargets(r); |
| | | model.sparkleshareId = JGitUtils.getSparkleshareId(r); |
| | | model.hasCommits = JGitUtils.hasCommits(r); |
| | | updateLastChangeFields(r, model); |
| | | r.close(); |
| | | |
| | | if (StringUtils.isEmpty(model.originRepository) && model.origin != null && model.origin.startsWith("file://")) { |
| | |
| | | File repoFolder = new File(getRepositoriesFolder(), originRepo); |
| | | if (repoFolder.exists()) { |
| | | model.originRepository = originRepo.toLowerCase(); |
| | | |
| | | // persist the fork origin |
| | | updateConfiguration(r, model); |
| | | } |
| | | } |
| | | } catch (URISyntaxException e) { |
| | |
| | | * @return the name of the user's fork, null otherwise |
| | | */ |
| | | public String getFork(String username, String origin) { |
| | | String userProject = "~" + username.toLowerCase(); |
| | | String userProject = ModelUtils.getPersonalPath(username); |
| | | if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { |
| | | String userPath = userProject + "/"; |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns the size in bytes 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. |
| | | * 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 |
| | | * @return size in bytes of the repository |
| | | */ |
| | | public long calculateSize(RepositoryModel model) { |
| | | if (repositorySizeCache.hasCurrent(model.name, model.lastChange)) { |
| | | return repositorySizeCache.getObject(model.name); |
| | | 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) { |
| | | model.size = null; |
| | | return 0L; |
| | | } |
| | | File gitDir = FileKey.resolve(new File(repositoriesFolder, model.name), FS.DETECTED); |
| | | long size = com.gitblit.utils.FileUtils.folderSize(gitDir); |
| | | repositorySizeCache.updateObject(model.name, model.lastChange, size); |
| | | if (!repositorySizeCache.hasCurrent(model.name, model.lastChange)) { |
| | | File gitDir = r.getDirectory(); |
| | | long sz = com.gitblit.utils.FileUtils.folderSize(gitDir); |
| | | repositorySizeCache.updateObject(model.name, model.lastChange, sz); |
| | | } |
| | | long size = repositorySizeCache.getObject(model.name); |
| | | ByteFormat byteFormat = new ByteFormat(); |
| | | model.size = byteFormat.format(size); |
| | | return size; |
| | | } |
| | | |
| | |
| | | // update settings |
| | | if (r != null) { |
| | | updateConfiguration(r, repository); |
| | | // Update the description file |
| | | File descFile = new File(r.getDirectory(), "description"); |
| | | if (repository.description != null) |
| | | { |
| | | com.gitblit.utils.FileUtils.writeContent(descFile, repository.description); |
| | | } |
| | | else if (descFile.exists() && !descFile.isDirectory()) { |
| | | descFile.delete(); |
| | | } |
| | | // only update symbolic head if it changes |
| | | String currentRef = JGitUtils.getHEADRef(r); |
| | | if (!StringUtils.isEmpty(repository.HEAD) && !repository.HEAD.equals(currentRef)) { |
| | |
| | | * @throws GitBlitException |
| | | */ |
| | | public RepositoryModel fork(RepositoryModel repository, UserModel user) throws GitBlitException { |
| | | String cloneName = MessageFormat.format("~{0}/{1}.git", user.username, StringUtils.stripDotGit(StringUtils.getLastPathElement(repository.name))); |
| | | 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); |
| | | |
| | | // clone the repository |