James Moger
2013-07-03 abab3a4e2bc221eb358f846f171cb24fc0f687ad
src/main/java/com/gitblit/GitBlit.java
@@ -102,6 +102,7 @@
import com.gitblit.models.GitClientApplication;
import com.gitblit.models.Metric;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RefModel;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.RepositoryUrl;
@@ -114,6 +115,7 @@
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.Base64;
import com.gitblit.utils.ByteFormat;
import com.gitblit.utils.CommitCache;
import com.gitblit.utils.ContainerUtils;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.FederationUtils;
@@ -273,6 +275,15 @@
         self().timezone = TimeZone.getTimeZone(tzid);
      }
      return self().timezone;
   }
   /**
    * Returns the active settings.
    *
    * @return the active settings
    */
   public static IStoredSettings getSettings() {
      return self().settings;
   }
   
   /**
@@ -723,6 +734,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[])
@@ -747,10 +770,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();
            }
         }
      }
@@ -837,6 +857,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
@@ -844,7 +865,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;
@@ -854,7 +876,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()));
            }
@@ -967,12 +989,24 @@
      userService.logout(user);
   }
   /**
    * Encode the username for user in an url.
    *
    * @param name
    * @return the encoded name
    */
   protected String encodeUsername(String name) {
      return name.replace("@", "%40");
      return name.replace("@", "%40").replace(" ", "%20").replace("\\", "%5C");
   }
   /**
    * Decode a username from an encoded url.
    *
    * @param name
    * @return the decoded name
    */
   protected String decodeUsername(String name) {
      return name.replace("%40", "@");
      return name.replace("%40", "@").replace("%20", " ").replace("%5C", "\\");
   }
   
   /**
@@ -1010,6 +1044,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;
   }
   /**
@@ -1461,7 +1502,10 @@
      }
      
      // return sorted copy of cached list
      List<String> list = new ArrayList<String>(repositoryListCache.keySet());
      List<String> list = new ArrayList<String>();
      for (RepositoryModel model : repositoryListCache.values()) {
         list.add(model.name);
      }
      StringUtils.sortRepositorynames(list);
      return list;
   }
@@ -1653,6 +1697,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);
      }
   }
   
   /**
    * Returns the map of project config.  This map is cached and reloaded if
@@ -1687,27 +1755,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);
         }
@@ -1829,6 +1877,8 @@
         // no repositories == no project
         return null;
      }
      reloadProjectMarkdown(project);
      return project;
   }
   
@@ -1931,6 +1981,7 @@
      
      if (config != null) {
         model.description = getConfig(config, "description", "");
         model.originRepository = getConfig(config, "originRepository", null);
         model.addOwners(ArrayUtils.fromString(getConfig(config, "owner", "")));
         model.useTickets = getConfig(config, "useTickets", false);
         model.useDocs = getConfig(config, "useDocs", false);
@@ -1986,7 +2037,7 @@
      model.sparkleshareId = JGitUtils.getSparkleshareId(r);
      r.close();
      
      if (model.origin != null && model.origin.startsWith("file://")) {
      if (StringUtils.isEmpty(model.originRepository) && model.origin != null && model.origin.startsWith("file://")) {
         // repository was cloned locally... perhaps as a fork
         try {
            File folder = new File(new URI(model.origin));
@@ -2395,6 +2446,7 @@
                     String origin = config.getString("remote", "origin", "url");
                     origin = origin.replace(repositoryName, repository.name);
                     config.setString("remote", "origin", "url", origin);
                     config.setString(Constants.CONFIG_GITBLIT, null, "originRepository", repository.name);
                     config.save();
                  } catch (Exception e) {
                     logger.error("Failed to update repository fork config for " + fork, e);
@@ -2403,11 +2455,12 @@
               }
            }
            
            // remove this repository from any origin model's fork list
            // update this repository's origin's fork list
            if (!StringUtils.isEmpty(repository.originRepository)) {
               RepositoryModel origin = repositoryListCache.get(repository.originRepository);
               if (origin != null && !ArrayUtils.isEmpty(origin.forks)) {
                  origin.forks.remove(repositoryName);
                  origin.forks.add(repository.name);
               }
            }
@@ -2456,6 +2509,7 @@
   public void updateConfiguration(Repository r, RepositoryModel repository) {
      StoredConfig config = r.getConfig();
      config.setString(Constants.CONFIG_GITBLIT, null, "description", repository.description);
      config.setString(Constants.CONFIG_GITBLIT, null, "originRepository", repository.originRepository);
      config.setString(Constants.CONFIG_GITBLIT, null, "owner", ArrayUtils.toString(repository.owners));
      config.setBoolean(Constants.CONFIG_GITBLIT, null, "useTickets", repository.useTickets);
      config.setBoolean(Constants.CONFIG_GITBLIT, null, "useDocs", repository.useDocs);
@@ -2907,8 +2961,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
@@ -3389,7 +3442,8 @@
      configureJGit();
      configureFanout();
      configureGitDaemon();
      configureCommitCache();
      ContainerUtils.CVE_2007_0450.test();
   }
   
@@ -3499,6 +3553,42 @@
      }
   }
   
   protected void configureCommitCache() {
      int daysToCache = settings.getInteger(Keys.web.activityCacheDays, 14);
      if (daysToCache <= 0) {
         logger.info("commit cache disabled");
      } else {
         long start = System.nanoTime();
         long repoCount = 0;
         long commitCount = 0;
         logger.info(MessageFormat.format("preparing {0} day commit cache. please wait...", daysToCache));
         CommitCache.instance().setCacheDays(daysToCache);
         Date cutoff = CommitCache.instance().getCutoffDate();
         for (String repositoryName : getRepositoryList()) {
            RepositoryModel model = getRepositoryModel(repositoryName);
            if (model.hasCommits && model.lastChange.after(cutoff)) {
               repoCount++;
               Repository repository = getRepository(repositoryName);
               for (RefModel ref : JGitUtils.getLocalBranches(repository, true, -1)) {
                  if (!ref.getDate().after(cutoff)) {
                     // branch not recently updated
                     continue;
                  }
                  List<?> commits = CommitCache.instance().getCommits(repositoryName, repository, ref.getName());
                  if (commits.size() > 0) {
                     logger.info(MessageFormat.format("  cached {0} commits for {1}:{2}",
                           commits.size(), repositoryName, ref.getName()));
                     commitCount += commits.size();
                  }
               }
               repository.close();
            }
         }
         logger.info(MessageFormat.format("built {0} day commit cache of {1} commits across {2} repositories in {3} msecs",
               daysToCache, commitCount, repoCount, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start)));
      }
   }
   protected final Logger getLogger() {
      return logger;
   }