Mostly working Diff presentation.
3 files added
7 files modified
| | |
| | | padding: 0px;
|
| | | }
|
| | |
|
| | | pre.prettyprint, pre.plainprint {
|
| | | pre, pre.prettyprint, pre.plainprint {
|
| | | color: black;
|
| | | font-family: monospace;
|
| | | font-size:12px;
|
| | | border:0px;
|
| | | }
|
| | |
| | | text-align: center;
|
| | | }
|
| | |
|
| | | div.diff {
|
| | | font-family: monospace;
|
| | | }
|
| | |
|
| | | div.diff.header {
|
| | | -moz-border-bottom-colors: none;
|
| | | -moz-border-image: none;
|
| | | -moz-border-left-colors: none;
|
| | | -moz-border-right-colors: none;
|
| | | -moz-border-top-colors: none;
|
| | | background-color: #EDECE6;
|
| | | border-color: #D9D8D1;
|
| | | border-style: solid;
|
| | | border-width: 1px 0;
|
| | | font-weight: bold;
|
| | | margin-top: 4px;
|
| | | padding: 4px 0 2px;
|
| | | }
|
| | |
|
| | | div.diff.extended_header {
|
| | | background-color: #F6F5EE;
|
| | | padding: 2px 0;
|
| | | font-family: inherit;
|
| | | }
|
| | |
|
| | | div.diff.add {
|
| | | color: #008800;
|
| | | font-family: inherit;
|
| | | }
|
| | |
|
| | | div.diff.remove {
|
| | | color: #cc0000;
|
| | | font-family: inherit;
|
| | | }
|
| | |
|
| | | div.diff.unchanged {
|
| | | color: inherit;
|
| | | font-family: inherit;
|
| | | }
|
| | |
|
| | | div.diff.hunk_header {
|
| | | -moz-border-bottom-colors: none;
|
| | | -moz-border-image: none;
|
| | | -moz-border-left-colors: none;
|
| | | -moz-border-right-colors: none;
|
| | | -moz-border-top-colors: none;
|
| | | border-color: #FFE0FF;
|
| | | border-style: dotted;
|
| | | border-width: 1px 0 0;
|
| | | margin-top: 2px;
|
| | | font-family: inherit;
|
| | | }
|
| | |
|
| | | span.diff.hunk_info {
|
| | | background-color: #FFEEFF; |
| | | color: #990099;
|
| | | font-family: inherit;
|
| | | }
|
| | |
|
| | | span.diff.hunk_section { |
| | | color: #AA22AA;
|
| | | font-family: inherit;
|
| | | }
|
| | |
|
| | | a.list {
|
| | | text-decoration: none;
|
| | | color: #000000;
|
| | |
| | |
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.TicGitTicket;
|
| | | import com.gitblit.wicket.models.PathModel;
|
| | | import com.gitblit.wicket.models.RefModel;
|
| | |
|
| | |
|
| | | public class JGitUtilsTest extends TestCase {
|
| | | |
| | |
|
| | | private File repositoriesFolder = new File("c:/projects/git");
|
| | | private boolean exportAll = true;
|
| | | private boolean readNested = true;
|
| | | |
| | |
|
| | | private List<String> getRepositories() {
|
| | | return JGitUtils.getRepositoryList(repositoriesFolder, exportAll, readNested);
|
| | | }
|
| | | |
| | |
|
| | | private Repository getRepository() throws Exception {
|
| | | return new FileRepository(new File(repositoriesFolder, getRepositories().get(0)) + "/" + Constants.DOT_GIT);
|
| | | }
|
| | | |
| | |
|
| | | public void testFindRepositories() {
|
| | | List<String> list = getRepositories();
|
| | | assertTrue("No repositories found in " + repositoriesFolder, list.size() > 0);
|
| | | }
|
| | | |
| | | public void testOpenRepository() throws Exception { |
| | |
|
| | | public void testOpenRepository() throws Exception {
|
| | | Repository r = getRepository();
|
| | | r.close();
|
| | | assertTrue("Could not find repository!", r != null);
|
| | | }
|
| | | |
| | | public void testLastChangeRepository() throws Exception { |
| | |
|
| | | public void testLastChangeRepository() throws Exception {
|
| | | Repository r = getRepository();
|
| | | Date date = JGitUtils.getLastChange(r);
|
| | | r.close();
|
| | | assertTrue("Could not get last repository change date!", date != null);
|
| | | }
|
| | | |
| | |
|
| | | public void testRetrieveRevObject() throws Exception {
|
| | | Repository r = getRepository();
|
| | | RevCommit commit = JGitUtils.getCommit(r, Constants.HEAD);
|
| | | RevTree tree = commit.getTree();
|
| | | RevObject object = JGitUtils.getRevObject(r, tree, "AUTHORS"); |
| | | RevObject object = JGitUtils.getRevObject(r, tree, "AUTHORS");
|
| | | r.close();
|
| | | assertTrue("Object is null!", object != null);
|
| | | }
|
| | | |
| | |
|
| | | public void testRetrieveStringContent() throws Exception {
|
| | | Repository r = getRepository();
|
| | | RevCommit commit = JGitUtils.getCommit(r, Constants.HEAD);
|
| | |
| | | r.close();
|
| | | assertTrue("Content is null!", content != null);
|
| | | }
|
| | | |
| | |
|
| | | public void testTicGit() throws Exception {
|
| | | Repository r = new FileRepository(new File(repositoriesFolder, "ticgit") + "/" + Constants.DOT_GIT);
|
| | | RefModel ticgit = JGitUtils.getTicGitBranch(r);
|
| | |
| | | r.close();
|
| | | }
|
| | |
|
| | | public void testFilesInCommit() throws Exception {
|
| | | Repository r = getRepository();
|
| | | RevCommit commit = JGitUtils.getCommit(r, Constants.HEAD);
|
| | | List<PathModel> paths = JGitUtils.getFilesInCommit(r, commit);
|
| | | r.close();
|
| | | assertTrue("No changed paths found!", paths.size() > 0);
|
| | | }
|
| | | |
| | | public void testCommitDiff() throws Exception {
|
| | | Repository r = getRepository();
|
| | | RevCommit commit = JGitUtils.getCommit(r, Constants.HEAD);
|
| | | String diff = JGitUtils.getCommitDiff(r, commit, false);
|
| | | r.close();
|
| | | System.out.println(diff);
|
| | | }
|
| | |
|
| | | }
|
New file |
| | |
| | | package com.gitblit.utils;
|
| | |
|
| | | import static org.eclipse.jgit.lib.Constants.encodeASCII;
|
| | |
|
| | | import java.io.IOException;
|
| | | import java.io.OutputStream;
|
| | |
|
| | | import org.eclipse.jgit.diff.DiffFormatter;
|
| | | import org.eclipse.jgit.diff.RawText;
|
| | |
|
| | | public class HtmlDiffFormatter extends DiffFormatter {
|
| | | private final OutputStream os;
|
| | |
|
| | | public HtmlDiffFormatter(OutputStream os) {
|
| | | super(os);
|
| | | this.os = os;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Output a hunk header
|
| | | * |
| | | * @param aStartLine
|
| | | * within first source
|
| | | * @param aEndLine
|
| | | * within first source
|
| | | * @param bStartLine
|
| | | * within second source
|
| | | * @param bEndLine
|
| | | * within second source
|
| | | * @throws IOException
|
| | | */
|
| | | @Override
|
| | | protected void writeHunkHeader(int aStartLine, int aEndLine, int bStartLine, int bEndLine) throws IOException {
|
| | | os.write("<div class=\"diff hunk_header\"><span class=\"diff hunk_info\">".getBytes());
|
| | | os.write('@');
|
| | | os.write('@');
|
| | | writeRange('-', aStartLine + 1, aEndLine - aStartLine);
|
| | | writeRange('+', bStartLine + 1, bEndLine - bStartLine);
|
| | | os.write(' ');
|
| | | os.write('@');
|
| | | os.write('@');
|
| | | // TODO not sure if JGit can determine hunk section
|
| | | //os.write("<span class=\"diff hunk_section\">".getBytes());
|
| | | //os.write("</span>".getBytes());
|
| | | os.write("</span></div>".getBytes());
|
| | | }
|
| | |
|
| | | private void writeRange(final char prefix, final int begin, final int cnt) throws IOException {
|
| | | os.write(' ');
|
| | | os.write(prefix);
|
| | | switch (cnt) {
|
| | | case 0:
|
| | | // If the range is empty, its beginning number must
|
| | | // be the
|
| | | // line just before the range, or 0 if the range is
|
| | | // at the
|
| | | // start of the file stream. Here, begin is always 1
|
| | | // based,
|
| | | // so an empty file would produce "0,0".
|
| | | //
|
| | | os.write(encodeASCII(begin - 1));
|
| | | os.write(',');
|
| | | os.write('0');
|
| | | break;
|
| | |
|
| | | case 1:
|
| | | // If the range is exactly one line, produce only
|
| | | // the number.
|
| | | //
|
| | | os.write(encodeASCII(begin));
|
| | | break;
|
| | |
|
| | | default:
|
| | | os.write(encodeASCII(begin));
|
| | | os.write(',');
|
| | | os.write(encodeASCII(cnt));
|
| | | break;
|
| | | }
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void writeLine(final char prefix, final RawText text, final int cur) throws IOException {
|
| | | switch (prefix) {
|
| | | case '+':
|
| | | os.write("<div class=\"diff add\">".getBytes());
|
| | | break;
|
| | | case '-':
|
| | | os.write("<div class=\"diff remove\">".getBytes());
|
| | | break;
|
| | | }
|
| | | os.write(prefix);
|
| | | text.writeLine(os, cur);
|
| | | switch (prefix) {
|
| | | case '+':
|
| | | case '-':
|
| | | os.write("</div>".getBytes());
|
| | | break;
|
| | | default:
|
| | | os.write('\n');
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * Workaround function for complex private methods in DiffFormatter. This
|
| | | * sets the html for the diff headers.
|
| | | * |
| | | * @return
|
| | | */
|
| | | public String getHtml() {
|
| | | String html = os.toString();
|
| | | String[] lines = html.split("\n");
|
| | | StringBuilder sb = new StringBuilder();
|
| | | sb.append("<div class=\"diff\">");
|
| | | for (String line : lines) {
|
| | | if (line.startsWith("diff")) {
|
| | | sb.append("<div class=\"diff header\">").append(line).append("</div>");
|
| | | } else if (line.startsWith("---")) {
|
| | | sb.append("<div class=\"diff remove\">").append(line).append("</div>");
|
| | | } else if (line.startsWith("+++")) {
|
| | | sb.append("<div class=\"diff add\">").append(line).append("</div>");
|
| | | } else {
|
| | | sb.append(line).append('\n');
|
| | | }
|
| | | }
|
| | | sb.append("</div>");
|
| | | return sb.toString();
|
| | | }
|
| | | }
|
| | |
| | | import java.util.Set;
|
| | |
|
| | | import org.eclipse.jgit.api.Git;
|
| | | import org.eclipse.jgit.diff.DiffEntry;
|
| | | import org.eclipse.jgit.diff.DiffFormatter;
|
| | | import org.eclipse.jgit.diff.RawTextComparator;
|
| | | import org.eclipse.jgit.errors.ConfigInvalidException;
|
| | | import org.eclipse.jgit.lib.AnyObjectId;
|
| | | import org.eclipse.jgit.lib.Constants;
|
| | |
| | | import org.eclipse.jgit.treewalk.TreeWalk;
|
| | | import org.eclipse.jgit.treewalk.filter.PathFilter;
|
| | | import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
|
| | | import org.eclipse.jgit.treewalk.filter.TreeFilter;
|
| | | import org.eclipse.jgit.util.io.DisabledOutputStream;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | |
| | | return list;
|
| | | }
|
| | |
|
| | | public static List<PathModel> getCommitChangedPaths(Repository r, String commitId) {
|
| | | public static List<PathModel> getFilesInCommit(Repository r, String commitId) {
|
| | | RevCommit commit = getCommit(r, commitId);
|
| | | return getCommitChangedPaths(r, commit);
|
| | | return getFilesInCommit(r, commit);
|
| | | }
|
| | |
|
| | | public static List<PathModel> getCommitChangedPaths(Repository r, RevCommit commit) {
|
| | | public static List<PathModel> getFilesInCommit(Repository r, RevCommit commit) {
|
| | | List<PathModel> list = new ArrayList<PathModel>();
|
| | | final TreeWalk walk = new TreeWalk(r);
|
| | | walk.setRecursive(false);
|
| | | try {
|
| | | walk.addTree(commit.getTree());
|
| | | while (walk.next()) {
|
| | | list.add(getPathModel(walk, null, commit));
|
| | | }
|
| | | final RevWalk rw = new RevWalk(r);
|
| | | RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
|
| | | RevTree parentTree = parent.getTree();
|
| | | RevTree commitTree = commit.getTree();
|
| | |
|
| | | } catch (IOException e) {
|
| | | LOGGER.error("Failed to get files for commit " + commit.getName(), e);
|
| | | } finally {
|
| | | if (walk != null) {
|
| | | walk.release();
|
| | | final TreeWalk walk = new TreeWalk(r);
|
| | | walk.reset();
|
| | | walk.setRecursive(true);
|
| | | walk.addTree(parentTree);
|
| | | walk.addTree(commitTree);
|
| | | walk.setFilter(TreeFilter.ANY_DIFF);
|
| | |
|
| | | RawTextComparator cmp = RawTextComparator.DEFAULT;
|
| | | DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
|
| | | df.setRepository(r);
|
| | | df.setDiffComparator(cmp);
|
| | | df.setDetectRenames(true);
|
| | | List<DiffEntry> diffs = df.scan(parentTree, commitTree);
|
| | | for (DiffEntry diff : diffs) {
|
| | | list.add(new PathModel(diff.getNewPath(), diff.getNewPath(), 0, diff.getNewMode().getBits(), commit.getId().getName()));
|
| | | }
|
| | | } catch (Throwable t) {
|
| | | LOGGER.error("failed to determine files in commit!", t);
|
| | | }
|
| | | return list;
|
| | | }
|
| | |
|
| | | public static String getCommitDiff(Repository r, RevCommit commit, boolean outputHtml) {
|
| | | return getCommitDiff(r, commit, null, outputHtml);
|
| | | }
|
| | | |
| | | public static String getCommitDiff(Repository r, RevCommit commit, String path, boolean outputHtml) {
|
| | | try {
|
| | | final RevWalk rw = new RevWalk(r);
|
| | | RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
|
| | | RevTree parentTree = parent.getTree();
|
| | | RevTree commitTree = commit.getTree();
|
| | |
|
| | | final TreeWalk walk = new TreeWalk(r);
|
| | | walk.reset();
|
| | | walk.setRecursive(true);
|
| | | walk.addTree(parentTree);
|
| | | walk.addTree(commitTree);
|
| | | if (path != null && path.trim().length() > 0) {
|
| | | walk.setFilter(PathFilter.create(path));
|
| | | } else {
|
| | | walk.setFilter(TreeFilter.ANY_DIFF);
|
| | | }
|
| | |
|
| | | final ByteArrayOutputStream os = new ByteArrayOutputStream();
|
| | | RawTextComparator cmp = RawTextComparator.DEFAULT;
|
| | | DiffFormatter df;
|
| | | if (outputHtml) {
|
| | | df = new HtmlDiffFormatter(os);
|
| | | } else {
|
| | | df = new DiffFormatter(os);
|
| | | }
|
| | | df.setRepository(r);
|
| | | df.setDiffComparator(cmp);
|
| | | df.setDetectRenames(true);
|
| | | List<DiffEntry> diffs = df.scan(parentTree, commitTree);
|
| | | df.format(diffs);
|
| | | String diff;
|
| | | if (outputHtml) {
|
| | | // workaround for complex private methods in DiffFormatter
|
| | | diff = ((HtmlDiffFormatter) df).getHtml();
|
| | | } else {
|
| | | diff = os.toString();
|
| | | }
|
| | | df.flush();
|
| | | return diff;
|
| | | } catch (Throwable t) {
|
| | | LOGGER.error("failed to generate commit diff!", t);
|
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | private static PathModel getPathModel(TreeWalk walk, String basePath, RevCommit commit) {
|
| | |
| | | }
|
| | | return null;
|
| | | }
|
| | | |
| | |
|
| | | private static void readTicketContents(Repository r, RefModel ticgitBranch, TicGitTicket ticket) {
|
| | | List<PathModel> ticketFiles = getFilesInPath(r, ticket.name, ticgitBranch.getCommit());
|
| | | for (PathModel file : ticketFiles) {
|
| | |
| | | import com.gitblit.wicket.pages.BlobPage;
|
| | | import com.gitblit.wicket.pages.BranchesPage;
|
| | | import com.gitblit.wicket.pages.CommitPage;
|
| | | import com.gitblit.wicket.pages.DiffPage;
|
| | | import com.gitblit.wicket.pages.RepositoriesPage;
|
| | | import com.gitblit.wicket.pages.ShortLogPage;
|
| | | import com.gitblit.wicket.pages.SummaryPage;
|
| | |
| | | mount(new MixedParamUrlCodingStrategy("/tag", TagPage.class, new String[] { "p", "h" }));
|
| | | mount(new MixedParamUrlCodingStrategy("/tree", TreePage.class, new String[] { "p", "h", "f" }));
|
| | | mount(new MixedParamUrlCodingStrategy("/blob", BlobPage.class, new String[] { "p", "h", "f" }));
|
| | | mount(new MixedParamUrlCodingStrategy("/diff", DiffPage.class, new String[] { "p", "h", "f" }));
|
| | |
|
| | | // setup extended urls
|
| | | mount(new MixedParamUrlCodingStrategy("/ticgit", TicGitPage.class, new String[] { "p" }));
|
| | |
| | | addFullText("fullMessage", c.getFullMessage(), true);
|
| | |
|
| | | // changed paths list
|
| | | List<PathModel> paths = JGitUtils.getCommitChangedPaths(r, c);
|
| | | List<PathModel> paths = JGitUtils.getFilesInCommit(r, c);
|
| | | ListDataProvider<PathModel> pathsDp = new ListDataProvider<PathModel>(paths);
|
| | | DataView<PathModel> pathsView = new DataView<PathModel>("changedPath", pathsDp) {
|
| | | private static final long serialVersionUID = 1L;
|
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?>
|
| | | <html xmlns="http://www.w3.org/1999/xhtml" >
|
| | | <head>
|
| | | <link href="prettify/prettify.css" type="text/css" rel="stylesheet" />
|
| | | <script type="text/javascript" src="prettify/prettify.js"></script>
|
| | | </head>
|
| | | <body onload="prettyPrint()">
|
| | | <!-- page header -->
|
| | | <div wicket:id="pageHeader"></div>
|
| | |
|
| | | <!-- page nav links --> |
| | | <div wicket:id="pageLinks"></div>
|
| | | |
| | | <!-- blob nav links --> |
| | | <div class="page_nav2">
|
| | | <span wicket:id="historyLink"></span> | <span wicket:id="rawLink"></span> | <span wicket:id="headLink"></span>
|
| | | </div> |
| | | |
| | | <!-- shortlog header -->
|
| | | <div class="header" wicket:id="shortlog"></div>
|
| | |
|
| | | <!-- breadcrumbs -->
|
| | | <div wicket:id="breadcrumbs"></div>
|
| | | |
| | | <!-- diff content -->
|
| | | <pre wicket:id="diffText"></pre>
|
| | | |
| | | <!-- footer -->
|
| | | <div wicket:id="pageFooter"></div>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | package com.gitblit.wicket.pages;
|
| | |
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | |
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.wicket.LinkPanel;
|
| | | import com.gitblit.wicket.RepositoryPage;
|
| | | import com.gitblit.wicket.panels.PathBreadcrumbsPanel;
|
| | |
|
| | | public class DiffPage extends RepositoryPage {
|
| | |
|
| | | public DiffPage(PageParameters params) {
|
| | | super(params, "diff");
|
| | |
|
| | | final String blobPath = params.getString("f", null);
|
| | |
|
| | | Repository r = getRepository();
|
| | | RevCommit commit = JGitUtils.getCommit(r, commitId);
|
| | | String diff;
|
| | | if (blobPath != null && blobPath.length() > 0) {
|
| | | // blob diff
|
| | | diff = JGitUtils.getCommitDiff(r, commit, blobPath, true);
|
| | | } else {
|
| | | // commit diff
|
| | | diff = JGitUtils.getCommitDiff(r, commit, true);
|
| | | }
|
| | | r.close();
|
| | |
|
| | | // diff page links
|
| | | add(new Label("historyLink", "history"));
|
| | | add(new Label("rawLink", "raw"));
|
| | | add(new Label("headLink", "HEAD"));
|
| | |
|
| | | add(new LinkPanel("shortlog", "title", commit.getShortMessage(), CommitPage.class, newCommitParameter()));
|
| | |
|
| | | add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, blobPath, commitId));
|
| | |
|
| | | add(new Label("diffText", diff).setEscapeModelStrings(false));
|
| | |
|
| | | // footer
|
| | | addFooter();
|
| | | }
|
| | | }
|
| | |
| | | import com.gitblit.wicket.LinkPanel;
|
| | | import com.gitblit.wicket.models.PathModel;
|
| | | import com.gitblit.wicket.pages.BlobPage;
|
| | | import com.gitblit.wicket.pages.DiffPage;
|
| | |
|
| | |
|
| | | public class PathLinksPanel extends Panel {
|
| | |
| | |
|
| | | public PathLinksPanel(String id, String repositoryName, PathModel path) {
|
| | | super(id);
|
| | | add(new Label("diff", "diff"));
|
| | | add(new LinkPanel("diff", null, "diff", DiffPage.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"));
|
| | | }
|
| | |
| | | package com.gitblit.wicket.panels;
|
| | |
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.panel.Panel;
|
| | |
|
| | | import com.gitblit.wicket.LinkPanel;
|
| | | import com.gitblit.wicket.pages.CommitPage;
|
| | | import com.gitblit.wicket.pages.DiffPage;
|
| | | import com.gitblit.wicket.pages.TreePage;
|
| | |
|
| | |
|
| | |
| | | super(id);
|
| | |
|
| | | add(new LinkPanel("commit", null, "commit", CommitPage.class, new PageParameters("p=" + repositoryName + ",h=" + commitId)));
|
| | | add(new Label("commitdiff", "commitdiff"));
|
| | | add(new LinkPanel("commitdiff", null, "commitdiff", DiffPage.class, new PageParameters("p=" + repositoryName + ",h=" + commitId)));
|
| | | add(new LinkPanel("tree", null, "tree", TreePage.class, new PageParameters("p=" + repositoryName + ",h=" + commitId)));
|
| | | }
|
| | | } |