From 7847af6e63e7adef6ec8d99a1809e91472d2bc2d Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Thu, 05 Sep 2013 09:14:22 -0400 Subject: [PATCH] Restore blockpush and localclone hooks to binaries (issue-303) --- src/main/java/com/gitblit/GitBlit.java | 239 ++++++++++++++++++++++++++++++++++++++--------------------- 1 files changed, 154 insertions(+), 85 deletions(-) diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java index 1f9a947..111e595 100644 --- a/src/main/java/com/gitblit/GitBlit.java +++ b/src/main/java/com/gitblit/GitBlit.java @@ -84,6 +84,7 @@ 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; @@ -121,6 +122,7 @@ 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.ObjectCache; @@ -230,6 +232,33 @@ } 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; + } /** * Determine if this is the GO variant of Gitblit. @@ -275,6 +304,15 @@ self().timezone = TimeZone.getTimeZone(tzid); } return self().timezone; + } + + /** + * Returns the active settings. + * + * @return the active settings + */ + public static IStoredSettings getSettings() { + return self().settings; } /** @@ -685,12 +723,12 @@ 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(); } } @@ -725,6 +763,18 @@ } /** + * Returns true if the username represents an internal account + * + * @param username + * @return true if the specified username represents an internal account + */ + protected boolean isInternalAccount(String username) { + return !StringUtils.isEmpty(username) + && (username.equalsIgnoreCase(Constants.FEDERATION_USER) + || username.equalsIgnoreCase(UserModel.ANONYMOUS.username)); + } + + /** * Authenticate a user based on a username and password. * * @see IUserService.authenticate(String, char[]) @@ -749,10 +799,7 @@ if (usernameDecoded.equalsIgnoreCase(Constants.FEDERATION_USER)) { List<String> tokens = getFederationTokens(); if (tokens.contains(pw)) { - // the federation user is an administrator - UserModel federationUser = new UserModel(Constants.FEDERATION_USER); - federationUser.canAdmin = true; - return federationUser; + return getFederationUser(); } } } @@ -839,6 +886,7 @@ if (principal != null) { String username = principal.getName(); if (!StringUtils.isEmpty(username)) { + boolean internalAccount = isInternalAccount(username); UserModel user = getUserModel(username); if (user != null) { // existing user @@ -846,7 +894,8 @@ logger.debug(MessageFormat.format("{0} authenticated by servlet container principal from {1}", user.username, httpRequest.getRemoteAddr())); return user; - } else if (settings.getBoolean(Keys.realm.container.autoCreateAccounts, true)) { + } else if (settings.getBoolean(Keys.realm.container.autoCreateAccounts, false) + && !internalAccount) { // auto-create user from an authenticated container principal user = new UserModel(username.toLowerCase()); user.displayName = username; @@ -856,7 +905,7 @@ logger.debug(MessageFormat.format("{0} authenticated and created by servlet container principal from {1}", user.username, httpRequest.getRemoteAddr())); return user; - } else { + } else if (!internalAccount) { logger.warn(MessageFormat.format("Failed to find UserModel for {0}, attempted servlet container authentication from {1}", principal.getName(), httpRequest.getRemoteAddr())); } @@ -1024,6 +1073,13 @@ } String usernameDecoded = decodeUsername(username); return userService.deleteUser(usernameDecoded); + } + + protected UserModel getFederationUser() { + // the federation user is an administrator + UserModel federationUser = new UserModel(Constants.FEDERATION_USER); + federationUser.canAdmin = true; + return federationUser; } /** @@ -1441,22 +1497,13 @@ } 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 @@ -1501,6 +1548,10 @@ * @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; @@ -1547,23 +1598,6 @@ } } } - 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)); @@ -1600,13 +1634,17 @@ * @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 @@ -1642,11 +1680,7 @@ 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(); @@ -1668,6 +1702,30 @@ } } return count; + } + + private void reloadProjectMarkdown(ProjectModel project) { + // project markdown + File pmkd = new File(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(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); + } } @@ -1704,27 +1762,7 @@ project.title = projectConfigs.getString("project", name, "title"); project.description = projectConfigs.getString("project", name, "description"); - // project markdown - File pmkd = new File(getRepositoriesFolder(), (project.isRoot ? "" : name) + "/project.mkd"); - if (pmkd.exists()) { - Date lm = new Date(pmkd.lastModified()); - if (!projectMarkdownCache.hasCurrent(name, lm)) { - String mkd = com.gitblit.utils.FileUtils.readContent(pmkd, "\n"); - projectMarkdownCache.updateObject(name, lm, mkd); - } - project.projectMarkdown = projectMarkdownCache.getObject(name); - } - - // project repositories markdown - File rmkd = new File(getRepositoriesFolder(), (project.isRoot ? "" : name) + "/repositories.mkd"); - if (rmkd.exists()) { - Date lm = new Date(rmkd.lastModified()); - if (!projectRepositoriesMarkdownCache.hasCurrent(name, lm)) { - String mkd = com.gitblit.utils.FileUtils.readContent(rmkd, "\n"); - projectRepositoriesMarkdownCache.updateObject(name, lm, mkd); - } - project.repositoriesMarkdown = projectRepositoriesMarkdownCache.getObject(name); - } + reloadProjectMarkdown(project); configs.put(name.toLowerCase(), project); } @@ -1846,6 +1884,8 @@ // no repositories == no project return null; } + + reloadProjectMarkdown(project); return project; } @@ -1939,14 +1979,20 @@ // 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", ""))); @@ -2002,6 +2048,8 @@ 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://")) { @@ -2014,6 +2062,9 @@ File repoFolder = new File(getRepositoriesFolder(), originRepo); if (repoFolder.exists()) { model.originRepository = originRepo.toLowerCase(); + + // persist the fork origin + updateConfiguration(r, model); } } } catch (URISyntaxException e) { @@ -2194,21 +2245,31 @@ } /** - * 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; } @@ -2444,6 +2505,15 @@ // 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)) { @@ -2928,8 +2998,7 @@ String cloneUrl = sb.toString(); // Retrieve all available repositories - UserModel user = new UserModel(Constants.FEDERATION_USER); - user.canAdmin = true; + UserModel user = getFederationUser(); List<RepositoryModel> list = getRepositoryModels(user); // create the [cloneurl, repositoryModel] map @@ -3534,7 +3603,7 @@ Date cutoff = CommitCache.instance().getCutoffDate(); for (String repositoryName : getRepositoryList()) { RepositoryModel model = getRepositoryModel(repositoryName); - if (model.hasCommits && model.lastChange.after(cutoff)) { + if (model != null && model.hasCommits && model.lastChange.after(cutoff)) { repoCount++; Repository repository = getRepository(repositoryName); for (RefModel ref : JGitUtils.getLocalBranches(repository, true, -1)) { -- Gitblit v1.9.1