(refs #180)Fix saving and deleting Wiki page.

This commit is contained in:
takezoe
2013-10-29 11:39:38 +09:00
parent 2642da3be3
commit afb2306904
2 changed files with 92 additions and 102 deletions

View File

@@ -195,7 +195,7 @@ trait WikiControllerBase extends ControllerBase with FlashMapSupport {
private def conflictForEdit: Constraint = new Constraint(){ private def conflictForEdit: Constraint = new Constraint(){
override def validate(name: String, value: String): Option[String] = { override def validate(name: String, value: String): Option[String] = {
optionIf(targetWikiPage.map(_.id != params("id")).getOrElse(true)){ optionIf(targetWikiPage.map(_.id != params("id")).getOrElse(false)){
Some("Someone has edited the wiki since you started. Please reload this page and re-apply your changes.") Some("Someone has edited the wiki since you started. Please reload this page and re-apply your changes.")
} }
} }

View File

@@ -1,21 +1,17 @@
package service package service
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.{StringUtil, Directory, JGitUtil, LockUtil} import util.{Directory, JGitUtil, LockUtil}
import _root_.util.ControlUtil._ import _root_.util.ControlUtil._
import org.eclipse.jgit.treewalk.{TreeWalk, CanonicalTreeParser} import org.eclipse.jgit.treewalk.{TreeWalk, CanonicalTreeParser}
import org.eclipse.jgit.diff.DiffFormatter
import org.eclipse.jgit.api.errors.PatchApplyException
import java.util
import org.eclipse.jgit.lib._ import org.eclipse.jgit.lib._
import org.eclipse.jgit.dircache.{DirCache, DirCacheEntry} import org.eclipse.jgit.dircache.{DirCache, DirCacheEntry}
import org.eclipse.jgit.merge.{ResolveMerger, MergeStrategy} import org.eclipse.jgit.merge.{ResolveMerger, MergeStrategy}
import scala.Some
import org.eclipse.jgit.revwalk.RevWalk import org.eclipse.jgit.revwalk.RevWalk
import org.eclipse.jgit.api.CheckoutCommand.Stage import scala.collection.JavaConverters._
object WikiService { object WikiService {
@@ -159,9 +155,6 @@ trait WikiService {
def saveWikiPage(owner: String, repository: String, currentPageName: String, newPageName: String, def saveWikiPage(owner: String, repository: String, currentPageName: String, newPageName: String,
content: String, committer: model.Account, message: String, currentId: Option[String]): Option[String] = { content: String, committer: model.Account, message: String, currentId: Option[String]): Option[String] = {
import scala.collection.JavaConverters._
// TODO conflict detection and rename page
LockUtil.lock(s"${owner}/${repository}/wiki"){ LockUtil.lock(s"${owner}/${repository}/wiki"){
using(Git.open(Directory.getWikiRepositoryDir(owner, repository))){ git => using(Git.open(Directory.getWikiRepositoryDir(owner, repository))){ git =>
val repo = git.getRepository() val repo = git.getRepository()
@@ -170,26 +163,32 @@ trait WikiService {
val inserter = repo.newObjectInserter() val inserter = repo.newObjectInserter()
val headId = repo.resolve(Constants.HEAD + "^{commit}") val headId = repo.resolve(Constants.HEAD + "^{commit}")
var created = true var created = true
var updated = false
var removed = false
using(new RevWalk(git.getRepository)){ revWalk => using(new RevWalk(git.getRepository)){ revWalk =>
val treeWalk = new TreeWalk(repo) val treeWalk = new TreeWalk(repo)
val hIdx = treeWalk.addTree(revWalk.parseTree(headId)) val index = treeWalk.addTree(revWalk.parseTree(headId))
treeWalk.setRecursive(true) treeWalk.setRecursive(true)
while(treeWalk.next){ while(treeWalk.next){
val path = treeWalk.getPathString val path = treeWalk.getPathString
if(path != newPageName + ".md"){ val tree = treeWalk.getTree(index, classOf[CanonicalTreeParser])
val hTree = treeWalk.getTree(hIdx, classOf[CanonicalTreeParser]) if(path == currentPageName + ".md" && currentPageName != newPageName){
removed = true
} else if(path != newPageName + ".md"){
val entry = new DirCacheEntry(path) val entry = new DirCacheEntry(path)
entry.setObjectId(hTree.getEntryObjectId()) entry.setObjectId(tree.getEntryObjectId())
entry.setFileMode(hTree.getEntryFileMode()) entry.setFileMode(tree.getEntryFileMode())
builder.add(entry) builder.add(entry)
} else { } else {
created = false created = false
updated = JGitUtil.getContent(git, tree.getEntryObjectId, true).map(new String(_, "UTF-8") != content).getOrElse(false)
} }
} }
treeWalk.release() treeWalk.release()
} }
optionIf(created || updated || removed){
val entry = new DirCacheEntry(newPageName + ".md") val entry = new DirCacheEntry(newPageName + ".md")
entry.setFileMode(FileMode.REGULAR_FILE) entry.setFileMode(FileMode.REGULAR_FILE)
entry.setObjectId(inserter.insert(Constants.OBJ_BLOB, content.getBytes("UTF-8"))) entry.setObjectId(inserter.insert(Constants.OBJ_BLOB, content.getBytes("UTF-8")))
@@ -202,7 +201,9 @@ trait WikiService {
newCommit.setCommitter(new PersonIdent(committer.fullName, committer.mailAddress)) newCommit.setCommitter(new PersonIdent(committer.fullName, committer.mailAddress))
newCommit.setAuthor(new PersonIdent(committer.fullName, committer.mailAddress)) newCommit.setAuthor(new PersonIdent(committer.fullName, committer.mailAddress))
newCommit.setMessage(if(message.trim.length == 0) { newCommit.setMessage(if(message.trim.length == 0) {
if(created){ if(removed){
s"Rename ${currentPageName} to ${newPageName}"
} else if(created){
s"Created ${newPageName}" s"Created ${newPageName}"
} else { } else {
s"Updated ${newPageName}" s"Updated ${newPageName}"
@@ -216,57 +217,14 @@ trait WikiService {
val newHeadId = inserter.insert(newCommit) val newHeadId = inserter.insert(newCommit)
inserter.flush() inserter.flush()
val ru = repo.updateRef(Constants.HEAD) val refUpdate = repo.updateRef(Constants.HEAD)
ru.setNewObjectId(newHeadId) refUpdate.setNewObjectId(newHeadId)
ru.update() refUpdate.update()
Some(newHeadId.getName) Some(newHeadId.getName)
} }
} }
}
// defining(Directory.getWikiWorkDir(owner, repository)){ workDir =>
// // clone working copy
// cloneOrPullWorkingCopy(workDir, owner, repository)
//
// // write as file
// using(Git.open(workDir)){ git =>
// defining(new File(workDir, newPageName + ".md")){ file =>
// // new page
// val created = !file.exists
//
// // created or updated
// val added = executeIf(!file.exists || FileUtils.readFileToString(file, "UTF-8") != content){
// FileUtils.writeStringToFile(file, content, "UTF-8")
// git.add.addFilepattern(file.getName).call
// }
//
// // delete file
// val deleted = executeIf(currentPageName != "" && currentPageName != newPageName){
// git.rm.addFilepattern(currentPageName + ".md").call
// }
//
// // commit and push
// optionIf(added || deleted){
// defining(git.commit.setCommitter(committer.fullName, committer.mailAddress)
// .setMessage(if(message.trim.length == 0){
// if(deleted){
// s"Rename ${currentPageName} to ${newPageName}"
// } else if(created){
// s"Created ${newPageName}"
// } else {
// s"Updated ${newPageName}"
// }
// } else {
// message
// }).call){ commit =>
// git.push.call
// Some(commit.getName)
// }
// }
// }
// }
// }
// }
} }
/** /**
@@ -274,23 +232,55 @@ trait WikiService {
*/ */
def deleteWikiPage(owner: String, repository: String, pageName: String, def deleteWikiPage(owner: String, repository: String, pageName: String,
committer: String, mailAddress: String, message: String): Unit = { committer: String, mailAddress: String, message: String): Unit = {
// LockUtil.lock(s"${owner}/${repository}/wiki"){ LockUtil.lock(s"${owner}/${repository}/wiki"){
// defining(Directory.getWikiWorkDir(owner, repository)){ workDir => using(Git.open(Directory.getWikiRepositoryDir(owner, repository))){ git =>
// // clone working copy val repo = git.getRepository()
// cloneOrPullWorkingCopy(workDir, owner, repository) val dirCache = DirCache.newInCore()
// val builder = dirCache.builder()
// // delete file val inserter = repo.newObjectInserter()
// new File(workDir, pageName + ".md").delete val headId = repo.resolve(Constants.HEAD + "^{commit}")
// var removed = false
// using(Git.open(workDir)){ git =>
// git.rm.addFilepattern(pageName + ".md").call using(new RevWalk(git.getRepository)){ revWalk =>
// val treeWalk = new TreeWalk(repo)
// // commit and push val index = treeWalk.addTree(revWalk.parseTree(headId))
// git.commit.setCommitter(committer, mailAddress).setMessage(message).call treeWalk.setRecursive(true)
// git.push.call while(treeWalk.next){
// } val path = treeWalk.getPathString
// } val tree = treeWalk.getTree(index, classOf[CanonicalTreeParser])
// } if(path != pageName + ".md"){
val entry = new DirCacheEntry(path)
entry.setObjectId(tree.getEntryObjectId())
entry.setFileMode(tree.getEntryFileMode())
builder.add(entry)
} else {
removed = true
}
}
treeWalk.release()
}
if(removed){
builder.finish()
val treeId = dirCache.writeTree(inserter)
val newCommit = new CommitBuilder()
newCommit.setCommitter(new PersonIdent(committer, mailAddress))
newCommit.setAuthor(new PersonIdent(committer, mailAddress))
newCommit.setMessage(message)
newCommit.setParentIds(List(headId).asJava)
newCommit.setTreeId(treeId)
val newHeadId = inserter.insert(newCommit)
inserter.flush()
val refUpdate = repo.updateRef(Constants.HEAD)
refUpdate.setNewObjectId(newHeadId)
refUpdate.update()
}
}
}
} }
// private def cloneOrPullWorkingCopy(workDir: File, owner: String, repository: String): Unit = { // private def cloneOrPullWorkingCopy(workDir: File, owner: String, repository: String): Unit = {