From f1720ca884bc3fa9da1288ad955e46f165aa4168 Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Wed, 01 Jun 2011 08:09:46 -0400 Subject: [PATCH] Unit testing. Disable links on first commit. Initial stats page. --- src/com/gitblit/utils/TimeUtils.java | 2 .gitignore | 1 src/com/gitblit/utils/ByteFormat.java | 2 src/com/gitblit/wicket/pages/RepositoryPage.java | 3 src/com/gitblit/wicket/resources/gitblit.css | 2 src/com/gitblit/wicket/WicketUtils.java | 65 ++++++ src/com/gitblit/wicket/pages/StatsPage.java | 189 ++++++++++++++++++ src/com/gitblit/wicket/pages/CommitDiffPage.html | 2 src/com/gitblit/wicket/pages/CommitPage.java | 5 tests/com/gitblit/tests/JGitUtilsTest.java | 59 ++++- src/com/gitblit/wicket/pages/RepositoryPage.html | 2 distrib/users.properties | 3 src/com/gitblit/wicket/panels/LogPanel.java | 2 src/com/gitblit/wicket/pages/CommitDiffPage.java | 3 src/com/gitblit/wicket/pages/StatsPage.html | 23 ++ src/com/gitblit/wicket/GitBlitWebApp.java | 4 src/com/gitblit/wicket/pages/SummaryPage.java | 50 ---- src/com/gitblit/utils/JGitUtils.java | 153 +++++++++++--- 18 files changed, 464 insertions(+), 106 deletions(-) diff --git a/.gitignore b/.gitignore index 4495e70..87e1b32 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /users.properties /site /git +/target diff --git a/distrib/users.properties b/distrib/users.properties index d552975..233e9f9 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 97b77bd..ea198de 100644 --- a/src/com/gitblit/utils/ByteFormat.java +++ b/src/com/gitblit/utils/ByteFormat.java @@ -28,7 +28,7 @@ } 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 ecf12e7..4c7f14f 100644 --- a/src/com/gitblit/utils/JGitUtils.java +++ b/src/com/gitblit/utils/JGitUtils.java @@ -75,9 +75,9 @@ 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 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 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 @@ } 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); + 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())); + 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) { @@ -509,10 +518,6 @@ return "missing"; } return "" + mode; - } - - public static boolean isTreeFromMode(int mode) { - return FileMode.TREE.equals(mode); } public static List<RevCommit> getRevLog(Repository r, int maxCount) { @@ -775,7 +780,45 @@ 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 @@ 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 805b44f..ece87dd 100644 --- a/src/com/gitblit/utils/TimeUtils.java +++ b/src/com/gitblit/utils/TimeUtils.java @@ -47,7 +47,7 @@ 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 1d251d9..71f5aad 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/com/gitblit/wicket/GitBlitWebApp.java @@ -41,6 +41,7 @@ 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 @@ 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 ac31488..aef68ee 100644 --- a/src/com/gitblit/wicket/WicketUtils.java +++ b/src/com/gitblit/wicket/WicketUtils.java @@ -17,6 +17,7 @@ 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.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 @@ 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 50a8877..8f238a7 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 1f492ac..e7af833 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.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 @@ 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 dc674a2..bc0d879 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.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 @@ } 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 0e0ce47..0f245ef 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 109c51a..2610c4c 100644 --- a/src/com/gitblit/wicket/pages/RepositoryPage.java +++ b/src/com/gitblit/wicket/pages/RepositoryPage.java @@ -75,6 +75,7 @@ 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 @@ 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 0000000..d6f23e0 --- /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 0000000..0b16211 --- /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 181de0d..1157d30 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.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 @@ 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 @@ 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 @@ 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) }); @@ -172,48 +171,5 @@ } else { 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 c5ccac4..436c24f 100644 --- a/src/com/gitblit/wicket/panels/LogPanel.java +++ b/src/com/gitblit/wicket/panels/LogPanel.java @@ -126,7 +126,7 @@ 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 64484d2..c9356c3 100644 --- a/src/com/gitblit/wicket/resources/gitblit.css +++ b/src/com/gitblit/wicket/resources/gitblit.css @@ -424,7 +424,7 @@ 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 d17ab5d..9007b42 100644 --- a/tests/com/gitblit/tests/JGitUtilsTest.java +++ b/tests/com/gitblit/tests/JGitUtilsTest.java @@ -29,6 +29,7 @@ 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 @@ 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 @@ 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); @@ -69,6 +65,43 @@ assertTrue("Incorrect first commit!", 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 { @@ -151,7 +184,7 @@ 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); } -- Gitblit v1.9.1