diff --git a/project/plugins.sbt b/project/plugins.sbt index 11c1511..bae8882 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,10 +1,12 @@ scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature") -addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.5.0") -addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.3.15") -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9") -addSbtPlugin("org.scalatra.sbt" % "sbt-scalatra" % "1.0.3") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.2") -addSbtCoursier +addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.5.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.3.15") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9") +addSbtPlugin("org.scalatra.sbt" % "sbt-scalatra" % "1.0.3") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.2") addSbtPlugin("com.typesafe.sbt" % "sbt-license-report" % "1.2.0") addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.2") +addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1") + +addSbtCoursier diff --git a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala index 18fd38d..022acf4 100644 --- a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala +++ b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala @@ -589,23 +589,26 @@ val mailAddresses = context.loginAccount.map(x => Seq(x.mailAddress) ++ getAccountExtraMailAddresses(x.userName)).getOrElse(Nil) - val branches = JGitUtil - .getBranches( - owner = repository.owner, - name = repository.name, - defaultBranch = repository.repository.defaultBranch, - origin = repository.repository.originUserName.isEmpty - ) - .filter { x => - x.mergeInfo.map(_.ahead).getOrElse(0) > 0 && x.mergeInfo.map(_.behind).getOrElse(0) == 0 && - x.commitTime.getTime > thresholdTime && - mailAddresses.contains(x.committerEmailAddress) + val branches = + using(Git.open(getRepositoryDir(repository.owner, repository.name))) { + git => + JGitUtil + .getBranches( + git = git, + defaultBranch = repository.repository.defaultBranch, + origin = repository.repository.originUserName.isEmpty + ) + .filter { x => + x.mergeInfo.map(_.ahead).getOrElse(0) > 0 && x.mergeInfo.map(_.behind).getOrElse(0) == 0 && + x.commitTime.getTime > thresholdTime && + mailAddresses.contains(x.committerEmailAddress) + } + .sortBy { br => + (br.mergeInfo.isEmpty, br.commitTime) + } + .map(_.name) + .reverse } - .sortBy { br => - (br.mergeInfo.isEmpty, br.commitTime) - } - .map(_.name) - .reverse val targetRepository = (for { parentUserName <- repository.repository.parentUserName diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index e8b9288..c842b22 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -723,29 +723,31 @@ */ get("/:owner/:repository/branches")(referrersOnly { repository => val protectedBranches = getProtectedBranchList(repository.owner, repository.name).toSet - val branches = JGitUtil - .getBranches( - owner = repository.owner, - name = repository.name, - defaultBranch = repository.repository.defaultBranch, - origin = repository.repository.originUserName.isEmpty - ) - .sortBy(br => (br.mergeInfo.isEmpty, br.commitTime)) - .map( - br => - ( - br, - getPullRequestByRequestCommit( - repository.owner, - repository.name, - repository.repository.defaultBranch, - br.name, - br.commitId - ), - protectedBranches.contains(br.name) - ) - ) - .reverse + val branches = using(Git.open(getRepositoryDir(repository.owner, repository.name))) { + git => + JGitUtil + .getBranches( + git = git, + defaultBranch = repository.repository.defaultBranch, + origin = repository.repository.originUserName.isEmpty + ) + .sortBy(br => (br.mergeInfo.isEmpty, br.commitTime)) + .map( + br => + ( + br, + getPullRequestByRequestCommit( + repository.owner, + repository.name, + repository.repository.defaultBranch, + br.name, + br.commitId + ), + protectedBranches.contains(br.name) + ) + ) + .reverse + } html.branches(branches, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), repository) }) @@ -920,7 +922,7 @@ repository, if (path == ".") Nil else path.split("/").toList, // current path new JGitUtil.CommitInfo(lastModifiedCommit), // last modified commit - JGitUtil.getCommitCount(repository.owner, repository.name, lastModifiedCommit.getName), + JGitUtil.getCommitCount(git, lastModifiedCommit.getName), files, readme, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), @@ -967,7 +969,7 @@ val entryPath = if (path.isEmpty) baseName + "/" + treeWalk.getPathString else path.split("/").last + treeWalk.getPathString.substring(path.length) - val size = JGitUtil.getFileSize(git, repository, treeWalk) + val size = JGitUtil.getContentSize(git.getRepository.open(treeWalk.getObjectId(0))) val mode = treeWalk.getFileMode.getBits val entry: ArchiveEntry = entryCreator(entryPath, size, date, mode) JGitUtil.openFile(git, repository, commit.getTree, treeWalk.getPathString) { in => diff --git a/src/main/scala/gitbucket/core/controller/api/ApiRepositoryBranchControllerBase.scala b/src/main/scala/gitbucket/core/controller/api/ApiRepositoryBranchControllerBase.scala index fa2d59a..04f42f6 100644 --- a/src/main/scala/gitbucket/core/controller/api/ApiRepositoryBranchControllerBase.scala +++ b/src/main/scala/gitbucket/core/controller/api/ApiRepositoryBranchControllerBase.scala @@ -3,8 +3,11 @@ import gitbucket.core.controller.ControllerBase import gitbucket.core.service.{AccountService, ProtectedBranchService, RepositoryService} import gitbucket.core.util._ +import gitbucket.core.util.SyntaxSugars._ +import gitbucket.core.util.Directory._ import gitbucket.core.util.Implicits._ import gitbucket.core.util.JGitUtil.getBranches +import org.eclipse.jgit.api.Git trait ApiRepositoryBranchControllerBase extends ControllerBase { self: RepositoryService @@ -22,18 +25,19 @@ * https://developer.github.com/v3/repos/branches/#list-branches */ get("/api/v3/repos/:owner/:repository/branches")(referrersOnly { repository => - JsonFormat( - JGitUtil - .getBranches( - owner = repository.owner, - name = repository.name, - defaultBranch = repository.repository.defaultBranch, - origin = repository.repository.originUserName.isEmpty - ) - .map { br => - ApiBranchForList(br.name, ApiBranchCommit(br.commitId)) - } - ) + using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git => + JsonFormat( + JGitUtil + .getBranches( + git = git, + defaultBranch = repository.repository.defaultBranch, + origin = repository.repository.originUserName.isEmpty + ) + .map { br => + ApiBranchForList(br.name, ApiBranchCommit(br.commitId)) + } + ) + } }) /** @@ -41,21 +45,22 @@ * https://developer.github.com/v3/repos/branches/#get-branch */ get("/api/v3/repos/:owner/:repository/branches/*")(referrersOnly { repository => - //import gitbucket.core.api._ - (for { - branch <- params.get("splat") if repository.branchList.contains(branch) - br <- getBranches( - repository.owner, - repository.name, - repository.repository.defaultBranch, - repository.repository.originUserName.isEmpty - ).find(_.name == branch) - } yield { - val protection = getProtectedBranchInfo(repository.owner, repository.name, branch) - JsonFormat( - ApiBranch(branch, ApiBranchCommit(br.commitId), ApiBranchProtection(protection))(RepositoryName(repository)) - ) - }) getOrElse NotFound() + using(Git.open(getRepositoryDir(repository.owner, repository.name))) { + git => + (for { + branch <- params.get("splat") if repository.branchList.contains(branch) + br <- getBranches( + git, + repository.repository.defaultBranch, + repository.repository.originUserName.isEmpty + ).find(_.name == branch) + } yield { + val protection = getProtectedBranchInfo(repository.owner, repository.name, branch) + JsonFormat( + ApiBranch(branch, ApiBranchCommit(br.commitId), ApiBranchProtection(protection))(RepositoryName(repository)) + ) + }) getOrElse NotFound() + } }) /* @@ -209,28 +214,30 @@ */ patch("/api/v3/repos/:owner/:repository/branches/*")(ownerOnly { repository => import gitbucket.core.api._ - (for { - branch <- params.get("splat") if repository.branchList.contains(branch) - protection <- extractFromJsonBody[ApiBranchProtection.EnablingAndDisabling].map(_.protection) - br <- getBranches( - repository.owner, - repository.name, - repository.repository.defaultBranch, - repository.repository.originUserName.isEmpty - ).find(_.name == branch) - } yield { - if (protection.enabled) { - enableBranchProtection( - repository.owner, - repository.name, - branch, - protection.status.enforcement_level == ApiBranchProtection.Everyone, - protection.status.contexts - ) - } else { - disableBranchProtection(repository.owner, repository.name, branch) - } - JsonFormat(ApiBranch(branch, ApiBranchCommit(br.commitId), protection)(RepositoryName(repository))) - }) getOrElse NotFound() + using(Git.open(getRepositoryDir(repository.owner, repository.name))) { + git => + (for { + branch <- params.get("splat") if repository.branchList.contains(branch) + protection <- extractFromJsonBody[ApiBranchProtection.EnablingAndDisabling].map(_.protection) + br <- getBranches( + git, + repository.repository.defaultBranch, + repository.repository.originUserName.isEmpty + ).find(_.name == branch) + } yield { + if (protection.enabled) { + enableBranchProtection( + repository.owner, + repository.name, + branch, + protection.status.enforcement_level == ApiBranchProtection.Everyone, + protection.status.contexts + ) + } else { + disableBranchProtection(repository.owner, repository.name, branch) + } + JsonFormat(ApiBranch(branch, ApiBranchCommit(br.commitId), protection)(RepositoryName(repository))) + }) getOrElse NotFound() + } }) } diff --git a/src/main/scala/gitbucket/core/util/JGitUtil.scala b/src/main/scala/gitbucket/core/util/JGitUtil.scala index 6e8084c..16d6e8e 100644 --- a/src/main/scala/gitbucket/core/util/JGitUtil.scala +++ b/src/main/scala/gitbucket/core/util/JGitUtil.scala @@ -240,18 +240,16 @@ * Returns the number of commits in the specified branch or commit. * If the specified branch has over 10000 commits, this method returns 100001. */ - def getCommitCount(owner: String, repository: String, branch: String): Int = { - val dir = getRepositoryDir(owner, repository) + def getCommitCount(git: Git, branch: String, max: Int = 10001): Int = { + val dir = git.getRepository.getDirectory val key = dir.getAbsolutePath + "@" + branch val entry = cache.getEntry(key) if (entry == null) { - using(Git.open(dir)) { git => - val commitId = git.getRepository.resolve(branch) - val commitCount = git.log.add(commitId).call.iterator.asScala.take(10001).size - cache.put(key, commitCount) - commitCount - } + val commitId = git.getRepository.resolve(branch) + val commitCount = git.log.add(commitId).call.iterator.asScala.take(max).size + cache.put(key, commitCount) + commitCount } else { entry.getValue } @@ -1110,6 +1108,7 @@ /** * Fetch pull request contents into refs/pull/${issueId}/head and return (commitIdTo, commitIdFrom) */ + // TODO should take Git instead of owner and username for testability def updatePullRequest( userName: String, repositoryName: String, @@ -1154,42 +1153,40 @@ git.log.add(startCommit).addPath(path).setMaxCount(1).call.iterator.next } - def getBranches(owner: String, name: String, defaultBranch: String, origin: Boolean): Seq[BranchInfo] = { - using(Git.open(getRepositoryDir(owner, name))) { git => - val repo = git.getRepository - val defaultObject = repo.resolve(defaultBranch) + def getBranches(git: Git, defaultBranch: String, origin: Boolean): Seq[BranchInfo] = { + val repo = git.getRepository + val defaultObject = repo.resolve(defaultBranch) - git.branchList.call.asScala.map { ref => - val walk = new RevWalk(repo) - try { - val defaultCommit = walk.parseCommit(defaultObject) - val branchName = ref.getName.stripPrefix("refs/heads/") - val branchCommit = walk.parseCommit(ref.getObjectId) - val when = branchCommit.getCommitterIdent.getWhen - val committer = branchCommit.getCommitterIdent.getName - val committerEmail = branchCommit.getCommitterIdent.getEmailAddress - val mergeInfo = if (origin && branchName == defaultBranch) { - None - } else { - walk.reset() - walk.setRevFilter(RevFilter.MERGE_BASE) - walk.markStart(branchCommit) - walk.markStart(defaultCommit) - val mergeBase = walk.next() - walk.reset() - walk.setRevFilter(RevFilter.ALL) - Some( - BranchMergeInfo( - ahead = RevWalkUtils.count(walk, branchCommit, mergeBase), - behind = RevWalkUtils.count(walk, defaultCommit, mergeBase), - isMerged = walk.isMergedInto(branchCommit, defaultCommit) - ) + git.branchList.call.asScala.map { ref => + val walk = new RevWalk(repo) + try { + val defaultCommit = walk.parseCommit(defaultObject) + val branchName = ref.getName.stripPrefix("refs/heads/") + val branchCommit = walk.parseCommit(ref.getObjectId) + val when = branchCommit.getCommitterIdent.getWhen + val committer = branchCommit.getCommitterIdent.getName + val committerEmail = branchCommit.getCommitterIdent.getEmailAddress + val mergeInfo = if (origin && branchName == defaultBranch) { + None + } else { + walk.reset() + walk.setRevFilter(RevFilter.MERGE_BASE) + walk.markStart(branchCommit) + walk.markStart(defaultCommit) + val mergeBase = walk.next() + walk.reset() + walk.setRevFilter(RevFilter.ALL) + Some( + BranchMergeInfo( + ahead = RevWalkUtils.count(walk, branchCommit, mergeBase), + behind = RevWalkUtils.count(walk, defaultCommit, mergeBase), + isMerged = walk.isMergedInto(branchCommit, defaultCommit) ) - } - BranchInfo(branchName, committer, when, committerEmail, mergeInfo, ref.getObjectId.name) - } finally { - walk.dispose() + ) } + BranchInfo(branchName, committer, when, committerEmail, mergeInfo, ref.getObjectId.name) + } finally { + walk.dispose() } } } @@ -1203,7 +1200,7 @@ val blame = blamer.call() var blameMap = Map[String, JGitUtil.BlameInfo]() var idLine = List[(String, Int)]() - val commits = 0.to(blame.getResultContents().size() - 1).map { i => + 0.to(blame.getResultContents().size() - 1).map { i => val c = blame.getSourceCommit(i) if (!blameMap.contains(c.name)) { blameMap += c.name -> JGitUtil.BlameInfo( @@ -1243,24 +1240,7 @@ } } - def getFileSize(git: Git, repository: RepositoryService.RepositoryInfo, treeWalk: TreeWalk): Long = { - val attrs = treeWalk.getAttributes - val loader = git.getRepository.open(treeWalk.getObjectId(0)) - if (attrs.containsKey("filter") && attrs.get("filter").getValue == "lfs") { - val lfsAttrs = getLfsAttributes(loader) - lfsAttrs.get("size").map(_.toLong).get - } else { - loader.getSize - } - } - - def getFileSize(git: Git, repository: RepositoryService.RepositoryInfo, tree: RevTree, path: String): Long = { - using(TreeWalk.forPath(git.getRepository, path, tree)) { treeWalk => - getFileSize(git, repository, treeWalk) - } - } - - def openFile[T](git: Git, repository: RepositoryService.RepositoryInfo, treeWalk: TreeWalk)( + private def openFile[T](git: Git, repository: RepositoryService.RepositoryInfo, treeWalk: TreeWalk)( f: InputStream => T ): T = { val attrs = treeWalk.getAttributes @@ -1270,7 +1250,6 @@ if (lfsAttrs.nonEmpty) { val oid = lfsAttrs("oid").split(":")(1) - val file = new File(FileUtil.getLfsFilePath(repository.owner, repository.name, oid)) using(new FileInputStream(FileUtil.getLfsFilePath(repository.owner, repository.name, oid))) { in => f(in) } diff --git a/src/main/twirl/gitbucket/core/repo/commits.scala.html b/src/main/twirl/gitbucket/core/repo/commits.scala.html index 2596721..e914702 100644 --- a/src/main/twirl/gitbucket/core/repo/commits.scala.html +++ b/src/main/twirl/gitbucket/core/repo/commits.scala.html @@ -133,5 +133,11 @@ }); }) + } } diff --git a/src/test/scala/gitbucket/core/util/GitSpecUtil.scala b/src/test/scala/gitbucket/core/util/GitSpecUtil.scala index 4bf8e0f..8462ed7 100644 --- a/src/test/scala/gitbucket/core/util/GitSpecUtil.scala +++ b/src/test/scala/gitbucket/core/util/GitSpecUtil.scala @@ -15,6 +15,7 @@ import java.io.File object GitSpecUtil { + def withTestFolder[U](f: File => U): U = { val folder = new File(System.getProperty("java.io.tmpdir"), "test-" + System.nanoTime) if (!folder.mkdirs()) { @@ -26,7 +27,9 @@ FileUtils.deleteQuietly(folder) } } + def withTestRepository[U](f: Git => U): U = withTestFolder(folder => using(Git.open(createTestRepository(folder)))(f)) + def createTestRepository(dir: File): File = { RepositoryCache.clear() FileUtils.deleteQuietly(dir) @@ -34,13 +37,14 @@ JGitUtil.initRepository(dir) dir } + def createFile( git: Git, branch: String, name: String, content: String, - autorName: String = "dummy", - autorEmail: String = "dummy@example.com", + authorName: String = "dummy", + authorEmail: String = "dummy@example.com", message: String = "test commit" ): Unit = { val builder = DirCache.newInCore.builder() @@ -67,13 +71,14 @@ headId, builder.getDirCache.writeTree(inserter), branch, - autorName, - autorEmail, + authorName, + authorEmail, message ) inserter.flush() inserter.close() } + 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 => @@ -89,6 +94,7 @@ } JGitUtil.getContentInfo(git, path, objectId) } + def mergeAndCommit(git: Git, into: String, branch: String, message: String = null): Unit = { val repository = git.getRepository val merger = MergeStrategy.RECURSIVE.newMerger(repository, true) diff --git a/src/test/scala/gitbucket/core/util/JGitUtilSpec.scala b/src/test/scala/gitbucket/core/util/JGitUtilSpec.scala index e85f00d..aff996b 100644 --- a/src/test/scala/gitbucket/core/util/JGitUtilSpec.scala +++ b/src/test/scala/gitbucket/core/util/JGitUtilSpec.scala @@ -1,10 +1,270 @@ package gitbucket.core.util import GitSpecUtil._ +import gitbucket.core.util.SyntaxSugars.using +import org.apache.commons.io.IOUtils +import org.eclipse.jgit.diff.DiffEntry +import org.eclipse.jgit.diff.DiffEntry.ChangeType +import org.eclipse.jgit.lib.Constants +import org.eclipse.jgit.treewalk.TreeWalk import org.scalatest.FunSuite +import scala.collection.JavaConverters._ + class JGitUtilSpec extends FunSuite { + test("isEmpty") { + withTestRepository { git => + assert(JGitUtil.isEmpty(git) == true) + + createFile(git, Constants.HEAD, "README.md", "body1", message = "commit1") + assert(JGitUtil.isEmpty(git) == false) + } + } + + test("getDiffs") { + withTestRepository { git => + createFile(git, Constants.HEAD, "README.md", "body1", message = "commit1") + + val branchId = git.getRepository.resolve("master") + val commit = JGitUtil.getRevCommitFromId(git, branchId) + + createFile(git, Constants.HEAD, "LICENSE", "Apache License", message = "commit1") + createFile(git, Constants.HEAD, "README.md", "body1\nbody2", message = "commit1") + + // latest commit + val diff1 = JGitUtil.getDiffs(git, None, "master", false, true) + assert(diff1.size == 1) + assert(diff1(0).changeType == ChangeType.MODIFY) + assert(diff1(0).oldPath == "README.md") + assert(diff1(0).newPath == "README.md") + assert(diff1(0).tooLarge == false) + assert(diff1(0).patch == Some("""@@ -1 +1,2 @@ + |-body1 + |\ No newline at end of file + |+body1 + |+body2 + |\ No newline at end of file""".stripMargin)) + + // from specified commit + val diff2 = JGitUtil.getDiffs(git, Some(commit.getName), "master", false, true) + assert(diff2.size == 2) + assert(diff2(0).changeType == ChangeType.ADD) + assert(diff2(0).oldPath == "/dev/null") + assert(diff2(0).newPath == "LICENSE") + assert(diff2(0).tooLarge == false) + assert(diff2(0).patch == Some("""+++ b/LICENSE + |@@ -0,0 +1 @@ + |+Apache License + |\ No newline at end of file""".stripMargin)) + + assert(diff2(1).changeType == ChangeType.MODIFY) + assert(diff2(1).oldPath == "README.md") + assert(diff2(1).newPath == "README.md") + assert(diff2(1).tooLarge == false) + assert(diff2(1).patch == Some("""@@ -1 +1,2 @@ + |-body1 + |\ No newline at end of file + |+body1 + |+body2 + |\ No newline at end of file""".stripMargin)) + } + } + + test("getRevCommitFromId") { + withTestRepository { git => + createFile(git, Constants.HEAD, "README.md", "body1", message = "commit1") + + // branch name + val branchId = git.getRepository.resolve("master") + val commit1 = JGitUtil.getRevCommitFromId(git, branchId) + + // commit id + val commitName = commit1.getName + val commitId = git.getRepository.resolve(commitName) + val commit2 = JGitUtil.getRevCommitFromId(git, commitId) + + // tag name + JGitUtil.createTag(git, "1.0", None, commitName) + val tagId = git.getRepository.resolve("1.0") + val commit3 = JGitUtil.getRevCommitFromId(git, tagId) + + // all refer same commit + assert(commit1 == commit2) + assert(commit1 == commit3) + assert(commit2 == commit3) + } + } + + test("getCommitCount and getAllCommitIds") { + withTestRepository { git => + // getCommitCount + createFile(git, Constants.HEAD, "README.md", "body1", message = "commit1") + assert(JGitUtil.getCommitCount(git, "master") == 1) + + createFile(git, Constants.HEAD, "README.md", "body2", message = "commit2") + assert(JGitUtil.getCommitCount(git, "master") == 2) + + // maximum limit + (3 to 10).foreach { i => + createFile(git, Constants.HEAD, "README.md", "body" + i, message = "commit" + i) + } + assert(JGitUtil.getCommitCount(git, "master", 5) == 5) + + // actual commit count + val gitLog = git.log.add(git.getRepository.resolve("master")).all + assert(gitLog.call.asScala.toSeq.size == 10) + + // getAllCommitIds + val allCommits = JGitUtil.getAllCommitIds(git) + assert(allCommits.size == 10) + } + } + + test("createBranch, branchesOfCommit and getBranches") { + withTestRepository { git => + createFile(git, Constants.HEAD, "README.md", "body1", message = "commit1") + + // createBranch + assert(JGitUtil.createBranch(git, "master", "test1") == Right("Branch created.")) + assert(JGitUtil.createBranch(git, "master", "test2") == Right("Branch created.")) + assert(JGitUtil.createBranch(git, "master", "test2") == Left("Sorry, that branch already exists.")) + + // verify + val branches = git.branchList.call() + assert(branches.size == 3) + assert(branches.get(0).getName == "refs/heads/master") + assert(branches.get(1).getName == "refs/heads/test1") + assert(branches.get(2).getName == "refs/heads/test2") + + // getBranchesOfCommit + val commit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve("master")) + val branchesOfCommit = JGitUtil.getBranchesOfCommit(git, commit.getName) + assert(branchesOfCommit.size == 3) + assert(branchesOfCommit(0) == "master") + assert(branchesOfCommit(1) == "test1") + assert(branchesOfCommit(2) == "test2") + } + } + + test("getBranches") { + withTestRepository { git => + createFile(git, Constants.HEAD, "README.md", "body1", message = "commit1") + JGitUtil.createBranch(git, "master", "test1") + + createFile(git, Constants.HEAD, "README.md", "body2", message = "commit2") + JGitUtil.createBranch(git, "master", "test2") + + // getBranches + val branches = JGitUtil.getBranches(git, "master", true) + assert(branches.size == 3) + + assert(branches(0).name == "master") + assert(branches(0).committerName == "dummy") + assert(branches(0).committerEmailAddress == "dummy@example.com") + + assert(branches(1).name == "test1") + assert(branches(1).committerName == "dummy") + assert(branches(1).committerEmailAddress == "dummy@example.com") + + assert(branches(2).name == "test2") + assert(branches(2).committerName == "dummy") + assert(branches(2).committerEmailAddress == "dummy@example.com") + + assert(branches(0).commitId != branches(1).commitId) + assert(branches(0).commitId == branches(2).commitId) + } + } + + test("createTag, getTagsOfCommit and getTagsOnCommit") { + withTestRepository { git => + createFile(git, Constants.HEAD, "README.md", "body1", message = "commit1") + + // createTag + assert(JGitUtil.createTag(git, "1.0", Some("test1"), "master") == Right("Tag added.")) + assert( + JGitUtil.createTag(git, "1.0", Some("test2"), "master") == Left("Sorry, some Git operation error occurs.") + ) + + // record current commit + val commit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve("master")) + + // createTag + createFile(git, Constants.HEAD, "LICENSE", "Apache License", message = "commit2") + assert(JGitUtil.createTag(git, "1.1", Some("test3"), "master") == Right("Tag added.")) + + // verify + val allTags = git.tagList().call().asScala + assert(allTags.size == 2) + assert(allTags(0).getName == "refs/tags/1.0") + assert(allTags(1).getName == "refs/tags/1.1") + + // getTagsOfCommit + val tagsOfCommit = JGitUtil.getTagsOfCommit(git, commit.getName) + assert(tagsOfCommit.size == 2) + assert(tagsOfCommit(0) == "1.1") + assert(tagsOfCommit(1) == "1.0") + + // getTagsOnCommit + val tagsOnCommit = JGitUtil.getTagsOnCommit(git, "master") + assert(tagsOnCommit.size == 1) + assert(tagsOnCommit(0) == "1.1") + } + } + + test("openFile for non-LFS file") { + withTestRepository { git => + createFile(git, Constants.HEAD, "README.md", "body1", message = "commit1") + createFile(git, Constants.HEAD, "LICENSE", "Apache License", message = "commit2") + + val objectId = git.getRepository.resolve("master") + val commit = JGitUtil.getRevCommitFromId(git, objectId) + + // Since Non-LFS file doesn't need RepositoryInfo give null + assert(JGitUtil.openFile(git, null, commit.getTree, "README.md") { in => + IOUtils.toString(in, "UTF-8") + } == "body1") + + assert(JGitUtil.openFile(git, null, commit.getTree, "LICENSE") { in => + IOUtils.toString(in, "UTF-8") + } == "Apache License") + } + } + + test("getContentFromPath") { + withTestRepository { git => + createFile(git, Constants.HEAD, "README.md", "body1", message = "commit1") + createFile(git, Constants.HEAD, "LARGE_FILE", "body1" * 1000000, message = "commit1") + + val objectId = git.getRepository.resolve("master") + val commit = JGitUtil.getRevCommitFromId(git, objectId) + + val content1 = JGitUtil.getContentFromPath(git, commit.getTree, "README.md", true) + assert(content1.map(x => new String(x, "UTF-8")) == Some("body1")) + + val content2 = JGitUtil.getContentFromPath(git, commit.getTree, "LARGE_FILE", false) + assert(content2.isEmpty) + + val content3 = JGitUtil.getContentFromPath(git, commit.getTree, "LARGE_FILE", true) + assert(content3.map(x => new String(x, "UTF-8")) == Some("body1" * 1000000)) + } + } + + test("getBlame") { + withTestRepository { git => + createFile(git, Constants.HEAD, "README.md", "body1\nbody2\nbody3", message = "commit1") + createFile(git, Constants.HEAD, "README.md", "body0\nbody2\nbody3", message = "commit2") + + val blames = JGitUtil.getBlame(git, "master", "README.md").toSeq + + assert(blames.size == 2) + assert(blames(0).message == "commit2") + assert(blames(0).lines == Set(0)) + assert(blames(1).message == "commit1") + assert(blames(1).lines == Set(1, 2)) + } + } + test("getFileList(git: Git, revision: String, path)") { withTestRepository { git => def list(branch: String, path: String) = @@ -170,4 +430,19 @@ assert(list("master", "test") == List(("text2.txt", "commit2", false))) } } + + test("getLfsObjects") { + val str = """version https://git-lfs.github.com/spec/v1 + |oid sha256:aa8a7a4903572ccd1571c03f442661a983d79b53bbb7bcdd50769429f0b24ab8 + |size 178643""".stripMargin + + val attrs = JGitUtil.getLfsObjects(str) + assert(attrs("oid") == "sha256:aa8a7a4903572ccd1571c03f442661a983d79b53bbb7bcdd50769429f0b24ab8") + assert(attrs("size") == "178643") + } + + test("getContentInfo") { + // TODO + } + }