James Moger
2011-06-01 424fe1b372d225d65eb42e6125b24cbb982c5969
Stats -> Metrics. Docs in distribution zip. Created MetricUtils.
1 files added
2 files renamed
12 files modified
570 ■■■■■ changed files
build.xml 138 ●●●● patch | view | raw | blame | history
docs/00_index.mkd 2 ●●● patch | view | raw | blame | history
src/com/gitblit/Build.java 3 ●●●● patch | view | raw | blame | history
src/com/gitblit/BuildSite.java 64 ●●●●● patch | view | raw | blame | history
src/com/gitblit/utils/JGitUtils.java 144 ●●●●● patch | view | raw | blame | history
src/com/gitblit/utils/MetricUtils.java 179 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebApp.java 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebApp.properties 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/MetricsPage.html patch | view | raw | blame | history
src/com/gitblit/wicket/pages/MetricsPage.java 16 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoryPage.html 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoryPage.java 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/SummaryPage.html 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/SummaryPage.java 7 ●●●●● patch | view | raw | blame | history
tests/com/gitblit/tests/JGitUtilsTest.java 3 ●●●● patch | view | raw | blame | history
build.xml
@@ -89,36 +89,6 @@
            </manifest>
        </jar>
        <!-- Delete the deploy folder -->
        <delete dir="${basedir}/deploy" />
        <!-- Create deployment folder structure -->
        <mkdir dir="${basedir}/deploy" />
        <copy todir="${basedir}/deploy" file="${project.jar}" />
        <copy todir="${basedir}/deploy">
            <fileset dir="${basedir}/distrib">
                <include name="**/*" />
            </fileset>
        </copy>
        <!-- Create Zip deployment -->
        <property name="distribution.zipfile" value="gitblit-${gb.version}.zip" />
        <zip destfile="${distribution.zipfile}">
            <fileset dir="${basedir}/deploy">
                <include name="**/*" />
            </fileset>
        </zip>
        <!-- Delete the deploy folder -->
        <delete dir="${basedir}/deploy" />
        <!-- Cleanup builds -->
        <delete>
            <fileset dir="${basedir}">
                <include name="${project.jar}" />
            </fileset>
        </delete>
        <!-- Build Site -->
        <delete dir="${basedir}/site" />
        <mkdir dir="${basedir}/site" />
@@ -195,7 +165,7 @@
            <arg value="--alias" />
            <arg value="index=overview" />
            <arg value="--alias" />
            <arg value="properties=gitblit.properties" />
@@ -216,6 +186,112 @@
        </java>
        <!-- Delete the deploy folder -->
        <delete dir="${basedir}/deploy" />
        <!-- Create deployment folder structure -->
        <mkdir dir="${basedir}/deploy" />
        <copy todir="${basedir}/deploy" file="${project.jar}" />
        <copy todir="${basedir}/deploy">
            <fileset dir="${basedir}/distrib">
                <include name="**/*" />
            </fileset>
        </copy>
        <!-- Build Deployment Docs -->
        <mkdir dir="${basedir}/deploy/docs" />
        <copy todir="${basedir}/deploy/docs">
            <!-- Copy selected Gitblit resources -->
            <fileset dir="${basedir}/src/com/gitblit/wicket/resources">
                <include name="background.png" />
                <include name="gitblit.css" />
                <include name="markdown.css" />
                <include name="gitblt_25.png" />
                <include name="gitblt-favicon.png" />
                <include name="lock_go_16x16.png" />
                <include name="lock_pull_16x16.png" />
                <include name="shield_16x16.png" />
                <include name="cold_16x16.png" />
                <include name="bug_16x16.png" />
                <include name="book_16x16.png" />
                <include name="blank.png" />
            </fileset>
            <!-- Copy Doc images -->
            <fileset dir="${basedir}/docs">
                <include name="*.png" />
            </fileset>
        </copy>
        <!-- Copy google-code-prettify -->
        <mkdir dir="${basedir}/src/com/gitblit/wicket/pages/prettify" />
        <copy todir="${basedir}/deploy/docs/prettify">
            <fileset dir="${basedir}/src/com/gitblit/wicket/pages/prettify">
                <exclude name="thumbs.db" />
            </fileset>
        </copy>
        <!-- Build deployment doc pages -->
        <java classpath="${project.build.dir}" classname="com.gitblit.BuildSite">
            <classpath refid="master-classpath" />
            <arg value="--sourceFolder" />
            <arg value="${basedir}/docs" />
            <arg value="--outputFolder" />
            <arg value="${basedir}/deploy/docs" />
            <arg value="--pageHeader" />
            <arg value="${basedir}/docs/page_header.html" />
            <arg value="--pageFooter" />
            <arg value="${basedir}/docs/page_footer.html" />
            <arg value="--skip" />
            <arg value="screenshots" />
            <arg value="--skip" />
            <arg value="releases" />
            <arg value="--alias" />
            <arg value="index=overview" />
            <arg value="--alias" />
            <arg value="properties=gitblit.properties" />
            <arg value="--substitute" />
            <arg value="%VERSION%=${gb.version}" />
            <arg value="--substitute" />
            <arg value="%DISTRIBUTION%=${distribution.zipfile}" />
            <arg value="--substitute" />
            <arg value="%BUILDDATE%=${gb.buildDate}" />
            <arg value="--substitute" />
            <arg value="%JGIT%=${jgit.version}" />
            <arg value="--load" />
            <arg value="%PROPERTIES%=${basedir}/distrib/gitblit.properties" />
        </java>
        <!-- Create Zip deployment -->
        <property name="distribution.zipfile" value="gitblit-${gb.version}.zip" />
        <zip destfile="${distribution.zipfile}">
            <fileset dir="${basedir}/deploy">
                <include name="**/*" />
            </fileset>
        </zip>
        <!-- Delete the deploy folder -->
        <delete dir="${basedir}/deploy" />
        <!-- Cleanup builds -->
        <delete>
            <fileset dir="${basedir}">
                <include name="${project.jar}" />
            </fileset>
        </delete>
        <!-- Cleanup -->
        <delete dir="${project.build.dir}" />
    </target>
docs/00_index.mkd
@@ -101,10 +101,10 @@
- [Log4j](http://logging.apache.org/log4j) (Apache 2.0) 
- [JCommander](http://jcommander.org) (Apache 2.0)
- [BouncyCastle](http://www.bouncycastle.org) (MIT/X11)
- [JSch - Java Secure Channel](http://www.jcraft.com/jsch) (BSD)
### Other Build Dependencies
- [Fancybox image viewer](http://fancybox.net) (MIT and GPL dual-licensed)
- [JSch - Java Secure Channel](http://www.jcraft.com/jsch) (BSD)
- [JUnit](http://junit.org) (Common Public License)
## Building from Source
src/com/gitblit/Build.java
@@ -60,6 +60,7 @@
        downloadFromApache(MavenObject.MARKDOWNPAPERS, BuildType.RUNTIME);
        downloadFromApache(MavenObject.BOUNCYCASTLE, BuildType.RUNTIME);
        downloadFromApache(MavenObject.BOUNCYCASTLE_MAIL, BuildType.RUNTIME);
        downloadFromApache(MavenObject.JSCH, BuildType.RUNTIME);
        downloadFromEclipse(MavenObject.JGIT, BuildType.RUNTIME);
        downloadFromEclipse(MavenObject.JGIT_HTTP, BuildType.RUNTIME);
@@ -80,8 +81,6 @@
        downloadFromApache(MavenObject.MARKDOWNPAPERS, BuildType.COMPILETIME);
        downloadFromApache(MavenObject.BOUNCYCASTLE, BuildType.COMPILETIME);
        downloadFromApache(MavenObject.BOUNCYCASTLE_MAIL, BuildType.COMPILETIME);
        downloadFromApache(MavenObject.JSCH, BuildType.RUNTIME);
        downloadFromApache(MavenObject.JSCH, BuildType.COMPILETIME);
        downloadFromEclipse(MavenObject.JGIT, BuildType.COMPILETIME);
src/com/gitblit/BuildSite.java
@@ -73,13 +73,15 @@
        StringBuilder sb = new StringBuilder();
        for (File file : markdownFiles) {
            String documentName = getDocumentName(file);
            String displayName = documentName;
            if (aliasMap.containsKey(documentName)) {
                displayName = aliasMap.get(documentName);
            if (!params.skips.contains(documentName)) {
                String displayName = documentName;
                if (aliasMap.containsKey(documentName)) {
                    displayName = aliasMap.get(documentName);
                }
                String fileName = documentName + ".html";
                sb.append(MessageFormat.format(linkPattern, fileName, displayName));
                sb.append(" | ");
            }
            String fileName = documentName + ".html";
            sb.append(MessageFormat.format(linkPattern, fileName, displayName));
            sb.append(" | ");
        }
        sb.setLength(sb.length() - 3);
        sb.trimToSize();
@@ -93,29 +95,32 @@
        for (File file : markdownFiles) {
            try {
                String documentName = getDocumentName(file);
                String fileName = documentName + ".html";
                System.out.println(MessageFormat.format("  {0} => {1}", file.getName(), fileName));
                InputStreamReader reader = new InputStreamReader(new FileInputStream(file),
                        Charset.forName("UTF-8"));
                String content = MarkdownUtils.transformMarkdown(reader);
                for (String token : params.substitutions) {
                    String[] kv = token.split("=");
                    content = content.replace(kv[0], kv[1]);
                if (!params.skips.contains(documentName)) {
                    String fileName = documentName + ".html";
                    System.out.println(MessageFormat.format("  {0} => {1}", file.getName(),
                            fileName));
                    InputStreamReader reader = new InputStreamReader(new FileInputStream(file),
                            Charset.forName("UTF-8"));
                    String content = MarkdownUtils.transformMarkdown(reader);
                    for (String token : params.substitutions) {
                        String[] kv = token.split("=");
                        content = content.replace(kv[0], kv[1]);
                    }
                    for (String alias : params.loads) {
                        String[] kv = alias.split("=");
                        String loadedContent = readContent(new File(kv[1]), "\n");
                        loadedContent = StringUtils.escapeForHtml(loadedContent, false);
                        loadedContent = StringUtils.breakLinesForHtml(loadedContent);
                        content = content.replace(kv[0], loadedContent);
                    }
                    OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(
                            new File(destinationFolder, fileName)), Charset.forName("UTF-8"));
                    writer.write(header);
                    writer.write(content);
                    writer.write(footer);
                    reader.close();
                    writer.close();
                }
                for (String alias : params.loads) {
                    String[] kv = alias.split("=");
                    String loadedContent = readContent(new File(kv[1]), "\n");
                    loadedContent = StringUtils.escapeForHtml(loadedContent, false);
                    loadedContent = StringUtils.breakLinesForHtml(loadedContent);
                    content = content.replace(kv[0], loadedContent);
                }
                OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(
                        destinationFolder, fileName)), Charset.forName("UTF-8"));
                writer.write(header);
                writer.write(content);
                writer.write(footer);
                reader.close();
                writer.close();
            } catch (Throwable t) {
                System.err.println("Failed to transform " + file.getName());
                t.printStackTrace();
@@ -179,6 +184,9 @@
        @Parameter(names = { "--pageFooter" }, description = "Page Footer HTML Snippet", required = true)
        public String pageFooter;
        @Parameter(names = { "--skip" }, description = "Filename to skip", required = false)
        public List<String> skips = new ArrayList<String>();
        @Parameter(names = { "--alias" }, description = "Filename=Linkname aliases", required = false)
        public List<String> aliases = new ArrayList<String>();
src/com/gitblit/utils/JGitUtils.java
@@ -21,9 +21,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -73,7 +71,6 @@
import org.slf4j.Logger;
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;
@@ -82,7 +79,7 @@
public class JGitUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);
    static final Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);
    public static Repository createRepository(File repositoriesFolder, String name, boolean bare) {
        Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(bare).call();
@@ -779,145 +776,6 @@
        }
        return false;
    }
    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>();
        if (hasCommits(r)) {
            final List<RefModel> tags = getTags(r, -1);
            final Map<ObjectId, RefModel> tagMap = new HashMap<ObjectId, RefModel>();
            for (RefModel tag : tags) {
                tagMap.put(tag.getCommitId(), tag);
            }
            try {
                RevWalk walk = new RevWalk(r);
                ObjectId object = r.resolve(Constants.HEAD);
                RevCommit firstCommit = getFirstCommit(r, Constants.HEAD);
                RevCommit lastCommit = walk.parseCommit(object);
                int diffDays = (lastCommit.getCommitTime() - firstCommit.getCommitTime())
                        / (60 * 60 * 24);
                total.duration = diffDays;
                DateFormat df;
                if (diffDays <= 90) {
                    // Days
                    df = new SimpleDateFormat("yyyy-MM-dd");
                } else if (diffDays > 90 && diffDays < 365) {
                    // Weeks
                    df = new SimpleDateFormat("yyyy-MM (w)");
                } else {
                    // Months
                    df = new SimpleDateFormat("yyyy-MM");
                }
                walk.markStart(lastCommit);
                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++;
                    if (tagMap.containsKey(rev.getId())) {
                        m.tag++;
                        total.tag++;
                    }
                }
            } 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> 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;
src/com/gitblit/utils/MetricUtils.java
New file
@@ -0,0 +1,179 @@
/*
 * Copyright 2011 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit.utils;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.models.Metric;
import com.gitblit.models.RefModel;
public class MetricUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(MetricUtils.class);
    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 (JGitUtils.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 = JGitUtils.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) {
                JGitUtils.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>();
        if (JGitUtils.hasCommits(r)) {
            final List<RefModel> tags = JGitUtils.getTags(r, -1);
            final Map<ObjectId, RefModel> tagMap = new HashMap<ObjectId, RefModel>();
            for (RefModel tag : tags) {
                tagMap.put(tag.getCommitId(), tag);
            }
            try {
                RevWalk walk = new RevWalk(r);
                ObjectId object = r.resolve(Constants.HEAD);
                RevCommit firstCommit = JGitUtils.getFirstCommit(r, Constants.HEAD);
                RevCommit lastCommit = walk.parseCommit(object);
                int diffDays = (lastCommit.getCommitTime() - firstCommit.getCommitTime())
                        / (60 * 60 * 24);
                total.duration = diffDays;
                DateFormat df;
                if (diffDays <= 90) {
                    // Days
                    df = new SimpleDateFormat("yyyy-MM-dd");
                } else if (diffDays > 90 && diffDays < 365) {
                    // Weeks
                    df = new SimpleDateFormat("yyyy-MM (w)");
                } else {
                    // Months
                    df = new SimpleDateFormat("yyyy-MM");
                }
                walk.markStart(lastCommit);
                Iterable<RevCommit> revlog = walk;
                for (RevCommit rev : revlog) {
                    Date d = JGitUtils.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++;
                    if (tagMap.containsKey(rev.getId())) {
                        m.tag++;
                        total.tag++;
                    }
                }
            } catch (Throwable t) {
                JGitUtils.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> getAuthorMetrics(Repository r) {
        Metric total = new Metric("TOTAL");
        final Map<String, Metric> metricMap = new HashMap<String, Metric>();
        if (JGitUtils.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) {
                JGitUtils.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;
    }
}
src/com/gitblit/wicket/GitBlitWebApp.java
@@ -41,7 +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.MetricsPage;
import com.gitblit.wicket.pages.SummaryPage;
import com.gitblit.wicket.pages.TagPage;
import com.gitblit.wicket.pages.TagsPage;
@@ -84,7 +84,7 @@
        mount("/patch", PatchPage.class, "r", "h", "f");
        mount("/history", HistoryPage.class, "r", "h", "f");
        mount("/search", SearchPage.class);
        mount("/stats", StatsPage.class, "r");
        mount("/metrics", MetricsPage.class, "r");
        
        // setup ticket urls
        mount("/tickets", TicketsPage.class, "r");
src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -54,7 +54,7 @@
gb.modification = modification
gb.deletion = deletion
gb.rename = rename
gb.stats = stats
gb.metrics = metrics
gb.markdown = markdown
gb.changedFiles = changed files 
gb.filesAdded = {0} files added
src/com/gitblit/wicket/pages/MetricsPage.html
src/com/gitblit/wicket/pages/MetricsPage.java
File was renamed from src/com/gitblit/wicket/pages/StatsPage.java
@@ -39,15 +39,15 @@
import org.wicketstuff.googlecharts.ShapeMarker;
import com.gitblit.models.Metric;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.MetricUtils;
import com.gitblit.wicket.WicketUtils;
public class StatsPage extends RepositoryPage {
public class MetricsPage extends RepositoryPage {
    public StatsPage(PageParameters params) {
    public MetricsPage(PageParameters params) {
        super(params);
        Repository r = getRepository();
        insertLinePlot("commitsChart", JGitUtils.getDateMetrics(r, false));
        insertLinePlot("commitsChart", MetricUtils.getDateMetrics(r, false));
        insertBarPlot("dayOfWeekChart", getDayOfWeekMetrics(r));
        insertLinePlot("timeOfDayChart", getTimeOfDayMetrics(r));
        insertPieChart("authorsChart", getAuthorMetrics(r));
@@ -119,7 +119,7 @@
    }
    private List<Metric> getDayOfWeekMetrics(Repository repository) {
        List<Metric> list = JGitUtils.getDateMetrics(repository, false, "E");
        List<Metric> list = MetricUtils.getDateMetrics(repository, false, "E");
        SimpleDateFormat sdf = new SimpleDateFormat("E");
        Calendar cal = Calendar.getInstance();
@@ -146,7 +146,7 @@
    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");
        List<Metric> list = MetricUtils.getDateMetrics(repository, false, "yyyy-MM-dd HH:mm");
        Calendar cal = Calendar.getInstance();
        for (Metric metric : list) {
@@ -164,7 +164,7 @@
    }
    private List<Metric> getAuthorMetrics(Repository repository) {
        List<Metric> authors = JGitUtils.getAuthorMetrics(repository);
        List<Metric> authors = MetricUtils.getAuthorMetrics(repository);
        Collections.sort(authors, new Comparator<Metric>() {
            @Override
            public int compare(Metric o1, Metric o2) {
@@ -184,6 +184,6 @@
    @Override
    protected String getPageName() {
        return getString("gb.stats");
        return getString("gb.metrics");
    }
}
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>  | <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>
                <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="metrics"><wicket:message key="gb.metrics"></wicket:message></a> <span wicket:id="extra"><span wicket:id="extraSeparator"></span><span wicket:id="extraLink"></span></span>
            </div>
        </div>
        
src/com/gitblit/wicket/pages/RepositoryPage.java
@@ -75,7 +75,7 @@
            put("branches", "gb.branches");
            put("tags", "gb.tags");
            put("tree", "gb.tree");
            put("stats", "gb.stats");
            put("metrics", "gb.metrics");
            put("tickets", "gb.tickets");
            put("edit", "gb.edit");
        }
@@ -104,7 +104,7 @@
                WicketUtils.newRepositoryParameter(repositoryName)));
        add(new BookmarkablePageLink<Void>("tree", TreePage.class,
                WicketUtils.newRepositoryParameter(repositoryName)));
        add(new BookmarkablePageLink<Void>("stats", StatsPage.class,
        add(new BookmarkablePageLink<Void>("metrics", MetricsPage.class,
                WicketUtils.newRepositoryParameter(repositoryName)));
        // per-repository extra page links
src/com/gitblit/wicket/pages/SummaryPage.html
@@ -19,7 +19,7 @@
                <tr><th><wicket:message key="gb.description">[description]</wicket:message></th><td><span wicket:id="repositoryDescription">[repository description]</span></td></tr>
                <tr><th><wicket:message key="gb.owner">[owner]</wicket:message></th><td><span wicket:id="repositoryOwner">[repository owner]</span></td></tr>
                <tr><th><wicket:message key="gb.lastChange">[last change]</wicket:message></th><td><span wicket:id="repositoryLastChange">[repository last change]</span></td></tr>
                <tr><th><wicket:message key="gb.stats">[stats]</wicket:message></th><td><span wicket:id="repositoryStats">[repository stats]</span></td></tr>
                <tr><th><wicket:message key="gb.metrics">[metrics]</wicket:message></th><td><span wicket:id="repositoryMetrics">[repository metrics]</span></td></tr>
                <tr><th valign="top"><wicket:message key="gb.url">[URL]</wicket:message></th><td><img style="vertical-align: top; padding-right:5px;" wicket:id="accessRestrictionIcon" /><span wicket:id="repositoryCloneUrl">[repository clone url]</span></td></tr>
            </table>
        </div>
src/com/gitblit/wicket/pages/SummaryPage.java
@@ -43,6 +43,7 @@
import com.gitblit.Keys;
import com.gitblit.models.Metric;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.MetricUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TimeUtils;
import com.gitblit.wicket.WicketUtils;
@@ -72,7 +73,7 @@
        List<Metric> metrics = null;
        Metric metricsTotal = null;
        if (GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
            metrics = JGitUtils.getDateMetrics(r, true);
            metrics = MetricUtils.getDateMetrics(r, true);
            metricsTotal = metrics.remove(0);
        }
@@ -83,9 +84,9 @@
        add(WicketUtils.createTimestampLabel("repositoryLastChange", JGitUtils.getLastChange(r),
                getTimeZone()));
        if (metricsTotal == null) {
            add(new Label("repositoryStats", ""));
            add(new Label("repositoryMetrics", ""));
        } else {
            add(new Label("repositoryStats", MessageFormat.format(
            add(new Label("repositoryMetrics", MessageFormat.format(
                    "{0} commits and {1} tags in {2}", metricsTotal.count, metricsTotal.tag,
                    TimeUtils.duration(metricsTotal.duration))));
        }
tests/com/gitblit/tests/JGitUtilsTest.java
@@ -36,6 +36,7 @@
import com.gitblit.models.TicketModel;
import com.gitblit.models.TicketModel.Comment;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.MetricUtils;
public class JGitUtilsTest extends TestCase {
@@ -184,7 +185,7 @@
    public void testMetrics() throws Exception {
        Repository repository = GitBlitSuite.getHelloworldRepository();
        List<Metric> metrics = JGitUtils.getDateMetrics(repository, true);
        List<Metric> metrics = MetricUtils.getDateMetrics(repository, true);
        repository.close();
        assertTrue("No metrics found!", metrics.size() > 0);
    }