Implemented squash merge strategy

This commit is contained in:
Naoki Takezoe
2017-12-11 12:32:52 +09:00
parent fcb374c5c2
commit eb61bc50d6
2 changed files with 52 additions and 18 deletions

View File

@@ -260,18 +260,19 @@ trait PullRequestsControllerBase extends ControllerBase {
recordMergeActivity(owner, name, loginAccount.userName, issueId, form.message)
// merge git repository
// TODO Implement merge strategy!
println(form.strategy)
form.strategy match {
case "merge-commit" =>
println("** merge commit **")
mergePullRequest(git, pullreq.branch, issueId,
s"Merge pull request #${issueId} from ${pullreq.requestUserName}/${pullreq.requestBranch}\n\n" + form.message,
new PersonIdent(loginAccount.fullName, loginAccount.mailAddress))
case "rebase" =>
println("** rebase **")
rebasePullRequest(git, pullreq.branch, issueId,
new PersonIdent(loginAccount.fullName, loginAccount.mailAddress))
case "squash" =>
squashPullRequest(git, pullreq.branch, issueId,
s"Merge pull request #${issueId} from ${pullreq.requestUserName}/${pullreq.requestBranch}\n\n" + form.message,
new PersonIdent(loginAccount.fullName, loginAccount.mailAddress))
}
val (commits, _) = getRequestCompareInfo(owner, name, pullreq.commitIdFrom,

View File

@@ -8,7 +8,7 @@ import org.eclipse.jgit.api.Git
import org.eclipse.jgit.transport.RefSpec
import org.eclipse.jgit.errors.NoMergeBaseException
import org.eclipse.jgit.lib.{CommitBuilder, ObjectId, PersonIdent, Repository}
import org.eclipse.jgit.revwalk.{RevCommit, RevWalk}
import org.eclipse.jgit.revwalk.RevWalk
trait MergeService {
import MergeService._
@@ -45,6 +45,10 @@ trait MergeService {
new MergeCacheInfo(git, branch, issueId).rebase(committer)
}
def squashPullRequest(git: Git, branch: String, issueId: Int, message: String, committer: PersonIdent): Unit = {
new MergeCacheInfo(git, branch, issueId).squash(message, committer)
}
/** fetch remote branch to my repository refs/pull/{issueId}/head */
def fetchAsPullRequest(userName: String, repositoryName: String, requestUserName: String, requestRepositoryName: String, requestBranch:String, issueId:Int){
using(Git.open(getRepositoryDir(userName, repositoryName))){ git =>
@@ -101,14 +105,15 @@ trait MergeService {
def pullRemote(localUserName: String, localRepositoryName: String, localBranch: String,
remoteUserName: String, remoteRepositoryName: String, remoteBranch: String,
loginAccount: Account, message: String): Option[ObjectId] = {
tryMergeRemote(localUserName, localRepositoryName, localBranch, remoteUserName, remoteRepositoryName, remoteBranch).map{ case (newTreeId, oldBaseId, oldHeadId) =>
using(Git.open(getRepositoryDir(localUserName, localRepositoryName))) { git =>
val committer = new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
val newCommit = Util.createMergeCommit(git.getRepository, newTreeId, committer, message, Seq(oldBaseId, oldHeadId))
Util.updateRefs(git.getRepository, s"refs/heads/${localBranch}", newCommit, false, committer, Some("merge"))
tryMergeRemote(localUserName, localRepositoryName, localBranch, remoteUserName, remoteRepositoryName, remoteBranch)
.map { case (newTreeId, oldBaseId, oldHeadId) =>
using(Git.open(getRepositoryDir(localUserName, localRepositoryName))) { git =>
val committer = new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
val newCommit = Util.createMergeCommit(git.getRepository, newTreeId, committer, message, Seq(oldBaseId, oldHeadId))
Util.updateRefs(git.getRepository, s"refs/heads/${localBranch}", newCommit, false, committer, Some("merge"))
}
oldBaseId
}
oldBaseId
}
}
}
@@ -184,24 +189,24 @@ object MergeService{
val mergeTipCommit = using(new RevWalk( repository ))(_.parseCommit( mergeTip ))
val committer = mergeTipCommit.getCommitterIdent
def updateBranch(treeId: ObjectId, message: String, branchName: String){
def _updateBranch(treeId: ObjectId, message: String, branchName: String){
// creates merge commit
val mergeCommitId = createMergeCommit(treeId, committer, message)
Util.updateRefs(repository, branchName, mergeCommitId, true, committer)
}
if(!conflicted){
updateBranch(merger.getResultTreeId, s"Merge ${mergeTip.name} into ${mergeBaseTip.name}", mergedBranchName)
_updateBranch(merger.getResultTreeId, s"Merge ${mergeTip.name} into ${mergeBaseTip.name}", mergedBranchName)
git.branchDelete().setForce(true).setBranchNames(conflictedBranchName).call()
} else {
updateBranch(mergeTipCommit.getTree().getId(), s"can't merge ${mergeTip.name} into ${mergeBaseTip.name}", conflictedBranchName)
_updateBranch(mergeTipCommit.getTree().getId(), s"can't merge ${mergeTip.name} into ${mergeBaseTip.name}", conflictedBranchName)
git.branchDelete().setForce(true).setBranchNames(mergedBranchName).call()
}
conflicted
}
// update branch from cache
def merge(message: String, committer: PersonIdent) = {
def merge(message: String, committer: PersonIdent): Unit = {
if(checkConflict()){
throw new RuntimeException("This pull request can't merge automatically.")
}
@@ -211,15 +216,43 @@ object MergeService{
// creates merge commit
val mergeCommitId = createMergeCommit(mergeResultCommit.getTree().getId(), committer, message)
// update refs
Util.updateRefs(repository, s"refs/heads/${branch}", mergeCommitId, false, committer, Some("merged"))
Util.updateRefs(repository, s"refs/heads/${branch}", mergeCommitId, false, committer, Some("merged")) // TODO reflog message
}
def rebase(committer: PersonIdent) = {
def rebase(committer: PersonIdent): Unit = {
if(checkConflict()){
throw new RuntimeException("This pull request can't merge automatically.")
}
val mergeTipCommit = using(new RevWalk( repository ))(_.parseCommit( mergeTip ))
Util.updateRefs(repository, s"refs/heads/${branch}", mergeTipCommit.getId, false, committer, Some("merged"))
Util.updateRefs(repository, s"refs/heads/${branch}", mergeTipCommit.getId, false, committer, Some("merged")) // TODO reflog message
}
def squash(message: String, committer: PersonIdent): Unit = {
if(checkConflict()){
throw new RuntimeException("This pull request can't merge automatically.")
}
val baseCommit = using(new RevWalk( repository ))(_.parseCommit(mergeBaseTip))
val mergeBranchHeadCommit = using(new RevWalk( repository ))(_.parseCommit(repository.resolve(mergedBranchName)))
// Create squash commit
val mergeCommit = new CommitBuilder()
mergeCommit.setTreeId(mergeBranchHeadCommit.getTree.getId)
mergeCommit.setParentId(baseCommit)
mergeCommit.setAuthor(mergeBranchHeadCommit.getAuthorIdent)
mergeCommit.setCommitter(committer)
mergeCommit.setMessage(message)
// insertObject and got squash commit Object Id
val inserter = repository.newObjectInserter
val newCommitId = inserter.insert(mergeCommit)
inserter.flush()
inserter.close()
Util.updateRefs(repository, mergedBranchName, newCommitId, true, committer)
// rebase to squash commit
Util.updateRefs(repository, s"refs/heads/${branch}", repository.resolve(mergedBranchName), false, committer, Some("merged")) // TODO reflog message
}
// return treeId