All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gitbucket.core.controller.api.ApiGitReferenceControllerBase.scala Maven / Gradle / Ivy

The newest version!
package gitbucket.core.controller.api
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, WritableUsersAuthenticator}
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.ObjectId
import org.eclipse.jgit.lib.RefUpdate.Result
import org.scalatra.{BadRequest, NoContent, UnprocessableEntity}
import org.slf4j.LoggerFactory

import scala.jdk.CollectionConverters._
import scala.util.Using

trait ApiGitReferenceControllerBase extends ControllerBase {
  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
   */
  get("/api/v3/repos/:owner/:repository/git/ref/*")(referrersOnly { repository =>
    val revstr = multiParams("splat").head
    getRef(revstr, repository)
  })

  // Some versions of GHE support this path
  get("/api/v3/repos/:owner/:repository/git/refs/*")(referrersOnly { repository =>
    logger.warn("git/refs/ endpoint may not be compatible with GitHub API v3. Consider using git/ref/ endpoint instead")
    val revstr = multiParams("splat").head
    getRef(revstr, repository)
  })

  /*
   * ii. Get all references
   * https://docs.github.com/en/free-pro-team@latest/rest/reference/git#list-matching-references
   */

  /*
   * iii. Create a reference
   * https://docs.github.com/en/free-pro-team@latest/rest/reference/git#create-a-reference
   */
  post("/api/v3/repos/:owner/:repository/git/refs")(writableUsersOnly { repository =>
    extractFromJsonBody[CreateARef].map { data =>
      Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
        val ref = git.getRepository.findRef(data.ref)
        if (ref == null) {
          val update = git.getRepository.updateRef(data.ref)
          update.setNewObjectId(ObjectId.fromString(data.sha))
          val result = update.update()
          result match {
            case Result.NEW =>
              JsonFormat(
                ApiRef
                  .fromRef(RepositoryName(repository.owner, repository.name), git.getRepository.findRef(data.ref))
              )
            case _ => UnprocessableEntity(result.name())
          }
        } else {
          UnprocessableEntity("Ref already exists.")
        }
      }
    } getOrElse BadRequest()
  })

  /*
   * 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/*")(writableUsersOnly { repository =>
    val refName = multiParams("splat").mkString("/")
    extractFromJsonBody[UpdateARef].map { data =>
      Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
        val ref = git.getRepository.findRef(refName)
        if (ref == null) {
          UnprocessableEntity("Ref does not exist.")
        } else {
          val update = git.getRepository.updateRef(ref.getName)
          update.setNewObjectId(ObjectId.fromString(data.sha))
          update.setForceUpdate(data.force)
          val result = update.update()
          result match {
            case Result.FORCED | Result.FAST_FORWARD | Result.NO_CHANGE =>
              JsonFormat(ApiRef.fromRef(RepositoryName(repository), git.getRepository.findRef(refName)))
            case _ => UnprocessableEntity(result.name())
          }
        }
      }
    } getOrElse BadRequest()
  })

  /*
   * 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/*")(writableUsersOnly { _ =>
    val refName = multiParams("splat").mkString("/")
    Using.resource(Git.open(getRepositoryDir(params("owner"), params("repository")))) { git =>
      val ref = git.getRepository.findRef(refName)
      if (ref == null) {
        UnprocessableEntity("Ref does not exist.")
      } else {
        val update = git.getRepository.updateRef(ref.getName)
        update.setForceUpdate(true)
        val result = update.delete()
        result match {
          case Result.FORCED => NoContent()
          case _             => UnprocessableEntity(result.name())
        }
      }
    }
  })

  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
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy