mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-01 11:06:06 +01:00
Enhance Git Reference APIs (#2937)
This commit is contained in:
@@ -39,11 +39,11 @@ object ApiRef {
|
||||
): ApiRef =
|
||||
ApiRef(
|
||||
ref = s"refs/tags/${tagInfo.name}",
|
||||
url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/refs/tags/${tagInfo.name}"),
|
||||
url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/git/refs/tags/${tagInfo.name}"),
|
||||
`object` = ApiRefCommit(
|
||||
sha = tagInfo.id,
|
||||
url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/git/tags/${tagInfo.id}"), // TODO This URL is not yet available?
|
||||
`type` = "commit"
|
||||
sha = tagInfo.objectId,
|
||||
url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/git/tags/${tagInfo.objectId}"), // TODO This URL is not yet available?
|
||||
`type` = "tag"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ trait ReleaseControllerBase extends ControllerBase {
|
||||
|
||||
get("/:owner/:repository/changelog/*...*")(writableUsersOnly { repository =>
|
||||
val Seq(previousTag, currentTag) = multiParams("splat")
|
||||
val previousTagId = repository.tags.collectFirst { case x if x.name == previousTag => x.id }.getOrElse("")
|
||||
val previousTagId = repository.tags.collectFirst { case x if x.name == previousTag => x.commitId }.getOrElse("")
|
||||
|
||||
val commitLog = Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
||||
val commits = JGitUtil.getCommitLog(git, previousTagId, currentTag).reverse
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package gitbucket.core.controller.api
|
||||
import gitbucket.core.api.{ApiRef, CreateARef, JsonFormat, UpdateARef}
|
||||
import gitbucket.core.api.{ApiError, ApiRef, CreateARef, JsonFormat, UpdateARef}
|
||||
import gitbucket.core.controller.ControllerBase
|
||||
import gitbucket.core.service.RepositoryService.RepositoryInfo
|
||||
import gitbucket.core.util.Directory.getRepositoryDir
|
||||
import gitbucket.core.util.Implicits._
|
||||
import gitbucket.core.util.{ReferrerAuthenticator, RepositoryName}
|
||||
import gitbucket.core.util.{ReferrerAuthenticator, RepositoryName, WritableUsersAuthenticator}
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.ObjectId
|
||||
import org.eclipse.jgit.lib.RefUpdate.Result
|
||||
@@ -15,10 +15,23 @@ import scala.jdk.CollectionConverters._
|
||||
import scala.util.Using
|
||||
|
||||
trait ApiGitReferenceControllerBase extends ControllerBase {
|
||||
self: ReferrerAuthenticator =>
|
||||
self: ReferrerAuthenticator with WritableUsersAuthenticator =>
|
||||
|
||||
private val logger = LoggerFactory.getLogger(classOf[ApiGitReferenceControllerBase])
|
||||
|
||||
get("/api/v3/repos/:owner/:repository/git/refs")(referrersOnly { repository =>
|
||||
val result = Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
||||
val refs = git
|
||||
.getRepository()
|
||||
.getRefDatabase()
|
||||
.getRefsByPrefix("refs")
|
||||
.asScala
|
||||
|
||||
refs.map(ApiRef.fromRef(RepositoryName(s"${repository.owner}/${repository.name}"), _))
|
||||
}
|
||||
JsonFormat(result)
|
||||
})
|
||||
|
||||
/*
|
||||
* i. Get a reference
|
||||
* https://docs.github.com/en/free-pro-team@latest/rest/reference/git#get-a-reference
|
||||
@@ -35,34 +48,6 @@ trait ApiGitReferenceControllerBase extends ControllerBase {
|
||||
getRef(revstr, repository)
|
||||
})
|
||||
|
||||
protected def getRef(revstr: String, repository: RepositoryInfo): String = {
|
||||
logger.debug(s"getRef: path '${revstr}'")
|
||||
|
||||
val name = RepositoryName(repository)
|
||||
val result = JsonFormat(revstr match {
|
||||
case tags if tags == "tags" =>
|
||||
repository.tags.map(ApiRef.fromTag(name, _))
|
||||
case other =>
|
||||
Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
||||
git.getRepository().findRef(other) match {
|
||||
case null =>
|
||||
val refs = git
|
||||
.getRepository()
|
||||
.getRefDatabase()
|
||||
.getRefsByPrefix("refs/")
|
||||
.asScala
|
||||
|
||||
refs.map(ApiRef.fromRef(name, _))
|
||||
case hit =>
|
||||
ApiRef.fromRef(name, hit)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
logger.debug(s"json result: $result")
|
||||
result
|
||||
}
|
||||
|
||||
/*
|
||||
* ii. Get all references
|
||||
* https://docs.github.com/en/free-pro-team@latest/rest/reference/git#list-matching-references
|
||||
@@ -96,7 +81,7 @@ trait ApiGitReferenceControllerBase extends ControllerBase {
|
||||
* iv. Update a reference
|
||||
* https://docs.github.com/en/free-pro-team@latest/rest/reference/git#update-a-reference
|
||||
*/
|
||||
patch("/api/v3/repos/:owner/:repository/git/refs/*")(referrersOnly { repository =>
|
||||
patch("/api/v3/repos/:owner/:repository/git/refs/*")(writableUsersOnly { repository =>
|
||||
val refName = multiParams("splat").mkString("/")
|
||||
extractFromJsonBody[UpdateARef].map {
|
||||
data =>
|
||||
@@ -123,7 +108,7 @@ trait ApiGitReferenceControllerBase extends ControllerBase {
|
||||
* v. Delete a reference
|
||||
* https://docs.github.com/en/free-pro-team@latest/rest/reference/git#delete-a-reference
|
||||
*/
|
||||
delete("/api/v3/repos/:owner/:repository/git/refs/*")(referrersOnly { repository =>
|
||||
delete("/api/v3/repos/:owner/:repository/git/refs/*")(writableUsersOnly { _ =>
|
||||
val refName = multiParams("splat").mkString("/")
|
||||
Using.resource(Git.open(getRepositoryDir(params("owner"), params("repository")))) { git =>
|
||||
val ref = git.getRepository.findRef(refName)
|
||||
@@ -140,4 +125,34 @@ trait ApiGitReferenceControllerBase extends ControllerBase {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
private def notFound(): ApiError = {
|
||||
response.setStatus(404)
|
||||
ApiError("Not Found")
|
||||
}
|
||||
|
||||
protected def getRef(revstr: String, repository: RepositoryInfo): AnyRef = {
|
||||
logger.debug(s"getRef: path '${revstr}'")
|
||||
|
||||
val name = RepositoryName(repository)
|
||||
val result = JsonFormat(revstr match {
|
||||
case "tags" => repository.tags.map(ApiRef.fromTag(name, _))
|
||||
case x if x.startsWith("tags/") =>
|
||||
val tagName = x.substring("tags/".length)
|
||||
repository.tags.find(_.name == tagName) match {
|
||||
case Some(tagInfo) => ApiRef.fromTag(name, tagInfo)
|
||||
case None => notFound()
|
||||
}
|
||||
case other =>
|
||||
Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
||||
git.getRepository().findRef(other) match {
|
||||
case null => notFound()
|
||||
case ref => ApiRef.fromRef(name, ref)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
logger.debug(s"json result: $result")
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,7 +579,7 @@ trait PullRequestService {
|
||||
case (oldGit, newGit) =>
|
||||
if (originRepository.branchList.contains(originId)) {
|
||||
val forkedId2 =
|
||||
forkedRepository.tags.collectFirst { case x if x.name == forkedId => x.id }.getOrElse(forkedId)
|
||||
forkedRepository.tags.collectFirst { case x if x.name == forkedId => x.commitId }.getOrElse(forkedId)
|
||||
|
||||
val originId2 = JGitUtil.getForkedCommitId(
|
||||
oldGit,
|
||||
@@ -596,9 +596,9 @@ trait PullRequestService {
|
||||
|
||||
} else {
|
||||
val originId2 =
|
||||
originRepository.tags.collectFirst { case x if x.name == originId => x.id }.getOrElse(originId)
|
||||
originRepository.tags.collectFirst { case x if x.name == originId => x.commitId }.getOrElse(originId)
|
||||
val forkedId2 =
|
||||
forkedRepository.tags.collectFirst { case x if x.name == forkedId => x.id }.getOrElse(forkedId)
|
||||
forkedRepository.tags.collectFirst { case x if x.name == forkedId => x.commitId }.getOrElse(forkedId)
|
||||
|
||||
(Option(oldGit.getRepository.resolve(originId2)), Option(newGit.getRepository.resolve(forkedId2)))
|
||||
}
|
||||
|
||||
@@ -228,10 +228,11 @@ object JGitUtil {
|
||||
*
|
||||
* @param name the tag name
|
||||
* @param time the tagged date
|
||||
* @param id the commit id
|
||||
* @param commitId the commit id
|
||||
* @param message the message of the tagged commit
|
||||
* @param objectId the tag object id
|
||||
*/
|
||||
case class TagInfo(name: String, time: Date, id: String, message: String)
|
||||
case class TagInfo(name: String, time: Date, commitId: String, message: String, objectId: String)
|
||||
|
||||
/**
|
||||
* The submodule data
|
||||
@@ -347,7 +348,8 @@ object JGitUtil {
|
||||
ref.getName.stripPrefix("refs/tags/"),
|
||||
revCommit.getCommitterIdent.getWhen,
|
||||
revCommit.getName,
|
||||
revCommit.getShortMessage
|
||||
revCommit.getShortMessage,
|
||||
ref.getObjectId.getName
|
||||
)
|
||||
)
|
||||
} catch {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<td>
|
||||
<div class="col-md-2 text-right">
|
||||
<a href="@helpers.url(repository)/tree/@helpers.urlEncode(tag.name)" class="strong"><i class="octicon octicon-tag"></i>@tag.name</a><br>
|
||||
<a href="@helpers.url(repository)/commit/@tag.id" class="monospace muted"><i class="octicon octicon-git-commit"></i>@tag.id.substring(0, 7)</a><br>
|
||||
<a href="@helpers.url(repository)/commit/@tag.commitId" class="monospace muted"><i class="octicon octicon-git-commit"></i>@tag.commitId.substring(0, 7)</a><br>
|
||||
<span class="muted">@gitbucket.core.helper.html.datetimeago(tag.time)</span>
|
||||
</div>
|
||||
<div class="col-md-10" style="border-left: 1px solid #eee">
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
@defining(repository.tags.find(_.name == release.tag)){ tag =>
|
||||
@tag.map { tag =>
|
||||
<a href="@helpers.url(repository)/tree/@helpers.urlEncode(tag.name)" class="strong"><i class="octicon octicon-tag"></i>@tag.name</a><br>
|
||||
<a href="@helpers.url(repository)/commit/@tag.id" class="monospace muted"><i class="octicon octicon-git-commit"></i>@tag.id.substring(0, 7)</a><br>
|
||||
<a href="@helpers.url(repository)/commit/@tag.commitId" class="monospace muted"><i class="octicon octicon-git-commit"></i>@tag.commitId.substring(0, 7)</a><br>
|
||||
<span class="muted">@gitbucket.core.helper.html.datetimeago(tag.time)</span>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ class TestingGitBucketServer(val port: Int = 19999) extends AutoCloseable {
|
||||
def client(login: String, password: String): GitHub =
|
||||
GitHub.connectToEnterprise(s"http://localhost:${port}/api/v3", login, password)
|
||||
|
||||
def getDirectory(): File = dir
|
||||
|
||||
private def addStatisticsHandler(handler: Handler) = { // The graceful shutdown is implemented via the statistics handler.
|
||||
// See the following: https://bugs.eclipse.org/bugs/show_bug.cgi?id=420142
|
||||
val statisticsHandler = new StatisticsHandler
|
||||
|
||||
@@ -2,11 +2,14 @@ package gitbucket.core.api
|
||||
|
||||
import gitbucket.core.TestingGitBucketServer
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
|
||||
import scala.util.Using
|
||||
import org.kohsuke.github.GHCommitState
|
||||
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Need to run `sbt package` before running this test.
|
||||
*/
|
||||
@@ -145,13 +148,16 @@ class ApiIntegrationTest extends AnyFunSuite {
|
||||
assert(ref.getObject.getType == "commit")
|
||||
}
|
||||
|
||||
// // get tag v1.0
|
||||
// {
|
||||
// val ref = repo.getRef("heads/tags/v1.0")
|
||||
// assert(ref.getRef == "heads/tags/v1.0")
|
||||
// assert(ref.getUrl == "tbd")
|
||||
// assert(ref.getObject.getType == "tag")
|
||||
// }
|
||||
// get tag v1.0
|
||||
{
|
||||
Using.resource(Git.open(new File(server.getDirectory(), "repositories/root/create_status_test"))) { git =>
|
||||
git.tag().setName("v1.0").call()
|
||||
}
|
||||
val ref = repo.getRef("tags/v1.0")
|
||||
assert(ref.getRef == "refs/tags/v1.0")
|
||||
assert(ref.getUrl.toString == "http://localhost:19999/api/v3/repos/root/create_status_test/git/refs/tags/v1.0")
|
||||
assert(ref.getObject.getType == "tag")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,8 +83,20 @@ object ApiSpecModels {
|
||||
milestoneCount = 1,
|
||||
branchList = Seq("master", "develop"),
|
||||
tags = Seq(
|
||||
TagInfo(name = "v1.0", time = date("2015-05-05T23:40:27Z"), id = "id1", message = "1.0 released"),
|
||||
TagInfo(name = "v2.0", time = date("2016-05-05T23:40:27Z"), id = "id2", message = "2.0 released")
|
||||
TagInfo(
|
||||
name = "v1.0",
|
||||
time = date("2015-05-05T23:40:27Z"),
|
||||
commitId = "id1",
|
||||
message = "1.0 released",
|
||||
objectId = "id1"
|
||||
),
|
||||
TagInfo(
|
||||
name = "v2.0",
|
||||
time = date("2016-05-05T23:40:27Z"),
|
||||
commitId = "id2",
|
||||
message = "2.0 released",
|
||||
objectId = "id2"
|
||||
)
|
||||
),
|
||||
managers = Seq("myboss")
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user