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,13 +74,11 @@ 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}")
// Create README.md val content = if(form.description.nonEmpty){
FileUtils.writeStringToFile(new File(tmpdir, "README.md"),
if(form.description.nonEmpty){
form.name + "\n" + form.name + "\n" +
"===============\n" + "===============\n" +
"\n" + "\n" +
@@ -87,14 +86,14 @@ trait CreateRepositoryControllerBase extends ControllerBase {
} else { } else {
form.name + "\n" + form.name + "\n" +
"===============\n" "===============\n"
}, "UTF-8") }
val git = Git.open(tmpdir) builder.add(JGitUtil.createDirCacheEntry("README.md", FileMode.REGULAR_FILE,
git.add.addFilepattern("README.md").call inserter.insert(Constants.OBJ_BLOB, content.getBytes("UTF-8"))))
git.commit builder.finish()
.setCommitter(new PersonIdent(loginAccount.fullName, loginAccount.mailAddress))
.setMessage("Initial commit").call JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter),
git.push.call loginAccount.fullName, loginAccount.mailAddress, "Initial commit")
} }
} }

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,6 +218,7 @@ trait WikiService {
var updated = false var updated = false
var removed = false var removed = false
if(headId != null){
using(new RevWalk(git.getRepository)){ revWalk => using(new RevWalk(git.getRepository)){ revWalk =>
using(new TreeWalk(git.getRepository)){ treeWalk => using(new TreeWalk(git.getRepository)){ treeWalk =>
val index = treeWalk.addTree(revWalk.parseTree(headId)) val index = treeWalk.addTree(revWalk.parseTree(headId))
@@ -228,7 +229,7 @@ trait WikiService {
if(path == currentPageName + ".md" && currentPageName != newPageName){ if(path == currentPageName + ".md" && currentPageName != newPageName){
removed = true removed = true
} else if(path != newPageName + ".md"){ } else if(path != newPageName + ".md"){
builder.add(createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId)) builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
} else { } else {
created = false created = false
updated = JGitUtil.getContent(git, tree.getEntryObjectId, true).map(new String(_, "UTF-8") != content).getOrElse(false) updated = JGitUtil.getContent(git, tree.getEntryObjectId, true).map(new String(_, "UTF-8") != content).getOrElse(false)
@@ -236,11 +237,12 @@ trait WikiService {
} }
} }
} }
}
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
}
} }