(refs #38)Add reverting wiki from history.

This commit is contained in:
takezoe
2013-10-03 03:42:38 +09:00
parent cf7caf55da
commit 70ca98d6a2
3 changed files with 104 additions and 12 deletions

View File

@@ -6,12 +6,14 @@ import util.Directory._
import util.ControlUtil._
import jp.sf.amateras.scalatra.forms._
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.errors.PatchApplyException
import org.scalatra.FlashMapSupport
class WikiController extends WikiControllerBase
with WikiService with RepositoryService with AccountService with ActivityService
with CollaboratorsAuthenticator with ReferrerAuthenticator
trait WikiControllerBase extends ControllerBase {
trait WikiControllerBase extends ControllerBase with FlashMapSupport {
self: WikiService with RepositoryService with ActivityService
with CollaboratorsAuthenticator with ReferrerAuthenticator =>
@@ -58,18 +60,45 @@ trait WikiControllerBase extends ControllerBase {
get("/:owner/:repository/wiki/:page/_compare/:commitId")(referrersOnly { repository =>
val pageName = StringUtil.urlDecode(params("page"))
val commitId = params("commitId").split("\\.\\.\\.")
using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git =>
wiki.html.compare(Some(pageName), JGitUtil.getDiffs(git, commitId(0), commitId(1), true), repository)
defining(params("commitId").split("\\.\\.\\.")){ case Array(from, to) =>
using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git =>
wiki.html.compare(Some(pageName), from, to, JGitUtil.getDiffs(git, from, to, true), repository,
hasWritePermission(repository.owner, repository.name, context.loginAccount), flash.get("info"))
}
}
})
get("/:owner/:repository/wiki/_compare/:commitId")(referrersOnly { repository =>
val commitId = params("commitId").split("\\.\\.\\.")
defining(params("commitId").split("\\.\\.\\.")){ case Array(from, to) =>
using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git =>
wiki.html.compare(None, from, to, JGitUtil.getDiffs(git, from, to, true), repository,
hasWritePermission(repository.owner, repository.name, context.loginAccount), flash.get("info"))
}
}
})
using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git =>
wiki.html.compare(None, JGitUtil.getDiffs(git, commitId(0), commitId(1), true), repository)
get("/:owner/:repository/wiki/:page/_revert/:commitId")(collaboratorsOnly { repository =>
val pageName = StringUtil.urlDecode(params("page"))
defining(params("commitId").split("\\.\\.\\.")){ case Array(from, to) =>
if(revertWikiPage(repository.owner, repository.name, from, to, context.loginAccount.get, Some(pageName))){
redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}")
} else {
flash += "info" -> "This patch was not able to be reversed."
redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}/_compare/${from}...${to}")
}
}
})
get("/:owner/:repository/wiki/_revert/:commitId")(collaboratorsOnly { repository =>
defining(params("commitId").split("\\.\\.\\.")){ case Array(from, to) =>
if(revertWikiPage(repository.owner, repository.name, from, to, context.loginAccount.get, None)){
redirect(s"/${repository.owner}/${repository.name}/wiki/}")
} else {
flash += "info" -> "This patch was not able to be reversed."
redirect(s"/${repository.owner}/${repository.name}/wiki/_compare/${from}...${to}")
}
}
})

View File

@@ -4,8 +4,11 @@ import java.io.File
import java.util.Date
import org.eclipse.jgit.api.Git
import org.apache.commons.io.FileUtils
import util.{Directory, JGitUtil, LockUtil}
import util.{StringUtil, Directory, JGitUtil, LockUtil}
import util.ControlUtil._
import org.eclipse.jgit.treewalk.CanonicalTreeParser
import org.eclipse.jgit.diff.DiffFormatter
import org.eclipse.jgit.api.errors.PatchApplyException
object WikiService {
@@ -90,6 +93,52 @@ trait WikiService {
}
}
/**
* Reverts specified changes.
*/
def revertWikiPage(owner: String, repository: String, from: String, to: String,
committer: model.Account, pageName: Option[String]): Boolean = {
LockUtil.lock(s"${owner}/${repository}/wiki"){
using(Git.open(Directory.getWikiWorkDir(owner, repository))){ git =>
val reader = git.getRepository.newObjectReader
val oldTreeIter = new CanonicalTreeParser
oldTreeIter.reset(reader, git.getRepository.resolve(from + "^{tree}"))
val newTreeIter = new CanonicalTreeParser
newTreeIter.reset(reader, git.getRepository.resolve(to + "^{tree}"))
import scala.collection.JavaConverters._
val diffs = git.diff.setNewTree(oldTreeIter).setOldTree(newTreeIter).call.asScala.filter { diff =>
pageName match {
case Some(x) => diff.getNewPath == x + ".md"
case None => true
}
}
val patch = using(new java.io.ByteArrayOutputStream()){ out =>
val formatter = new DiffFormatter(out)
formatter.setRepository(git.getRepository)
formatter.format(diffs.asJava)
new String(out.toByteArray, "UTF-8")
}
try {
git.apply.setPatch(new java.io.ByteArrayInputStream(patch.getBytes("UTF-8"))).call
git.add.addFilepattern(".").call
git.commit.setCommitter(committer.userName, committer.mailAddress).setMessage(pageName match {
case Some(x) => s"Revert ${from} ... ${to} on ${x}"
case None => s"Revert ${from} ... ${to}"
}).call
git.push.call
true
} catch {
case ex: PatchApplyException => false
}
}
}
}
/**
* Save the wiki page.
*/

View File

@@ -1,10 +1,15 @@
@(pageName: Option[String],
from: String,
to: String,
diffs: Seq[util.JGitUtil.DiffInfo],
repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context)
repository: service.RepositoryService.RepositoryInfo,
hasWritePermission: Boolean,
info: Option[Any])(implicit context: app.Context)
@import context._
@import view.helpers._
@import org.eclipse.jgit.diff.DiffEntry.ChangeType
@html.main(s"Compare Revisions - ${repository.owner}/${repository.name}", Some(repository)){
@helper.html.information(info)
@html.header("wiki", repository)
@tab("history", repository)
<ul class="nav nav-tabs">
@@ -23,4 +28,13 @@
</li>
</ul>
@helper.html.diff(diffs, repository, None, None, false)
@if(hasWritePermission){
<div>
@if(pageName.isDefined){
<a href="@url(repository)/wiki/@urlEncode(pageName)/_revert/@from...@to" class="btn">Revert Changes</a>
} else {
<a href="@url(repository)/wiki/_revert/@from...@to" class="btn">Revert Changes</a>
}
</div>
}
}