</manifest> | </manifest> | ||||
</jar> | </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 --> | <!-- Build Site --> | ||||
<delete dir="${basedir}/site" /> | <delete dir="${basedir}/site" /> | ||||
<mkdir dir="${basedir}/site" /> | <mkdir dir="${basedir}/site" /> | ||||
<arg value="--alias" /> | <arg value="--alias" /> | ||||
<arg value="index=overview" /> | <arg value="index=overview" /> | ||||
<arg value="--alias" /> | <arg value="--alias" /> | ||||
<arg value="properties=gitblit.properties" /> | <arg value="properties=gitblit.properties" /> | ||||
</java> | </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 --> | <!-- Cleanup --> | ||||
<delete dir="${project.build.dir}" /> | <delete dir="${project.build.dir}" /> | ||||
</target> | </target> |
- [Log4j](http://logging.apache.org/log4j) (Apache 2.0) | - [Log4j](http://logging.apache.org/log4j) (Apache 2.0) | ||||
- [JCommander](http://jcommander.org) (Apache 2.0) | - [JCommander](http://jcommander.org) (Apache 2.0) | ||||
- [BouncyCastle](http://www.bouncycastle.org) (MIT/X11) | - [BouncyCastle](http://www.bouncycastle.org) (MIT/X11) | ||||
- [JSch - Java Secure Channel](http://www.jcraft.com/jsch) (BSD) | |||||
### Other Build Dependencies | ### Other Build Dependencies | ||||
- [Fancybox image viewer](http://fancybox.net) (MIT and GPL dual-licensed) | - [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) | - [JUnit](http://junit.org) (Common Public License) | ||||
## Building from Source | ## Building from Source |
downloadFromApache(MavenObject.MARKDOWNPAPERS, BuildType.RUNTIME); | downloadFromApache(MavenObject.MARKDOWNPAPERS, BuildType.RUNTIME); | ||||
downloadFromApache(MavenObject.BOUNCYCASTLE, BuildType.RUNTIME); | downloadFromApache(MavenObject.BOUNCYCASTLE, BuildType.RUNTIME); | ||||
downloadFromApache(MavenObject.BOUNCYCASTLE_MAIL, BuildType.RUNTIME); | downloadFromApache(MavenObject.BOUNCYCASTLE_MAIL, BuildType.RUNTIME); | ||||
downloadFromApache(MavenObject.JSCH, BuildType.RUNTIME); | |||||
downloadFromEclipse(MavenObject.JGIT, BuildType.RUNTIME); | downloadFromEclipse(MavenObject.JGIT, BuildType.RUNTIME); | ||||
downloadFromEclipse(MavenObject.JGIT_HTTP, BuildType.RUNTIME); | downloadFromEclipse(MavenObject.JGIT_HTTP, BuildType.RUNTIME); | ||||
downloadFromApache(MavenObject.MARKDOWNPAPERS, BuildType.COMPILETIME); | downloadFromApache(MavenObject.MARKDOWNPAPERS, BuildType.COMPILETIME); | ||||
downloadFromApache(MavenObject.BOUNCYCASTLE, BuildType.COMPILETIME); | downloadFromApache(MavenObject.BOUNCYCASTLE, BuildType.COMPILETIME); | ||||
downloadFromApache(MavenObject.BOUNCYCASTLE_MAIL, BuildType.COMPILETIME); | downloadFromApache(MavenObject.BOUNCYCASTLE_MAIL, BuildType.COMPILETIME); | ||||
downloadFromApache(MavenObject.JSCH, BuildType.RUNTIME); | |||||
downloadFromApache(MavenObject.JSCH, BuildType.COMPILETIME); | downloadFromApache(MavenObject.JSCH, BuildType.COMPILETIME); | ||||
downloadFromEclipse(MavenObject.JGIT, BuildType.COMPILETIME); | downloadFromEclipse(MavenObject.JGIT, BuildType.COMPILETIME); |
StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); | ||||
for (File file : markdownFiles) { | for (File file : markdownFiles) { | ||||
String documentName = getDocumentName(file); | 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.setLength(sb.length() - 3); | ||||
sb.trimToSize(); | sb.trimToSize(); | ||||
for (File file : markdownFiles) { | for (File file : markdownFiles) { | ||||
try { | try { | ||||
String documentName = getDocumentName(file); | 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) { | } catch (Throwable t) { | ||||
System.err.println("Failed to transform " + file.getName()); | System.err.println("Failed to transform " + file.getName()); | ||||
t.printStackTrace(); | t.printStackTrace(); | ||||
@Parameter(names = { "--pageFooter" }, description = "Page Footer HTML Snippet", required = true) | @Parameter(names = { "--pageFooter" }, description = "Page Footer HTML Snippet", required = true) | ||||
public String pageFooter; | 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) | @Parameter(names = { "--alias" }, description = "Filename=Linkname aliases", required = false) | ||||
public List<String> aliases = new ArrayList<String>(); | public List<String> aliases = new ArrayList<String>(); | ||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.nio.charset.Charset; | import java.nio.charset.Charset; | ||||
import java.text.DateFormat; | |||||
import java.text.ParseException; | import java.text.ParseException; | ||||
import java.text.SimpleDateFormat; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Collections; | import java.util.Collections; | ||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import com.gitblit.models.Metric; | |||||
import com.gitblit.models.PathModel; | import com.gitblit.models.PathModel; | ||||
import com.gitblit.models.PathModel.PathChangeModel; | import com.gitblit.models.PathModel.PathChangeModel; | ||||
import com.gitblit.models.RefModel; | import com.gitblit.models.RefModel; | ||||
public class JGitUtils { | 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) { | public static Repository createRepository(File repositoriesFolder, String name, boolean bare) { | ||||
Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(bare).call(); | Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(bare).call(); | ||||
return false; | 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) { | public static RefModel getTicketsBranch(Repository r) { | ||||
RefModel ticgitBranch = null; | RefModel ticgitBranch = null; | ||||
try { | try { |
/* | |||||
* 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; | |||||
} | |||||
} |
import com.gitblit.wicket.pages.RawPage; | import com.gitblit.wicket.pages.RawPage; | ||||
import com.gitblit.wicket.pages.RepositoriesPage; | import com.gitblit.wicket.pages.RepositoriesPage; | ||||
import com.gitblit.wicket.pages.SearchPage; | 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.SummaryPage; | ||||
import com.gitblit.wicket.pages.TagPage; | import com.gitblit.wicket.pages.TagPage; | ||||
import com.gitblit.wicket.pages.TagsPage; | import com.gitblit.wicket.pages.TagsPage; | ||||
mount("/patch", PatchPage.class, "r", "h", "f"); | mount("/patch", PatchPage.class, "r", "h", "f"); | ||||
mount("/history", HistoryPage.class, "r", "h", "f"); | mount("/history", HistoryPage.class, "r", "h", "f"); | ||||
mount("/search", SearchPage.class); | mount("/search", SearchPage.class); | ||||
mount("/stats", StatsPage.class, "r"); | |||||
mount("/metrics", MetricsPage.class, "r"); | |||||
// setup ticket urls | // setup ticket urls | ||||
mount("/tickets", TicketsPage.class, "r"); | mount("/tickets", TicketsPage.class, "r"); |
gb.modification = modification | gb.modification = modification | ||||
gb.deletion = deletion | gb.deletion = deletion | ||||
gb.rename = rename | gb.rename = rename | ||||
gb.stats = stats | |||||
gb.metrics = metrics | |||||
gb.markdown = markdown | gb.markdown = markdown | ||||
gb.changedFiles = changed files | gb.changedFiles = changed files | ||||
gb.filesAdded = {0} files added | gb.filesAdded = {0} files added |
import org.wicketstuff.googlecharts.ShapeMarker; | import org.wicketstuff.googlecharts.ShapeMarker; | ||||
import com.gitblit.models.Metric; | import com.gitblit.models.Metric; | ||||
import com.gitblit.utils.JGitUtils; | |||||
import com.gitblit.utils.MetricUtils; | |||||
import com.gitblit.wicket.WicketUtils; | 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); | super(params); | ||||
Repository r = getRepository(); | Repository r = getRepository(); | ||||
insertLinePlot("commitsChart", JGitUtils.getDateMetrics(r, false)); | |||||
insertLinePlot("commitsChart", MetricUtils.getDateMetrics(r, false)); | |||||
insertBarPlot("dayOfWeekChart", getDayOfWeekMetrics(r)); | insertBarPlot("dayOfWeekChart", getDayOfWeekMetrics(r)); | ||||
insertLinePlot("timeOfDayChart", getTimeOfDayMetrics(r)); | insertLinePlot("timeOfDayChart", getTimeOfDayMetrics(r)); | ||||
insertPieChart("authorsChart", getAuthorMetrics(r)); | insertPieChart("authorsChart", getAuthorMetrics(r)); | ||||
} | } | ||||
private List<Metric> getDayOfWeekMetrics(Repository repository) { | 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"); | SimpleDateFormat sdf = new SimpleDateFormat("E"); | ||||
Calendar cal = Calendar.getInstance(); | Calendar cal = Calendar.getInstance(); | ||||
private List<Metric> getTimeOfDayMetrics(Repository repository) { | private List<Metric> getTimeOfDayMetrics(Repository repository) { | ||||
SimpleDateFormat ndf = new SimpleDateFormat("yyyy-MM-dd"); | SimpleDateFormat ndf = new SimpleDateFormat("yyyy-MM-dd"); | ||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); | 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(); | Calendar cal = Calendar.getInstance(); | ||||
for (Metric metric : list) { | for (Metric metric : list) { | ||||
} | } | ||||
private List<Metric> getAuthorMetrics(Repository repository) { | private List<Metric> getAuthorMetrics(Repository repository) { | ||||
List<Metric> authors = JGitUtils.getAuthorMetrics(repository); | |||||
List<Metric> authors = MetricUtils.getAuthorMetrics(repository); | |||||
Collections.sort(authors, new Comparator<Metric>() { | Collections.sort(authors, new Comparator<Metric>() { | ||||
@Override | @Override | ||||
public int compare(Metric o1, Metric o2) { | public int compare(Metric o1, Metric o2) { | ||||
@Override | @Override | ||||
protected String getPageName() { | protected String getPageName() { | ||||
return getString("gb.stats"); | |||||
return getString("gb.metrics"); | |||||
} | } | ||||
} | } |
<!-- page nav links --> | <!-- page nav links --> | ||||
<div class="page_nav"> | <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> | ||||
</div> | </div> | ||||
put("branches", "gb.branches"); | put("branches", "gb.branches"); | ||||
put("tags", "gb.tags"); | put("tags", "gb.tags"); | ||||
put("tree", "gb.tree"); | put("tree", "gb.tree"); | ||||
put("stats", "gb.stats"); | |||||
put("metrics", "gb.metrics"); | |||||
put("tickets", "gb.tickets"); | put("tickets", "gb.tickets"); | ||||
put("edit", "gb.edit"); | put("edit", "gb.edit"); | ||||
} | } | ||||
WicketUtils.newRepositoryParameter(repositoryName))); | WicketUtils.newRepositoryParameter(repositoryName))); | ||||
add(new BookmarkablePageLink<Void>("tree", TreePage.class, | add(new BookmarkablePageLink<Void>("tree", TreePage.class, | ||||
WicketUtils.newRepositoryParameter(repositoryName))); | WicketUtils.newRepositoryParameter(repositoryName))); | ||||
add(new BookmarkablePageLink<Void>("stats", StatsPage.class, | |||||
add(new BookmarkablePageLink<Void>("metrics", MetricsPage.class, | |||||
WicketUtils.newRepositoryParameter(repositoryName))); | WicketUtils.newRepositoryParameter(repositoryName))); | ||||
// per-repository extra page links | // per-repository extra page links |
<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.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.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.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> | <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> | </table> | ||||
</div> | </div> |
import com.gitblit.Keys; | import com.gitblit.Keys; | ||||
import com.gitblit.models.Metric; | import com.gitblit.models.Metric; | ||||
import com.gitblit.utils.JGitUtils; | import com.gitblit.utils.JGitUtils; | ||||
import com.gitblit.utils.MetricUtils; | |||||
import com.gitblit.utils.StringUtils; | import com.gitblit.utils.StringUtils; | ||||
import com.gitblit.utils.TimeUtils; | import com.gitblit.utils.TimeUtils; | ||||
import com.gitblit.wicket.WicketUtils; | import com.gitblit.wicket.WicketUtils; | ||||
List<Metric> metrics = null; | List<Metric> metrics = null; | ||||
Metric metricsTotal = null; | Metric metricsTotal = null; | ||||
if (GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) { | if (GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) { | ||||
metrics = JGitUtils.getDateMetrics(r, true); | |||||
metrics = MetricUtils.getDateMetrics(r, true); | |||||
metricsTotal = metrics.remove(0); | metricsTotal = metrics.remove(0); | ||||
} | } | ||||
add(WicketUtils.createTimestampLabel("repositoryLastChange", JGitUtils.getLastChange(r), | add(WicketUtils.createTimestampLabel("repositoryLastChange", JGitUtils.getLastChange(r), | ||||
getTimeZone())); | getTimeZone())); | ||||
if (metricsTotal == null) { | if (metricsTotal == null) { | ||||
add(new Label("repositoryStats", "")); | |||||
add(new Label("repositoryMetrics", "")); | |||||
} else { | } else { | ||||
add(new Label("repositoryStats", MessageFormat.format( | |||||
add(new Label("repositoryMetrics", MessageFormat.format( | |||||
"{0} commits and {1} tags in {2}", metricsTotal.count, metricsTotal.tag, | "{0} commits and {1} tags in {2}", metricsTotal.count, metricsTotal.tag, | ||||
TimeUtils.duration(metricsTotal.duration)))); | TimeUtils.duration(metricsTotal.duration)))); | ||||
} | } |
import com.gitblit.models.TicketModel; | import com.gitblit.models.TicketModel; | ||||
import com.gitblit.models.TicketModel.Comment; | import com.gitblit.models.TicketModel.Comment; | ||||
import com.gitblit.utils.JGitUtils; | import com.gitblit.utils.JGitUtils; | ||||
import com.gitblit.utils.MetricUtils; | |||||
public class JGitUtilsTest extends TestCase { | public class JGitUtilsTest extends TestCase { | ||||
public void testMetrics() throws Exception { | public void testMetrics() throws Exception { | ||||
Repository repository = GitBlitSuite.getHelloworldRepository(); | Repository repository = GitBlitSuite.getHelloworldRepository(); | ||||
List<Metric> metrics = JGitUtils.getDateMetrics(repository, true); | |||||
List<Metric> metrics = MetricUtils.getDateMetrics(repository, true); | |||||
repository.close(); | repository.close(); | ||||
assertTrue("No metrics found!", metrics.size() > 0); | assertTrue("No metrics found!", metrics.size() > 0); | ||||
} | } |