Bret K. Ikehara
2013-08-04 cd9461c0c05958444d1313b794be57df39d98956
src/main/java/com/gitblit/GitBlit.java
@@ -32,6 +32,7 @@
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;
@@ -87,6 +88,7 @@
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;
@@ -124,7 +126,9 @@
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;
@@ -1243,8 +1247,8 @@
               // 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
@@ -1853,8 +1857,8 @@
      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";
@@ -1985,6 +1989,16 @@
      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", "")));
@@ -2003,6 +2017,8 @@
         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(
@@ -2030,7 +2046,7 @@
               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)) {
@@ -2118,7 +2134,7 @@
    * @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 + "/";
@@ -2418,7 +2434,8 @@
         }
         // 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)) {
@@ -2497,6 +2514,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)) {
@@ -2511,7 +2537,13 @@
         // 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
@@ -2569,6 +2601,16 @@
         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);
@@ -2658,12 +2700,56 @@
    * 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)) {
@@ -2687,14 +2773,14 @@
         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;
   }
   /**
@@ -3422,6 +3508,10 @@
      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());
@@ -3586,7 +3676,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)) {
@@ -3801,7 +3891,7 @@
    * @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