mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-10-30 01:56:09 +01:00
Added compare revisions for Wiki changes.
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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>
|
||||
94
src/main/twirl/diff.scala.html
Normal file
94
src/main/twirl/diff.scala.html
Normal 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>
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
24
src/main/twirl/wikicompare.scala.html
Normal file
24
src/main/twirl/wikicompare.scala.html
Normal 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)
|
||||
}
|
||||
@@ -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>
|
||||
}
|
||||
Reference in New Issue
Block a user