diff options
author | James Moger <james.moger@gitblit.com> | 2013-06-10 18:45:32 -0400 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2013-06-10 18:45:32 -0400 |
commit | cedf138f3c9afeae7bcbda5dbb0511ebec297d10 (patch) | |
tree | abc868068abaa620fa4c320c777303deaf8171b2 | |
parent | 1078f80f6999d3a94ca47815a1d9fec471766b1d (diff) | |
download | gitblit-cedf138f3c9afeae7bcbda5dbb0511ebec297d10.tar.gz gitblit-cedf138f3c9afeae7bcbda5dbb0511ebec297d10.zip |
Globl and per-repository setting to exclude authors form metrics (issue-251)
-rw-r--r-- | releases.moxie | 2 | ||||
-rw-r--r-- | src/main/distrib/data/gitblit.properties | 7 | ||||
-rw-r--r-- | src/main/java/com/gitblit/GitBlit.java | 3 | ||||
-rw-r--r-- | src/main/java/com/gitblit/models/Activity.java | 30 | ||||
-rw-r--r-- | src/main/java/com/gitblit/models/RepositoryModel.java | 3 | ||||
-rw-r--r-- | src/main/java/com/gitblit/utils/ActivityUtils.java | 16 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/charting/GooglePieChart.java | 25 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/DashboardPage.java | 30 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html | 15 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java | 23 |
10 files changed, 131 insertions, 23 deletions
diff --git a/releases.moxie b/releases.moxie index 0a73d5bb..d5c04ae2 100644 --- a/releases.moxie +++ b/releases.moxie @@ -42,6 +42,7 @@ r17: { - Updated Japanese translation
additions:
+ - Global and per-repository setting to exclude authors from metrics (issue-251)
- Added SalesForce.com user service
- Added simple star/unstar function to flag or bookmark interesting repositories
- Added Dashboard page which shows a news feed for starred repositories and offers a filterable list of repositories you care about
@@ -110,6 +111,7 @@ r17: { - { name: 'web.activityDurationChoices', defaultValue: '7 14 28 60 90 180' }
- { name: 'web.allowAppCloneLinks', defaultValue: true }
- { name: 'web.forceDefaultLocale', defaultValue: ' ' }
+ - { name: 'web.metricAuthorExclusions', defaultValue: ' ' }
- { name: 'web.overviewPushCount', defaultValue: 5 }
- { name: 'web.pushesPerPage', defaultValue: 10 }
- { name: 'server.nioThreadPoolSize', defaultValue: 50 }
diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index a6dc3158..1671507f 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -826,6 +826,13 @@ web.activityDuration = 7 # SINCE 1.3.0
web.activityDurationChoices = 7 14 28 60 90 180
+# Case-insensitive list of authors to exclude from metrics. Useful for
+# eliminating bots.
+#
+# SPACE-DELIMITED
+# SINCE 1.3.0
+web.metricAuthorExclusions =
+
# The number of commits to display on the summary page
# Value must exceed 0 else default of 20 is used
#
diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java index ceb40c13..df17edd9 100644 --- a/src/main/java/com/gitblit/GitBlit.java +++ b/src/main/java/com/gitblit/GitBlit.java @@ -1939,6 +1939,8 @@ public class GitBlit implements ServletContextListener { Constants.CONFIG_GITBLIT, null, "mailingList"))); model.indexedBranches = new ArrayList<String>(Arrays.asList(config.getStringList( 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>(); @@ -2465,6 +2467,7 @@ public class GitBlit implements ServletContextListener { updateList(config, "postReceiveScript", repository.postReceiveScripts); updateList(config, "mailingList", repository.mailingLists); updateList(config, "indexBranch", repository.indexedBranches); + updateList(config, "metricAuthorExclusions", repository.metricAuthorExclusions); // User Defined Properties if (repository.customFields != null) { diff --git a/src/main/java/com/gitblit/models/Activity.java b/src/main/java/com/gitblit/models/Activity.java index 59405c7f..547c348f 100644 --- a/src/main/java/com/gitblit/models/Activity.java +++ b/src/main/java/com/gitblit/models/Activity.java @@ -17,6 +17,7 @@ package com.gitblit.models; import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@@ -24,6 +25,7 @@ import java.util.LinkedHashSet; import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -43,13 +45,15 @@ public class Activity implements Serializable, Comparable<Activity> { public final Date startDate;
public final Date endDate;
-
+
private final Set<RepositoryCommit> commits;
private final Map<String, Metric> authorMetrics;
private final Map<String, Metric> repositoryMetrics;
+ private final Set<String> authorExclusions;
+
/**
* Constructor for one day of activity.
*
@@ -73,6 +77,18 @@ public class Activity implements Serializable, Comparable<Activity> { commits = new LinkedHashSet<RepositoryCommit>();
authorMetrics = new HashMap<String, Metric>();
repositoryMetrics = new HashMap<String, Metric>();
+ authorExclusions = new TreeSet<String>();
+ }
+
+ /**
+ * Exclude the specified authors from the metrics.
+ *
+ * @param authors
+ */
+ public void excludeAuthors(Collection<String> authors) {
+ for (String author : authors) {
+ authorExclusions.add(author.toLowerCase());
+ }
}
/**
@@ -88,16 +104,20 @@ public class Activity implements Serializable, Comparable<Activity> { public RepositoryCommit addCommit(String repository, String branch, RevCommit commit) {
RepositoryCommit commitModel = new RepositoryCommit(repository, branch, commit);
if (commits.add(commitModel)) {
+ String author = StringUtils.removeNewlines(commit.getAuthorIdent().getName());
+ String authorName = author.toLowerCase();
+ String authorEmail = StringUtils.removeNewlines(commit.getAuthorIdent().getEmailAddress()).toLowerCase();
if (!repositoryMetrics.containsKey(repository)) {
repositoryMetrics.put(repository, new Metric(repository));
}
repositoryMetrics.get(repository).count++;
- String author = StringUtils.removeNewlines(commit.getAuthorIdent().getEmailAddress()).toLowerCase();
- if (!authorMetrics.containsKey(author)) {
- authorMetrics.put(author, new Metric(author));
+ if (!authorExclusions.contains(authorName) && !authorExclusions.contains(authorEmail)) {
+ if (!authorMetrics.containsKey(author)) {
+ authorMetrics.put(author, new Metric(author));
+ }
+ authorMetrics.get(author).count++;
}
- authorMetrics.get(author).count++;
return commitModel;
}
return null;
diff --git a/src/main/java/com/gitblit/models/RepositoryModel.java b/src/main/java/com/gitblit/models/RepositoryModel.java index 0e39d912..5eb51b4b 100644 --- a/src/main/java/com/gitblit/models/RepositoryModel.java +++ b/src/main/java/com/gitblit/models/RepositoryModel.java @@ -81,7 +81,8 @@ public class RepositoryModel implements Serializable, Comparable<RepositoryModel public boolean verifyCommitter;
public String gcThreshold;
public int gcPeriod;
- public int maxActivityCommits;
+ public int maxActivityCommits;
+ public List<String> metricAuthorExclusions;
public transient boolean isCollectingGarbage;
public Date lastGC;
diff --git a/src/main/java/com/gitblit/utils/ActivityUtils.java b/src/main/java/com/gitblit/utils/ActivityUtils.java index 015e8d3d..edeb01ad 100644 --- a/src/main/java/com/gitblit/utils/ActivityUtils.java +++ b/src/main/java/com/gitblit/utils/ActivityUtils.java @@ -27,7 +27,9 @@ 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.ObjectId;
@@ -35,6 +37,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit;
import com.gitblit.GitBlit;
+import com.gitblit.Keys;
import com.gitblit.models.Activity;
import com.gitblit.models.GravatarProfile;
import com.gitblit.models.RefModel;
@@ -78,6 +81,15 @@ public class ActivityUtils { 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) {
@@ -124,7 +136,9 @@ public class ActivityUtils { cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
- activity.put(dateStr, new Activity(cal.getTime()));
+ Activity a = new Activity(cal.getTime());
+ a.excludeAuthors(authorExclusions);
+ activity.put(dateStr, a);
}
RepositoryCommit commitModel = activity.get(dateStr)
.addCommit(model.name, shortName, commit);
diff --git a/src/main/java/com/gitblit/wicket/charting/GooglePieChart.java b/src/main/java/com/gitblit/wicket/charting/GooglePieChart.java index 945e08b1..a9b46670 100644 --- a/src/main/java/com/gitblit/wicket/charting/GooglePieChart.java +++ b/src/main/java/com/gitblit/wicket/charting/GooglePieChart.java @@ -16,7 +16,9 @@ package com.gitblit.wicket.charting;
import java.text.MessageFormat;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import com.gitblit.utils.StringUtils;
@@ -44,10 +46,27 @@ public class GooglePieChart extends GoogleChart { line(sb, MessageFormat.format("{0}.addRows({1,number,0});", dName, values.size()));
Collections.sort(values);
-
- StringBuilder colors = new StringBuilder("colors:[");
- for (int i = 0; i < values.size(); i++) {
+ List<ChartValue> list = new ArrayList<ChartValue>();
+
+ int maxSlices = 10;
+ int maxCount = Math.min(maxSlices - 1, values.size());
+
+ for (int i = 0; i < maxCount; i++) {
ChartValue value = values.get(i);
+ list.add(value);
+ }
+ if (values.size() >= maxSlices) {
+ float others = 0;
+ for (int i = maxSlices - 1; i < values.size(); i++) {
+ others += values.get(i).value;
+ }
+ ChartValue other = new ChartValue("other", others);
+ list.add(other);
+ }
+
+ StringBuilder colors = new StringBuilder("colors:[");
+ for (int i = 0; i < list.size(); i++) {
+ ChartValue value = list.get(i);
colors.append('\'');
colors.append(StringUtils.getColor(value.name));
colors.append('\'');
diff --git a/src/main/java/com/gitblit/wicket/pages/DashboardPage.java b/src/main/java/com/gitblit/wicket/pages/DashboardPage.java index 39771aef..66bbf734 100644 --- a/src/main/java/com/gitblit/wicket/pages/DashboardPage.java +++ b/src/main/java/com/gitblit/wicket/pages/DashboardPage.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
+import java.util.TreeSet;
import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
@@ -187,7 +188,20 @@ public class DashboardPage extends RootPage { // add the nifty charts
if (!ArrayUtils.isEmpty(pushes)) {
- GoogleCharts charts = createCharts(pushes);
+ // aggregate author exclusions
+ Set<String> authorExclusions = new TreeSet<String>();
+ for (String author : GitBlit.getStrings(Keys.web.metricAuthorExclusions)) {
+ authorExclusions.add(author.toLowerCase());
+ }
+ for (RepositoryModel model : feedSources) {
+ if (!ArrayUtils.isEmpty(model.metricAuthorExclusions)) {
+ for (String author : model.metricAuthorExclusions) {
+ authorExclusions.add(author.toLowerCase());
+ }
+ }
+ }
+
+ GoogleCharts charts = createCharts(pushes, authorExclusions);
add(new HeaderContributor(charts));
}
@@ -359,7 +373,7 @@ public class DashboardPage extends RootPage { * @param recentPushes
* @return
*/
- private GoogleCharts createCharts(List<PushLogEntry> recentPushes) {
+ private GoogleCharts createCharts(List<PushLogEntry> recentPushes, Set<String> authorExclusions) {
// activity metrics
Map<String, Metric> repositoryMetrics = new HashMap<String, Metric>();
Map<String, Metric> authorMetrics = new HashMap<String, Metric>();
@@ -375,11 +389,15 @@ public class DashboardPage extends RootPage { repositoryMetrics.get(repository).count += 1;
for (RepositoryCommit commit : push.getCommits()) {
- String author = commit.getAuthorIdent().getName();
- if (!authorMetrics.containsKey(author)) {
- authorMetrics.put(author, new Metric(author));
+ String author = StringUtils.removeNewlines(commit.getAuthorIdent().getName());
+ String authorName = author.toLowerCase();
+ String authorEmail = StringUtils.removeNewlines(commit.getAuthorIdent().getEmailAddress()).toLowerCase();
+ if (!authorExclusions.contains(authorName) && !authorExclusions.contains(authorEmail)) {
+ if (!authorMetrics.containsKey(author)) {
+ authorMetrics.put(author, new Metric(author));
+ }
+ authorMetrics.get(author).count += 1;
}
- authorMetrics.get(author).count += 1;
}
}
diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html index f8ecb992..38070273 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html @@ -41,8 +41,9 @@ <tr><th><wicket:message key="gb.skipSizeCalculation"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="skipSizeCalculation" tabindex="11" /> <span class="help-inline"><wicket:message key="gb.skipSizeCalculationDescription"></wicket:message></span></label></td></tr>
<tr><th><wicket:message key="gb.skipSummaryMetrics"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="skipSummaryMetrics" tabindex="12" /> <span class="help-inline"><wicket:message key="gb.skipSummaryMetricsDescription"></wicket:message></span></label></td></tr>
<tr><th><wicket:message key="gb.maxActivityCommits"></wicket:message></th><td class="edit"><select class="span2" wicket:id="maxActivityCommits" tabindex="13" /> <span class="help-inline"><wicket:message key="gb.maxActivityCommitsDescription"></wicket:message></span></td></tr>
+ <tr><th><wicket:message key="gb.metricAuthorExclusions"></wicket:message></th><td class="edit"><input class="span8" type="text" wicket:id="metricAuthorExclusions" size="40" tabindex="14" /></td></tr>
<tr><th colspan="2"><hr/></th></tr>
- <tr><th><wicket:message key="gb.mailingLists"></wicket:message></th><td class="edit"><input class="span8" type="text" wicket:id="mailingLists" size="40" tabindex="14" /></td></tr>
+ <tr><th><wicket:message key="gb.mailingLists"></wicket:message></th><td class="edit"><input class="span8" type="text" wicket:id="mailingLists" size="40" tabindex="15" /></td></tr>
</tbody>
</table>
</div>
@@ -51,15 +52,15 @@ <div class="tab-pane" id="permissions">
<table class="plain">
<tbody class="settings">
- <tr><th><wicket:message key="gb.owners"></wicket:message></th><td class="edit"><span wicket:id="owners" tabindex="15" /> </td></tr>
+ <tr><th><wicket:message key="gb.owners"></wicket:message></th><td class="edit"><span wicket:id="owners" tabindex="16" /> </td></tr>
<tr><th colspan="2"><hr/></th></tr>
- <tr><th><wicket:message key="gb.accessRestriction"></wicket:message></th><td class="edit"><select class="span4" wicket:id="accessRestriction" tabindex="16" /></td></tr>
+ <tr><th><wicket:message key="gb.accessRestriction"></wicket:message></th><td class="edit"><select class="span4" wicket:id="accessRestriction" tabindex="17" /></td></tr>
<tr><th colspan="2"><hr/></th></tr>
<tr><th><wicket:message key="gb.authorizationControl"></wicket:message></th><td style="padding:2px;"><span class="authorizationControl" wicket:id="authorizationControl"></span></td></tr>
<tr><th colspan="2"><hr/></th></tr>
- <tr><th><wicket:message key="gb.isFrozen"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="isFrozen" tabindex="17" /> <span class="help-inline"><wicket:message key="gb.isFrozenDescription"></wicket:message></span></label></td></tr>
- <tr><th><wicket:message key="gb.allowForks"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="allowForks" tabindex="18" /> <span class="help-inline"><wicket:message key="gb.allowForksDescription"></wicket:message></span></label></td></tr>
- <tr><th><wicket:message key="gb.verifyCommitter"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="verifyCommitter" tabindex="19" /> <span class="help-inline"><wicket:message key="gb.verifyCommitterDescription"></wicket:message></span><br/><span class="help-inline" style="padding-left:10px;"><wicket:message key="gb.verifyCommitterNote"></wicket:message></span></label></td></tr>
+ <tr><th><wicket:message key="gb.isFrozen"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="isFrozen" tabindex="18" /> <span class="help-inline"><wicket:message key="gb.isFrozenDescription"></wicket:message></span></label></td></tr>
+ <tr><th><wicket:message key="gb.allowForks"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="allowForks" tabindex="19" /> <span class="help-inline"><wicket:message key="gb.allowForksDescription"></wicket:message></span></label></td></tr>
+ <tr><th><wicket:message key="gb.verifyCommitter"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="verifyCommitter" tabindex="20" /> <span class="help-inline"><wicket:message key="gb.verifyCommitterDescription"></wicket:message></span><br/><span class="help-inline" style="padding-left:10px;"><wicket:message key="gb.verifyCommitterNote"></wicket:message></span></label></td></tr>
<tr><th colspan="2"><hr/></th></tr>
<tr><th><wicket:message key="gb.userPermissions"></wicket:message></th><td style="padding:2px;"><span wicket:id="users"></span></td></tr>
<tr><th colspan="2"><hr/></th></tr>
@@ -72,7 +73,7 @@ <div class="tab-pane" id="federation">
<table class="plain">
<tbody class="settings">
- <tr><th><wicket:message key="gb.federationStrategy"></wicket:message></th><td class="edit"><select class="span4" wicket:id="federationStrategy" tabindex="20" /></td></tr>
+ <tr><th><wicket:message key="gb.federationStrategy"></wicket:message></th><td class="edit"><select class="span4" wicket:id="federationStrategy" tabindex="21" /></td></tr>
<tr><th><wicket:message key="gb.federationSets"></wicket:message></th><td style="padding:2px;"><span wicket:id="federationSets"></span></td></tr>
</tbody>
</table>
diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index 938b05e3..4c471a1e 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -76,6 +76,8 @@ public class EditRepositoryPage extends RootSubPage { RepositoryModel repositoryModel;
+ private IModel<String> metricAuthorExclusions;
+
private IModel<String> mailingLists;
public EditRepositoryPage() {
@@ -316,6 +318,23 @@ public class EditRepositoryPage extends RootSubPage { }
}
+ // set author metric exclusions
+ String ax = metricAuthorExclusions.getObject();
+ if (!StringUtils.isEmpty(ax)) {
+ Set<String> list = new HashSet<String>();
+ for (String exclusion : StringUtils.getStringsFromValue(ax, " ")) {
+ if (StringUtils.isEmpty(exclusion)) {
+ continue;
+ }
+ if (exclusion.indexOf(' ') > -1) {
+ list.add("\"" + exclusion + "\"");
+ } else {
+ list.add(exclusion);
+ }
+ }
+ repositoryModel.metricAuthorExclusions = new ArrayList<String>(list);
+ }
+
// set mailing lists
String ml = mailingLists.getObject();
if (!StringUtils.isEmpty(ml)) {
@@ -435,6 +454,10 @@ public class EditRepositoryPage extends RootSubPage { List<Integer> maxActivityCommits = Arrays.asList(-1, 0, 25, 50, 75, 100, 150, 200, 250, 500 );
form.add(new DropDownChoice<Integer>("maxActivityCommits", maxActivityCommits, new MaxActivityCommitsRenderer()));
+ metricAuthorExclusions = new Model<String>(ArrayUtils.isEmpty(repositoryModel.metricAuthorExclusions) ? ""
+ : StringUtils.flattenStrings(repositoryModel.metricAuthorExclusions, " "));
+ form.add(new TextField<String>("metricAuthorExclusions", metricAuthorExclusions));
+
mailingLists = new Model<String>(ArrayUtils.isEmpty(repositoryModel.mailingLists) ? ""
: StringUtils.flattenStrings(repositoryModel.mailingLists, " "));
form.add(new TextField<String>("mailingLists", mailingLists));
|