From f66e89662c091e082bd1d2feb6ac91513ccff273 Mon Sep 17 00:00:00 2001
From: Rafael Cavazin <rafaelcavazin@gmail.com>
Date: Sun, 21 Jul 2013 09:59:00 -0400
Subject: [PATCH] Merge branch 'master' of https://github.com/gitblit/gitblit
---
src/main/java/com/gitblit/utils/ActivityUtils.java | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 233 insertions(+), 0 deletions(-)
diff --git a/src/main/java/com/gitblit/utils/ActivityUtils.java b/src/main/java/com/gitblit/utils/ActivityUtils.java
new file mode 100644
index 0000000..c4e9587
--- /dev/null
+++ b/src/main/java/com/gitblit/utils/ActivityUtils.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.TreeSet;
+
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+
+import com.gitblit.GitBlit;
+import com.gitblit.Keys;
+import com.gitblit.models.Activity;
+import com.gitblit.models.GravatarProfile;
+import com.gitblit.models.RefModel;
+import com.gitblit.models.RepositoryCommit;
+import com.gitblit.models.RepositoryModel;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * Utility class for building activity information from repositories.
+ *
+ * @author James Moger
+ *
+ */
+public class ActivityUtils {
+
+ /**
+ * Gets the recent activity from the repositories for the last daysBack days
+ * on the specified branch.
+ *
+ * @param models
+ * the list of repositories to query
+ * @param daysBack
+ * the number of days back from Now to collect
+ * @param objectId
+ * 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, TimeZone timezone) {
+
+ // Activity panel shows last daysBack of activity across all
+ // repositories.
+ Date thresholdDate = new Date(System.currentTimeMillis() - daysBack * TimeUtils.ONEDAY);
+
+ // 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);
+
+ // aggregate author exclusions
+ Set<String> authorExclusions = new TreeSet<String>();
+ authorExclusions.addAll(GitBlit.getStrings(Keys.web.metricAuthorExclusions));
+ for (RepositoryModel model : models) {
+ if (!ArrayUtils.isEmpty(model.metricAuthorExclusions)) {
+ authorExclusions.addAll(model.metricAuthorExclusions);
+ }
+ }
+
+ Map<String, Activity> activity = new HashMap<String, Activity>();
+ for (RepositoryModel model : models) {
+ if (!model.isShowActivity()) {
+ // skip this repository
+ continue;
+ }
+ if (model.hasCommits && model.lastChange.after(thresholdDate)) {
+ if (model.isCollectingGarbage) {
+ continue;
+ }
+ 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)) {
+ if (!local.getDate().after(thresholdDate)) {
+ // branch not recently updated
+ continue;
+ }
+ branches.add(local.getName());
+ }
+ } else {
+ branches.add(objectId);
+ }
+
+ for (String branch : branches) {
+ String shortName = branch;
+ if (shortName.startsWith(Constants.R_HEADS)) {
+ shortName = shortName.substring(Constants.R_HEADS.length());
+ }
+ List<RepositoryCommit> commits = CommitCache.instance().getCommits(model.name, repository, branch, thresholdDate);
+ if (model.maxActivityCommits > 0 && commits.size() > model.maxActivityCommits) {
+ // trim commits to maximum count
+ commits = commits.subList(0, model.maxActivityCommits);
+ }
+ for (RepositoryCommit commit : commits) {
+ Date date = commit.getCommitDate();
+ 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 a = new Activity(cal.getTime());
+ a.excludeAuthors(authorExclusions);
+ activity.put(dateStr, a);
+ }
+ activity.get(dateStr).addCommit(commit);
+ }
+ }
+
+ // close the repository
+ repository.close();
+ }
+ }
+
+ List<Activity> recentActivity = new ArrayList<Activity>(activity.values());
+ 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 getGravatarIdenticonUrl(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;
+ }
+
+ /**
+ * 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=mm", 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;
+ }
+}
--
Gitblit v1.9.1