Globl and per-repository setting to exclude authors form metrics (issue-251)
| | |
| | | - 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
|
| | |
| | | - { 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 }
|
| | |
| | | # 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
|
| | | #
|
| | |
| | | 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>(); |
| | |
| | | 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) { |
| | |
| | |
|
| | | import java.io.Serializable;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Collection;
|
| | | import java.util.Collections;
|
| | | import java.util.Date;
|
| | | import java.util.HashMap;
|
| | |
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | | import java.util.Set;
|
| | | import java.util.TreeSet;
|
| | |
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | |
|
| | |
| | |
|
| | | private final Map<String, Metric> repositoryMetrics;
|
| | |
|
| | | private final Set<String> authorExclusions;
|
| | |
|
| | | /**
|
| | | * Constructor for one day of 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());
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | 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 (!authorExclusions.contains(authorName) && !authorExclusions.contains(authorEmail)) {
|
| | | if (!authorMetrics.containsKey(author)) {
|
| | | authorMetrics.put(author, new Metric(author));
|
| | | }
|
| | | authorMetrics.get(author).count++;
|
| | | }
|
| | | return commitModel;
|
| | | }
|
| | | return null;
|
| | |
| | | public String gcThreshold;
|
| | | public int gcPeriod;
|
| | | public int maxActivityCommits;
|
| | | public List<String> metricAuthorExclusions;
|
| | |
|
| | | public transient boolean isCollectingGarbage;
|
| | | public Date lastGC;
|
| | |
| | | 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;
|
| | |
| | | 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;
|
| | |
| | | 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) {
|
| | |
| | | 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);
|
| | |
| | | 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;
|
| | |
|
| | |
| | | line(sb, MessageFormat.format("{0}.addRows({1,number,0});", dName, values.size()));
|
| | |
|
| | | Collections.sort(values);
|
| | | 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 < values.size(); i++) {
|
| | | ChartValue value = values.get(i);
|
| | | for (int i = 0; i < list.size(); i++) {
|
| | | ChartValue value = list.get(i);
|
| | | colors.append('\'');
|
| | | colors.append(StringUtils.getColor(value.name));
|
| | | colors.append('\'');
|
| | |
| | | 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;
|
| | |
| | |
|
| | | // 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));
|
| | | }
|
| | |
|
| | |
| | | * @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>();
|
| | |
| | | repositoryMetrics.get(repository).count += 1;
|
| | |
|
| | | for (RepositoryCommit commit : push.getCommits()) {
|
| | | String author = commit.getAuthorIdent().getName();
|
| | | 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;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | // build google charts
|
| | | GoogleCharts charts = new GoogleCharts();
|
| | |
| | | <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>
|
| | |
| | | <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>
|
| | |
| | | <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>
|
| | |
| | |
|
| | | RepositoryModel repositoryModel;
|
| | |
|
| | | private IModel<String> metricAuthorExclusions;
|
| | | |
| | | private IModel<String> mailingLists;
|
| | |
|
| | | public EditRepositoryPage() {
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | // 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)) {
|
| | |
| | | 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));
|