Added compare revisions for Wiki changes.

This commit is contained in:
takezoe
2013-05-04 02:09:14 +09:00
parent fc8bd7d3a6
commit 66db3a898b
8 changed files with 223 additions and 98 deletions

View File

@@ -45,6 +45,32 @@ class WikiController extends ControllerBase {
JGitUtil.getRepositoryInfo(owner, repository, servletContext))
}
get("/:owner/:repository/wiki/:page/_compare/:commitId"){
val owner = params("owner")
val repository = params("repository")
val page = params("page")
val commitId = params("commitId").split("\\.\\.\\.")
println(commitId(0))
println(commitId(1))
html.wikicompare(Some(page),
WikiUtil.getDiffs(Git.open(WikiUtil.getWikiRepositoryDir(owner, repository)), commitId(0), commitId(1)),
JGitUtil.getRepositoryInfo(owner, repository, servletContext))
}
get("/:owner/:repository/wiki/_compare/:commitId"){
val owner = params("owner")
val repository = params("repository")
val commitId = params("commitId").split("\\.\\.\\.")
println(commitId(0))
println(commitId(1))
html.wikicompare(None,
WikiUtil.getDiffs(Git.open(WikiUtil.getWikiRepositoryDir(owner, repository)), commitId(0), commitId(1)),
JGitUtil.getRepositoryInfo(owner, repository, servletContext))
}
get("/:owner/:repository/wiki/:page/_edit"){
val owner = params("owner")

View File

@@ -5,6 +5,12 @@ import java.util.Date
import org.eclipse.jgit.api.Git
import org.apache.commons.io.FileUtils
import org.eclipse.jgit.lib.RepositoryBuilder
import app.DiffInfo
import org.eclipse.jgit.treewalk.CanonicalTreeParser
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.treewalk.TreeWalk
import org.eclipse.jgit.revwalk.RevWalk
import org.eclipse.jgit.diff.DiffEntry.ChangeType
object WikiUtil {
@@ -121,4 +127,53 @@ object WikiUtil {
}
}
def getDiffs(git: Git, commitId1: String, commitId2: String): List[DiffInfo] = {
// @scala.annotation.tailrec
// def getCommitLog(i: java.util.Iterator[RevCommit], logs: List[RevCommit]): List[RevCommit] =
// i.hasNext match {
// case true if(logs.size < 2) => getCommitLog(i, logs :+ i.next)
// case _ => logs
// }
//
// val revWalk = new RevWalk(git.getRepository)
// revWalk.markStart(revWalk.parseCommit(git.getRepository.resolve(commitId2)))
//
// val commits = getCommitLog(revWalk.iterator, Nil)
// revWalk.release
//
// val revCommit = commits(0)
//
//// if(commits.length >= 2){
// // not initial commit
// val oldCommit = commits(1)
// get diff between specified commit and its previous commit
val reader = git.getRepository.newObjectReader
val oldTreeIter = new CanonicalTreeParser
oldTreeIter.reset(reader, git.getRepository.resolve(commitId1 + "^{tree}"))
val newTreeIter = new CanonicalTreeParser
newTreeIter.reset(reader, git.getRepository.resolve(commitId2 + "^{tree}"))
import scala.collection.JavaConverters._
git.diff.setNewTree(newTreeIter).setOldTree(oldTreeIter).call.asScala.map { diff =>
DiffInfo(diff.getChangeType, diff.getOldPath, diff.getNewPath,
JGitUtil.getContent(git, diff.getOldId.toObjectId, false).map(new String(_, "UTF-8")),
JGitUtil.getContent(git, diff.getNewId.toObjectId, false).map(new String(_, "UTF-8")))
}.toList
// } else {
// // initial commit
// val walk = new TreeWalk(git.getRepository)
// walk.addTree(revCommit.getTree)
// val buffer = new scala.collection.mutable.ListBuffer[DiffInfo]()
// while(walk.next){
// buffer.append(DiffInfo(ChangeType.ADD, null, walk.getPathString, None,
// JGitUtil.getContent(git, walk.getObjectId(0), false).map(new String(_, "UTF-8"))))
// }
// walk.release
// buffer.toList
// }
}
}

View File

@@ -21,95 +21,5 @@
</td>
</tr>
</table>
@diffs.zipWithIndex.map { case (diff, i) =>
<table class="table table-bordered">
<tr>
<th style="font-weight: normal;">
@if(diff.changeType == ChangeType.COPY || diff.changeType == ChangeType.RENAME){
@diff.oldPath -> @diff.newPath
}
@if(diff.changeType == ChangeType.ADD || diff.changeType == ChangeType.DELETE || diff.changeType == ChangeType.MODIFY){
@diff.newPath
}
<div class="pull-right align-right">
<a href="@path/@repository.owner/@repository.name/blob/@commit.id/@diff.newPath" class="btn btn-small">View file @@ @commit.id.substring(0, 10)</a>
</div>
</th>
</tr>
<tr>
<td>
@if(diff.newContent != None || diff.oldContent != None){
<div id="diff-@i"></div>
<textarea id="newText-@i" style="display: none;">@diff.newContent.getOrElse("")</textarea>
<textarea id="oldText-@i" style="display: none;">@diff.oldContent.getOrElse("")</textarea>
} else {
Too big file not shown
}
</td>
</tr>
</table>
}
@diff(diffs, repository, Some(commit.id))
}
<script type="text/javascript" src="@path/assets/jsdifflib/difflib.js"></script>
<script type="text/javascript" src="@path/assets/jsdifflib/diffview.js"></script>
<link href="@path/assets/jsdifflib/diffview.css" type="text/css" rel="stylesheet" />
<style type="text/css">
table.inlinediff {
width: 100%;
}
table.inlinediff thead {
display: none;
}
td.insert, td.equal, td.delete {
width: 100%;
}
</style>
<script>
function diffUsingJS(oldTextId, newTextId, outputId) {
// get the baseText and newText values from the two textboxes, and split them into lines
var oldText = document.getElementById(oldTextId).value;
if(oldText == ''){
var oldLines = [];
} else {
var oldLines = difflib.stringAsLines(oldText);
}
var newText = document.getElementById(newTextId).value
if(newText == ''){
var newLines = [];
} else {
var newLines = difflib.stringAsLines(newText);
}
// create a SequenceMatcher instance that diffs the two sets of lines
var sm = new difflib.SequenceMatcher(oldLines, newLines);
// get the opcodes from the SequenceMatcher instance
// opcodes is a list of 3-tuples describing what changes should be made to the base text
// in order to yield the new text
var opcodes = sm.get_opcodes();
var diffoutputdiv = document.getElementById(outputId);
while (diffoutputdiv.firstChild) diffoutputdiv.removeChild(diffoutputdiv.firstChild);
// build the diff view and add it to the current DOM
diffoutputdiv.appendChild(diffview.buildView({
baseTextLines: oldLines,
newTextLines: newLines,
opcodes: opcodes,
contextSize: 4,
viewType: 1
}));
}
$(function(){
@diffs.zipWithIndex.map { case (diff, i) =>
@if(diff.newContent != None || diff.oldContent != None){
diffUsingJS('oldText-@i', 'newText-@i', 'diff-@i');
}
}
});
</script>

View File

@@ -0,0 +1,94 @@
@(diffs: Seq[app.DiffInfo], repository: app.RepositoryInfo, commitId: Option[String])(implicit context: app.Context)
@import context._
@import org.eclipse.jgit.diff.DiffEntry.ChangeType
@diffs.zipWithIndex.map { case (diff, i) =>
<table class="table table-bordered">
<tr>
<th style="font-weight: normal;">
@if(diff.changeType == ChangeType.COPY || diff.changeType == ChangeType.RENAME){
@diff.oldPath -> @diff.newPath
}
@if(diff.changeType == ChangeType.ADD || diff.changeType == ChangeType.DELETE || diff.changeType == ChangeType.MODIFY){
@diff.newPath
}
@if(commitId.isDefined){
<div class="pull-right align-right">
<a href="@path/@repository.owner/@repository.name/blob/@commitId.get/@diff.newPath" class="btn btn-small">View file @@ @commitId.get.substring(0, 10)</a>
</div>
}
</th>
</tr>
<tr>
<td>
@if(diff.newContent != None || diff.oldContent != None){
<div id="diff-@i"></div>
<textarea id="newText-@i" style="display: none;">@diff.newContent.getOrElse("")</textarea>
<textarea id="oldText-@i" style="display: none;">@diff.oldContent.getOrElse("")</textarea>
} else {
Too big file not shown
}
</td>
</tr>
</table>
}
<script type="text/javascript" src="@path/assets/jsdifflib/difflib.js"></script>
<script type="text/javascript" src="@path/assets/jsdifflib/diffview.js"></script>
<link href="@path/assets/jsdifflib/diffview.css" type="text/css" rel="stylesheet" />
<style type="text/css">
table.inlinediff {
width: 100%;
}
table.inlinediff thead {
display: none;
}
td.insert, td.equal, td.delete {
width: 100%;
}
</style>
<script>
function diffUsingJS(oldTextId, newTextId, outputId) {
// get the baseText and newText values from the two textboxes, and split them into lines
var oldText = document.getElementById(oldTextId).value;
if(oldText == ''){
var oldLines = [];
} else {
var oldLines = difflib.stringAsLines(oldText);
}
var newText = document.getElementById(newTextId).value
if(newText == ''){
var newLines = [];
} else {
var newLines = difflib.stringAsLines(newText);
}
// create a SequenceMatcher instance that diffs the two sets of lines
var sm = new difflib.SequenceMatcher(oldLines, newLines);
// get the opcodes from the SequenceMatcher instance
// opcodes is a list of 3-tuples describing what changes should be made to the base text
// in order to yield the new text
var opcodes = sm.get_opcodes();
var diffoutputdiv = document.getElementById(outputId);
while (diffoutputdiv.firstChild) diffoutputdiv.removeChild(diffoutputdiv.firstChild);
// build the diff view and add it to the current DOM
diffoutputdiv.appendChild(diffview.buildView({
baseTextLines: oldLines,
newTextLines: newLines,
opcodes: opcodes,
contextSize: 4,
viewType: 1
}));
}
$(function(){
@diffs.zipWithIndex.map { case (diff, i) =>
@if(diff.newContent != None || diff.oldContent != None){
diffUsingJS('oldText-@i', 'newText-@i', 'diff-@i');
}
}
});
</script>

View File

@@ -1,7 +1,7 @@
@(branch: String, repository: app.RepositoryInfo, pathList: List[String], latestCommit: app.CommitInfo, files: List[app.FileInfo], readme: Option[String])(implicit context: app.Context)
@import context._
@import view.helpers
@main(repository.owner+"/"+repository.name) {
@main(repository.owner + "/" + repository.name) {
@header("code", repository)
@navtab(branch, repository, "files")
<div class="head">

View File

@@ -4,7 +4,7 @@
<html>
<head>
<meta charset="utf-8">
<title>@title - GitBucket</title>
<title>@title</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Le styles -->
<link href="@path/assets/bootstrap/css/bootstrap.css" rel="stylesheet">

View File

@@ -0,0 +1,24 @@
@(pageName: Option[String], diffs: Seq[app.DiffInfo], repository: app.RepositoryInfo)(implicit context: app.Context)
@import view.helpers
@import context._
@import org.eclipse.jgit.diff.DiffEntry.ChangeType
@main("Compare Revisions - " + repository.owner + "/" + repository.name){
@header("wiki", repository)
@wikitab("history", repository)
<ul class="nav nav-tabs">
<li>
<h1 class="wiki-title"><span class="description">Compare Revisions</span></h1>
</li>
<li class="pull-right">
<div class="btn-group">
@if(pageName.isDefined){
<a class="btn" href="@path/@repository.owner/@repository.name/wiki/@pageName">View Page</a>
<a class="btn" href="@path/@repository.owner/@repository.name/wiki/@pageName/_history">Back to Page History</a>
} else {
<a class="btn" href="@path/@repository.owner/@repository.name/wiki/_history">Back to Wiki History</a>
}
</div>
</li>
</ul>
@diff(diffs, repository, None)
}

View File

@@ -7,11 +7,10 @@
<ul class="nav nav-tabs">
<li>
<h1 class="wiki-title">
@if(pageName.nonEmpty){
<span class="description">History for</span> @pageName.get
}
@if(pageName.isEmpty){
<span class="description">History</span>
} else {
<span class="description">History for</span> @pageName.get
}
</h1>
</li>
@@ -33,13 +32,30 @@
</tr>
}
</table>
<input type="button" value="Compare Revisions" class="btn"/>
<input type="button" value="Back to Top" class="btn"/>
<input type="button" id="compare" value="Compare Revisions" class="btn"/>
<input type="button" id="top" value="Back to Top" class="btn"/>
<script>
$(function(){
$('input[name=commitId]').click(function(){
return !($('input[name=commitId]:checked').length == 3);
});
$('#compare').click(function(){
var e = $('input[name=commitId]:checked');
if(e.length == 2){
@if(pageName.isEmpty){
location.href = '@path/@repository.owner/@repository.name/wiki/_compare/' +
$(e.get(1)).attr('value') + '...' + $(e.get(0)).attr('value');
} else {
location.href = '@path/@repository.owner/@repository.name/wiki/@pageName.get/_compare/' +
$(e.get(1)).attr('value') + '...' + $(e.get(0)).attr('value');
}
}
});
$('#top').click(function(){
$('html,body').animate({ scrollTop: 0 }, 'fast');
});
});
</script>
}