(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 util.ControlUtil._
import jp.sf.amateras.scalatra.forms._ import jp.sf.amateras.scalatra.forms._
import org.eclipse.jgit.api.Git import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.errors.PatchApplyException
import org.scalatra.FlashMapSupport
class WikiController extends WikiControllerBase class WikiController extends WikiControllerBase
with WikiService with RepositoryService with AccountService with ActivityService with WikiService with RepositoryService with AccountService with ActivityService
with CollaboratorsAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with ReferrerAuthenticator
trait WikiControllerBase extends ControllerBase { trait WikiControllerBase extends ControllerBase with FlashMapSupport {
self: WikiService with RepositoryService with ActivityService self: WikiService with RepositoryService with ActivityService
with CollaboratorsAuthenticator with ReferrerAuthenticator => with CollaboratorsAuthenticator with ReferrerAuthenticator =>
@@ -58,21 +60,48 @@ trait WikiControllerBase extends ControllerBase {
get("/:owner/:repository/wiki/:page/_compare/:commitId")(referrersOnly { repository => get("/:owner/:repository/wiki/:page/_compare/:commitId")(referrersOnly { repository =>
val pageName = StringUtil.urlDecode(params("page")) val pageName = StringUtil.urlDecode(params("page"))
val commitId = params("commitId").split("\\.\\.\\.")
using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git => defining(params("commitId").split("\\.\\.\\.")){ case Array(from, to) =>
wiki.html.compare(Some(pageName), JGitUtil.getDiffs(git, commitId(0), commitId(1), true), repository) 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 => 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 =>
using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git => wiki.html.compare(None, from, to, JGitUtil.getDiffs(git, from, to, true), repository,
wiki.html.compare(None, JGitUtil.getDiffs(git, commitId(0), commitId(1), true), repository) hasWritePermission(repository.owner, repository.name, context.loginAccount), flash.get("info"))
}
} }
}) })
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}")
}
}
})
get("/:owner/:repository/wiki/:page/_edit")(collaboratorsOnly { repository => get("/:owner/:repository/wiki/:page/_edit")(collaboratorsOnly { repository =>
val pageName = StringUtil.urlDecode(params("page")) val pageName = StringUtil.urlDecode(params("page"))
wiki.html.edit(pageName, getWikiPage(repository.owner, repository.name, pageName), repository) wiki.html.edit(pageName, getWikiPage(repository.owner, repository.name, pageName), repository)

View File

@@ -4,8 +4,11 @@ import java.io.File
import java.util.Date import java.util.Date
import org.eclipse.jgit.api.Git import org.eclipse.jgit.api.Git
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import util.{Directory, JGitUtil, LockUtil} import util.{StringUtil, Directory, JGitUtil, LockUtil}
import util.ControlUtil._ import util.ControlUtil._
import org.eclipse.jgit.treewalk.CanonicalTreeParser
import org.eclipse.jgit.diff.DiffFormatter
import org.eclipse.jgit.api.errors.PatchApplyException
object WikiService { object WikiService {
@@ -89,7 +92,53 @@ trait WikiService {
.sortBy(x => x) .sortBy(x => x)
} }
} }
/**
* 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. * Save the wiki page.
*/ */

View File

@@ -1,10 +1,15 @@
@(pageName: Option[String], @(pageName: Option[String],
from: String,
to: String,
diffs: Seq[util.JGitUtil.DiffInfo], 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 context._
@import view.helpers._ @import view.helpers._
@import org.eclipse.jgit.diff.DiffEntry.ChangeType @import org.eclipse.jgit.diff.DiffEntry.ChangeType
@html.main(s"Compare Revisions - ${repository.owner}/${repository.name}", Some(repository)){ @html.main(s"Compare Revisions - ${repository.owner}/${repository.name}", Some(repository)){
@helper.html.information(info)
@html.header("wiki", repository) @html.header("wiki", repository)
@tab("history", repository) @tab("history", repository)
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
@@ -23,4 +28,13 @@
</li> </li>
</ul> </ul>
@helper.html.diff(diffs, repository, None, None, false) @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>
}
} }