lemval
2012-01-31 1c30dad2115fc513791d8a5b292ad0f7d7b85749
src/com/gitblit/utils/MetricUtils.java
@@ -16,6 +16,7 @@
package com.gitblit.utils;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
@@ -24,7 +25,6 @@
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -35,49 +35,103 @@
import com.gitblit.models.Metric;
import com.gitblit.models.RefModel;
/**
 * Utility class for collecting metrics on a branch, tag, or other ref within
 * the repository.
 *
 * @author James Moger
 *
 */
public class MetricUtils {
   private static final Logger LOGGER = LoggerFactory.getLogger(MetricUtils.class);
   public static List<Metric> getDateMetrics(Repository r, boolean includeTotal, String format) {
   /**
    * Log an error message and exception.
    *
    * @param t
    * @param repository
    *            if repository is not null it MUST be the {0} parameter in the
    *            pattern.
    * @param pattern
    * @param objects
    */
   private static void error(Throwable t, Repository repository, String pattern, Object... objects) {
      List<Object> parameters = new ArrayList<Object>();
      if (objects != null && objects.length > 0) {
         for (Object o : objects) {
            parameters.add(o);
         }
      }
      if (repository != null) {
         parameters.add(0, repository.getDirectory().getAbsolutePath());
      }
      LOGGER.error(MessageFormat.format(pattern, parameters.toArray()), t);
   }
   /**
    * Returns the list of metrics for the specified commit reference, branch,
    * or tag within the repository. If includeTotal is true, the total of all
    * the metrics will be included as the first element in the returned list.
    *
    * If the dateformat is unspecified an attempt is made to determine an
    * appropriate date format by determining the time difference between the
    * first commit on the branch and the most recent commit. This assumes that
    * the commits are linear.
    *
    * @param repository
    * @param objectId
    *            if null or empty, HEAD is assumed.
    * @param includeTotal
    * @param dateFormat
    * @return list of metrics
    */
   public static List<Metric> getDateMetrics(Repository repository, String objectId,
         boolean includeTotal, String dateFormat) {
      Metric total = new Metric("TOTAL");
      final Map<String, Metric> metricMap = new HashMap<String, Metric>();
      if (JGitUtils.hasCommits(r)) {
         final List<RefModel> tags = JGitUtils.getTags(r, -1);
      if (JGitUtils.hasCommits(repository)) {
         final List<RefModel> tags = JGitUtils.getTags(repository, true, -1);
         final Map<ObjectId, RefModel> tagMap = new HashMap<ObjectId, RefModel>();
         for (RefModel tag : tags) {
            tagMap.put(tag.getReferencedObjectId(), tag);
         }
         RevWalk revWalk = null;
         try {
            RevWalk walk = new RevWalk(r);
            ObjectId object = r.resolve(Constants.HEAD);
            RevCommit lastCommit = walk.parseCommit(object);
            walk.markStart(lastCommit);
            // resolve branch
            ObjectId branchObject;
            if (StringUtils.isEmpty(objectId)) {
               branchObject = JGitUtils.getDefaultBranch(repository);
            } else {
               branchObject = repository.resolve(objectId);
            }
            revWalk = new RevWalk(repository);
            RevCommit lastCommit = revWalk.parseCommit(branchObject);
            revWalk.markStart(lastCommit);
            DateFormat df;
            if (StringUtils.isEmpty(format)) {
            if (StringUtils.isEmpty(dateFormat)) {
               // dynamically determine date format
               RevCommit firstCommit = JGitUtils.getFirstCommit(r, Constants.HEAD);
               RevCommit firstCommit = JGitUtils.getFirstCommit(repository,
                     branchObject.getName());
               int diffDays = (lastCommit.getCommitTime() - firstCommit.getCommitTime())
                     / (60 * 60 * 24);
               total.duration = diffDays;
               if (diffDays <= 90) {
               if (diffDays <= 365) {
                  // Days
                  df = new SimpleDateFormat("yyyy-MM-dd");
               } else if (diffDays > 90 && diffDays < 365) {
                  // Weeks
                  df = new SimpleDateFormat("yyyy-MM (w)");
               } else {
                  // Months
                  df = new SimpleDateFormat("yyyy-MM");
               }
            } else {
               // use specified date format
               df = new SimpleDateFormat(format);
               df = new SimpleDateFormat(dateFormat);
            }
            Iterable<RevCommit> revlog = walk;
            Iterable<RevCommit> revlog = revWalk;
            for (RevCommit rev : revlog) {
               Date d = JGitUtils.getCommitDate(rev);
               String p = df.format(d);
@@ -93,7 +147,12 @@
               }
            }
         } catch (Throwable t) {
            LOGGER.error("Failed to mine log history for date metrics", t);
            error(t, repository, "{0} failed to mine log history for date metrics of {1}",
                  objectId);
         } finally {
            if (revWalk != null) {
               revWalk.dispose();
            }
         }
      }
      List<String> keys = new ArrayList<String>(metricMap.keySet());
@@ -108,28 +167,44 @@
      return metrics;
   }
   public static List<Metric> getAuthorMetrics(Repository r, boolean byEmail) {
   /**
    * Returns a list of author metrics for the specified repository.
    *
    * @param repository
    * @param objectId
    *            if null or empty, HEAD is assumed.
    * @param byEmailAddress
    *            group metrics by author email address otherwise by author name
    * @return list of metrics
    */
   public static List<Metric> getAuthorMetrics(Repository repository, String objectId,
         boolean byEmailAddress) {
      final Map<String, Metric> metricMap = new HashMap<String, Metric>();
      if (JGitUtils.hasCommits(r)) {
      if (JGitUtils.hasCommits(repository)) {
         try {
            RevWalk walk = new RevWalk(r);
            ObjectId object = r.resolve(Constants.HEAD);
            RevCommit lastCommit = walk.parseCommit(object);
            RevWalk walk = new RevWalk(repository);
            // resolve branch
            ObjectId branchObject;
            if (StringUtils.isEmpty(objectId)) {
               branchObject = JGitUtils.getDefaultBranch(repository);
            } else {
               branchObject = repository.resolve(objectId);
            }
            RevCommit lastCommit = walk.parseCommit(branchObject);
            walk.markStart(lastCommit);
            Iterable<RevCommit> revlog = walk;
            for (RevCommit rev : revlog) {
               String p;
               if (byEmail) {
                  p = rev.getAuthorIdent().getEmailAddress();
               if (byEmailAddress) {
                  p = rev.getAuthorIdent().getEmailAddress().toLowerCase();
                  if (StringUtils.isEmpty(p)) {
                     p = rev.getAuthorIdent().getName();
                     p = rev.getAuthorIdent().getName().toLowerCase();
                  }
               } else {
                  p = rev.getAuthorIdent().getName();
                  p = rev.getAuthorIdent().getName().toLowerCase();
                  if (StringUtils.isEmpty(p)) {
                     p = rev.getAuthorIdent().getEmailAddress();
                     p = rev.getAuthorIdent().getEmailAddress().toLowerCase();
                  }
               }
               if (!metricMap.containsKey(p)) {
@@ -139,7 +214,8 @@
               m.count++;
            }
         } catch (Throwable t) {
            LOGGER.error("Failed to mine log history for author metrics", t);
            error(t, repository, "{0} failed to mine log history for author metrics of {1}",
                  objectId);
         }
      }
      List<String> keys = new ArrayList<String>(metricMap.keySet());