James Moger
2012-10-13 c658df9e87d65b08d5482cf04489cb0532ff83dd
src/com/gitblit/utils/ActivityUtils.java
@@ -15,15 +15,19 @@
 */
package com.gitblit.utils;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
@@ -33,8 +37,10 @@
import com.gitblit.GitBlit;
import com.gitblit.models.Activity;
import com.gitblit.models.Activity.RepositoryCommit;
import com.gitblit.models.GravatarProfile;
import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryModel;
import com.google.gson.reflect.TypeToken;
/**
 * Utility class for building activity information from repositories.
@@ -53,12 +59,14 @@
    * @param daysBack
    *            the number of days back from Now to collect
    * @param objectId
    *            the branch to retrieve. If this value is null the default
    *            branch of the repository is used.
    *            the branch to retrieve. If this value is null or empty all
    *            branches are queried.
    * @param timezone
    *            the timezone for aggregating commits
    * @return
    */
   public static List<Activity> getRecentActivity(List<RepositoryModel> models, int daysBack,
         String objectId) {
         String objectId, TimeZone timezone) {
      // Activity panel shows last daysBack of activity across all
      // repositories.
@@ -67,64 +75,120 @@
      // Build a map of DailyActivity from the available repositories for the
      // specified threshold date.
      DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
      df.setTimeZone(timezone);
      Calendar cal = Calendar.getInstance();
      cal.setTimeZone(timezone);
      Map<String, Activity> activity = new HashMap<String, Activity>();
      for (RepositoryModel model : models) {
         if (model.hasCommits && model.lastChange.after(thresholdDate)) {
            Repository repository = GitBlit.self().getRepository(model.name);
            List<RevCommit> commits = JGitUtils.getRevLog(repository, objectId, thresholdDate);
            Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository);
            Repository repository = GitBlit.self()
                  .getRepository(model.name);
            List<String> branches = new ArrayList<String>();
            if (StringUtils.isEmpty(objectId)) {
               for (RefModel local : JGitUtils.getLocalBranches(
                     repository, true, -1)) {
                  branches.add(local.getName());
               }
            } else {
               branches.add(objectId);
            }
            Map<ObjectId, List<RefModel>> allRefs = JGitUtils
                  .getAllRefs(repository, model.showRemoteBranches);
            for (String branch : branches) {
               String shortName = branch;
               if (shortName.startsWith(Constants.R_HEADS)) {
                  shortName = shortName.substring(Constants.R_HEADS.length());
               }
               List<RevCommit> commits = JGitUtils.getRevLog(repository,
                     branch, thresholdDate);
               for (RevCommit commit : commits) {
                  Date date = JGitUtils.getCommitDate(commit);
                  String dateStr = df.format(date);
                  if (!activity.containsKey(dateStr)) {
                     // Normalize the date to midnight
                     cal.setTime(date);
                     cal.set(Calendar.HOUR_OF_DAY, 0);
                     cal.set(Calendar.MINUTE, 0);
                     cal.set(Calendar.SECOND, 0);
                     cal.set(Calendar.MILLISECOND, 0);
                     activity.put(dateStr, new Activity(cal.getTime()));
                  }
                  RepositoryCommit commitModel = activity.get(dateStr)
                        .addCommit(model.name, shortName, commit);
                  if (commitModel != null) {
                     commitModel.setRefs(allRefs.get(commit.getId()));
                  }
               }
            }
            // close the repository
            repository.close();
            // determine commit branch
            String branch = objectId;
            if (StringUtils.isEmpty(branch)) {
               List<RefModel> headRefs = allRefs.get(commits.get(0).getId());
               List<String> localBranches = new ArrayList<String>();
               for (RefModel ref : headRefs) {
                  if (ref.getName().startsWith(Constants.R_HEADS)) {
                     localBranches.add(ref.getName().substring(Constants.R_HEADS.length()));
                  }
               }
               // determine branch
               if (localBranches.size() == 1) {
                  // only one branch, choose it
                  branch = localBranches.get(0);
               } else if (localBranches.size() > 1) {
                  if (localBranches.contains("master")) {
                     // choose master
                     branch = "master";
                  } else {
                     // choose first branch
                     branch = localBranches.get(0);
                  }
               }
            }
            for (RevCommit commit : commits) {
               Date date = JGitUtils.getCommitDate(commit);
               String dateStr = df.format(date);
               if (!activity.containsKey(dateStr)) {
                  // Normalize the date to midnight
                  cal.setTime(date);
                  cal.set(Calendar.HOUR_OF_DAY, 0);
                  cal.set(Calendar.MINUTE, 0);
                  cal.set(Calendar.SECOND, 0);
                  cal.set(Calendar.MILLISECOND, 0);
                  activity.put(dateStr, new Activity(cal.getTime()));
               }
               RepositoryCommit commitModel = activity.get(dateStr).addCommit(model.name,
                     branch, commit);
               commitModel.setRefs(allRefs.get(commit.getId()));
            }
         }
      }
      List<Activity> recentActivity = new ArrayList<Activity>(activity.values());
      for (Activity daily : recentActivity) {
         Collections.sort(daily.commits);
      }
      return recentActivity;
   }
   /**
    * Returns the Gravatar profile, if available, for the specified email
    * address.
    *
    * @param emailaddress
    * @return a Gravatar Profile
    * @throws IOException
    */
   public static GravatarProfile getGravatarProfileFromAddress(String emailaddress)
         throws IOException {
      return getGravatarProfile(StringUtils.getMD5(emailaddress.toLowerCase()));
   }
   /**
    * Creates a Gravatar thumbnail url from the specified email address.
    *
    * @param email
    *            address to query Gravatar
    * @param width
    *            size of thumbnail. if width <= 0, the default of 50 is used.
    * @return
    */
   public static String getGravatarThumbnailUrl(String email, int width) {
      if (width <= 0) {
         width = 50;
      }
      String emailHash = StringUtils.getMD5(email);
      String url = MessageFormat.format(
            "https://www.gravatar.com/avatar/{0}?s={1,number,0}&d=identicon", emailHash, width);
      return url;
   }
   /**
    * Returns the Gravatar profile, if available, for the specified hashcode.
    * address.
    *
    * @param hash
    *            the hash of the email address
    * @return a Gravatar Profile
    * @throws IOException
    */
   public static GravatarProfile getGravatarProfile(String hash) throws IOException {
      String url = MessageFormat.format("https://www.gravatar.com/{0}.json", hash);
      // Gravatar has a complex json structure
      Type profileType = new TypeToken<Map<String, List<GravatarProfile>>>() {
      }.getType();
      Map<String, List<GravatarProfile>> profiles = null;
      try {
         profiles = JsonUtils.retrieveJson(url, profileType);
      } catch (FileNotFoundException e) {
      }
      if (profiles == null || profiles.size() == 0) {
         return null;
      }
      // due to the complex json structure we need to pull out the profile
      // from a list 2 levels deep
      GravatarProfile profile = profiles.values().iterator().next().get(0);
      return profile;
   }
}