Improve repository creation to not use the working repository.

This commit is contained in:
takezoe
2013-10-30 14:52:55 +09:00
parent 35c8f02f90
commit bd0ecd0a9d
4 changed files with 72 additions and 79 deletions

View File

@@ -8,7 +8,8 @@ import java.io.File
import org.eclipse.jgit.api.Git import org.eclipse.jgit.api.Git
import org.apache.commons.io._ import org.apache.commons.io._
import jp.sf.amateras.scalatra.forms._ import jp.sf.amateras.scalatra.forms._
import org.eclipse.jgit.lib.PersonIdent import org.eclipse.jgit.lib.{FileMode, Constants, PersonIdent}
import org.eclipse.jgit.dircache.DirCache
class CreateRepositoryController extends CreateRepositoryControllerBase class CreateRepositoryController extends CreateRepositoryControllerBase
with RepositoryService with AccountService with WikiService with LabelsService with ActivityService with RepositoryService with AccountService with WikiService with LabelsService with ActivityService
@@ -73,28 +74,26 @@ trait CreateRepositoryControllerBase extends ControllerBase {
JGitUtil.initRepository(gitdir) JGitUtil.initRepository(gitdir)
if(form.createReadme){ if(form.createReadme){
FileUtil.withTmpDir(getInitRepositoryDir(form.owner, form.name)){ tmpdir => using(Git.open(gitdir)){ git =>
// Clone the repository val builder = DirCache.newInCore.builder()
Git.cloneRepository.setURI(gitdir.toURI.toString).setDirectory(tmpdir).call val inserter = git.getRepository.newObjectInserter()
val headId = git.getRepository.resolve(Constants.HEAD + "^{commit}")
val content = if(form.description.nonEmpty){
form.name + "\n" +
"===============\n" +
"\n" +
form.description.get
} else {
form.name + "\n" +
"===============\n"
}
// Create README.md builder.add(JGitUtil.createDirCacheEntry("README.md", FileMode.REGULAR_FILE,
FileUtils.writeStringToFile(new File(tmpdir, "README.md"), inserter.insert(Constants.OBJ_BLOB, content.getBytes("UTF-8"))))
if(form.description.nonEmpty){ builder.finish()
form.name + "\n" +
"===============\n" +
"\n" +
form.description.get
} else {
form.name + "\n" +
"===============\n"
}, "UTF-8")
val git = Git.open(tmpdir) JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter),
git.add.addFilepattern("README.md").call loginAccount.fullName, loginAccount.mailAddress, "Initial commit")
git.commit
.setCommitter(new PersonIdent(loginAccount.fullName, loginAccount.mailAddress))
.setMessage("Initial commit").call
git.push.call
} }
} }

View File

@@ -176,18 +176,18 @@ trait WikiService {
val path = treeWalk.getPathString val path = treeWalk.getPathString
val tree = treeWalk.getTree(index, classOf[CanonicalTreeParser]) val tree = treeWalk.getTree(index, classOf[CanonicalTreeParser])
if(revertInfo.find(x => x.filePath == path).isEmpty){ if(revertInfo.find(x => x.filePath == path).isEmpty){
builder.add(createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId)) builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
} }
} }
} }
} }
revertInfo.filter(_.operation == "ADD").foreach { x => revertInfo.filter(_.operation == "ADD").foreach { x =>
builder.add(createDirCacheEntry(x.filePath, FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, x.source.getBytes("UTF-8")))) builder.add(JGitUtil.createDirCacheEntry(x.filePath, FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, x.source.getBytes("UTF-8"))))
} }
builder.finish() builder.finish()
createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), committer.fullName, committer.mailAddress, JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), committer.fullName, committer.mailAddress,
pageName match { pageName match {
case Some(x) => s"Revert ${from} ... ${to} on ${x}" case Some(x) => s"Revert ${from} ... ${to} on ${x}"
case None => s"Revert ${from} ... ${to}" case None => s"Revert ${from} ... ${to}"
@@ -218,29 +218,31 @@ trait WikiService {
var updated = false var updated = false
var removed = false var removed = false
using(new RevWalk(git.getRepository)){ revWalk => if(headId != null){
using(new TreeWalk(git.getRepository)){ treeWalk => using(new RevWalk(git.getRepository)){ revWalk =>
val index = treeWalk.addTree(revWalk.parseTree(headId)) using(new TreeWalk(git.getRepository)){ treeWalk =>
treeWalk.setRecursive(true) val index = treeWalk.addTree(revWalk.parseTree(headId))
while(treeWalk.next){ treeWalk.setRecursive(true)
val path = treeWalk.getPathString while(treeWalk.next){
val tree = treeWalk.getTree(index, classOf[CanonicalTreeParser]) val path = treeWalk.getPathString
if(path == currentPageName + ".md" && currentPageName != newPageName){ val tree = treeWalk.getTree(index, classOf[CanonicalTreeParser])
removed = true if(path == currentPageName + ".md" && currentPageName != newPageName){
} else if(path != newPageName + ".md"){ removed = true
builder.add(createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId)) } else if(path != newPageName + ".md"){
} else { builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
created = false } else {
updated = JGitUtil.getContent(git, tree.getEntryObjectId, true).map(new String(_, "UTF-8") != content).getOrElse(false) created = false
updated = JGitUtil.getContent(git, tree.getEntryObjectId, true).map(new String(_, "UTF-8") != content).getOrElse(false)
}
} }
} }
} }
} }
optionIf(created || updated || removed){ optionIf(created || updated || removed){
builder.add(createDirCacheEntry(newPageName + ".md", FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, content.getBytes("UTF-8")))) builder.add(JGitUtil.createDirCacheEntry(newPageName + ".md", FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, content.getBytes("UTF-8"))))
builder.finish() builder.finish()
val newHeadId = createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), committer.fullName, committer.mailAddress, val newHeadId = JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), committer.fullName, committer.mailAddress,
if(message.trim.length == 0) { if(message.trim.length == 0) {
if(removed){ if(removed){
s"Rename ${currentPageName} to ${newPageName}" s"Rename ${currentPageName} to ${newPageName}"
@@ -279,7 +281,7 @@ trait WikiService {
val path = treeWalk.getPathString val path = treeWalk.getPathString
val tree = treeWalk.getTree(index, classOf[CanonicalTreeParser]) val tree = treeWalk.getTree(index, classOf[CanonicalTreeParser])
if(path != pageName + ".md"){ if(path != pageName + ".md"){
builder.add(createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId)) builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
} else { } else {
removed = true removed = true
} }
@@ -288,39 +290,11 @@ trait WikiService {
if(removed){ if(removed){
builder.finish() builder.finish()
createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), committer, mailAddress, message) JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), committer, mailAddress, message)
} }
} }
} }
} }
} }
// This method should be moved to JGitUtil?
private def createDirCacheEntry(path: String, mode: FileMode, objectId: ObjectId): DirCacheEntry = {
val entry = new DirCacheEntry(path)
entry.setFileMode(mode)
entry.setObjectId(objectId)
entry
}
// This method should be moved to JGitUtil?
private def createNewCommit(git: Git, inserter: ObjectInserter, headId: AnyObjectId, treeId: AnyObjectId,
fullName: String, mailAddress: String, message: String): String = {
val newCommit = new CommitBuilder()
newCommit.setCommitter(new PersonIdent(fullName, mailAddress))
newCommit.setAuthor(new PersonIdent(fullName, mailAddress))
newCommit.setMessage(message)
newCommit.setParentIds(List(headId).asJava)
newCommit.setTreeId(treeId)
val newHeadId = inserter.insert(newCommit)
inserter.flush()
val refUpdate = git.getRepository.updateRef(Constants.HEAD)
refUpdate.setNewObjectId(newHeadId)
refUpdate.update()
newHeadId.getName
}
} }

View File

@@ -56,15 +56,6 @@ object Directory {
def getDownloadWorkDir(owner: String, repository: String, sessionId: String): File = def getDownloadWorkDir(owner: String, repository: String, sessionId: String): File =
new File(getTemporaryDir(owner, repository), s"download/${sessionId}") new File(getTemporaryDir(owner, repository), s"download/${sessionId}")
/**
* Temporary directory which is used in the repository creation.
*
* GitBucket generates initial repository contents in this directory and push them.
* This directory is removed after the repository creation.
*/
def getInitRepositoryDir(owner: String, repository: String): File =
new File(getTemporaryDir(owner, repository), "init")
/** /**
* Substance directory of the wiki repository. * Substance directory of the wiki repository.
*/ */

View File

@@ -15,6 +15,7 @@ import org.eclipse.jgit.errors.MissingObjectException
import java.util.Date import java.util.Date
import org.eclipse.jgit.api.errors.NoHeadException import org.eclipse.jgit.api.errors.NoHeadException
import service.RepositoryService import service.RepositoryService
import org.eclipse.jgit.dircache.DirCacheEntry
/** /**
* Provides complex JGit operations. * Provides complex JGit operations.
@@ -464,4 +465,32 @@ object JGitUtil {
}.find(_._1 != null) }.find(_._1 != null)
} }
def createDirCacheEntry(path: String, mode: FileMode, objectId: ObjectId): DirCacheEntry = {
val entry = new DirCacheEntry(path)
entry.setFileMode(mode)
entry.setObjectId(objectId)
entry
}
def createNewCommit(git: Git, inserter: ObjectInserter, headId: AnyObjectId, treeId: AnyObjectId,
fullName: String, mailAddress: String, message: String): String = {
val newCommit = new CommitBuilder()
newCommit.setCommitter(new PersonIdent(fullName, mailAddress))
newCommit.setAuthor(new PersonIdent(fullName, mailAddress))
newCommit.setMessage(message)
if(headId != null){
newCommit.setParentIds(List(headId).asJava)
}
newCommit.setTreeId(treeId)
val newHeadId = inserter.insert(newCommit)
inserter.flush()
val refUpdate = git.getRepository.updateRef(Constants.HEAD)
refUpdate.setNewObjectId(newHeadId)
refUpdate.update()
newHeadId.getName
}
} }