James Moger
2011-04-04 fc84260e4238fda10842c1bd3b9fb0cb74b95426
Dropped log links, created new stylesheet, added activity graph.
2 files deleted
34 files added
32 files modified
2579 ■■■■ changed files
.classpath 1 ●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/AbstractChartData.java 46 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/AreaFillType.java 22 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/AxisAlignment.java 23 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/Chart.java 602 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ChartAxis.java 79 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ChartAxisType.java 25 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ChartDataEncoding.java 82 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ChartGrid.java 51 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ChartProvider.java 176 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ChartType.java 34 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/FillArea.java 54 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/IChartAxis.java 26 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/IChartData.java 16 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/IChartFill.java 10 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/IChartGrid.java 18 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/IChartProvider.java 47 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/IFillArea.java 21 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ILineStyle.java 16 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ILinearGradientFill.java 18 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ILinearStripesFill.java 18 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/IRangeMarker.java 20 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/IShapeMarker.java 22 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ISolidFill.java 13 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/LineStyle.java 43 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/LinearGradientFill.java 49 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/LinearStripesFill.java 49 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/MarkerType.java 31 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/Range.java 32 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/RangeMarker.java 55 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/RangeType.java 22 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/ShapeMarker.java 65 ●●●●● patch | view | raw | blame | history
contrib/com/codecommit/wicket/SolidFill.java 25 ●●●●● patch | view | raw | blame | history
gitblit.properties 8 ●●●● patch | view | raw | blame | history
resources/blank.png patch | view | raw | blame | history
resources/gitblit.css 296 ●●●●● patch | view | raw | blame | history
src/com/gitblit/utils/JGitUtils.java 30 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebApp.java 2 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/WicketUtils.java 20 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/models/Metric.java 15 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/models/PathModel.java 9 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/BlobPage.java 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/CommitPage.html 30 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/HeadsPage.html 3 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/LogPage.html 33 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/LogPage.java 69 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoriesPage.html 7 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoriesPage.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/ShortLogPage.html 13 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/SummaryPage.html 62 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/SummaryPage.java 81 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/TagPage.html 12 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/TagsPage.html 10 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/TagsPage.java 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/TreePage.html 7 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/TreePage.java 10 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/HeadLinksPanel.html 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/HeadLinksPanel.java 2 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/PageFooter.html 5 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/PageFooter.java 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/PageHeader.html 3 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/PageLinksPanel.html 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/PageLinksPanel.java 8 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.java 3 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/PathLinksPanel.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/TagLinksPanel.html 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/TagLinksPanel.java 2 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/TreeLinksPanel.java 6 ●●●● patch | view | raw | blame | history
.classpath
@@ -2,6 +2,7 @@
<classpath>
    <classpathentry kind="src" path="src"/>
    <classpathentry kind="src" path="resources"/>
    <classpathentry kind="src" path="contrib"/>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
    <classpathentry kind="lib" path="lib/jgit-0.11.3.jar" sourcepath="/org.eclipse.jgit"/>
    <classpathentry kind="lib" path="lib/jgit-http-0.11.3.jar" sourcepath="/org.eclipse.jgit.http.server"/>
contrib/com/codecommit/wicket/AbstractChartData.java
New file
@@ -0,0 +1,46 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.io.Serializable;
/**
 * @author Daniel Spiewak
 */
public abstract class AbstractChartData implements IChartData, Serializable {
    private static final long serialVersionUID = 1L;
    private ChartDataEncoding encoding;
    private double max;
    public AbstractChartData() {
        this(62);
    }
    public AbstractChartData(double max) {
        this(ChartDataEncoding.SIMPLE, max);
    }
    public AbstractChartData(ChartDataEncoding encoding, double max) {
        this.encoding = encoding;
        this.max = max;
    }
    public ChartDataEncoding getEncoding() {
        return encoding;
    }
    public double getMax() {
        return max;
    }
    public void setEncoding(ChartDataEncoding encoding) {
        this.encoding = encoding;
    }
    public void setMax(double max) {
        this.max = max;
    }
}
contrib/com/codecommit/wicket/AreaFillType.java
New file
@@ -0,0 +1,22 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public enum AreaFillType {
    BETWEEN("b"),
    DOWN("B");
    private final String rendering;
    private AreaFillType(String rendering) {
        this.rendering = rendering;
    }
    public String getRendering() {
        return rendering;
    }
}
contrib/com/codecommit/wicket/AxisAlignment.java
New file
@@ -0,0 +1,23 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public enum AxisAlignment {
    LEFT(-1),
    CENTER(0),
    RIGHT(1);
    private final int rendering;
    private AxisAlignment(int rendering) {
        this.rendering = rendering;
    }
    public int getRendering() {
        return rendering;
    }
}
contrib/com/codecommit/wicket/Chart.java
New file
@@ -0,0 +1,602 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
import java.awt.Dimension;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebComponent;
/**
 * @author Daniel Spiewak
 */
public class Chart extends WebComponent {
    private static final long serialVersionUID = 1L;
    private IChartProvider provider;
    private StringBuilder url;
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    public Chart(String id, IChartProvider provider) {
        super(id);
        this.provider = provider;
    }
    @Override
    public boolean getStatelessHint() {
        return false;
    }
    public void invalidate() {
        lock.writeLock().lock();
        try {
            url = null;
        } finally {
            lock.writeLock().unlock();
        }
    }
    public CharSequence constructURL() {
        lock.writeLock().lock();
        try {
            if (url != null) {
                return url;
            }
            url = new StringBuilder("http://chart.apis.google.com/chart?");
            addParameter(url, "chs", render(provider.getSize()));
            addParameter(url, "chd", render(provider.getData()));
            addParameter(url, "cht", render(provider.getType()));
            addParameter(url, "chbh", render(provider.getBarWidth(), provider.getBarGroupSpacing()));
            addParameter(url, "chtt", render(provider.getTitle()));
            addParameter(url, "chdl", render(provider.getLegend()));
            addParameter(url, "chco", render(provider.getColors()));
            IChartFill bgFill = provider.getBackgroundFill();
            IChartFill fgFill = provider.getChartFill();
            StringBuilder fillParam = new StringBuilder();
            if (bgFill != null) {
                fillParam.append("bg,").append(render(bgFill));
            }
            if (fgFill != null) {
                if (fillParam.length() > 0) {
                    fillParam.append('|');
                }
                fillParam.append("c,").append(render(fgFill));
            }
            if (fillParam.toString().trim().equals("")) {
                fillParam = null;
            }
            addParameter(url, "chf", fillParam);
            IChartAxis[] axes = provider.getAxes();
            addParameter(url, "chxt", renderTypes(axes));
            addParameter(url, "chxl", renderLabels(axes));
            addParameter(url, "chxp", renderPositions(axes));
            addParameter(url, "chxr", renderRanges(axes));
            addParameter(url, "chxs", renderStyles(axes));
            addParameter(url, "chg", render(provider.getGrid()));
            addParameter(url, "chm", render(provider.getShapeMarkers()));
            addParameter(url, "chm", render(provider.getRangeMarkers()));
            addParameter(url, "chls", render(provider.getLineStyles()));
            addParameter(url, "chm", render(provider.getFillAreas()));
            addParameter(url, "chl", render(provider.getPieLabels()));
            return url;
        } finally {
            lock.writeLock().unlock();
        }
    }
    private void addParameter(StringBuilder url, CharSequence param, CharSequence value) {
        if (value == null || value.length() == 0) {
            return;
        }
        if (url.charAt(url.length() - 1) != '?') {
            url.append('&');
        }
        url.append(param).append('=').append(value);
    }
    private CharSequence render(Dimension dim) {
        if (dim == null) {
            return null;
        }
        return new StringBuilder().append(dim.width).append('x').append(dim.height);
    }
    private CharSequence render(IChartData data) {
        if (data == null) {
            return null;
        }
        ChartDataEncoding encoding = data.getEncoding();
        StringBuilder back = new StringBuilder();
        back.append(render(encoding)).append(':');
        for (double[] set : data.getData()) {
            if (set == null || set.length == 0) {
                back.append(encoding.convert(-1, data.getMax()));
            } else {
                for (double value : set) {
                    back.append(encoding.convert(value, data.getMax())).append(encoding.getValueSeparator());
                }
                if (back.substring(back.length() - encoding.getValueSeparator().length(),
                        back.length()).equals(encoding.getValueSeparator())) {
                    back.setLength(back.length() - encoding.getValueSeparator().length());
                }
            }
            back.append(encoding.getSetSeparator());
        }
        if (back.substring(back.length() - encoding.getSetSeparator().length(),
                back.length()).equals(encoding.getSetSeparator())) {
            back.setLength(back.length() - encoding.getSetSeparator().length());
        }
        return back;
    }
    private CharSequence render(Enum<?> value) {
        if (value == null) {
            return null;
        }
        try {
            Object back = value.getClass().getMethod("getRendering").invoke(value);
            if (back != null) {
                return back.toString();
            }
        } catch (IllegalArgumentException e) {
        } catch (SecurityException e) {
        } catch (IllegalAccessException e) {
        } catch (InvocationTargetException e) {
        } catch (NoSuchMethodException e) {
        }
        return null;
    }
    private CharSequence render(int barWidth, int groupSpacing) {
        if (barWidth == -1) {
            return null;
        }
        StringBuilder back = new StringBuilder(barWidth);
        if (groupSpacing >= 0) {
            back.append(',').append(groupSpacing);
        }
        return back;
    }
    private CharSequence render(String[] values) {
        if (values == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (String value : values) {
            CharSequence toRender = render(value);
            if (toRender == null) {
                toRender = "";
            }
            back.append(toRender).append('|');
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    private CharSequence render(String value) {
        if (value == null) {
            return value;
        }
        StringBuilder back = new StringBuilder();
        for (char c : value.toCharArray()) {
            if (c == ' ') {
                back.append('+');
            } else {
                back.append(c);
            }
        }
        return back;
    }
    private CharSequence render(Color[] values) {
        if (values == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (Color value : values) {
            CharSequence toRender = render(value);
            if (toRender == null) {
                continue;
            }
            char delimiter = ',';
            switch(provider.getType()) {
            case PIE:
            case PIE_3D:
            case BAR_VERTICAL_SET:
                delimiter = '|';
                break;
            }
            back.append(toRender).append(delimiter);
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    private CharSequence render(Color value) {
        if (value == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        {
            String toPad = Integer.toHexString(value.getRed());
            if (toPad.length() == 1) {
                back.append(0);
            }
            back.append(toPad);
        }
        {
            String toPad = Integer.toHexString(value.getGreen());
            if (toPad.length() == 1) {
                back.append(0);
            }
            back.append(toPad);
        }
        {
            String toPad = Integer.toHexString(value.getBlue());
            if (toPad.length() == 1) {
                back.append(0);
            }
            back.append(toPad);
        }
        {
            String toPad = Integer.toHexString(value.getAlpha());
            if (toPad.length() == 1) {
                back.append(0);
            }
            back.append(toPad);
        }
        return back;
    }
    private CharSequence render(IChartFill fill) {
        if (fill == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        if (fill instanceof ISolidFill) {
            ISolidFill solidFill = (ISolidFill) fill;
            back.append("s,");
            back.append(render(solidFill.getColor()));
        } else if (fill instanceof ILinearGradientFill) {
            ILinearGradientFill gradientFill = (ILinearGradientFill) fill;
            back.append("lg,").append(gradientFill.getAngle()).append(',');
            Color[] colors = gradientFill.getColors();
            double[] offsets = gradientFill.getOffsets();
            for (int i = 0; i < colors.length; i++) {
                back.append(render(colors[i])).append(',').append(offsets[i]).append(',');
            }
            back.setLength(back.length() - 1);
        } else if (fill instanceof ILinearStripesFill) {
            ILinearStripesFill stripesFill = (ILinearStripesFill) fill;
            back.append("ls,").append(stripesFill.getAngle()).append(',');
            Color[] colors = stripesFill.getColors();
            double[] widths = stripesFill.getWidths();
            for (int i = 0; i < colors.length; i++) {
                back.append(render(colors[i])).append(',').append(widths[i]).append(',');
            }
            back.setLength(back.length() - 1);
        } else {
            return null;
        }
        return back;
    }
    private CharSequence renderTypes(IChartAxis[] axes) {
        if (axes == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (IChartAxis axis : axes) {
            back.append(render(axis.getType())).append(',');
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    private CharSequence renderLabels(IChartAxis[] axes) {
        if (axes == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (int i = 0; i < axes.length; i++) {
            if (axes[i] == null || axes[i].getLabels() == null) {
                continue;
            }
            back.append(i).append(":|");
            for (String label : axes[i].getLabels()) {
                if (label == null) {
                    back.append('|');
                    continue;
                }
                back.append(render(label)).append('|');
            }
            if (i == axes.length - 1) {
                back.setLength(back.length() - 1);
            }
        }
        return back;
    }
    private CharSequence renderPositions(IChartAxis[] axes) {
        if (axes == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (int i = 0; i < axes.length; i++) {
            if (axes[i] == null || axes[i].getPositions() == null) {
                continue;
            }
            back.append(i).append(',');
            for (double position : axes[i].getPositions()) {
                back.append(position).append(',');
            }
            back.setLength(back.length() - 1);
            back.append('|');
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    private CharSequence renderRanges(IChartAxis[] axes) {
        if (axes == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (int i = 0; i < axes.length; i++) {
            if (axes[i] == null || axes[i].getRange() == null) {
                continue;
            }
            back.append(i).append(',');
            Range range = axes[i].getRange();
            back.append(range.getStart()).append(',').append(range.getEnd()).append('|');
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    private CharSequence renderStyles(IChartAxis[] axes) {
        if (axes == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (int i = 0; i < axes.length; i++) {
            if (axes[i] == null || axes[i].getColor() == null
                    || axes[i].getFontSize() < 0 || axes[i].getAlignment() == null) {
                continue;
            }
            back.append(i).append(',');
            back.append(render(axes[i].getColor())).append(',');
            back.append(axes[i].getFontSize()).append(',');
            back.append(render(axes[i].getAlignment())).append('|');
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    private CharSequence render(IChartGrid grid) {
        if (grid == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        back.append(grid.getXStepSize()).append(',');
        back.append(grid.getYStepSize());
        if (grid.getSegmentLength() >= 0) {
            back.append(',').append(grid.getSegmentLength());
            back.append(',').append(grid.getBlankLength());
        }
        return back;
    }
    private CharSequence render(IShapeMarker[] markers) {
        if (markers == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (IShapeMarker marker : markers) {
            back.append(render(marker.getType())).append(',');
            back.append(render(marker.getColor())).append(',');
            back.append(marker.getIndex()).append(',');
            back.append(marker.getPoint()).append(',');
            back.append(marker.getSize()).append('|');
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    private CharSequence render(IRangeMarker[] markers) {
        if (markers == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (IRangeMarker marker : markers) {
            back.append(render(marker.getType())).append(',');
            back.append(render(marker.getColor())).append(',');
            back.append(0).append(',');
            back.append(marker.getStart()).append(',');
            back.append(marker.getEnd()).append('|');
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    private CharSequence render(IFillArea[] areas) {
        if (areas == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (IFillArea area : areas) {
            back.append(render(area.getType())).append(',');
            back.append(render(area.getColor())).append(',');
            back.append(area.getStartIndex()).append(',');
            back.append(area.getEndIndex()).append(',');
            back.append(0).append('|');
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    private CharSequence render(ILineStyle[] styles) {
        if (styles == null) {
            return null;
        }
        StringBuilder back = new StringBuilder();
        for (ILineStyle style : styles) {
            if (style == null) {
                back.append('|');
                continue;
            }
            back.append(style.getThickness()).append(',');
            back.append(style.getSegmentLength()).append(',');
            back.append(style.getBlankLength()).append('|');
        }
        if (back.length() > 0) {
            back.setLength(back.length() - 1);
        }
        return back;
    }
    @Override
    protected void onComponentTag(ComponentTag tag) {
        checkComponentTag(tag, "img");
        super.onComponentTag(tag);
        tag.put("src", constructURL());
    }
}
contrib/com/codecommit/wicket/ChartAxis.java
New file
@@ -0,0 +1,79 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public class ChartAxis implements IChartAxis {
    private AxisAlignment alignment;
    private Color color;
    private int fontSize = -1;
    private String[] labels;
    private double[] positions;
    private Range range;
    private ChartAxisType type;
    public ChartAxis(ChartAxisType type) {
        this.type = type;
    }
    public AxisAlignment getAlignment() {
        return alignment;
    }
    public Color getColor() {
        return color;
    }
    public int getFontSize() {
        return fontSize;
    }
    public String[] getLabels() {
        return labels;
    }
    public double[] getPositions() {
        return positions;
    }
    public Range getRange() {
        return range;
    }
    public ChartAxisType getType() {
        return type;
    }
    public void setAlignment(AxisAlignment alignment) {
        this.alignment = alignment;
    }
    public void setColor(Color color) {
        this.color = color;
    }
    public void setFontSize(int fontSize) {
        this.fontSize = fontSize;
    }
    public void setLabels(String[] labels) {
        this.labels = labels;
    }
    public void setPositions(double[] positions) {
        this.positions = positions;
    }
    public void setRange(Range range) {
        this.range = range;
    }
    public void setType(ChartAxisType type) {
        this.type = type;
    }
}
contrib/com/codecommit/wicket/ChartAxisType.java
New file
@@ -0,0 +1,25 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public enum ChartAxisType {
    BOTTOM("x"),
    TOP("t"),
    LEFT("y"),
    RIGHT("r");
    private final String rendering;
    private ChartAxisType(String rendering) {
        this.rendering = rendering;
    }
    public String getRendering() {
        return rendering;
    }
}
contrib/com/codecommit/wicket/ChartDataEncoding.java
New file
@@ -0,0 +1,82 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public enum ChartDataEncoding {
    SIMPLE("s", "", ",") {
        CharSequence convert(double value, double max) {
            if (value < 0) {
                return "_";
            }
            value = Math.round((CHARS.length() - 1) * value / max);
            if (value > CHARS.length() - 1) {
                throw new IllegalArgumentException(value + " is out of range for SIMPLE encoding");
            }
            return Character.toString(CHARS.charAt((int) value));
        }
    },
    TEXT("t", ",", "|") {
        CharSequence convert(double value, double max) {
            if (value < 0) {
                value = -1;
            }
            if (value > 100) {
                throw new IllegalArgumentException(value + " is out of range for TEXT encoding");
            }
            return Double.toString(value);
        }
    },
    EXTENDED("e", "", ",") {
        CharSequence convert(double value, double max) {
            if (value < 0) {
                return "__";
            }
            value = Math.round(value);
            if (value > (EXT_CHARS.length() - 1) * (EXT_CHARS.length() - 1)) {
                throw new IllegalArgumentException(value + " is out of range for EXTENDED encoding");
            }
            int rem = (int) (value % EXT_CHARS.length());
            int exp = (int) (value / EXT_CHARS.length());
            return new StringBuilder().append(EXT_CHARS.charAt(exp)).append(EXT_CHARS.charAt(rem));
        }
    };
    private static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    private static final String EXT_CHARS = CHARS + "-_.";
    private final String rendering, valueSeparator, setSeparator;
    private ChartDataEncoding(String rendering, String valueSeparator, String setSeparator) {
        this.rendering = rendering;
        this.valueSeparator = valueSeparator;
        this.setSeparator = setSeparator;
    }
    public String getRendering() {
        return rendering;
    }
    public String getValueSeparator() {
        return valueSeparator;
    }
    public String getSetSeparator() {
        return setSeparator;
    }
    abstract CharSequence convert(double value, double max);
}
contrib/com/codecommit/wicket/ChartGrid.java
New file
@@ -0,0 +1,51 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public class ChartGrid implements IChartGrid {
    private int blankLength = -1;
    private int segmentLength = -1;
    private int xStepSize = -1;
    private int yStepSize = -1;
    public ChartGrid(int xStepSize, int yStepSize) {
        this.xStepSize = xStepSize;
        this.yStepSize = yStepSize;
    }
    public int getBlankLength() {
        return blankLength;
    }
    public int getSegmentLength() {
        return segmentLength;
    }
    public double getXStepSize() {
        return xStepSize;
    }
    public double getYStepSize() {
        return yStepSize;
    }
    public void setBlankLength(int blankLength) {
        this.blankLength = blankLength;
    }
    public void setSegmentLength(int segmentLength) {
        this.segmentLength = segmentLength;
    }
    public void setXStepSize(int stepSize) {
        xStepSize = stepSize;
    }
    public void setYStepSize(int stepSize) {
        yStepSize = stepSize;
    }
}
contrib/com/codecommit/wicket/ChartProvider.java
New file
@@ -0,0 +1,176 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
import java.awt.Dimension;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
 * @author Daniel Spiewak
 */
public class ChartProvider implements IChartProvider, Serializable {
    private static final long serialVersionUID = 1L;
    private List<IChartAxis> axes = new ArrayList<IChartAxis>();
    private IChartFill backgroundFill;
    private int barGroupSpacing = -1;
    private int barWidth = -1;
    private IChartFill chartFill;
    private Color[] colors;
    private List<IFillArea> fillAreas = new ArrayList<IFillArea>();
    private IChartGrid grid;
    private String[] legend;
    private ILineStyle[] lineStyles;
    private String[] pieLabels;
    private List<IRangeMarker> rangeMarkers = new ArrayList<IRangeMarker>();
    private List<IShapeMarker> shapeMarkers = new ArrayList<IShapeMarker>();
    private Dimension size;
    private String title;
    private ChartType type;
    private IChartData data;
    public ChartProvider(Dimension size, ChartType type, IChartData data) {
        this.size = size;
        this.type = type;
        this.data = data;
    }
    public IChartAxis[] getAxes() {
        return axes.toArray(new IChartAxis[axes.size()]);
    }
    public IChartFill getBackgroundFill() {
        return backgroundFill;
    }
    public int getBarGroupSpacing() {
        return barGroupSpacing;
    }
    public int getBarWidth() {
        return barWidth;
    }
    public IChartFill getChartFill() {
        return chartFill;
    }
    public Color[] getColors() {
        return colors;
    }
    public IFillArea[] getFillAreas() {
        return fillAreas.toArray(new IFillArea[fillAreas.size()]);
    }
    public IChartGrid getGrid() {
        return grid;
    }
    public String[] getLegend() {
        return legend;
    }
    public ILineStyle[] getLineStyles() {
        return lineStyles;
    }
    public String[] getPieLabels() {
        return pieLabels;
    }
    public IRangeMarker[] getRangeMarkers() {
        return rangeMarkers.toArray(new IRangeMarker[rangeMarkers.size()]);
    }
    public IShapeMarker[] getShapeMarkers() {
        return shapeMarkers.toArray(new IShapeMarker[shapeMarkers.size()]);
    }
    public Dimension getSize() {
        return size;
    }
    public String getTitle() {
        return title;
    }
    public ChartType getType() {
        return type;
    }
    public void addFillArea(IFillArea fillArea) {
        fillAreas.add(fillArea);
    }
    public void addAxis(IChartAxis axis) {
        axes.add(axis);
    }
    public void setBackgroundFill(IChartFill backgroundFill) {
        this.backgroundFill = backgroundFill;
    }
    public void setBarGroupSpacing(int barGroupSpacing) {
        this.barGroupSpacing = barGroupSpacing;
    }
    public void setBarWidth(int barWidth) {
        this.barWidth = barWidth;
    }
    public void setChartFill(IChartFill chartFill) {
        this.chartFill = chartFill;
    }
    public void setColors(Color[] colors) {
        this.colors = colors;
    }
    public void setGrid(IChartGrid grid) {
        this.grid = grid;
    }
    public void setLegend(String[] legend) {
        this.legend = legend;
    }
    public void setLineStyles(ILineStyle[] lineStyles) {
        this.lineStyles = lineStyles;
    }
    public void setPieLabels(String[] pieLabels) {
        this.pieLabels = pieLabels;
    }
    public void addRangeMarker(IRangeMarker rangeMarker) {
        rangeMarkers.add(rangeMarker);
    }
    public void addShapeMarker(IShapeMarker shapeMarker) {
        shapeMarkers.add(shapeMarker);
    }
    public void setSize(Dimension size) {
        this.size = size;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public void setType(ChartType type) {
        this.type = type;
    }
    public IChartData getData() {
        return data;
    }
    public void setData(IChartData data) {
        this.data = data;
    }
}
contrib/com/codecommit/wicket/ChartType.java
New file
@@ -0,0 +1,34 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public enum ChartType {
    LINE("lc"),
    LINE_XY("lxy"),
    BAR_HORIZONTAL_SET("bhs"),
    BAR_VERTICAL_SET("bvs"),
    BAR_HORIZONTAL_GROUP("bhg"),
    BAR_VERTICAL_GROUP("bvg"),
    PIE("p"),
    PIE_3D("p3"),
    VENN("v"),
    SCATTER("s");
    private final String rendering;
    private ChartType(String rendering) {
        this.rendering = rendering;
    }
    public String getRendering() {
        return rendering;
    }
}
contrib/com/codecommit/wicket/FillArea.java
New file
@@ -0,0 +1,54 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public class FillArea implements IFillArea {
    private Color color;
    private int endIndex = -1;
    private int startIndex = -1;
    private AreaFillType type = AreaFillType.BETWEEN;
    public FillArea(Color color, int startIndex, int endIndex) {
        this.color = color;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }
    public Color getColor() {
        return color;
    }
    public int getEndIndex() {
        return endIndex;
    }
    public int getStartIndex() {
        return startIndex;
    }
    public AreaFillType getType() {
        return type;
    }
    public void setColor(Color color) {
        this.color = color;
    }
    public void setEndIndex(int endIndex) {
        this.endIndex = endIndex;
    }
    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }
    public void setType(AreaFillType type) {
        this.type = type;
    }
}
contrib/com/codecommit/wicket/IChartAxis.java
New file
@@ -0,0 +1,26 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public interface IChartAxis {
    public ChartAxisType getType();
    public String[] getLabels();
    public double[] getPositions();
    public Range getRange();
    public Color getColor();
    public int getFontSize();
    public AxisAlignment getAlignment();
}
contrib/com/codecommit/wicket/IChartData.java
New file
@@ -0,0 +1,16 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public interface IChartData {
    public ChartDataEncoding getEncoding();
    public double[][] getData();
    public double getMax();
}
contrib/com/codecommit/wicket/IChartFill.java
New file
@@ -0,0 +1,10 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public interface IChartFill {
}
contrib/com/codecommit/wicket/IChartGrid.java
New file
@@ -0,0 +1,18 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public interface IChartGrid {
    public double getXStepSize();
    public double getYStepSize();
    public int getSegmentLength();
    public int getBlankLength();
}
contrib/com/codecommit/wicket/IChartProvider.java
New file
@@ -0,0 +1,47 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
import java.awt.Dimension;
/**
 * @author Daniel Spiewak
 */
public interface IChartProvider {
    public Dimension getSize();
    public IChartData getData();
    public ChartType getType();
    public int getBarWidth();
    public int getBarGroupSpacing();
    public String getTitle();
    public String[] getLegend();
    public Color[] getColors();
    public IChartFill getChartFill();
    public IChartFill getBackgroundFill();
    public String[] getPieLabels();
    public IChartAxis[] getAxes();
    public ILineStyle[] getLineStyles();
    public IChartGrid getGrid();
    public IShapeMarker[] getShapeMarkers();
    public IRangeMarker[] getRangeMarkers();
    public IFillArea[] getFillAreas();
}
contrib/com/codecommit/wicket/IFillArea.java
New file
@@ -0,0 +1,21 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public interface IFillArea {
    public AreaFillType getType();
    public Color getColor();
    public int getStartIndex();
    // unnecessary if BOTTOM
    public int getEndIndex();
}
contrib/com/codecommit/wicket/ILineStyle.java
New file
@@ -0,0 +1,16 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public interface ILineStyle {
    public int getThickness();
    public int getSegmentLength();
    public int getBlankLength();
}
contrib/com/codecommit/wicket/ILinearGradientFill.java
New file
@@ -0,0 +1,18 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public interface ILinearGradientFill extends IChartFill {
    public int getAngle();
    public Color[] getColors();
    public double[] getOffsets();
}
contrib/com/codecommit/wicket/ILinearStripesFill.java
New file
@@ -0,0 +1,18 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public interface ILinearStripesFill extends IChartFill {
    public int getAngle();
    public Color[] getColors();
    public double[] getWidths();
}
contrib/com/codecommit/wicket/IRangeMarker.java
New file
@@ -0,0 +1,20 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public interface IRangeMarker {
    public RangeType getType();
    public Color getColor();
    public double getStart();
    public double getEnd();
}
contrib/com/codecommit/wicket/IShapeMarker.java
New file
@@ -0,0 +1,22 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public interface IShapeMarker {
    public MarkerType getType();
    public Color getColor();
    public int getIndex();
    public double getPoint();
    public int getSize();
}
contrib/com/codecommit/wicket/ISolidFill.java
New file
@@ -0,0 +1,13 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public interface ISolidFill extends IChartFill {
    public Color getColor();
}
contrib/com/codecommit/wicket/LineStyle.java
New file
@@ -0,0 +1,43 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public class LineStyle implements ILineStyle {
    private int blankLength = -1;
    private int segmentLength = -1;
    private int thickness = -1;
    public LineStyle(int thickness, int segmentLength, int blankLength) {
        this.thickness = thickness;
        this.segmentLength = segmentLength;
        this.blankLength = blankLength;
    }
    public int getBlankLength() {
        return blankLength;
    }
    public int getSegmentLength() {
        return segmentLength;
    }
    public int getThickness() {
        return thickness;
    }
    public void setBlankLength(int blankLength) {
        this.blankLength = blankLength;
    }
    public void setSegmentLength(int segmentLength) {
        this.segmentLength = segmentLength;
    }
    public void setThickness(int thickness) {
        this.thickness = thickness;
    }
}
contrib/com/codecommit/wicket/LinearGradientFill.java
New file
@@ -0,0 +1,49 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public class LinearGradientFill implements ILinearGradientFill {
    private int angle = -1;
    private Color[] colors;
    private double[] offsets;
    public LinearGradientFill(int angle, Color[] colors, double[] offsets) {
        if (colors.length != offsets.length) {
            throw new IllegalArgumentException("Must be same number of colors as offsets");
        }
        this.angle = angle;
        this.colors = colors;
        this.offsets = offsets;
    }
    public int getAngle() {
        return angle;
    }
    public Color[] getColors() {
        return colors;
    }
    public double[] getOffsets() {
        return offsets;
    }
    public void setAngle(int angle) {
        this.angle = angle;
    }
    public void setColors(Color[] colors) {
        this.colors = colors;
    }
    public void setOffsets(double[] offsets) {
        this.offsets = offsets;
    }
}
contrib/com/codecommit/wicket/LinearStripesFill.java
New file
@@ -0,0 +1,49 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public class LinearStripesFill implements ILinearStripesFill {
    private int angle = -1;
    private Color[] colors;
    private double[] widths;
    public LinearStripesFill(int angle, Color[] colors, double[] widths) {
        if (colors.length != widths.length) {
            throw new IllegalArgumentException("Must be same number of colors as widths");
        }
        this.angle = angle;
        this.colors = colors;
        this.widths = widths;
    }
    public int getAngle() {
        return angle;
    }
    public Color[] getColors() {
        return colors;
    }
    public double[] getWidths() {
        return widths;
    }
    public void setAngle(int angle) {
        this.angle = angle;
    }
    public void setColors(Color[] colors) {
        this.colors = colors;
    }
    public void setWidths(double[] widths) {
        this.widths = widths;
    }
}
contrib/com/codecommit/wicket/MarkerType.java
New file
@@ -0,0 +1,31 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public enum MarkerType {
    ARROW("a"),
    CROSS("c"),
    DIAMOND("d"),
    CIRCLE("o"),
    SQUARE("s"),
    VERTICAL_TO_DATA("v"),
    VERTICAL_TO_TOP("V"),
    HORIZONTAL_ACROSS("h"),
    X("x");
    private final String rendering;
    private MarkerType(String rendering) {
        this.rendering = rendering;
    }
    public String getRendering() {
        return rendering;
    }
}
contrib/com/codecommit/wicket/Range.java
New file
@@ -0,0 +1,32 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public class Range {
    private double start, end;
    public Range(double start, double end) {
        this.start = start;
        this.end = end;
    }
    public double getStart() {
        return start;
    }
    public void setStart(double start) {
        this.start = start;
    }
    public double getEnd() {
        return end;
    }
    public void setEnd(double end) {
        this.end = end;
    }
}
contrib/com/codecommit/wicket/RangeMarker.java
New file
@@ -0,0 +1,55 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public class RangeMarker implements IRangeMarker {
    private Color color;
    private double end = -1;
    private double start = -1;
    private RangeType type;
    public RangeMarker(RangeType type, Color color, double start, double end) {
        this.type = type;
        this.color = color;
        this.start = start;
        this.end = end;
    }
    public Color getColor() {
        return color;
    }
    public double getEnd() {
        return end;
    }
    public double getStart() {
        return start;
    }
    public RangeType getType() {
        return type;
    }
    public void setColor(Color color) {
        this.color = color;
    }
    public void setEnd(double end) {
        this.end = end;
    }
    public void setStart(double start) {
        this.start = start;
    }
    public void setType(RangeType type) {
        this.type = type;
    }
}
contrib/com/codecommit/wicket/RangeType.java
New file
@@ -0,0 +1,22 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
/**
 * @author Daniel Spiewak
 */
public enum RangeType {
    HORIZONTAL("r"),
    VERTICAL("R");
    private final String rendering;
    private RangeType(String rendering) {
        this.rendering = rendering;
    }
    public String getRendering() {
        return rendering;
    }
}
contrib/com/codecommit/wicket/ShapeMarker.java
New file
@@ -0,0 +1,65 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public class ShapeMarker implements IShapeMarker {
    private Color color;
    private int index = -1;
    private double point = -1;
    private int size = -1;
    private MarkerType type;
    public ShapeMarker(MarkerType type, Color color, int index, double point, int size) {
        this.type = type;
        this.color = color;
        this.index = index;
        this.point = point;
        this.size = size;
    }
    public Color getColor() {
        return color;
    }
    public int getIndex() {
        return index;
    }
    public double getPoint() {
        return point;
    }
    public int getSize() {
        return size;
    }
    public MarkerType getType() {
        return type;
    }
    public void setColor(Color color) {
        this.color = color;
    }
    public void setIndex(int index) {
        this.index = index;
    }
    public void setPoint(double point) {
        this.point = point;
    }
    public void setSize(int size) {
        this.size = size;
    }
    public void setType(MarkerType type) {
        this.type = type;
    }
}
contrib/com/codecommit/wicket/SolidFill.java
New file
@@ -0,0 +1,25 @@
/*
 * Created on Dec 11, 2007
 */
package com.codecommit.wicket;
import java.awt.Color;
/**
 * @author Daniel Spiewak
 */
public class SolidFill implements ISolidFill {
    private Color color;
    public SolidFill(Color color) {
        this.color = color;
    }
    public Color getColor() {
        return color;
    }
    public void setColor(Color color) {
        this.color = color;
    }
}
gitblit.properties
@@ -49,9 +49,11 @@
#
# Git:Blit UI Settings
#
siteName = Git:Blit
siteName = Repositories
allowAdministration = true
indexMessage = Welcome to Git:Blit!<br>A quick and easy way to host your own GIT repositories.<br>Built with <a href="http://eclipse.org/jgit">JGit</a>, <a href="http://wicket.apache.org">Wicket</a>, <a href="http://code.google.com/p/google-code-prettify/">google-code-prettify</a>, <a href="http://eclipse.org/jetty">Jetty</a>, <a href="http://www.slf4j.org">SLF4J</a>, <a href="http://logging.apache.org/log4j">Log4j</a>, and <a href="http://jcommander.org">JCommander</a>.
# Date and Time formats
timestampFormat = h:mm a
datestampShortFormat = yyyy-MM-dd
@@ -60,6 +62,10 @@
datetimestampShortFormat = yyyy-MM-dd h:mm a
datetimestampLongFormat = EEEE, MMMM d, yyyy h:mm a
# Generates a line graph of repository activity over time on the Summary page.
# This is a real-time graph so generation may be expensive.
generateActivityGraph = true
# Registered extensions for google-code-prettify
prettyPrintExtensions = c cpp cs css htm html java js php pl prefs properties py rb sh sql xml vb
resources/blank.png
resources/gitblit.css
@@ -1,16 +1,74 @@
/*
 JGitWeb css.
 Git:Blit css.
*/
body, table, tr, th, td { font-size: 13px; }
table.object_header td, div.page_body, table.diff_tree td {
html, body, table, dl, dt, dd, ol, ul, li, form, a, span, tr, th, td, div, em {
    font-family: verdana, sans-serif;
    font-size: 12px;
    line-height: 15px;
}
table.diff_tree td div.link {
    padding: 2px 5px;
    font-family: sans-serif;
    font-size: 9px;
body {
    margin: 5px;
    background-color: #ffffff;
    color: #000000;
}
pre.prettyprint, pre.plainprint {
    color: black;
    font-size:12px;
    border:0px;
}
/* age0: age < 60*60*2 */
.age0 {
    color: #009900;
    font-style: italic;
    font-weight: bold;
}
/* age1: 60*60*2 <= age < 60*60*24*2 */
.age1 {
    color: #009900;
    font-style: italic;
}
/* age2: 60*60*24*2 <= age */
.age2 {
    font-style: italic;
}
a {
    color: #0000cc;
}
a:hover, a:visited, a:active {
    color: #880000;
}
img.logo {
    float: right;
    border-width: 0px;
}
div.header {
    background-color: #D2C3AF;
    padding: 3px;
    border: 1px solid #808080;
}
div.header a {
    color: black;
    text-decoration: none;
    font-weight: bold;
}
div.header a:hover {
    text-decoration: underline;
}
div.pager {
    padding: 0px 0px 15px 5px;
}
div.link {
@@ -19,38 +77,222 @@
    font-size: 9px;
}
pre.prettyprint, pre.plainprint {
    font-size:12px;
    border:0px;
div.link a {
    font-size: 9px;
}
div.page_header {
    height: 25px;
    padding: 5px;
    font-family: sans-serif;
    font-weight: bold;
    font-size: 150%;
    color: #ccc;
    background-color: #ffffff;
}
div.page_header span {
    font-family: inherit;
    font-size: inherit;
}
div.page_header a  {
    font-size: inherit;
    font-family: inherit;
    text-decoration: none;
}
div.page_header a:visited {
    color: #000000;
}
div.page_header a:hover {
    color: E66C2C;
    text-decoration: underline;
}
div.page_footer {
    color: black;
    background-color: #ffffff;
    padding: 5px;
    border-top: 1px solid #bbb;
    font-style: italic;
}
div.page_nav {
    color: #ccc;
    background-color: #000070;
    padding: 5px;
}
div.page_nav a {
    color: yellow;
    text-decoration: none;
}
div.page_nav a:hover {
    text-decoration: underline;
}
div.page_nav2 {
    padding: 0px 8px 8px 8px;
    padding: 2px 5px 7px 5px;
}
table.project_list tr th a { padding-right: 15px; background-position: right; background-repeat:no-repeat; }
table.project_list tr th.wicket_orderDown a {font-weight: bold; background-image: url(arrow_down.png); }
table.project_list tr th.wicket_orderUp a { font-weight: bold; background-image: url(arrow_up.png); }
table.project_list tr th.wicket_orderNone a { font-weight: normal; background-image: url(arrow_off.png); }
.repositories_message {
    border: solid #bbb;
    border-width: 0px 0px 1px;
    padding: 8px;
}
/* age0: age < 60*60*2 */
table.project_list .age0 {
    color: #009900;
    font-style: italic;
div.page_path {
    padding: 8px;
    font-weight: bold;
    border: solid #bbb;
    border-width: 0px 0px 1px;
}
/* age1: 60*60*2 <= age < 60*60*24*2 */
table.project_list .age1 {
    color: #009900;
div.commit_message {
    padding: 8px;
    border: solid #bbb;
    border-width: 1px 0px 1px;
}
a.list {
    text-decoration: none;
    color: #000000;
}
a.list:hover {
    text-decoration: underline;
    color: #880000;
}
table {
    border-spacing: 0px;
}
th {
    padding: 2px 5px;
    font-size: 100%;
    text-align: left;
}
table.plain {
    padding: 8px;
}
table.pretty, table.repositories {
    margin-top:5px;
    margin-bottom:5px;
    border-spacing: 0px;
    border-top: 1px solid #bbb;
    border-left: 1px solid #bbb;
    border-right: 1px solid #bbb;
}
table.repositories {
    width:100%;
}
table.repositories th {
    background-color:#D3BDA1;
    padding: 5px;
    border-bottom: 1px solid #bbb;
}
tr th a { padding-right: 15px; background-position: right; background-repeat:no-repeat; }
tr th.wicket_orderDown a {font-weight: bold; background-image: url(arrow_down.png); }
tr th.wicket_orderUp a { font-weight: bold; background-image: url(arrow_up.png); }
tr th.wicket_orderNone a { font-weight: normal; background-image: url(arrow_off.png); }
tr.light {
    background-color: #ffffff;
}
tr.light td {
    border-bottom: 1px solid #bbb;
}
tr.dark {
    background-color: #faf8dc;
    border-bottom: 1px solid #bbb;
}
tr.dark td {
    border-bottom: 1px solid #bbb;
}
/* currently both use the same, but it can change */
tr.light:hover,
tr.dark:hover {
    background-color: #f6a234;
}
td {
    padding-left: 7px;
    padding-right: 7px;
}
td.author {
    font-style: italic;
}
/* age2: 60*60*24*2 <= age */
table.project_list .age2 {
td.date {
    font-style: italic;
    width:90px;
}
td.sha1, td.sha1 span {
    font-family: monospace;
    font-size: 13px;
}
td.mode {
    font-family: monospace;
    width:90px;
    padding-right:15px;
}
td.size {
    text-align: right;
    width:100px;
    padding-right:15px;
}
span.refs span {
    padding: 0px 4px;
    font-family: sans-serif;
    font-size: 70%;
    font-weight: normal;
    border: 1px solid;
    background-color: #ffaaff;
    border-color: #ffccff #ff00ee #ff00ee #ffccff;
}
span.refs span a {
    text-decoration: none;
    color: inherit;
}
span.refs span a:hover {
    text-decoration: underline;
}
span.refs span.indirect {
    font-style: italic;
}
table.diff_tree td.size {
    width:80px;
span.refs span.ref {
    background-color: #aaaaff;
    border-color: #ccccff #0033cc #0033cc #ccccff;
}
span.refs span.tag {
    background-color: #ffffaa;
    border-color: #ffffcc #ffee00 #ffee00 #ffffcc;
}
span.refs span.head {
    background-color: #aaffaa;
    border-color: #ccffcc #00cc33 #00cc33 #ccffcc;
}
src/com/gitblit/utils/JGitUtils.java
@@ -5,6 +5,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@@ -35,9 +37,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.wicket.models.Metric;
import com.gitblit.wicket.models.PathModel;
import com.gitblit.wicket.models.RefModel;
public class JGitUtils {
@@ -310,7 +312,6 @@
        return FileMode.TREE.equals(mode);
    }
    public static List<RevCommit> getRevLog(Repository r, int maxCount) {
        List<RevCommit> list = new ArrayList<RevCommit>();
        try {
@@ -427,4 +428,29 @@
        }
        return null;
    }
    public static List<Metric> getDateMetrics(Repository r) {
        final Map<String, Metric> map = new HashMap<String, Metric>();
        try {
            DateFormat df = new SimpleDateFormat("yyyy-MM");
            Git git = new Git(r);
            Iterable<RevCommit> revlog = git.log().call();
            for (RevCommit rev : revlog) {
                Date d = getCommitDate(rev);
                String p = df.format(d);
                if (!map.containsKey(p))
                    map.put(p, new Metric(p));
                map.get(p).count++;
            }
        } catch (Throwable t) {
            LOGGER.error("Failed to mine log history for metrics", t);
        }
        List<String> keys = new ArrayList<String>(map.keySet());
        Collections.sort(keys);
        List<Metric> metrics = new ArrayList<Metric>();
        for (String key:keys) {
            metrics.add(map.get(key));
        }
        return metrics;
    }
}
src/com/gitblit/wicket/GitBlitWebApp.java
@@ -32,7 +32,6 @@
import com.gitblit.wicket.pages.BlobPage;
import com.gitblit.wicket.pages.CommitPage;
import com.gitblit.wicket.pages.HeadsPage;
import com.gitblit.wicket.pages.LogPage;
import com.gitblit.wicket.pages.RepositoriesPage;
import com.gitblit.wicket.pages.ShortLogPage;
import com.gitblit.wicket.pages.SummaryPage;
@@ -64,7 +63,6 @@
        mount(new MixedParamUrlCodingStrategy("/about", AboutPage.class, new String[] { }));
        mount(new MixedParamUrlCodingStrategy("/summary", SummaryPage.class, new String[] { "p" }));
        mount(new MixedParamUrlCodingStrategy("/shortlog", ShortLogPage.class, new String[] { "p", "h" }));
        mount(new MixedParamUrlCodingStrategy("/log", LogPage.class, new String[] { "p", "h" }));
        mount(new MixedParamUrlCodingStrategy("/tags", TagsPage.class, new String[] { "p" }));
        mount(new MixedParamUrlCodingStrategy("/heads", HeadsPage.class, new String[] { "p" }));
        mount(new MixedParamUrlCodingStrategy("/commit", CommitPage.class, new String[] { "p", "h" }));
src/com/gitblit/wicket/WicketUtils.java
@@ -1,32 +1,20 @@
package com.gitblit.wicket;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.behavior.SimpleAttributeModifier;
public class WicketUtils {
    public static void setCssClass(Component container, String value) {
        container.add(newAttributeModifier("class", value));
        container.add(new SimpleAttributeModifier("class", value));
    }
    public static void setCssStyle(Component container, String value) {
        container.add(newAttributeModifier("style", value));
        container.add(new SimpleAttributeModifier("style", value));
    }
    public static void setHtmlTitle(Component container, String value) {
        container.add(newAttributeModifier("title", value));
    }
    private static AttributeModifier newAttributeModifier(String attrib, final String value) {
        return new AttributeModifier(attrib, true, new AbstractReadOnlyModel<String>() {
            private static final long serialVersionUID = 1L;
            @Override
            public String getObject() {
                return value;
            }
        });
        container.add(new SimpleAttributeModifier("title", value));
    }
    public static String breakLines(String string) {
src/com/gitblit/wicket/models/Metric.java
New file
@@ -0,0 +1,15 @@
package com.gitblit.wicket.models;
import java.io.Serializable;
public class Metric implements Serializable {
    private static final long serialVersionUID = 1L;
    public String name;
    public double count;
    public Metric(String name) {
        this.name = name;
    }
}
src/com/gitblit/wicket/models/PathModel.java
@@ -40,6 +40,15 @@
    @Override
    public int compareTo(PathModel o) {
        boolean isTree = isTree();
        boolean otherTree = o.isTree();
        if (isTree && otherTree) {
        return path.compareTo(o.path);
        } else if (!isTree && !otherTree) {
            return path.compareTo(o.path);
        } else if (isTree && !otherTree) {
            return -1;
        }
        return 1;
    }
}
src/com/gitblit/wicket/pages/BlobPage.java
@@ -20,7 +20,7 @@
public class BlobPage extends RepositoryPage {
    public BlobPage(PageParameters params) {
        super(params, "blob");
        super(params, "view");
        final String blobPath = params.getString("f", null);
@@ -29,7 +29,7 @@
        // blob page links
        add(new Label("historyLink", "history"));
        add(new Label("rawLink", "raw"));
        add(new Label("rawLink", "download"));
        add(new Label("headLink", "HEAD"));
        add(new LinkPanel("shortlog", "title", commit.getShortMessage(), CommitPage.class, newCommitParameter()));
src/com/gitblit/wicket/pages/CommitPage.html
@@ -9,38 +9,32 @@
    
    <!-- commit nav links -->    
    <div class="page_nav2">
        (parent: <span wicket:id="parentLink"></span>) | <span wicket:id="patchLink"></span>
        parent: <span wicket:id="parentLink"></span> | <span wicket:id="patchLink"></span>
    </div>    
    
    <!-- shortlog header -->
    <div class="header" wicket:id="shortlog"></div>
    
    <!-- Refs -->
    <div wicket:id="refsPanel"></div>
    <!-- commit info -->
    <div class="title_text">
    <table class="object_header">
        <tr><td>author</td><td><span wicket:id="commitAuthor">Message goes here</span></td></tr>
        <tr><td></td><td><span wicket:id="commitAuthorDate">Message goes here</span></td></tr>
        <tr><td>committer</td><td><span wicket:id="commitCommitter">Message goes here</span></td></tr>
        <tr><td></td><td><span wicket:id="commitCommitterDate">Message goes here</span></td></tr>
        <tr><td>commit</td><td class="sha1"><span wicket:id="commitId">Message goes here</span></td></tr>
        <tr><td>tree</td><td class="sha1"><span wicket:id="commitTree">Message goes here</span></td></tr>
        <tr><td>parent</td><td class="sha1"><span wicket:id="commitParents">
    <table class="plain">
        <tr><th>refs</th><td><div wicket:id="refsPanel"></div></td></tr>
        <tr><th>author</th><td><span wicket:id="commitAuthor">Message goes here</span></td></tr>
        <tr><th></th><td><span wicket:id="commitAuthorDate">Message goes here</span></td></tr>
        <tr><th>committer</th><td><span wicket:id="commitCommitter">Message goes here</span></td></tr>
        <tr><th></th><td><span wicket:id="commitCommitterDate">Message goes here</span></td></tr>
        <tr><th>commit</th><td class="sha1"><span wicket:id="commitId">Message goes here</span></td></tr>
        <tr><th>tree</th><td class="sha1"><span wicket:id="commitTree">Message goes here</span></td></tr>
        <tr><th>parent</th><td class="sha1"><span wicket:id="commitParents">
            <div wicket:id="commitParent">Message goes here</div></span></td></tr>
    </table>
    </div>
    
    <!-- full message -->
    <div class="page_body" wicket:id="fullMessage"></div>
    <div class="commit_message" wicket:id="fullMessage"></div>
    
    <!-- changed paths -->
    <div class="list_head"></div>
    <table class="diff_tree">
    <table class="pretty">
        <tr wicket:id="changedPath">
            <td class="path"><span wicket:id="pathName"></span></td>
            <td></td>
            <td><span wicket:id="pathLinks"></span></td>
        </tr>
    </table>
src/com/gitblit/wicket/pages/HeadsPage.html
@@ -9,8 +9,7 @@
    
    <!-- shortlog -->    
    <div class="header" wicket:id="summary"></div>
    <table class="heads">
    <table>
        <tbody>
               <tr wicket:id="head">
                 <td><i><span wicket:id="headDate"></span></i></td>
src/com/gitblit/wicket/pages/LogPage.html
File was deleted
src/com/gitblit/wicket/pages/LogPage.java
File was deleted
src/com/gitblit/wicket/pages/RepositoriesPage.html
@@ -2,15 +2,13 @@
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
    <div wicket:id="pageHeader"></div>
    <div class="index_include" wicket:id="indexInclude"></div>
    <table class="project_list">
    <div class="repositories_message" wicket:id="indexInclude"></div>
    <table class="repositories">
        <tr>
            <th wicket:id="orderByRepository">Repository</th>
            <th wicket:id="orderByDescription">Description</th>
            <th wicket:id="orderByOwner">Owner</th>
            <th wicket:id="orderByDate">Last Change</th>
            <th></th>
        </tr>
        <tbody>
               <tr wicket:id="repository">
@@ -18,7 +16,6 @@
                 <td><div class="list" wicket:id="repositoryDescription"></div></td>
                 <td><i><span wicket:id="repositoryOwner"></span></i></td>
                 <td><span wicket:id="repositoryLastChange"></span></td>
                 <td></td>
               </tr>
        </tbody>
    </table>
src/com/gitblit/wicket/pages/RepositoriesPage.java
@@ -63,7 +63,7 @@
        add(newSort("orderByOwner", SortBy.owner, dp, dataView));
        add(newSort("orderByDate", SortBy.date, dp, dataView));
        add(new PageFooter("pageFooter"));
        add(new PageFooter("pageFooter", ""));
    }
    protected enum SortBy {
src/com/gitblit/wicket/pages/ShortLogPage.html
@@ -8,22 +8,19 @@
    <div wicket:id="pageLinks"></div>
    
    <!-- shortlog -->    
    <div class="header" wicket:id="summary"></div>
    <table class="project_list">
    <div style="margin-top:5px;" class="header" wicket:id="summary"></div>
    <table class="pretty">
        <tbody>
               <tr wicket:id="commit">
                 <td><span wicket:id="commitDate"></span></td>
                 <td><i><span wicket:id="commitAuthor"></span></i></td>
                 <td class="date"><span wicket:id="commitDate"></span></td>
                 <td class="author"><span wicket:id="commitAuthor"></span></td>
                 <td><div wicket:id="commitShortMessage"></div></td>
                 <td><div wicket:id="commitRefs"></div></td>                 
                 <td><span wicket:id="commitLinks"></span></td>
               </tr>
               <tr>
                <td colspan="4"><div wicket:id="navigator"></div></td>
               </tr>
        </tbody>
    </table>    
    <div class="pager" wicket:id="navigator"></div>
    
    <!-- footer -->
    <div wicket:id="pageFooter"></div>
src/com/gitblit/wicket/pages/SummaryPage.html
@@ -7,70 +7,76 @@
    <!-- page nav links -->    
    <div wicket:id="pageLinks"></div>
    
    <!-- repository info -->
    <div class="title">&nbsp;</div>
    <table class="projects_list">
        <tr id="metadata_desc"><td>description</td><td><span wicket:id="repositoryDescription">Message goes here</span></td></tr>
        <tr id="metadata_owner"><td>owner</td><td><span wicket:id="repositoryOwner">Message goes here</span></td></tr>
        <tr id="metadata_lchange"><td>last change</td><td><span wicket:id="repositoryLastChange">Message goes here</span></td></tr>
        <tr class="metadata_url"><td>URL</td><td><span wicket:id="repositoryCloneUrl">Message goes here</span></td></tr>
    </table>
    <div>
        <!-- Repository Activity Chart -->
        <div style="width:50%;float:right;">
            <img style="padding-top:8px;" wicket:id="commitsChart" />
        </div>
        <!-- Repository info -->
        <div style="width:50%;">
            <table class="plain">
                <tr><th>description</th><td><span wicket:id="repositoryDescription">Message goes here</span></td></tr>
                <tr><th>owner</th><td><span wicket:id="repositoryOwner">Message goes here</span></td></tr>
                <tr><th>last change</th><td><span wicket:id="repositoryLastChange">Message goes here</span></td></tr>
                <tr><th>URL</th><td><span wicket:id="repositoryCloneUrl">Message goes here</span></td></tr>
            </table>
        </div>
    </div>
    <!-- shortlog -->    
    <div class="header" wicket:id="shortlog"></div>
    <table class="project_list">
    <table style="width:100%" class="pretty">
        <tbody>
               <tr wicket:id="commit">
                 <td><span wicket:id="commitDate"></span></td>
                 <td><i><span wicket:id="commitAuthor"></span></i></td>
                 <td class="date"><span wicket:id="commitDate"></span></td>
                 <td class="author"><span wicket:id="commitAuthor"></span></td>
                 <td><div wicket:id="commitShortMessage"></div></td>
                 <td><div wicket:id="commitRefs"></div></td>
                 <td><span wicket:id="commitLinks"></span></td>
               </tr>
               <tr>
                <td colspan="4"><div wicket:id="shortlogMore"></div></td>
            </tr>
        </tbody>
    </table>    
    <div class="pager" wicket:id="shortlogMore"></div>
    <!-- Open additional graphs body -->
    <div style="width:25%;float:right;">
    </div>
    <!-- Open Tags and Heads body -->
    <div style="width:65%">
    <!-- tags -->
    <div class="header" wicket:id="tags"></div>
    <table class="project_list">
        <table style="width:100%" class="pretty">
        <tbody>
               <tr wicket:id="tag">
                 <td><i><span wicket:id="tagDate"></span></i></td>
                 <td><div wicket:id="tagName"></div></td>
                     <td class="date"><span wicket:id="tagDate"></span></td>
                     <td><b><div wicket:id="tagName"></div></b></td>
                 <td><div wicket:id="tagDescription"></div></td>
                 <td><span wicket:id="tagLinks"></span></td>
               </tr>
            <tr>
                <td colspan="4"><div wicket:id="tagsMore"></div></td>
            </tr>
        </tbody>
    </table>
    <div class="pager" wicket:id="tagsMore"></div>
    <!-- heads -->
    <div class="header" wicket:id="heads"></div>
    <table class="heads">
    <table style="width:100%" class="pretty">
        <tbody>
               <tr wicket:id="head">
                 <td><i><span wicket:id="headDate"></span></i></td>
                   <td class="date"><span wicket:id="headDate"></span></td>
                 <td><div wicket:id="headName"></div></td>
                 <td><span wicket:id="headLinks"></span></td>
               </tr>
        </tbody>
    </table>
    <!-- Close Tags and Heads Body -->
    </div>
    <!-- footer -->
    <div wicket:id="pageFooter"></div>
    <div style="clear:both;" wicket:id="pageFooter"></div>
</body>
</html>
src/com/gitblit/wicket/pages/SummaryPage.java
@@ -1,11 +1,13 @@
package com.gitblit.wicket.pages;
import java.awt.Dimension;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.image.ContextImage;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
@@ -13,18 +15,26 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import com.codecommit.wicket.AbstractChartData;
import com.codecommit.wicket.Chart;
import com.codecommit.wicket.ChartAxis;
import com.codecommit.wicket.ChartAxisType;
import com.codecommit.wicket.ChartProvider;
import com.codecommit.wicket.ChartType;
import com.codecommit.wicket.IChartData;
import com.gitblit.StoredSettings;
import com.gitblit.utils.JGitUtils;
import com.gitblit.wicket.GitBlitWebApp;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.RepositoryPage;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.models.Metric;
import com.gitblit.wicket.models.RefModel;
import com.gitblit.wicket.panels.HeadLinksPanel;
import com.gitblit.wicket.panels.RefsPanel;
import com.gitblit.wicket.panels.ShortLogLinksPanel;
import com.gitblit.wicket.panels.TagLinksPanel;
public class SummaryPage extends RepositoryPage {
@@ -82,7 +92,7 @@
            }
        };
        add(shortlogView);
        add(new LinkPanel("shortlogMore", "link", "...", ShortLogPage.class, newRepositoryParameter()));
        add(new LinkPanel("shortlogMore", "link", "more...", ShortLogPage.class, newRepositoryParameter()));
        // tags
        List<RefModel> tags = JGitUtils.getTags(r, summaryCount);
@@ -115,7 +125,8 @@
            }
        };
        add(tagView);
        add(new LinkPanel("tagsMore", "link", "...", TagsPage.class, newRepositoryParameter()));
        add(new LinkPanel("tagsMore", "link", "more...", TagsPage.class, newRepositoryParameter()));
        // heads
        List<RefModel> heads = JGitUtils.getHeads(r, summaryCount);
        add(new LinkPanel("heads", "title", "heads", HeadsPage.class, newRepositoryParameter()));
@@ -140,10 +151,74 @@
        };
        add(headsView);
        // Display an activity line graph
        insertActivityGraph(r);
        // close the repository
        r.close();
        // footer
        addFooter();
    }
    private void insertActivityGraph(Repository r) {
        if (StoredSettings.getBoolean("generateActivityGraph", true)) {
            List<Metric> dates = JGitUtils.getDateMetrics(r);
            IChartData data = getChartData(dates);
            ChartProvider provider = new ChartProvider(new Dimension(400, 80), ChartType.LINE, data);
            ChartAxis dateAxis = new ChartAxis(ChartAxisType.BOTTOM);
            dateAxis.setLabels(new String[] { dates.get(0).name, dates.get(dates.size() / 2).name, dates.get(dates.size() - 1).name });
            provider.addAxis(dateAxis);
            ChartAxis commitAxis = new ChartAxis(ChartAxisType.LEFT);
            commitAxis.setLabels(new String[] { "", String.valueOf((int) maxValue(dates)) });
            provider.addAxis(commitAxis);
            add(new Chart("commitsChart", provider));
        } else {
            add(new ContextImage("commitsChart", "blank.png"));
        }
    }
    protected IChartData getChartData(List<Metric> results) {
        final double[] counts = new double[results.size()];
        int i = 0;
        double max = 0;
        for (Metric m : results) {
            counts[i++] = m.count;
            max = Math.max(max, m.count);
        }
        final double dmax = max;
        IChartData data = new AbstractChartData() {
            private static final long serialVersionUID = 1L;
            public double[][] getData() {
                return new double[][] { counts };
            }
            public double getMax() {
                return dmax;
            }
        };
        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;
    }
}
src/com/gitblit/wicket/pages/TagPage.html
@@ -11,16 +11,14 @@
    <div class="header" wicket:id="commit"></div>
    
    <!-- commit info -->
    <div class="title_text">
    <table class="object_header">
        <tr><td>object</td><td><span wicket:id="tagId">Message goes here</span></td></tr>
        <tr><td>author</td><td><span wicket:id="tagAuthor">Message goes here</span></td></tr>
        <tr><td></td><td><span wicket:id="tagDate">Message goes here</span></td></tr>
    <table>
        <tr><th>object</th><td><span wicket:id="tagId">Message goes here</span></td></tr>
        <tr><th>author</th><td><span wicket:id="tagAuthor">Message goes here</span></td></tr>
        <tr><th></th><td><span wicket:id="tagDate">Message goes here</span></td></tr>
    </table>
    </div>
    
    <!--  full message -->
    <div class="page_body" wicket:id="fullMessage"></div>
    <div class="commit_message" wicket:id="fullMessage"></div>
    
    <!-- footer -->
    <div wicket:id="pageFooter"></div>
src/com/gitblit/wicket/pages/TagsPage.html
@@ -9,17 +9,13 @@
    <!-- shortlog -->    
    <div class="header" wicket:id="summary"></div>
    <table class="tags">
    <table>
        <tbody>
               <tr wicket:id="tag">
                 <td><i><span wicket:id="tagDate"></span></i></td>
                 <td><div wicket:id="tagName"></div></td>
                 <td class="date"><span wicket:id="tagDate"></span></td>
                 <td><b><div wicket:id="tagName"></div></b></td>
                 <td><div wicket:id="tagDescription"></div></td>
                 <td><span wicket:id="tagLinks"></span></td>
               </tr>
               <tr>
                <td colspan="4"><div wicket:id="navigator"></div></td>
               </tr>                   
        </tbody>
    </table>    
src/com/gitblit/wicket/pages/TagsPage.java
@@ -4,14 +4,12 @@
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
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.lib.Repository;
import com.gitblit.utils.JGitUtils;
import com.gitblit.wicket.GitBlitWebApp;
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.RepositoryPage;
import com.gitblit.wicket.models.RefModel;
@@ -54,9 +52,7 @@
                counter++;
            }
        };
        tagView.setItemsPerPage(GitBlitWebApp.PAGING_ITEM_COUNT);
        add(tagView);
        add(new PagingNavigator("navigator", tagView));
        // footer
        addFooter();
src/com/gitblit/wicket/pages/TreePage.html
@@ -19,12 +19,11 @@
    <div wicket:id="breadcrumbs"></div>
        
    <!-- changed paths -->
    <div class="list_head"></div>
    <table class="diff_tree">
    <table class="pretty">
        <tr wicket:id="changedPath">
            <td class="mode"><span wicket:id="pathPermissions"></span></td>
            <td class="size"><span wicket:id="pathSize"></span></td>
            <td><span wicket:id="pathName"></span></td>            
            <td class="size"><span wicket:id="pathSize"></span></td>
            <td class="mode"><span wicket:id="pathPermissions"></span></td>
            <td><span wicket:id="treeLinks"></span></td>
        </tr>
    </table>
src/com/gitblit/wicket/pages/TreePage.java
@@ -38,10 +38,8 @@
        add(new LinkPanel("shortlog", "title", commit.getShortMessage(), CommitPage.class, newCommitParameter()));
        // breadcrumbs
        if (basePath == null || basePath.trim().length() == 0) {
            add(new Label("breadcrumbs", "").setVisible(false));
        } else {
            add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, basePath, commitId));
        if (basePath != null && basePath.trim().length() > 0) {
            paths.add(0, PathModel.getParentPath(basePath, commitId));
        }
@@ -58,13 +56,13 @@
                item.add(new Label("pathPermissions", JGitUtils.getPermissionsFromMode(entry.mode)));
                if (entry.isParentPath) {
                    // parent .. path
                    item.add(new Label("pathSize", "").setVisible(false));
                    item.add(new Label("pathSize", ""));
                    item.add(new LinkPanel("pathName", null, entry.name, TreePage.class, newPathParameter(entry.path)));
                    item.add(new Label("treeLinks", "").setVisible(false));
                    item.add(new Label("treeLinks", ""));
                } else {
                    if (entry.isTree()) {
                        // folder/tree link
                        item.add(new Label("pathSize", "-"));
                        item.add(new Label("pathSize", ""));
                        item.add(new LinkPanel("pathName", null, entry.name, TreePage.class, newPathParameter(entry.path)));
                    } else {
                        // blob link
src/com/gitblit/wicket/panels/HeadLinksPanel.html
@@ -2,7 +2,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<wicket:panel>
    <div class="link">
        <span wicket:id="shortlog"></span> | <span wicket:id="log"></span>  | <span wicket:id="tree"></span>
        <span wicket:id="shortlog"></span> | <span wicket:id="tree"></span>
    </div>    
</wicket:panel>
</html>
src/com/gitblit/wicket/panels/HeadLinksPanel.java
@@ -6,7 +6,6 @@
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.models.RefModel;
import com.gitblit.wicket.pages.LogPage;
import com.gitblit.wicket.pages.ShortLogPage;
@@ -17,7 +16,6 @@
    public HeadLinksPanel(String id, String repositoryName, RefModel tag) {
        super(id);
        add(new LinkPanel("shortlog", null, "shortlog", ShortLogPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getName())));
        add(new LinkPanel("log", null, "log", LogPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getName())));
        add(new Label("tree", "tree"));
    }
}
src/com/gitblit/wicket/panels/PageFooter.html
@@ -2,11 +2,10 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<wicket:panel>
    <div class="page_footer">
        <div class="cachetime"><span wicket:id="cacheTime"></span></div>
        <div class="page_footer_text"><span wicket:id="footerText"></span></div>
        <div class="page_footer_text" style="text-align:right">
        <div style="float:right">
            <a title="about git:blit" href="about">About Git:Blit</a>
        </div>
        <div wicket:id="footerText"></div>
    </div>    
</wicket:panel>
</html>
src/com/gitblit/wicket/panels/PageFooter.java
@@ -1,12 +1,9 @@
package com.gitblit.wicket.panels;
import java.util.Date;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import com.gitblit.StoredSettings;
import com.gitblit.wicket.GitBlitWebSession;
public class PageFooter extends Panel {
@@ -19,7 +16,6 @@
    public PageFooter(String id, String description) {
        super(id);
        add(new Label("cacheTime", "Page Last Updated: " + GitBlitWebSession.get().formatDateTimeLong(new Date())));
        add(new Label("footerText", description));
        if (StoredSettings.getBoolean("aggressiveGC", false)) {
            System.gc();
src/com/gitblit/wicket/panels/PageHeader.html
@@ -4,12 +4,11 @@
    <head>
        <title wicket:id="title">Message goes here</title>
        <link rel="stylesheet" type="text/css" href="gitblit.css"/>
        <link rel="stylesheet" type="text/css" href="gitweb.css"/>
        <link rel="shortcut icon" href="git-favicon.png" type="image/png" />
    </head>
    
    <div class="page_header">
        <a title="gitblit homepage" href="http://gitblit.com/"><img src="gitblt-logo.png" width="91" height="31" alt="gitblit" class="logo"/></a><a href="/"><span wicket:id="siteName">name</span></a> / <span wicket:id="repositoryName">name</span> <span wicket:id="pageName">name</span>
        <a title="gitblit homepage" href="http://gitblit.com/"><img src="gitblt_25.png" width="79" height="25" alt="gitblit" class="logo"/></a><a href="/"><span wicket:id="siteName">name</span></a> / <span wicket:id="repositoryName">name</span> <span wicket:id="pageName">name</span>
    </div>
</wicket:panel>
</html>
src/com/gitblit/wicket/panels/PageLinksPanel.html
@@ -3,7 +3,7 @@
<wicket:panel>
    <!-- page nav links -->    
    <div class="page_nav">
        <span wicket:id="summary"></span> | <span wicket:id="shortlog"></span> | <span wicket:id="log"></span> | <span wicket:id="commit"></span> | <span wicket:id="commitdiff"></span> | <span wicket:id="tree"></span>
        <span wicket:id="summary"></span> | <span wicket:id="shortlog"></span> | <span wicket:id="commit"></span> | <span wicket:id="commitdiff"></span> | <span wicket:id="tree"></span>
    </div>    
</wicket:panel>
</html>
src/com/gitblit/wicket/panels/PageLinksPanel.java
@@ -6,7 +6,6 @@
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.pages.CommitPage;
import com.gitblit.wicket.pages.LogPage;
import com.gitblit.wicket.pages.ShortLogPage;
import com.gitblit.wicket.pages.SummaryPage;
import com.gitblit.wicket.pages.TreePage;
@@ -30,13 +29,6 @@
            add(new Label("shortlog", pageName));
        } else {
            add(new LinkPanel("shortlog", null, "shortlog", ShortLogPage.class, new PageParameters("p=" + repositoryName)));
        }
        // log
        if (pageName.equals("log")) {
            add(new Label("log", pageName));
        } else {
            add(new LinkPanel("log", null, "log", LogPage.class, new PageParameters("p=" + repositoryName)));
        }
        // commit
src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.java
@@ -14,7 +14,6 @@
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.pages.TreePage;
public class PathBreadcrumbsPanel extends Panel {
    private static final long serialVersionUID = 1L;
@@ -26,6 +25,7 @@
        List<BreadCrumb> crumbs = new ArrayList<BreadCrumb>();
        crumbs.add(new BreadCrumb("[" + repositoryName + "]", ROOT, false));
        if (pathName != null && pathName.length() > 0) {
        String[] paths = pathName.split("/");
        StringBuilder sb = new StringBuilder();
        
@@ -35,6 +35,7 @@
            crumbs.add(new BreadCrumb(path, sb.toString(), (i == (paths.length - 1))));
            sb.append("/");
        }
        }
        ListDataProvider<BreadCrumb> crumbsDp = new ListDataProvider<BreadCrumb>(crumbs);
        DataView<BreadCrumb> pathsView = new DataView<BreadCrumb>("path", crumbsDp) {
src/com/gitblit/wicket/panels/PathLinksPanel.java
@@ -16,7 +16,7 @@
    public PathLinksPanel(String id, String repositoryName, PathModel path) {
        super(id);
        add(new Label("diff", "diff"));
        add(new LinkPanel("blob", null, "blob", BlobPage.class, new PageParameters("p=" + repositoryName + ",h=" + path.commitId + ",f=" + path.path)));
        add(new LinkPanel("blob", null, "view", BlobPage.class, new PageParameters("p=" + repositoryName + ",h=" + path.commitId + ",f=" + path.path)));
        add(new Label("history", "history"));
    }
}
src/com/gitblit/wicket/panels/TagLinksPanel.html
@@ -2,7 +2,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<wicket:panel>
    <div class="link">
        <span wicket:id="commit"></span> | <span wicket:id="shortlog"></span> | <span wicket:id="log"></span>
        <span wicket:id="commit"></span> | <span wicket:id="shortlog"></span>
    </div>    
</wicket:panel>
</html>
src/com/gitblit/wicket/panels/TagLinksPanel.java
@@ -6,7 +6,6 @@
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.models.RefModel;
import com.gitblit.wicket.pages.CommitPage;
import com.gitblit.wicket.pages.LogPage;
import com.gitblit.wicket.pages.ShortLogPage;
@@ -18,6 +17,5 @@
        super(id);
        add(new LinkPanel("commit", null, "commit", CommitPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getCommitId().getName())));
        add(new LinkPanel("shortlog", null, "shortlog", ShortLogPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getName())));
        add(new LinkPanel("log", null, "log", LogPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getName())));
    }
}
src/com/gitblit/wicket/panels/TreeLinksPanel.java
@@ -19,11 +19,11 @@
        if (path.isTree()) {
            add(new LinkPanel("link", null, "tree", TreePage.class, new PageParameters("p=" + repositoryName + ",h=" + path.commitId + ",f=" + path.path)));
            add(new Label("history", "history"));
            add(new Label("raw", "").setVisible(false));
            add(new Label("raw", ""));
        } else {
            add(new LinkPanel("link", null, "blob", BlobPage.class, new PageParameters("p=" + repositoryName + ",h=" + path.commitId + ",f=" + path.path)));
            add(new LinkPanel("link", null, "view", BlobPage.class, new PageParameters("p=" + repositoryName + ",h=" + path.commitId + ",f=" + path.path)));
            add(new Label("history", "history"));
            add(new Label("raw", "raw"));
            add(new Label("raw", "download"));
        }
    }
}