| | |
| | | import java.nio.charset.Charset; |
| | | import java.security.Principal; |
| | | import java.text.MessageFormat; |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | |
| | | import com.gitblit.Constants.AccountType; |
| | | import com.gitblit.Constants.AuthenticationType; |
| | | import com.gitblit.Constants.AuthorizationControl; |
| | | import com.gitblit.Constants.CommitMessageRenderer; |
| | | import com.gitblit.Constants.FederationRequest; |
| | | import com.gitblit.Constants.FederationStrategy; |
| | | import com.gitblit.Constants.FederationToken; |
| | |
| | | import com.gitblit.utils.JGitUtils; |
| | | import com.gitblit.utils.JGitUtils.LastChange; |
| | | import com.gitblit.utils.JsonUtils; |
| | | import com.gitblit.utils.MarkdownUtils; |
| | | 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; |
| | |
| | | // 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 |
| | |
| | | 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"; |
| | |
| | | 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()) { |
| | | String desc = com.gitblit.utils.FileUtils.readContent(descFile, System.getProperty("line.separator")); |
| | | if (!desc.toLowerCase().startsWith("unnamed repository")) { |
| | | config.setString(Constants.CONFIG_GITBLIT, null, "description", desc); |
| | | } |
| | | } |
| | | } |
| | | model.description = getConfig(config, "description", ""); |
| | | model.originRepository = getConfig(config, "originRepository", null); |
| | | model.addOwners(ArrayUtils.fromString(getConfig(config, "owner", ""))); |
| | |
| | | model.showReadme = getConfig(config, "showReadme", false); |
| | | model.skipSizeCalculation = getConfig(config, "skipSizeCalculation", false); |
| | | model.skipSummaryMetrics = getConfig(config, "skipSummaryMetrics", false); |
| | | model.commitMessageRenderer = CommitMessageRenderer.fromName(getConfig(config, "commitMessageRenderer", |
| | | settings.getString(Keys.web.commitMessageRenderer, null))); |
| | | model.federationStrategy = FederationStrategy.fromName(getConfig(config, |
| | | "federationStrategy", null)); |
| | | model.federationSets = new ArrayList<String>(Arrays.asList(config.getStringList( |
| | |
| | | Constants.CONFIG_GITBLIT, null, "indexBranch"))); |
| | | model.metricAuthorExclusions = new ArrayList<String>(Arrays.asList(config.getStringList( |
| | | Constants.CONFIG_GITBLIT, null, "metricAuthorExclusions"))); |
| | | |
| | | |
| | | // Custom defined properties |
| | | model.customFields = new LinkedHashMap<String, String>(); |
| | | for (String aProperty : config.getNames(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS)) { |
| | |
| | | * @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 + "/"; |
| | | |
| | |
| | | } |
| | | // create repository |
| | | logger.info("create repository " + repository.name); |
| | | r = JGitUtils.createRepository(repositoriesFolder, repository.name); |
| | | String shared = getString(Keys.git.createRepositoriesShared, "FALSE"); |
| | | r = JGitUtils.createRepository(repositoriesFolder, repository.name, shared); |
| | | } else { |
| | | // rename repository |
| | | if (!repositoryName.equalsIgnoreCase(repository.name)) { |
| | |
| | | // 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)) { |
| | |
| | | // close the repository object |
| | | r.close(); |
| | | } |
| | | |
| | | |
| | | // Adjust permissions in case we updated the config files |
| | | JGitUtils.adjustSharedPerm(new File(r.getDirectory().getAbsolutePath(), "config"), |
| | | getString(Keys.git.createRepositoriesShared, "FALSE")); |
| | | JGitUtils.adjustSharedPerm(new File(r.getDirectory().getAbsolutePath(), "HEAD"), |
| | | getString(Keys.git.createRepositoriesShared, "FALSE")); |
| | | |
| | | // update repository cache |
| | | removeFromCachedRepositoryList(repositoryName); |
| | | // model will actually be replaced on next load because config is stale |
| | |
| | | config.setInt(Constants.CONFIG_GITBLIT, null, "maxActivityCommits", repository.maxActivityCommits); |
| | | } |
| | | |
| | | CommitMessageRenderer defaultRenderer = CommitMessageRenderer.fromName(settings.getString(Keys.web.commitMessageRenderer, null)); |
| | | if (repository.commitMessageRenderer == null || repository.commitMessageRenderer == defaultRenderer) { |
| | | // use default from config |
| | | config.unset(Constants.CONFIG_GITBLIT, null, "commitMessageRenderer"); |
| | | } else { |
| | | // repository overrides default |
| | | config.setString(Constants.CONFIG_GITBLIT, null, "commitMessageRenderer", |
| | | repository.commitMessageRenderer.name()); |
| | | } |
| | | |
| | | updateList(config, "federationSets", repository.federationSets); |
| | | updateList(config, "preReceiveScript", repository.preReceiveScripts); |
| | | updateList(config, "postReceiveScript", repository.postReceiveScripts); |
| | |
| | | * Returns an html version of the commit message with any global or |
| | | * repository-specific regular expression substitution applied. |
| | | * |
| | | * This method uses the preferred renderer to transform the commit message. |
| | | * |
| | | * @param repository |
| | | * @param text |
| | | * @return html version of the commit message |
| | | */ |
| | | public String processCommitMessage(RepositoryModel repository, String text) { |
| | | switch (repository.commitMessageRenderer) { |
| | | case MARKDOWN: |
| | | try { |
| | | String prepared = processCommitMessageRegex(repository.name, text); |
| | | return MarkdownUtils.transformMarkdown(prepared); |
| | | } catch (ParseException e) { |
| | | logger.error("Failed to render commit message as markdown", e); |
| | | } |
| | | break; |
| | | default: |
| | | // noop |
| | | break; |
| | | } |
| | | |
| | | return processPlainCommitMessage(repository.name, text); |
| | | } |
| | | |
| | | /** |
| | | * Returns an html version of the commit message with any global or |
| | | * repository-specific regular expression substitution applied. |
| | | * |
| | | * This method assumes the commit message is plain text. |
| | | * |
| | | * @param repositoryName |
| | | * @param text |
| | | * @return html version of the commit message |
| | | */ |
| | | public String processCommitMessage(String repositoryName, String text) { |
| | | String html = StringUtils.breakLinesForHtml(text); |
| | | public String processPlainCommitMessage(String repositoryName, String text) { |
| | | String html = StringUtils.escapeForHtml(text, false); |
| | | html = processCommitMessageRegex(repositoryName, html); |
| | | return StringUtils.breakLinesForHtml(html); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * Apply globally or per-repository specified regex substitutions to the |
| | | * commit message. |
| | | * |
| | | * @param repositoryName |
| | | * @param text |
| | | * @return the processed commit message |
| | | */ |
| | | protected String processCommitMessageRegex(String repositoryName, String text) { |
| | | Map<String, String> map = new HashMap<String, String>(); |
| | | // global regex keys |
| | | if (settings.getBoolean(Keys.regex.global, false)) { |
| | |
| | | String definition = entry.getValue().trim(); |
| | | String[] chunks = definition.split("!!!"); |
| | | if (chunks.length == 2) { |
| | | html = html.replaceAll(chunks[0], chunks[1]); |
| | | text = text.replaceAll(chunks[0], chunks[1]); |
| | | } else { |
| | | logger.warn(entry.getKey() |
| | | + " improperly formatted. Use !!! to separate match from replacement: " |
| | | + definition); |
| | | } |
| | | } |
| | | return html; |
| | | return text; |
| | | } |
| | | |
| | | /** |
| | |
| | | luceneExecutor = new LuceneExecutor(settings, repositoriesFolder); |
| | | gcExecutor = new GCExecutor(settings); |
| | | |
| | | // initialize utilities |
| | | String prefix = settings.getString(Keys.git.userRepositoryPrefix, "~"); |
| | | ModelUtils.setUserRepoPrefix(prefix); |
| | | |
| | | // calculate repository list settings checksum for future config changes |
| | | repositoryListSettingsChecksum.set(getRepositoryListSettingsChecksum()); |
| | | |
| | |
| | | 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)) { |
| | |
| | | * @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 |