Newer
Older
gitbucket_jkp / src / test / scala / service / MergeServiceSpec.scala
package service
import org.specs2.mutable.Specification
import java.util.Date
import model._
import util.JGitUtil
import util.Directory._
import java.nio.file._
import util.Implicits._
import util.ControlUtil._
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.dircache.DirCache
import org.eclipse.jgit.lib._
import org.eclipse.jgit.treewalk._
import org.eclipse.jgit.revwalk._
import org.apache.commons.io.FileUtils

class MergeServiceSpec extends Specification {
  sequential
  val service = new MergeService{}
  val branch = "master"
  val issueId = 10
  def initRepository(owner:String, name:String) = {
      val repo1Dir = getRepositoryDir(owner, name)
      RepositoryCache.clear()
      FileUtils.deleteQuietly(repo1Dir)
      Files.createDirectories(repo1Dir.toPath())
      JGitUtil.initRepository(repo1Dir)
      using(Git.open(repo1Dir)){ git =>
        createFile(git, s"refs/heads/master", "test.txt", "hoge" )
        git.branchCreate().setStartPoint(s"refs/heads/master").setName(s"refs/pull/${issueId}/head").call()
      }
      repo1Dir
  }
  def createFile(git:Git, branch:String, name:String, content:String){
    val builder  = DirCache.newInCore.builder()
    val inserter = git.getRepository.newObjectInserter()
    val headId   = git.getRepository.resolve(branch + "^{commit}")
    builder.add(JGitUtil.createDirCacheEntry(name, FileMode.REGULAR_FILE,
      inserter.insert(Constants.OBJ_BLOB, content.getBytes("UTF-8"))))
    builder.finish()
    JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter),
      branch, "dummy", "dummy@example.com", "Initial commit")
  }
  def getFile(git:Git, branch:String, path:String) = {
      val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch))
        val objectId = using(new TreeWalk(git.getRepository)){ walk =>
          walk.addTree(revCommit.getTree)
          walk.setRecursive(true)
          @scala.annotation.tailrec
          def _getPathObjectId: ObjectId = walk.next match {
            case true if(walk.getPathString == path) => walk.getObjectId(0)
            case true  => _getPathObjectId
            case false => throw new Exception(s"not found ${branch} / ${path}")
          }
          _getPathObjectId
        }
        JGitUtil.getContentInfo(git, path, objectId)
  }
  def createConfrict(git:Git) = {
    createFile(git, s"refs/heads/${branch}", "test.txt", "hoge2" )
    createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge4" )
  }
  "checkConflict, checkConflictCache" should {
    "checkConflict false if not conflicted, and create cache" in {
      val repo1Dir = initRepository("user1","repo1")
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None
      val conflicted = service.checkConflict("user1", "repo1", branch, issueId)
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false)
      conflicted  mustEqual false
    }
    "checkConflict true if not conflicted, and create cache" in {
      val repo1Dir = initRepository("user1","repo1")
      using(Git.open(repo1Dir)){ git =>
        createConfrict(git)
      }
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None
      val conflicted = service.checkConflict("user1", "repo1", branch, issueId)
      conflicted  mustEqual true
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(true)
    }
  }
  "checkConflictCache" should {
    "merged cache invalid if origin branch moved" in {
      val repo1Dir = initRepository("user1","repo1")
      service.checkConflict("user1", "repo1", branch, issueId) mustEqual false
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false)
      using(Git.open(repo1Dir)){ git =>
        createFile(git, s"refs/heads/${branch}", "test.txt", "hoge2" )
      }
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None
    }
    "merged cache invalid if request branch moved" in {
      val repo1Dir = initRepository("user1","repo1")
      service.checkConflict("user1", "repo1", branch, issueId) mustEqual false
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false)
      using(Git.open(repo1Dir)){ git =>
        createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge4" )
      }
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None
    }
    "merged cache invalid if origin branch moved" in {
      val repo1Dir = initRepository("user1","repo1")
      service.checkConflict("user1", "repo1", branch, issueId) mustEqual false
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false)
      using(Git.open(repo1Dir)){ git =>
        createFile(git, s"refs/heads/${branch}", "test.txt", "hoge2" )
      }
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None
    }
    "conflicted cache invalid if request branch moved" in {
      val repo1Dir = initRepository("user1","repo1")
      using(Git.open(repo1Dir)){ git =>
        createConfrict(git)
      }
      service.checkConflict("user1", "repo1", branch, issueId) mustEqual true
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(true)
      using(Git.open(repo1Dir)){ git =>
        createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge4" )
      }
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None
    }
    "conflicted cache invalid if origin branch moved" in {
      val repo1Dir = initRepository("user1","repo1")
      using(Git.open(repo1Dir)){ git =>
        createConfrict(git)
      }
      service.checkConflict("user1", "repo1", branch, issueId) mustEqual true
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(true)
      using(Git.open(repo1Dir)){ git =>
        createFile(git, s"refs/heads/${branch}", "test.txt", "hoge4" )
      }
      service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None
    }
  }
  "mergePullRequest" should {
    "can merge" in {
      val repo1Dir = initRepository("user1","repo1")
      using(Git.open(repo1Dir)){ git =>
        createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge2" )
        val committer = new PersonIdent("dummy2", "dummy2@example.com")
        getFile(git, branch, "test.txt").content.get mustEqual "hoge"
        val requestBranchId = git.getRepository.resolve(s"refs/pull/${issueId}/head")
        val masterId = git.getRepository.resolve(branch)
        service.mergePullRequest(git, branch, issueId, "merged", committer)
        val lastCommitId = git.getRepository.resolve(branch);
        val commit = using(new RevWalk(git.getRepository))(_.parseCommit(lastCommitId))
        commit.getCommitterIdent() mustEqual committer
        commit.getAuthorIdent() mustEqual committer
        commit.getFullMessage() mustEqual "merged"
        commit.getParents.toSet mustEqual Set( requestBranchId, masterId )
        getFile(git, branch, "test.txt").content.get mustEqual "hoge2"
      }
    }
  }
}