diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | distrib/users.properties | 3 | ||||
-rw-r--r-- | src/com/gitblit/utils/ByteFormat.java | 2 | ||||
-rw-r--r-- | src/com/gitblit/utils/JGitUtils.java | 155 | ||||
-rw-r--r-- | src/com/gitblit/utils/TimeUtils.java | 2 | ||||
-rw-r--r-- | src/com/gitblit/wicket/GitBlitWebApp.java | 4 | ||||
-rw-r--r-- | src/com/gitblit/wicket/WicketUtils.java | 65 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/CommitDiffPage.html | 2 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/CommitDiffPage.java | 3 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/CommitPage.java | 5 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/RepositoryPage.html | 2 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/RepositoryPage.java | 3 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/StatsPage.html | 23 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/StatsPage.java | 189 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/SummaryPage.java | 50 | ||||
-rw-r--r-- | src/com/gitblit/wicket/panels/LogPanel.java | 2 | ||||
-rw-r--r-- | src/com/gitblit/wicket/resources/gitblit.css | 2 | ||||
-rw-r--r-- | tests/com/gitblit/tests/JGitUtilsTest.java | 59 |
18 files changed, 465 insertions, 107 deletions
@@ -8,3 +8,4 @@ /users.properties /site /git +/target diff --git a/distrib/users.properties b/distrib/users.properties index d5529756..233e9f93 100644 --- a/distrib/users.properties +++ b/distrib/users.properties @@ -1,2 +1,3 @@ -# Gitblit realm file format: username=password,\#permission,repository1,repository2...
+## Git:Blit realm file format: username=password,\#permission,repository1,repository2...
+#Tue May 31 11:19:53 EDT 2011
admin=admin,\#admin
diff --git a/src/com/gitblit/utils/ByteFormat.java b/src/com/gitblit/utils/ByteFormat.java index 97b77bde..ea198de0 100644 --- a/src/com/gitblit/utils/ByteFormat.java +++ b/src/com/gitblit/utils/ByteFormat.java @@ -28,7 +28,7 @@ public class ByteFormat extends Format { } public String format(long value) { - return format(new Long(value)); + return format(Long.valueOf(value)); } public StringBuffer format(Object obj, StringBuffer buf, FieldPosition pos) { diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java index ecf12e7f..4c7f14f6 100644 --- a/src/com/gitblit/utils/JGitUtils.java +++ b/src/com/gitblit/utils/JGitUtils.java @@ -75,9 +75,9 @@ import org.slf4j.LoggerFactory; import com.gitblit.models.Metric;
import com.gitblit.models.PathModel;
+import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.RefModel;
import com.gitblit.models.TicketModel;
-import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.TicketModel.Comment;
public class JGitUtils {
@@ -100,11 +100,11 @@ public class JGitUtils { public static List<String> getNestedRepositories(File repositoriesFolder, File folder,
boolean exportAll, boolean readNested) {
- String basefile = repositoriesFolder.getAbsolutePath();
List<String> list = new ArrayList<String>();
if (folder == null || !folder.exists()) {
return list;
}
+ String basefile = repositoriesFolder.getAbsolutePath();
for (File file : folder.listFiles()) {
if (file.isDirectory() && !file.getName().equalsIgnoreCase(Constants.DOT_GIT)) {
// if this is a git repository add it to the list
@@ -169,17 +169,15 @@ public class JGitUtils { }
public static Date getFirstChange(Repository r, String branch) {
- try {
- RevCommit commit = getFirstCommit(r, branch);
- if (commit == null) {
- // fresh repository
- return new Date(r.getDirectory().lastModified());
+ RevCommit commit = getFirstCommit(r, branch);
+ if (commit == null) {
+ if (r == null || !r.getDirectory().exists()) {
+ return new Date(0);
}
- return getCommitDate(commit);
- } catch (Throwable t) {
- LOGGER.error("Failed to determine first change", t);
+ // fresh repository
+ return new Date(r.getDirectory().lastModified());
}
- return null;
+ return getCommitDate(commit);
}
public static boolean hasCommits(Repository r) {
@@ -375,30 +373,41 @@ public class JGitUtils { }
try {
final RevWalk rw = new RevWalk(r);
- RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
- RevTree parentTree = parent.getTree();
+
RevTree commitTree = commit.getTree();
final TreeWalk walk = new TreeWalk(r);
walk.reset();
walk.setRecursive(true);
- walk.addTree(parentTree);
- walk.addTree(commitTree);
- walk.setFilter(TreeFilter.ANY_DIFF);
-
- RawTextComparator cmp = RawTextComparator.DEFAULT;
- DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
- df.setRepository(r);
- df.setDiffComparator(cmp);
- df.setDetectRenames(true);
- List<DiffEntry> diffs = df.scan(parentTree, commitTree);
- for (DiffEntry diff : diffs) {
- if (diff.getChangeType().equals(ChangeType.DELETE)) {
- list.add(new PathChangeModel(diff.getOldPath(), diff.getOldPath(), 0, diff
- .getNewMode().getBits(), commit.getId().getName(), diff.getChangeType()));
- } else {
- list.add(new PathChangeModel(diff.getNewPath(), diff.getNewPath(), 0, diff
- .getNewMode().getBits(), commit.getId().getName(), diff.getChangeType()));
+ if (commit.getParentCount() == 0) {
+ walk.addTree(commitTree);
+ while (walk.next()) {
+ list.add(new PathChangeModel(walk.getPathString(), walk.getPathString(), 0,
+ walk.getRawMode(0), commit.getId().getName(), ChangeType.ADD));
+ }
+ } else {
+ RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
+ RevTree parentTree = parent.getTree();
+ walk.addTree(parentTree);
+ walk.addTree(commitTree);
+ walk.setFilter(TreeFilter.ANY_DIFF);
+
+ RawTextComparator cmp = RawTextComparator.DEFAULT;
+ DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
+ df.setRepository(r);
+ df.setDiffComparator(cmp);
+ df.setDetectRenames(true);
+ List<DiffEntry> diffs = df.scan(parentTree, commitTree);
+ for (DiffEntry diff : diffs) {
+ if (diff.getChangeType().equals(ChangeType.DELETE)) {
+ list.add(new PathChangeModel(diff.getOldPath(), diff.getOldPath(), 0, diff
+ .getNewMode().getBits(), commit.getId().getName(), diff
+ .getChangeType()));
+ } else {
+ list.add(new PathChangeModel(diff.getNewPath(), diff.getNewPath(), 0, diff
+ .getNewMode().getBits(), commit.getId().getName(), diff
+ .getChangeType()));
+ }
}
}
} catch (Throwable t) {
@@ -511,10 +520,6 @@ public class JGitUtils { return "" + mode;
}
- public static boolean isTreeFromMode(int mode) {
- return FileMode.TREE.equals(mode);
- }
-
public static List<RevCommit> getRevLog(Repository r, int maxCount) {
return getRevLog(r, Constants.HEAD, 0, maxCount);
}
@@ -775,7 +780,45 @@ public class JGitUtils { return false;
}
- public static List<Metric> getDateMetrics(Repository r) {
+ public static List<Metric> getDateMetrics(Repository r, boolean includeTotal, String format) {
+ Metric total = new Metric("TOTAL");
+ final Map<String, Metric> metricMap = new HashMap<String, Metric>();
+
+ if (hasCommits(r)) {
+ try {
+ RevWalk walk = new RevWalk(r);
+ ObjectId object = r.resolve(Constants.HEAD);
+ RevCommit lastCommit = walk.parseCommit(object);
+ walk.markStart(lastCommit);
+ SimpleDateFormat df = new SimpleDateFormat(format);
+ Iterable<RevCommit> revlog = walk;
+ for (RevCommit rev : revlog) {
+ Date d = getCommitDate(rev);
+ String p = df.format(d);
+ if (!metricMap.containsKey(p)) {
+ metricMap.put(p, new Metric(p));
+ }
+ Metric m = metricMap.get(p);
+ m.count++;
+ total.count++;
+ }
+ } catch (Throwable t) {
+ LOGGER.error("Failed to mine log history for metrics", t);
+ }
+ }
+ List<String> keys = new ArrayList<String>(metricMap.keySet());
+ Collections.sort(keys);
+ List<Metric> metrics = new ArrayList<Metric>();
+ for (String key : keys) {
+ metrics.add(metricMap.get(key));
+ }
+ if (includeTotal) {
+ metrics.add(0, total);
+ }
+ return metrics;
+ }
+
+ public static List<Metric> getDateMetrics(Repository r, boolean includeTotal) {
Metric total = new Metric("TOTAL");
final Map<String, Metric> metricMap = new HashMap<String, Metric>();
@@ -832,9 +875,49 @@ public class JGitUtils { for (String key : keys) {
metrics.add(metricMap.get(key));
}
- metrics.add(0, total);
+ if (includeTotal) {
+ metrics.add(0, total);
+ }
return metrics;
}
+
+ public static List<Metric> getAuthorMetrics(Repository r) {
+ Metric total = new Metric("TOTAL");
+ final Map<String, Metric> metricMap = new HashMap<String, Metric>();
+
+ if (hasCommits(r)) {
+ try {
+ RevWalk walk = new RevWalk(r);
+ ObjectId object = r.resolve(Constants.HEAD);
+ RevCommit lastCommit = walk.parseCommit(object);
+ walk.markStart(lastCommit);
+
+ Iterable<RevCommit> revlog = walk;
+ for (RevCommit rev : revlog) {
+ String p = rev.getAuthorIdent().getName();
+ if (StringUtils.isEmpty(p)) {
+ p = rev.getAuthorIdent().getEmailAddress();
+ }
+ if (!metricMap.containsKey(p)) {
+ metricMap.put(p, new Metric(p));
+ }
+ Metric m = metricMap.get(p);
+ m.count++;
+ total.count++;
+ }
+ } catch (Throwable t) {
+ LOGGER.error("Failed to mine log history for metrics", t);
+ }
+ }
+ List<String> keys = new ArrayList<String>(metricMap.keySet());
+ Collections.sort(keys);
+ List<Metric> metrics = new ArrayList<Metric>();
+ for (String key : keys) {
+ metrics.add(metricMap.get(key));
+ }
+ return metrics;
+ }
+
public static RefModel getTicketsBranch(Repository r) {
RefModel ticgitBranch = null;
diff --git a/src/com/gitblit/utils/TimeUtils.java b/src/com/gitblit/utils/TimeUtils.java index 805b44f5..ece87dd8 100644 --- a/src/com/gitblit/utils/TimeUtils.java +++ b/src/com/gitblit/utils/TimeUtils.java @@ -47,7 +47,7 @@ public class TimeUtils { return days + (days > 1 ? " days" : " day");
} else if (days < 365) {
int rem = days % 30;
- return (days / 30) + (rem >= 15 ? 1 : 0) + " months";
+ return ((days / 30) + (rem >= 15 ? 1 : 0)) + " months";
} else {
int years = days / 365;
int rem = days % 365;
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.java b/src/com/gitblit/wicket/GitBlitWebApp.java index 1d251d9c..71f5aada 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/com/gitblit/wicket/GitBlitWebApp.java @@ -41,6 +41,7 @@ import com.gitblit.wicket.pages.PatchPage; import com.gitblit.wicket.pages.RawPage;
import com.gitblit.wicket.pages.RepositoriesPage;
import com.gitblit.wicket.pages.SearchPage;
+import com.gitblit.wicket.pages.StatsPage;
import com.gitblit.wicket.pages.SummaryPage;
import com.gitblit.wicket.pages.TagPage;
import com.gitblit.wicket.pages.TagsPage;
@@ -83,7 +84,8 @@ public class GitBlitWebApp extends WebApplication { mount("/patch", PatchPage.class, "r", "h", "f");
mount("/history", HistoryPage.class, "r", "h", "f");
mount("/search", SearchPage.class);
-
+ mount("/stats", StatsPage.class, "r");
+
// setup ticket urls
mount("/tickets", TicketsPage.class, "r");
mount("/ticket", TicketPage.class, "r", "h", "f");
diff --git a/src/com/gitblit/wicket/WicketUtils.java b/src/com/gitblit/wicket/WicketUtils.java index ac31488c..aef68eee 100644 --- a/src/com/gitblit/wicket/WicketUtils.java +++ b/src/com/gitblit/wicket/WicketUtils.java @@ -17,6 +17,7 @@ package com.gitblit.wicket; import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
@@ -29,9 +30,12 @@ import org.apache.wicket.markup.html.image.ContextImage; import org.apache.wicket.resource.ContextRelativeResource;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.Constants;
+import org.wicketstuff.googlecharts.AbstractChartData;
+import org.wicketstuff.googlecharts.IChartData;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
+import com.gitblit.models.Metric;
import com.gitblit.utils.JGitUtils.SearchType;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TimeUtils;
@@ -295,4 +299,65 @@ public class WicketUtils { WicketUtils.setHtmlTooltip(label, title);
return label;
}
+
+ public static IChartData getChartData(Collection<Metric> metrics) {
+ final double[] commits = new double[metrics.size()];
+ final double[] tags = new double[metrics.size()];
+ int i = 0;
+ double max = 0;
+ for (Metric m : metrics) {
+ commits[i] = m.count;
+ if (m.tag > 0) {
+ tags[i] = m.count;
+ } else {
+ tags[i] = -1d;
+ }
+ max = Math.max(max, m.count);
+ i++;
+ }
+ IChartData data = new AbstractChartData(max) {
+ private static final long serialVersionUID = 1L;
+
+ public double[][] getData() {
+ return new double[][] { commits, tags };
+ }
+ };
+ return data;
+ }
+
+ public static double maxValue(Collection<Metric> metrics) {
+ double max = Double.MIN_VALUE;
+ for (Metric m : metrics) {
+ if (m.count > max) {
+ max = m.count;
+ }
+ }
+ return max;
+ }
+
+ public static IChartData getScatterData(Collection<Metric> metrics) {
+ final double[] y = new double[metrics.size()];
+ final double[] x = new double[metrics.size()];
+ int i = 0;
+ double max = 0;
+ for (Metric m : metrics) {
+ y[i] = m.count;
+ if (m.duration > 0) {
+ x[i] = m.duration;
+ } else {
+ x[i] = -1d;
+ }
+ max = Math.max(max, m.count);
+ i++;
+ }
+ IChartData data = new AbstractChartData(max) {
+ private static final long serialVersionUID = 1L;
+
+ public double[][] getData() {
+ return new double[][] { x, y };
+ }
+ };
+ return data;
+ }
+
}
diff --git a/src/com/gitblit/wicket/pages/CommitDiffPage.html b/src/com/gitblit/wicket/pages/CommitDiffPage.html index 50a88776..8f238a7a 100644 --- a/src/com/gitblit/wicket/pages/CommitDiffPage.html +++ b/src/com/gitblit/wicket/pages/CommitDiffPage.html @@ -16,7 +16,7 @@ <div wicket:id="commitHeader">[commit header]</div>
<!-- changed paths -->
- <div style="padding-top:15px;">
+ <div style="padding-top:15px">
<!-- commit legend -->
<div style="text-align:right;" wicket:id="commitLegend"></div>
diff --git a/src/com/gitblit/wicket/pages/CommitDiffPage.java b/src/com/gitblit/wicket/pages/CommitDiffPage.java index 1f492aca..e7af833d 100644 --- a/src/com/gitblit/wicket/pages/CommitDiffPage.java +++ b/src/com/gitblit/wicket/pages/CommitDiffPage.java @@ -24,6 +24,7 @@ import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -99,7 +100,7 @@ public class CommitDiffPage extends RepositoryPage { newPathParameter(entry.path)));
item.add(new BookmarkablePageLink<Void>("blame", BlobPage.class).setEnabled(false));
item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class,
- newPathParameter(entry.path)));
+ newPathParameter(entry.path)).setEnabled(!entry.changeType.equals(ChangeType.ADD) && !entry.changeType.equals(ChangeType.DELETE)));
WicketUtils.setAlternatingBackground(item, counter);
counter++;
diff --git a/src/com/gitblit/wicket/pages/CommitPage.java b/src/com/gitblit/wicket/pages/CommitPage.java index dc674a2e..bc0d8792 100644 --- a/src/com/gitblit/wicket/pages/CommitPage.java +++ b/src/com/gitblit/wicket/pages/CommitPage.java @@ -26,6 +26,7 @@ import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import org.apache.wicket.model.StringResourceModel;
+import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -134,12 +135,12 @@ public class CommitPage extends RepositoryPage { }
item.add(new BookmarkablePageLink<Void>("diff", BlobDiffPage.class,
- newPathParameter(entry.path)));
+ newPathParameter(entry.path)).setEnabled(!entry.changeType.equals(ChangeType.ADD) && !entry.changeType.equals(ChangeType.DELETE)));
item.add(new BookmarkablePageLink<Void>("view", BlobPage.class,
newPathParameter(entry.path)));
item.add(new BookmarkablePageLink<Void>("blame", BlobPage.class).setEnabled(false));
item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class,
- newPathParameter(entry.path)));
+ newPathParameter(entry.path)).setEnabled(!entry.changeType.equals(ChangeType.ADD)));
WicketUtils.setAlternatingBackground(item, counter);
counter++;
diff --git a/src/com/gitblit/wicket/pages/RepositoryPage.html b/src/com/gitblit/wicket/pages/RepositoryPage.html index 0e0ce476..0f245eff 100644 --- a/src/com/gitblit/wicket/pages/RepositoryPage.html +++ b/src/com/gitblit/wicket/pages/RepositoryPage.html @@ -18,7 +18,7 @@ <!-- page nav links -->
<div class="page_nav">
- <a wicket:id="summary"><wicket:message key="gb.summary"></wicket:message></a> | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | <a wicket:id="branches"><wicket:message key="gb.branches"></wicket:message></a> | <a wicket:id="tags"><wicket:message key="gb.tags"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> <span wicket:id="extra"><span wicket:id="extraSeparator"></span><span wicket:id="extraLink"></span></span>
+ <a wicket:id="summary"><wicket:message key="gb.summary"></wicket:message></a> | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | <a wicket:id="branches"><wicket:message key="gb.branches"></wicket:message></a> | <a wicket:id="tags"><wicket:message key="gb.tags"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="stats"><wicket:message key="gb.stats"></wicket:message></a> <span wicket:id="extra"><span wicket:id="extraSeparator"></span><span wicket:id="extraLink"></span></span>
</div>
</div>
diff --git a/src/com/gitblit/wicket/pages/RepositoryPage.java b/src/com/gitblit/wicket/pages/RepositoryPage.java index 109c51a8..2610c4c6 100644 --- a/src/com/gitblit/wicket/pages/RepositoryPage.java +++ b/src/com/gitblit/wicket/pages/RepositoryPage.java @@ -75,6 +75,7 @@ public abstract class RepositoryPage extends BasePage { put("branches", "gb.branches");
put("tags", "gb.tags");
put("tree", "gb.tree");
+ put("stats", "gb.stats");
put("tickets", "gb.tickets");
put("edit", "gb.edit");
}
@@ -103,6 +104,8 @@ public abstract class RepositoryPage extends BasePage { WicketUtils.newRepositoryParameter(repositoryName)));
add(new BookmarkablePageLink<Void>("tree", TreePage.class,
WicketUtils.newRepositoryParameter(repositoryName)));
+ add(new BookmarkablePageLink<Void>("stats", StatsPage.class,
+ WicketUtils.newRepositoryParameter(repositoryName)));
// per-repository extra page links
List<String> extraPageLinks = new ArrayList<String>();
diff --git a/src/com/gitblit/wicket/pages/StatsPage.html b/src/com/gitblit/wicket/pages/StatsPage.html new file mode 100644 index 00000000..d6f23e01 --- /dev/null +++ b/src/com/gitblit/wicket/pages/StatsPage.html @@ -0,0 +1,23 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"
+ xml:lang="en"
+ lang="en">
+
+<body>
+<wicket:extend>
+ <h2>Commit Activity</h2>
+ <div><img wicket:id="commitsChart" /></div>
+
+ <h2>Commit Activity by Day of Week</h2>
+ <div><img wicket:id="dayOfWeekChart" /></div>
+
+ <h2>Commit Activity by Time of Day</h2>
+ <div><img wicket:id="timeOfDayChart" /></div>
+
+ <h2>Most Prolific Authors</h2>
+ <div><img wicket:id="authorsChart" /></div>
+
+</wicket:extend>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/StatsPage.java b/src/com/gitblit/wicket/pages/StatsPage.java new file mode 100644 index 00000000..0b16211e --- /dev/null +++ b/src/com/gitblit/wicket/pages/StatsPage.java @@ -0,0 +1,189 @@ +/*
+ * 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.wicket.pages;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.wicket.PageParameters;
+import org.eclipse.jgit.lib.Repository;
+import org.wicketstuff.googlecharts.Chart;
+import org.wicketstuff.googlecharts.ChartAxis;
+import org.wicketstuff.googlecharts.ChartAxisType;
+import org.wicketstuff.googlecharts.ChartProvider;
+import org.wicketstuff.googlecharts.ChartType;
+import org.wicketstuff.googlecharts.IChartData;
+import org.wicketstuff.googlecharts.LineStyle;
+import org.wicketstuff.googlecharts.MarkerType;
+import org.wicketstuff.googlecharts.ShapeMarker;
+
+import com.gitblit.models.Metric;
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.WicketUtils;
+
+public class StatsPage extends RepositoryPage {
+
+ public StatsPage(PageParameters params) {
+ super(params);
+ Repository r = getRepository();
+ insertLinePlot("commitsChart", JGitUtils.getDateMetrics(r, false));
+ insertBarPlot("dayOfWeekChart", getDayOfWeekMetrics(r));
+ insertLinePlot("timeOfDayChart", getTimeOfDayMetrics(r));
+ insertPieChart("authorsChart", getAuthorMetrics(r));
+ }
+
+ private void insertLinePlot(String wicketId, List<Metric> metrics) {
+ if ((metrics != null) && (metrics.size() > 0)) {
+ IChartData data = WicketUtils.getChartData(metrics);
+
+ ChartProvider provider = new ChartProvider(new Dimension(400, 100), ChartType.LINE,
+ data);
+ ChartAxis dateAxis = new ChartAxis(ChartAxisType.BOTTOM);
+ dateAxis.setLabels(new String[] { metrics.get(0).name,
+ metrics.get(metrics.size() / 2).name, metrics.get(metrics.size() - 1).name });
+ provider.addAxis(dateAxis);
+
+ ChartAxis commitAxis = new ChartAxis(ChartAxisType.LEFT);
+ commitAxis.setLabels(new String[] { "",
+ String.valueOf((int) WicketUtils.maxValue(metrics)) });
+ provider.addAxis(commitAxis);
+
+ provider.setLineStyles(new LineStyle[] { new LineStyle(2, 4, 0), new LineStyle(0, 4, 1) });
+ provider.addShapeMarker(new ShapeMarker(MarkerType.CIRCLE, Color.BLUE, 1, -1, 5));
+
+ add(new Chart(wicketId, provider));
+ } else {
+ add(WicketUtils.newBlankImage(wicketId));
+ }
+ }
+
+ private void insertBarPlot(String wicketId, List<Metric> metrics) {
+ if ((metrics != null) && (metrics.size() > 0)) {
+ IChartData data = WicketUtils.getChartData(metrics);
+
+ ChartProvider provider = new ChartProvider(new Dimension(400, 100),
+ ChartType.BAR_VERTICAL_SET, data);
+ ChartAxis dateAxis = new ChartAxis(ChartAxisType.BOTTOM);
+ List<String> labels = new ArrayList<String>();
+ for (Metric metric : metrics) {
+ labels.add(metric.name);
+ }
+ dateAxis.setLabels(labels.toArray(new String[labels.size()]));
+ provider.addAxis(dateAxis);
+
+ ChartAxis commitAxis = new ChartAxis(ChartAxisType.LEFT);
+ commitAxis.setLabels(new String[] { "",
+ String.valueOf((int) WicketUtils.maxValue(metrics)) });
+ provider.addAxis(commitAxis);
+
+ add(new Chart(wicketId, provider));
+ } else {
+ add(WicketUtils.newBlankImage(wicketId));
+ }
+ }
+
+ private void insertPieChart(String wicketId, List<Metric> metrics) {
+ if ((metrics != null) && (metrics.size() > 0)) {
+ IChartData data = WicketUtils.getChartData(metrics);
+ List<String> labels = new ArrayList<String>();
+ for (Metric metric : metrics) {
+ labels.add(metric.name);
+ }
+ ChartProvider provider = new ChartProvider(new Dimension(400, 200), ChartType.PIE, data);
+ provider.setPieLabels(labels.toArray(new String[labels.size()]));
+ add(new Chart(wicketId, provider));
+ } else {
+ add(WicketUtils.newBlankImage(wicketId));
+ }
+ }
+
+ private List<Metric> getDayOfWeekMetrics(Repository repository) {
+ List<Metric> list = JGitUtils.getDateMetrics(repository, false, "E");
+ SimpleDateFormat sdf = new SimpleDateFormat("E");
+ Calendar cal = Calendar.getInstance();
+
+ List<Metric> sorted = new ArrayList<Metric>(7);
+ int firstDayOfWeek = cal.getFirstDayOfWeek();
+ int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
+
+ // rewind date to first day of week
+ cal.add(Calendar.DATE, firstDayOfWeek - dayOfWeek);
+ for (int i = 0; i < 7; i++) {
+ String day = sdf.format(cal.getTime());
+ for (Metric metric : list) {
+ if (metric.name.equals(day)) {
+ sorted.add(i, metric);
+ list.remove(metric);
+ break;
+ }
+ }
+ cal.add(Calendar.DATE, 1);
+ }
+ return sorted;
+ }
+
+ private List<Metric> getTimeOfDayMetrics(Repository repository) {
+ SimpleDateFormat ndf = new SimpleDateFormat("yyyy-MM-dd");
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+ List<Metric> list = JGitUtils.getDateMetrics(repository, false, "yyyy-MM-dd HH:mm");
+ Calendar cal = Calendar.getInstance();
+
+ for (Metric metric : list) {
+ try {
+ Date date = sdf.parse(metric.name);
+ cal.setTime(date);
+ double y = cal.get(Calendar.HOUR_OF_DAY) + (cal.get(Calendar.MINUTE) / 60d);
+ metric.duration = (int) (date.getTime() / 60000L);
+ metric.count = y;
+ metric.name = ndf.format(date);
+ } catch (ParseException p) {
+ }
+ }
+ return list;
+ }
+
+ private List<Metric> getAuthorMetrics(Repository repository) {
+ List<Metric> authors = JGitUtils.getAuthorMetrics(repository);
+ Collections.sort(authors, new Comparator<Metric>() {
+ @Override
+ public int compare(Metric o1, Metric o2) {
+ if (o1.count > o2.count) {
+ return -1;
+ } else if (o1.count < o2.count) {
+ return 1;
+ }
+ return 0;
+ }
+ });
+ if (authors.size() > 10) {
+ return authors.subList(0, 9);
+ }
+ return authors;
+ }
+
+ @Override
+ protected String getPageName() {
+ return getString("gb.stats");
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/SummaryPage.java b/src/com/gitblit/wicket/pages/SummaryPage.java index 181de0da..1157d30c 100644 --- a/src/com/gitblit/wicket/pages/SummaryPage.java +++ b/src/com/gitblit/wicket/pages/SummaryPage.java @@ -27,7 +27,6 @@ import org.apache.wicket.PageParameters; import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.protocol.http.WebRequest;
import org.eclipse.jgit.lib.Repository;
-import org.wicketstuff.googlecharts.AbstractChartData;
import org.wicketstuff.googlecharts.Chart;
import org.wicketstuff.googlecharts.ChartAxis;
import org.wicketstuff.googlecharts.ChartAxisType;
@@ -73,7 +72,7 @@ public class SummaryPage extends RepositoryPage { List<Metric> metrics = null;
Metric metricsTotal = null;
if (GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
- metrics = JGitUtils.getDateMetrics(r);
+ metrics = JGitUtils.getDateMetrics(r, true);
metricsTotal = metrics.remove(0);
}
@@ -152,7 +151,7 @@ public class SummaryPage extends RepositoryPage { private void insertActivityGraph(List<Metric> metrics) {
if ((metrics != null) && (metrics.size() > 0)
&& GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
- IChartData data = getChartData(metrics);
+ IChartData data = WicketUtils.getChartData(metrics);
ChartProvider provider = new ChartProvider(new Dimension(400, 100), ChartType.LINE,
data);
@@ -162,7 +161,7 @@ public class SummaryPage extends RepositoryPage { provider.addAxis(dateAxis);
ChartAxis commitAxis = new ChartAxis(ChartAxisType.LEFT);
- commitAxis.setLabels(new String[] { "", String.valueOf((int) maxValue(metrics)) });
+ commitAxis.setLabels(new String[] { "", String.valueOf((int) WicketUtils.maxValue(metrics)) });
provider.addAxis(commitAxis);
provider.setLineStyles(new LineStyle[] { new LineStyle(2, 4, 0), new LineStyle(0, 4, 1) });
@@ -173,47 +172,4 @@ public class SummaryPage extends RepositoryPage { add(WicketUtils.newBlankImage("commitsChart"));
}
}
-
- protected IChartData getChartData(List<Metric> metrics) {
- final double[] commits = new double[metrics.size()];
- final double[] tags = new double[metrics.size()];
- int i = 0;
- double max = 0;
- for (Metric m : metrics) {
- commits[i] = m.count;
- if (m.tag > 0) {
- tags[i] = m.count;
- } else {
- tags[i] = -1d;
- }
- max = Math.max(max, m.count);
- i++;
- }
- IChartData data = new AbstractChartData(max) {
- private static final long serialVersionUID = 1L;
-
- public double[][] getData() {
- return new double[][] { commits, tags };
- }
- };
- return data;
- }
-
- protected String[] getNames(List<Metric> results) {
- String[] names = new String[results.size()];
- for (int i = 0; i < results.size(); i++) {
- names[i] = results.get(i).name;
- }
- return names;
- }
-
- protected double maxValue(List<Metric> metrics) {
- double max = Double.MIN_VALUE;
- for (Metric m : metrics) {
- if (m.count > max) {
- max = m.count;
- }
- }
- return max;
- }
}
diff --git a/src/com/gitblit/wicket/panels/LogPanel.java b/src/com/gitblit/wicket/panels/LogPanel.java index c5ccac43..436c24f7 100644 --- a/src/com/gitblit/wicket/panels/LogPanel.java +++ b/src/com/gitblit/wicket/panels/LogPanel.java @@ -126,7 +126,7 @@ public class LogPanel extends BasePanel { item.add(new BookmarkablePageLink<Void>("view", CommitPage.class, WicketUtils
.newObjectParameter(repositoryName, entry.getName())));
item.add(new BookmarkablePageLink<Void>("diff", CommitDiffPage.class, WicketUtils
- .newObjectParameter(repositoryName, entry.getName())));
+ .newObjectParameter(repositoryName, entry.getName())).setEnabled(entry.getParentCount() > 0));
item.add(new BookmarkablePageLink<Void>("tree", TreePage.class, WicketUtils
.newObjectParameter(repositoryName, entry.getName())));
diff --git a/src/com/gitblit/wicket/resources/gitblit.css b/src/com/gitblit/wicket/resources/gitblit.css index 64484d27..c9356c3d 100644 --- a/src/com/gitblit/wicket/resources/gitblit.css +++ b/src/com/gitblit/wicket/resources/gitblit.css @@ -424,7 +424,7 @@ span.rename { div.commitLegend {
float: right;
- padding: 0.4em;
+ padding: 0.4em 0.4em 0.2em 0.4em;
vertical-align:top;
margin: 0px;
}
diff --git a/tests/com/gitblit/tests/JGitUtilsTest.java b/tests/com/gitblit/tests/JGitUtilsTest.java index d17ab5df..9007b42e 100644 --- a/tests/com/gitblit/tests/JGitUtilsTest.java +++ b/tests/com/gitblit/tests/JGitUtilsTest.java @@ -29,6 +29,7 @@ import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTree;
+import com.gitblit.GitBlit;
import com.gitblit.models.Metric;
import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.RefModel;
@@ -38,12 +39,12 @@ import com.gitblit.utils.JGitUtils; public class JGitUtilsTest extends TestCase {
- private List<String> getRepositories() {
- return JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, true, true);
- }
-
public void testFindRepositories() {
- List<String> list = getRepositories();
+ List<String> list = JGitUtils.getRepositoryList(null, true, true);
+ assertTrue(list.size() == 0);
+ list.addAll(JGitUtils.getRepositoryList(new File("DoesNotExist"), true, true));
+ assertTrue(list.size() == 0);
+ list.addAll(JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, true, true));
assertTrue("No repositories found in " + GitBlitSuite.REPOSITORIES, list.size() > 0);
}
@@ -53,14 +54,9 @@ public class JGitUtilsTest extends TestCase { assertTrue("Could not find repository!", repository != null);
}
- public void testLastChangeRepository() throws Exception {
- Repository repository = GitBlitSuite.getHelloworldRepository();
- Date date = JGitUtils.getLastChange(repository);
- repository.close();
- assertTrue("Could not get last repository change date!", date != null);
- }
-
public void testFirstCommit() throws Exception {
+ assertTrue(JGitUtils.getFirstChange(null, null).equals(new Date(0)));
+
Repository repository = GitBlitSuite.getHelloworldRepository();
RevCommit commit = JGitUtils.getFirstCommit(repository, null);
Date firstChange = JGitUtils.getFirstChange(repository, null);
@@ -70,6 +66,43 @@ public class JGitUtilsTest extends TestCase { commit.getName().equals("f554664a346629dc2b839f7292d06bad2db4aece"));
assertTrue(firstChange.equals(new Date(commit.getCommitTime() * 1000L)));
}
+
+ public void testLastCommit() throws Exception {
+ assertTrue(JGitUtils.getLastChange(null).equals(new Date(0)));
+
+ Repository repository = GitBlitSuite.getHelloworldRepository();
+ assertTrue(JGitUtils.getCommit(repository, null) != null);
+ Date date = JGitUtils.getLastChange(repository);
+ repository.close();
+ assertTrue("Could not get last repository change date!", date != null);
+ }
+
+
+
+ public void testCreateRepository() throws Exception {
+ String[] repositories = { "NewTestRepository.git", "NewTestRepository" };
+ for (String repositoryName : repositories) {
+ boolean isBare = repositoryName.endsWith(".git");
+ Repository repository = JGitUtils.createRepository(GitBlitSuite.REPOSITORIES,
+ repositoryName, isBare);
+ File folder;
+ if (isBare) {
+ folder = new File(GitBlitSuite.REPOSITORIES, repositoryName);
+ } else {
+ folder = new File(GitBlitSuite.REPOSITORIES, repositoryName + "/.git");
+ }
+ assertTrue(repository != null);
+ assertFalse(JGitUtils.hasCommits(repository));
+ assertTrue(JGitUtils.getFirstCommit(repository, null) == null);
+ assertTrue(JGitUtils.getFirstChange(repository, null).getTime() == folder
+ .lastModified());
+ assertTrue(JGitUtils.getLastChange(repository).getTime() == folder
+ .lastModified());
+ assertTrue(JGitUtils.getCommit(repository, null) == null);
+ repository.close();
+ assertTrue(GitBlit.self().deleteRepository(repositoryName));
+ }
+ }
public void testRefs() throws Exception {
Repository repository = GitBlitSuite.getTicgitRepository();
@@ -151,7 +184,7 @@ public class JGitUtilsTest extends TestCase { public void testMetrics() throws Exception {
Repository repository = GitBlitSuite.getHelloworldRepository();
- List<Metric> metrics = JGitUtils.getDateMetrics(repository);
+ List<Metric> metrics = JGitUtils.getDateMetrics(repository, true);
repository.close();
assertTrue("No metrics found!", metrics.size() > 0);
}
|