mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-25 01:21:38 +02:00
Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
actions_service "code.gitea.io/gitea/services/actions"
|
||||
@@ -120,27 +119,7 @@ func (s *Service) UpdateTask(
|
||||
ctx context.Context,
|
||||
req *connect.Request[runnerv1.UpdateTaskRequest],
|
||||
) (*connect.Response[runnerv1.UpdateTaskResponse], error) {
|
||||
{
|
||||
// to debug strange runner behaviors, it could be removed if all problems have been solved.
|
||||
stateMsg, _ := json.Marshal(req.Msg.State)
|
||||
log.Trace("update task with state: %s", stateMsg)
|
||||
}
|
||||
|
||||
// Get Task first
|
||||
task, err := actions_model.GetTaskByID(ctx, req.Msg.State.Id)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "can't find the task: %v", err)
|
||||
}
|
||||
if task.Status.IsCancelled() {
|
||||
return connect.NewResponse(&runnerv1.UpdateTaskResponse{
|
||||
State: &runnerv1.TaskState{
|
||||
Id: req.Msg.State.Id,
|
||||
Result: task.Status.AsResult(),
|
||||
},
|
||||
}), nil
|
||||
}
|
||||
|
||||
task, err = actions_model.UpdateTaskByState(ctx, req.Msg.State)
|
||||
task, err := actions_model.UpdateTaskByState(ctx, req.Msg.State)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "update task: %v", err)
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"code.gitea.io/gitea/routers/api/packages/nuget"
|
||||
"code.gitea.io/gitea/routers/api/packages/pub"
|
||||
"code.gitea.io/gitea/routers/api/packages/pypi"
|
||||
"code.gitea.io/gitea/routers/api/packages/rpm"
|
||||
"code.gitea.io/gitea/routers/api/packages/rubygems"
|
||||
"code.gitea.io/gitea/routers/api/packages/swift"
|
||||
"code.gitea.io/gitea/routers/api/packages/vagrant"
|
||||
@@ -119,6 +120,12 @@ func CommonRoutes(ctx gocontext.Context) *web.Route {
|
||||
r.Get("/owners", cargo.ListOwners)
|
||||
})
|
||||
})
|
||||
r.Get("/config.json", cargo.RepositoryConfig)
|
||||
r.Get("/1/{package}", cargo.EnumeratePackageVersions)
|
||||
r.Get("/2/{package}", cargo.EnumeratePackageVersions)
|
||||
// Use dummy placeholders because these parts are not of interest
|
||||
r.Get("/3/{_}/{package}", cargo.EnumeratePackageVersions)
|
||||
r.Get("/{_}/{__}/{package}", cargo.EnumeratePackageVersions)
|
||||
}, reqPackageAccess(perm.AccessModeRead))
|
||||
r.Group("/chef", func() {
|
||||
r.Group("/api/v1", func() {
|
||||
@@ -414,6 +421,16 @@ func CommonRoutes(ctx gocontext.Context) *web.Route {
|
||||
r.Get("/files/{id}/{version}/{filename}", pypi.DownloadPackageFile)
|
||||
r.Get("/simple/{id}", pypi.PackageMetadata)
|
||||
}, reqPackageAccess(perm.AccessModeRead))
|
||||
r.Group("/rpm", func() {
|
||||
r.Get(".repo", rpm.GetRepositoryConfig)
|
||||
r.Get("/repository.key", rpm.GetRepositoryKey)
|
||||
r.Put("/upload", reqPackageAccess(perm.AccessModeWrite), rpm.UploadPackageFile)
|
||||
r.Group("/package/{name}/{version}/{architecture}", func() {
|
||||
r.Get("", rpm.DownloadPackageFile)
|
||||
r.Delete("", reqPackageAccess(perm.AccessModeWrite), rpm.DeletePackageFile)
|
||||
})
|
||||
r.Get("/repodata/{filename}", rpm.GetRepositoryFile)
|
||||
}, reqPackageAccess(perm.AccessModeRead))
|
||||
r.Group("/rubygems", func() {
|
||||
r.Get("/specs.4.8.gz", rubygems.EnumeratePackages)
|
||||
r.Get("/latest_specs.4.8.gz", rubygems.EnumeratePackagesLatest)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package cargo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -45,6 +46,35 @@ func apiError(ctx *context.Context, status int, obj interface{}) {
|
||||
})
|
||||
}
|
||||
|
||||
// https://rust-lang.github.io/rfcs/2789-sparse-index.html
|
||||
func RepositoryConfig(ctx *context.Context) {
|
||||
ctx.JSON(http.StatusOK, cargo_service.BuildConfig(ctx.Package.Owner))
|
||||
}
|
||||
|
||||
func EnumeratePackageVersions(ctx *context.Context) {
|
||||
p, err := packages_model.GetPackageByName(ctx, ctx.Package.Owner.ID, packages_model.TypeCargo, ctx.Params("package"))
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
apiError(ctx, http.StatusNotFound, err)
|
||||
} else {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
b, err := cargo_service.BuildPackageIndex(ctx, p)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if b == nil {
|
||||
apiError(ctx, http.StatusNotFound, nil)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.PlainTextBytes(http.StatusOK, b.Bytes())
|
||||
}
|
||||
|
||||
type SearchResult struct {
|
||||
Crates []*SearchResultCrate `json:"crates"`
|
||||
Meta SearchResultMeta `json:"meta"`
|
||||
|
||||
@@ -585,7 +585,7 @@ func DownloadSymbolFile(ctx *context.Context) {
|
||||
|
||||
pfs, _, err := packages_model.SearchFiles(ctx, &packages_model.PackageFileSearchOptions{
|
||||
OwnerID: ctx.Package.Owner.ID,
|
||||
PackageType: string(packages_model.TypeNuGet),
|
||||
PackageType: packages_model.TypeNuGet,
|
||||
Query: filename,
|
||||
Properties: map[string]string{
|
||||
nuget_module.PropertySymbolID: strings.ToLower(guid),
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package rpm
|
||||
|
||||
import (
|
||||
stdctx "context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
packages_model "code.gitea.io/gitea/models/packages"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/notification"
|
||||
packages_module "code.gitea.io/gitea/modules/packages"
|
||||
rpm_module "code.gitea.io/gitea/modules/packages/rpm"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/routers/api/packages/helper"
|
||||
packages_service "code.gitea.io/gitea/services/packages"
|
||||
rpm_service "code.gitea.io/gitea/services/packages/rpm"
|
||||
)
|
||||
|
||||
func apiError(ctx *context.Context, status int, obj interface{}) {
|
||||
helper.LogAndProcessError(ctx, status, obj, func(message string) {
|
||||
ctx.PlainText(status, message)
|
||||
})
|
||||
}
|
||||
|
||||
// https://dnf.readthedocs.io/en/latest/conf_ref.html
|
||||
func GetRepositoryConfig(ctx *context.Context) {
|
||||
url := fmt.Sprintf("%sapi/packages/%s/rpm", setting.AppURL, ctx.Package.Owner.Name)
|
||||
|
||||
ctx.PlainText(http.StatusOK, `[gitea-`+ctx.Package.Owner.LowerName+`]
|
||||
name=`+ctx.Package.Owner.Name+` - `+setting.AppName+`
|
||||
baseurl=`+url+`
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
gpgkey=`+url+`/repository.key`)
|
||||
}
|
||||
|
||||
// Gets or creates the PGP public key used to sign repository metadata files
|
||||
func GetRepositoryKey(ctx *context.Context) {
|
||||
_, pub, err := rpm_service.GetOrCreateKeyPair(ctx.Package.Owner.ID)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.ServeContent(strings.NewReader(pub), &context.ServeHeaderOptions{
|
||||
ContentType: "application/pgp-keys",
|
||||
Filename: "repository.key",
|
||||
})
|
||||
}
|
||||
|
||||
// Gets a pre-generated repository metadata file
|
||||
func GetRepositoryFile(ctx *context.Context) {
|
||||
pv, err := rpm_service.GetOrCreateRepositoryVersion(ctx.Package.Owner.ID)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
s, pf, err := packages_service.GetFileStreamByPackageVersion(
|
||||
ctx,
|
||||
pv,
|
||||
&packages_service.PackageFileInfo{
|
||||
Filename: ctx.Params("filename"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
apiError(ctx, http.StatusNotFound, err)
|
||||
} else {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
ctx.ServeContent(s, &context.ServeHeaderOptions{
|
||||
Filename: pf.Name,
|
||||
LastModified: pf.CreatedUnix.AsLocalTime(),
|
||||
})
|
||||
}
|
||||
|
||||
func UploadPackageFile(ctx *context.Context) {
|
||||
upload, close, err := ctx.UploadStream()
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if close {
|
||||
defer upload.Close()
|
||||
}
|
||||
|
||||
buf, err := packages_module.CreateHashedBufferFromReader(upload)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
defer buf.Close()
|
||||
|
||||
pck, err := rpm_module.ParsePackage(buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
apiError(ctx, http.StatusBadRequest, err)
|
||||
} else {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := buf.Seek(0, io.SeekStart); err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
fileMetadataRaw, err := json.Marshal(pck.FileMetadata)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
_, _, err = packages_service.CreatePackageOrAddFileToExisting(
|
||||
&packages_service.PackageCreationInfo{
|
||||
PackageInfo: packages_service.PackageInfo{
|
||||
Owner: ctx.Package.Owner,
|
||||
PackageType: packages_model.TypeRpm,
|
||||
Name: pck.Name,
|
||||
Version: pck.Version,
|
||||
},
|
||||
Creator: ctx.Doer,
|
||||
Metadata: pck.VersionMetadata,
|
||||
},
|
||||
&packages_service.PackageFileCreationInfo{
|
||||
PackageFileInfo: packages_service.PackageFileInfo{
|
||||
Filename: fmt.Sprintf("%s-%s.%s.rpm", pck.Name, pck.Version, pck.FileMetadata.Architecture),
|
||||
},
|
||||
Creator: ctx.Doer,
|
||||
Data: buf,
|
||||
IsLead: true,
|
||||
Properties: map[string]string{
|
||||
rpm_module.PropertyMetadata: string(fileMetadataRaw),
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case packages_model.ErrDuplicatePackageVersion, packages_model.ErrDuplicatePackageFile:
|
||||
apiError(ctx, http.StatusConflict, err)
|
||||
case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize:
|
||||
apiError(ctx, http.StatusForbidden, err)
|
||||
default:
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := rpm_service.BuildRepositoryFiles(ctx, ctx.Package.Owner.ID); err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusCreated)
|
||||
}
|
||||
|
||||
func DownloadPackageFile(ctx *context.Context) {
|
||||
name := ctx.Params("name")
|
||||
version := ctx.Params("version")
|
||||
|
||||
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
|
||||
ctx,
|
||||
&packages_service.PackageInfo{
|
||||
Owner: ctx.Package.Owner,
|
||||
PackageType: packages_model.TypeRpm,
|
||||
Name: name,
|
||||
Version: version,
|
||||
},
|
||||
&packages_service.PackageFileInfo{
|
||||
Filename: fmt.Sprintf("%s-%s.%s.rpm", name, version, ctx.Params("architecture")),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
apiError(ctx, http.StatusNotFound, err)
|
||||
} else {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
ctx.ServeContent(s, &context.ServeHeaderOptions{
|
||||
ContentType: "application/x-rpm",
|
||||
Filename: pf.Name,
|
||||
LastModified: pf.CreatedUnix.AsLocalTime(),
|
||||
})
|
||||
}
|
||||
|
||||
func DeletePackageFile(webctx *context.Context) {
|
||||
name := webctx.Params("name")
|
||||
version := webctx.Params("version")
|
||||
architecture := webctx.Params("architecture")
|
||||
|
||||
var pd *packages_model.PackageDescriptor
|
||||
|
||||
err := db.WithTx(webctx, func(ctx stdctx.Context) error {
|
||||
pv, err := packages_model.GetVersionByNameAndVersion(ctx, webctx.Package.Owner.ID, packages_model.TypeRpm, name, version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pf, err := packages_model.GetFileForVersionByName(
|
||||
ctx,
|
||||
pv.ID,
|
||||
fmt.Sprintf("%s-%s.%s.rpm", name, version, architecture),
|
||||
packages_model.EmptyFileKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := packages_service.DeletePackageFile(ctx, pf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
has, err := packages_model.HasVersionFileReferences(ctx, pv.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
pd, err = packages_model.GetPackageDescriptor(ctx, pv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := packages_service.DeletePackageVersionAndReferences(ctx, pv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
apiError(webctx, http.StatusNotFound, err)
|
||||
} else {
|
||||
apiError(webctx, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if pd != nil {
|
||||
notification.NotifyPackageDelete(webctx, webctx.Doer, pd)
|
||||
}
|
||||
|
||||
if err := rpm_service.BuildRepositoryFiles(webctx, webctx.Package.Owner.ID); err != nil {
|
||||
apiError(webctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
webctx.Status(http.StatusNoContent)
|
||||
}
|
||||
@@ -103,7 +103,6 @@ func CreateUser(ctx *context.APIContext) {
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
ctx.Data["Err_Password"] = true
|
||||
ctx.Error(http.StatusBadRequest, "PasswordPwned", errors.New("PasswordPwned"))
|
||||
return
|
||||
}
|
||||
@@ -201,7 +200,6 @@ func EditUser(ctx *context.APIContext) {
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
ctx.Data["Err_Password"] = true
|
||||
ctx.Error(http.StatusBadRequest, "PasswordPwned", errors.New("PasswordPwned"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ func reqSiteAdmin() func(ctx *context.APIContext) {
|
||||
// reqOwner user should be the owner of the repo or site admin.
|
||||
func reqOwner() func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if !ctx.IsUserRepoOwner() && !ctx.IsUserSiteAdmin() {
|
||||
if !ctx.Repo.IsOwner() && !ctx.IsUserSiteAdmin() {
|
||||
ctx.Error(http.StatusForbidden, "reqOwner", "user should be the owner of the repo")
|
||||
return
|
||||
}
|
||||
@@ -355,7 +355,7 @@ func reqRepoBranchWriter(ctx *context.APIContext) {
|
||||
// reqRepoReader user should have specific read permission or be a repo admin or a site admin
|
||||
func reqRepoReader(unitType unit.Type) func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if !ctx.IsUserRepoReaderSpecific(unitType) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() {
|
||||
if !ctx.Repo.CanRead(unitType) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() {
|
||||
ctx.Error(http.StatusForbidden, "reqRepoReader", "user should have specific read permission or be a repo admin or a site admin")
|
||||
return
|
||||
}
|
||||
@@ -365,7 +365,7 @@ func reqRepoReader(unitType unit.Type) func(ctx *context.APIContext) {
|
||||
// reqAnyRepoReader user should have any permission to read repository or permissions of site admin
|
||||
func reqAnyRepoReader() func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if !ctx.IsUserRepoReaderAny() && !ctx.IsUserSiteAdmin() {
|
||||
if !ctx.Repo.HasAccess() && !ctx.IsUserSiteAdmin() {
|
||||
ctx.Error(http.StatusForbidden, "reqAnyRepoReader", "user should have any permission to read repository or permissions of site admin")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -36,7 +37,7 @@ func createContext(req *http.Request) (*context.Context, *httptest.ResponseRecor
|
||||
Req: req,
|
||||
Resp: context.NewResponse(resp),
|
||||
Render: rnd,
|
||||
Data: make(map[string]interface{}),
|
||||
Data: make(middleware.ContextData),
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ func ListPackages(ctx *context.APIContext) {
|
||||
// in: query
|
||||
// description: package type filter
|
||||
// type: string
|
||||
// enum: [cargo, chef, composer, conan, conda, container, debian, generic, helm, maven, npm, nuget, pub, pypi, rubygems, swift, vagrant]
|
||||
// enum: [cargo, chef, composer, conan, conda, container, debian, generic, helm, maven, npm, nuget, pub, pypi, rpm, rubygems, swift, vagrant]
|
||||
// - name: q
|
||||
// in: query
|
||||
// description: name filter
|
||||
|
||||
@@ -173,11 +173,35 @@ func CreateBranch(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
if len(opt.OldBranchName) == 0 {
|
||||
opt.OldBranchName = ctx.Repo.Repository.DefaultBranch
|
||||
var oldCommit *git.Commit
|
||||
var err error
|
||||
|
||||
if len(opt.OldRefName) > 0 {
|
||||
oldCommit, err = ctx.Repo.GitRepo.GetCommit(opt.OldRefName)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetCommit", err)
|
||||
return
|
||||
}
|
||||
} else if len(opt.OldBranchName) > 0 { //nolint
|
||||
if ctx.Repo.GitRepo.IsBranchExist(opt.OldBranchName) { //nolint
|
||||
oldCommit, err = ctx.Repo.GitRepo.GetBranchCommit(opt.OldBranchName) //nolint
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
ctx.Error(http.StatusNotFound, "", "The old branch does not exist")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
oldCommit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err := repo_service.CreateNewBranch(ctx, ctx.Doer, ctx.Repo.Repository, opt.OldBranchName, opt.BranchName)
|
||||
err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, oldCommit.ID.String(), opt.BranchName)
|
||||
if err != nil {
|
||||
if models.IsErrBranchDoesNotExist(err) {
|
||||
ctx.Error(http.StatusNotFound, "", "The old branch does not exist")
|
||||
@@ -189,7 +213,7 @@ func CreateBranch(ctx *context.APIContext) {
|
||||
} else if models.IsErrBranchNameConflict(err) {
|
||||
ctx.Error(http.StatusConflict, "", "The branch with the same name already exists.")
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "CreateRepoBranch", err)
|
||||
ctx.Error(http.StatusInternalServerError, "CreateNewBranchFromCommit", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -42,6 +42,18 @@ func GetSingleCommit(ctx *context.APIContext) {
|
||||
// description: a git ref or commit sha
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: stat
|
||||
// in: query
|
||||
// description: include diff stats for every commit (disable for speedup, default 'true')
|
||||
// type: boolean
|
||||
// - name: verification
|
||||
// in: query
|
||||
// description: include verification for every commit (disable for speedup, default 'true')
|
||||
// type: boolean
|
||||
// - name: files
|
||||
// in: query
|
||||
// description: include a list of affected files for every commit (disable for speedup, default 'true')
|
||||
// type: boolean
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/Commit"
|
||||
@@ -55,10 +67,11 @@ func GetSingleCommit(ctx *context.APIContext) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "no valid ref or sha", fmt.Sprintf("no valid ref or sha: %s", sha))
|
||||
return
|
||||
}
|
||||
getCommit(ctx, sha)
|
||||
|
||||
getCommit(ctx, sha, convert.ParseCommitOptions(ctx))
|
||||
}
|
||||
|
||||
func getCommit(ctx *context.APIContext, identifier string) {
|
||||
func getCommit(ctx *context.APIContext, identifier string, toCommitOpts convert.ToCommitOptions) {
|
||||
commit, err := ctx.Repo.GitRepo.GetCommit(identifier)
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
@@ -69,7 +82,7 @@ func getCommit(ctx *context.APIContext, identifier string) {
|
||||
return
|
||||
}
|
||||
|
||||
json, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, commit, nil, true)
|
||||
json, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, commit, nil, toCommitOpts)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "toCommit", err)
|
||||
return
|
||||
@@ -107,6 +120,14 @@ func GetAllCommits(ctx *context.APIContext) {
|
||||
// in: query
|
||||
// description: include diff stats for every commit (disable for speedup, default 'true')
|
||||
// type: boolean
|
||||
// - name: verification
|
||||
// in: query
|
||||
// description: include verification for every commit (disable for speedup, default 'true')
|
||||
// type: boolean
|
||||
// - name: files
|
||||
// in: query
|
||||
// description: include a list of affected files for every commit (disable for speedup, default 'true')
|
||||
// type: boolean
|
||||
// - name: page
|
||||
// in: query
|
||||
// description: page number of results to return (1-based)
|
||||
@@ -146,6 +167,7 @@ func GetAllCommits(ctx *context.APIContext) {
|
||||
|
||||
sha := ctx.FormString("sha")
|
||||
path := ctx.FormString("path")
|
||||
not := ctx.FormString("not")
|
||||
|
||||
var (
|
||||
commitsCountTotal int64
|
||||
@@ -178,14 +200,18 @@ func GetAllCommits(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
// Total commit count
|
||||
commitsCountTotal, err = baseCommit.CommitsCount()
|
||||
commitsCountTotal, err = git.CommitsCount(ctx.Repo.GitRepo.Ctx, git.CommitsCountOptions{
|
||||
RepoPath: ctx.Repo.GitRepo.Path,
|
||||
Not: not,
|
||||
Revision: []string{baseCommit.ID.String()},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetCommitsCount", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Query commits
|
||||
not := ctx.FormString("not")
|
||||
commits, err = baseCommit.CommitsByRange(listOptions.Page, listOptions.PageSize, not)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "CommitsByRange", err)
|
||||
@@ -196,7 +222,14 @@ func GetAllCommits(ctx *context.APIContext) {
|
||||
sha = ctx.Repo.Repository.DefaultBranch
|
||||
}
|
||||
|
||||
commitsCountTotal, err = ctx.Repo.GitRepo.FileCommitsCount(sha, path)
|
||||
commitsCountTotal, err = git.CommitsCount(ctx,
|
||||
git.CommitsCountOptions{
|
||||
RepoPath: ctx.Repo.GitRepo.Path,
|
||||
Not: not,
|
||||
Revision: []string{sha},
|
||||
RelPath: []string{path},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "FileCommitsCount", err)
|
||||
return
|
||||
@@ -205,7 +238,14 @@ func GetAllCommits(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
commits, err = ctx.Repo.GitRepo.CommitsByFileAndRange(sha, path, listOptions.Page)
|
||||
commits, err = ctx.Repo.GitRepo.CommitsByFileAndRange(
|
||||
git.CommitsByFileAndRangeOptions{
|
||||
Revision: sha,
|
||||
File: path,
|
||||
Not: not,
|
||||
Page: listOptions.Page,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRange", err)
|
||||
return
|
||||
@@ -213,16 +253,12 @@ func GetAllCommits(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
pageCount := int(math.Ceil(float64(commitsCountTotal) / float64(listOptions.PageSize)))
|
||||
|
||||
userCache := make(map[string]*user_model.User)
|
||||
|
||||
apiCommits := make([]*api.Commit, len(commits))
|
||||
|
||||
stat := ctx.FormString("stat") == "" || ctx.FormBool("stat")
|
||||
|
||||
for i, commit := range commits {
|
||||
// Create json struct
|
||||
apiCommits[i], err = convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, commit, userCache, stat)
|
||||
apiCommits[i], err = convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, commit, userCache, convert.ParseCommitOptions(ctx))
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "toCommit", err)
|
||||
return
|
||||
|
||||
@@ -150,6 +150,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME: code from #19689, what if the file is large ... OOM ...
|
||||
buf, err := io.ReadAll(dataRc)
|
||||
if err != nil {
|
||||
_ = dataRc.Close()
|
||||
@@ -164,7 +165,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
|
||||
// Check if the blob represents a pointer
|
||||
pointer, _ := lfs.ReadPointer(bytes.NewReader(buf))
|
||||
|
||||
// if its not a pointer just serve the data directly
|
||||
// if it's not a pointer, just serve the data directly
|
||||
if !pointer.IsValid() {
|
||||
// First handle caching for the blob
|
||||
if httpcache.HandleGenericETagTimeCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`, lastModified) {
|
||||
@@ -172,25 +173,21 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
// OK not cached - serve!
|
||||
if err := common.ServeData(ctx.Context, ctx.Repo.TreePath, blob.Size(), bytes.NewReader(buf)); err != nil {
|
||||
ctx.ServerError("ServeBlob", err)
|
||||
}
|
||||
common.ServeContentByReader(ctx.Context, ctx.Repo.TreePath, blob.Size(), bytes.NewReader(buf))
|
||||
return
|
||||
}
|
||||
|
||||
// Now check if there is a meta object for this pointer
|
||||
// Now check if there is a MetaObject for this pointer
|
||||
meta, err := git_model.GetLFSMetaObjectByOid(ctx, ctx.Repo.Repository.ID, pointer.Oid)
|
||||
|
||||
// If there isn't one just serve the data directly
|
||||
// If there isn't one, just serve the data directly
|
||||
if err == git_model.ErrLFSObjectNotExist {
|
||||
// Handle caching for the blob SHA (not the LFS object OID)
|
||||
if httpcache.HandleGenericETagTimeCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`, lastModified) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := common.ServeData(ctx.Context, ctx.Repo.TreePath, blob.Size(), bytes.NewReader(buf)); err != nil {
|
||||
ctx.ServerError("ServeBlob", err)
|
||||
}
|
||||
common.ServeContentByReader(ctx.Context, ctx.Repo.TreePath, blob.Size(), bytes.NewReader(buf))
|
||||
return
|
||||
} else if err != nil {
|
||||
ctx.ServerError("GetLFSMetaObjectByOid", err)
|
||||
@@ -218,9 +215,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
|
||||
}
|
||||
defer lfsDataRc.Close()
|
||||
|
||||
if err := common.ServeData(ctx.Context, ctx.Repo.TreePath, meta.Size, lfsDataRc); err != nil {
|
||||
ctx.ServerError("ServeData", err)
|
||||
}
|
||||
common.ServeContentByReadSeeker(ctx.Context, ctx.Repo.TreePath, lastModified, lfsDataRc)
|
||||
}
|
||||
|
||||
func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEntry, lastModified time.Time) {
|
||||
|
||||
@@ -13,10 +13,11 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
setting.InitProviderAndLoadCommonSettingsForTest()
|
||||
setting.LoadQueueSettings()
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", "..", ".."),
|
||||
SetUp: webhook_service.Init,
|
||||
SetUp: func() error {
|
||||
setting.LoadQueueSettings()
|
||||
return webhook_service.Init()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func getNote(ctx *context.APIContext, identifier string) {
|
||||
return
|
||||
}
|
||||
|
||||
cmt, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, note.Commit, nil, true)
|
||||
cmt, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, note.Commit, nil, convert.ToCommitOptions{Stat: true})
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "ToCommit", err)
|
||||
return
|
||||
|
||||
@@ -1318,7 +1318,7 @@ func GetPullRequestCommits(ctx *context.APIContext) {
|
||||
|
||||
apiCommits := make([]*api.Commit, 0, end-start)
|
||||
for i := start; i < end; i++ {
|
||||
apiCommit, err := convert.ToCommit(ctx, ctx.Repo.Repository, baseGitRepo, commits[i], userCache, true)
|
||||
apiCommit, err := convert.ToCommit(ctx, ctx.Repo.Repository, baseGitRepo, commits[i], userCache, convert.ToCommitOptions{Stat: true})
|
||||
if err != nil {
|
||||
ctx.ServerError("toCommit", err)
|
||||
return
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||
"code.gitea.io/gitea/services/convert"
|
||||
"code.gitea.io/gitea/services/issue"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
)
|
||||
|
||||
@@ -178,7 +179,7 @@ func Search(ctx *context.APIContext) {
|
||||
if len(sortOrder) == 0 {
|
||||
sortOrder = "asc"
|
||||
}
|
||||
if searchModeMap, ok := context.SearchOrderByMap[sortOrder]; ok {
|
||||
if searchModeMap, ok := repo_model.SearchOrderByMap[sortOrder]; ok {
|
||||
if orderBy, ok := searchModeMap[sortMode]; ok {
|
||||
opts.OrderBy = orderBy
|
||||
} else {
|
||||
@@ -975,9 +976,11 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := repo_model.UpdateRepositoryUnits(repo, units, deleteUnitTypes); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "UpdateRepositoryUnits", err)
|
||||
return err
|
||||
if len(units)+len(deleteUnitTypes) > 0 {
|
||||
if err := repo_model.UpdateRepositoryUnits(repo, units, deleteUnitTypes); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "UpdateRepositoryUnits", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Trace("Repository advanced settings updated: %s/%s", owner.Name, repo.Name)
|
||||
@@ -1147,8 +1150,12 @@ func GetIssueTemplates(ctx *context.APIContext) {
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/IssueTemplates"
|
||||
|
||||
ctx.JSON(http.StatusOK, ctx.IssueTemplatesFromDefaultBranch())
|
||||
ret, err := issue.GetTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetTemplatesFromDefaultBranch", err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, ret)
|
||||
}
|
||||
|
||||
// GetIssueConfig returns the issue config for a repo
|
||||
@@ -1172,7 +1179,7 @@ func GetIssueConfig(ctx *context.APIContext) {
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RepoIssueConfig"
|
||||
issueConfig, _ := ctx.IssueConfigFromDefaultBranch()
|
||||
issueConfig, _ := issue.GetTemplateConfigFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
||||
ctx.JSON(http.StatusOK, issueConfig)
|
||||
}
|
||||
|
||||
@@ -1197,7 +1204,7 @@ func ValidateIssueConfig(ctx *context.APIContext) {
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RepoIssueConfigValidation"
|
||||
_, err := ctx.IssueConfigFromDefaultBranch()
|
||||
_, err := issue.GetTemplateConfigFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
||||
|
||||
if err == nil {
|
||||
ctx.JSON(http.StatusOK, api.IssueConfigValidation{Valid: true, Message: ""})
|
||||
|
||||
@@ -429,7 +429,12 @@ func ListPageRevisions(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
// get Commit Count
|
||||
commitsHistory, err := wikiRepo.CommitsByFileAndRange("master", pageFilename, page)
|
||||
commitsHistory, err := wikiRepo.CommitsByFileAndRange(
|
||||
git.CommitsByFileAndRangeOptions{
|
||||
Revision: "master",
|
||||
File: pageFilename,
|
||||
Page: page,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRange", err)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user