mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-09 09:33:24 +02:00
Merge remote-tracking branch 'origin/main' into test
This commit is contained in:
commit
c2e9532c38
482 files changed
+6150
-5726
No files matched your search
@@ -43,7 +43,7 @@ func validateRunID(ctx *ArtifactContext) (*actions.ActionTask, int64, bool) {
|
||||
return task, runID, true
|
||||
}
|
||||
|
||||
func validateRunIDV4(ctx *ArtifactContext, rawRunID string) (*actions.ActionTask, int64, bool) { //nolint:unparam
|
||||
func validateRunIDV4(ctx *ArtifactContext, rawRunID string) (*actions.ActionTask, int64, bool) { //nolint:unparam // ActionTask is never used
|
||||
task := ctx.ActionTask
|
||||
runID, err := strconv.ParseInt(rawRunID, 10, 64)
|
||||
if err != nil || task.Job.RunID != runID {
|
||||
|
||||
@@ -467,7 +467,9 @@ func CommonRoutes() *web.Router {
|
||||
g.MatchPath("HEAD", "/<group:*>/repodata/<filename>", rpm.CheckRepositoryFileExistence)
|
||||
g.MatchPath("GET", "/<group:*>/repodata/<filename>", rpm.GetRepositoryFile)
|
||||
g.MatchPath("PUT", "/<group:*>/upload", reqPackageAccess(perm.AccessModeWrite), rpm.UploadPackageFile)
|
||||
// this URL pattern is only used internally in the RPM index, it is generated by us, the filename part is not really used (can be anything)
|
||||
g.MatchPath("HEAD,GET", "/<group:*>/package/<name>/<version>/<architecture>", rpm.DownloadPackageFile)
|
||||
g.MatchPath("HEAD,GET", "/<group:*>/package/<name>/<version>/<architecture>/<filename>", rpm.DownloadPackageFile)
|
||||
g.MatchPath("DELETE", "/<group:*>/package/<name>/<version>/<architecture>", reqPackageAccess(perm.AccessModeWrite), rpm.DeletePackageFile)
|
||||
}, reqPackageAccess(perm.AccessModeRead))
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ func ListOrGetPackages(ctx *context.Context) {
|
||||
DownloadPackageFile(ctx)
|
||||
return
|
||||
}
|
||||
ctx.NotFound(nil)
|
||||
http.NotFound(ctx.Resp, ctx.Req)
|
||||
}
|
||||
|
||||
func EnumeratePackages(ctx *context.Context) {
|
||||
|
||||
@@ -21,7 +21,7 @@ func (a *Auth) Name() string {
|
||||
}
|
||||
|
||||
// Verify extracts the user from the Bearer token
|
||||
// If it's an anonymous session a ghost user is returned
|
||||
// If it's an anonymous session, a ghost user is returned
|
||||
func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) (*user_model.User, error) {
|
||||
packageMeta, err := packages.ParseAuthorizationRequest(req)
|
||||
if err != nil {
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
|
||||
// saveAsPackageBlob creates a package blob from an upload
|
||||
// The uploaded blob gets stored in a special upload version to link them to the package/image
|
||||
func saveAsPackageBlob(ctx context.Context, hsr packages_module.HashedSizeReader, pci *packages_service.PackageCreationInfo) (*packages_model.PackageBlob, error) { //nolint:unparam
|
||||
func saveAsPackageBlob(ctx context.Context, hsr packages_module.HashedSizeReader, pci *packages_service.PackageCreationInfo) (*packages_model.PackageBlob, error) { //nolint:unparam // PackageBlob is never used
|
||||
pb := packages_service.NewPackageBlob(hsr)
|
||||
|
||||
exists := false
|
||||
@@ -95,15 +95,13 @@ func containerGlobalLockKey(piOwnerID int64, piName, usage string) string {
|
||||
}
|
||||
|
||||
func getOrCreateUploadVersion(ctx context.Context, pi *packages_service.PackageInfo) (*packages_model.PackageVersion, error) {
|
||||
var uploadVersion *packages_model.PackageVersion
|
||||
|
||||
releaser, err := globallock.Lock(ctx, containerGlobalLockKey(pi.Owner.ID, pi.Name, "package"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer releaser()
|
||||
|
||||
err = db.WithTx(ctx, func(ctx context.Context) error {
|
||||
return db.WithTx2(ctx, func(ctx context.Context) (*packages_model.PackageVersion, error) {
|
||||
created := true
|
||||
p := &packages_model.Package{
|
||||
OwnerID: pi.Owner.ID,
|
||||
@@ -115,7 +113,7 @@ func getOrCreateUploadVersion(ctx context.Context, pi *packages_service.PackageI
|
||||
if p, err = packages_model.TryInsertPackage(ctx, p); err != nil {
|
||||
if !errors.Is(err, packages_model.ErrDuplicatePackage) {
|
||||
log.Error("Error inserting package: %v", err)
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
created = false
|
||||
}
|
||||
@@ -123,7 +121,7 @@ func getOrCreateUploadVersion(ctx context.Context, pi *packages_service.PackageI
|
||||
if created {
|
||||
if _, err := packages_model.InsertProperty(ctx, packages_model.PropertyTypePackage, p.ID, container_module.PropertyRepository, strings.ToLower(pi.Owner.LowerName+"/"+pi.Name)); err != nil {
|
||||
log.Error("Error setting package property: %v", err)
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,16 +136,11 @@ func getOrCreateUploadVersion(ctx context.Context, pi *packages_service.PackageI
|
||||
if pv, err = packages_model.GetOrInsertVersion(ctx, pv); err != nil {
|
||||
if !errors.Is(err, packages_model.ErrDuplicatePackageVersion) {
|
||||
log.Error("Error inserting package: %v", err)
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
uploadVersion = pv
|
||||
|
||||
return nil
|
||||
return pv, nil
|
||||
})
|
||||
|
||||
return uploadVersion, err
|
||||
}
|
||||
|
||||
func createFileForBlob(ctx context.Context, pv *packages_model.PackageVersion, pb *packages_model.PackageBlob) error {
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
packages_model "code.gitea.io/gitea/models/packages"
|
||||
@@ -39,10 +40,14 @@ import (
|
||||
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-manifests
|
||||
const maxManifestSize = 10 * 1024 * 1024
|
||||
|
||||
var (
|
||||
imageNamePattern = regexp.MustCompile(`\A[a-z0-9]+([._-][a-z0-9]+)*(/[a-z0-9]+([._-][a-z0-9]+)*)*\z`)
|
||||
referencePattern = regexp.MustCompile(`\A[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}\z`)
|
||||
)
|
||||
var globalVars = sync.OnceValue(func() (ret struct {
|
||||
imageNamePattern, referencePattern *regexp.Regexp
|
||||
},
|
||||
) {
|
||||
ret.imageNamePattern = regexp.MustCompile(`\A[a-z0-9]+([._-][a-z0-9]+)*(/[a-z0-9]+([._-][a-z0-9]+)*)*\z`)
|
||||
ret.referencePattern = regexp.MustCompile(`\A[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}\z`)
|
||||
return ret
|
||||
})
|
||||
|
||||
type containerHeaders struct {
|
||||
Status int
|
||||
@@ -84,9 +89,7 @@ func jsonResponse(ctx *context.Context, status int, obj any) {
|
||||
Status: status,
|
||||
ContentType: "application/json",
|
||||
})
|
||||
if err := json.NewEncoder(ctx.Resp).Encode(obj); err != nil {
|
||||
log.Error("JSON encode: %v", err)
|
||||
}
|
||||
_ = json.NewEncoder(ctx.Resp).Encode(obj) // ignore network errors
|
||||
}
|
||||
|
||||
func apiError(ctx *context.Context, status int, err error) {
|
||||
@@ -134,7 +137,7 @@ func ReqContainerAccess(ctx *context.Context) {
|
||||
|
||||
// VerifyImageName is a middleware which checks if the image name is allowed
|
||||
func VerifyImageName(ctx *context.Context) {
|
||||
if !imageNamePattern.MatchString(ctx.PathParam("image")) {
|
||||
if !globalVars().imageNamePattern.MatchString(ctx.PathParam("image")) {
|
||||
apiErrorDefined(ctx, errNameInvalid)
|
||||
}
|
||||
}
|
||||
@@ -216,7 +219,7 @@ func GetRepositoryList(ctx *context.Context) {
|
||||
if len(repositories) == n {
|
||||
v := url.Values{}
|
||||
if n > 0 {
|
||||
v.Add("n", strconv.Itoa(n))
|
||||
v.Add("n", strconv.Itoa(n)) // FIXME: "n" can't be zero here, the logic is inconsistent with GetTagsList
|
||||
}
|
||||
v.Add("last", repositories[len(repositories)-1])
|
||||
|
||||
@@ -565,7 +568,7 @@ func PutManifest(ctx *context.Context) {
|
||||
IsTagged: digest.Digest(reference).Validate() != nil,
|
||||
}
|
||||
|
||||
if mci.IsTagged && !referencePattern.MatchString(reference) {
|
||||
if mci.IsTagged && !globalVars().referencePattern.MatchString(reference) {
|
||||
apiErrorDefined(ctx, errManifestInvalid.WithMessage("Tag is invalid"))
|
||||
return
|
||||
}
|
||||
@@ -618,7 +621,7 @@ func getBlobSearchOptionsFromContext(ctx *context.Context) (*container_model.Blo
|
||||
reference := ctx.PathParam("reference")
|
||||
if d := digest.Digest(reference); d.Validate() == nil {
|
||||
opts.Digest = string(d)
|
||||
} else if referencePattern.MatchString(reference) {
|
||||
} else if globalVars().referencePattern.MatchString(reference) {
|
||||
opts.Tag = reference
|
||||
opts.OnlyLead = true
|
||||
} else {
|
||||
@@ -782,7 +785,8 @@ func GetTagsList(ctx *context.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// FIXME: Workaround to be removed in v1.20
|
||||
// FIXME: Workaround to be removed in v1.20.
|
||||
// Update maybe we should never really remote it, as long as there is legacy data?
|
||||
// https://github.com/go-gitea/gitea/issues/19586
|
||||
func workaroundGetContainerBlob(ctx *context.Context, opts *container_model.BlobSearchOptions) (*packages_model.PackageFileDescriptor, error) {
|
||||
blob, err := container_model.GetContainerBlob(ctx, opts)
|
||||
|
||||
@@ -46,11 +46,9 @@ func processManifest(ctx context.Context, mci *manifestCreationInfo, buf *packag
|
||||
if err := json.NewDecoder(buf).Decode(&index); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if index.SchemaVersion != 2 {
|
||||
return "", errUnsupported.WithMessage("Schema version is not supported")
|
||||
}
|
||||
|
||||
if _, err := buf.Seek(0, io.SeekStart); err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -77,24 +75,41 @@ func processManifest(ctx context.Context, mci *manifestCreationInfo, buf *packag
|
||||
return "", errManifestInvalid
|
||||
}
|
||||
|
||||
func processOciImageManifest(ctx context.Context, mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (string, error) {
|
||||
manifestDigest := ""
|
||||
type processManifestTxRet struct {
|
||||
pv *packages_model.PackageVersion
|
||||
pb *packages_model.PackageBlob
|
||||
created bool
|
||||
digest string
|
||||
}
|
||||
|
||||
err := func() error {
|
||||
manifest, configDescriptor, metadata, err := container_service.ParseManifestMetadata(ctx, buf, mci.Owner.ID, mci.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = buf.Seek(0, io.SeekStart); err != nil {
|
||||
return err
|
||||
func handleCreateManifestResult(ctx context.Context, err error, mci *manifestCreationInfo, contentStore *packages_module.ContentStore, txRet *processManifestTxRet) (string, error) {
|
||||
if err != nil && txRet.created && txRet.pb != nil {
|
||||
if err := contentStore.Delete(packages_module.BlobHash256Key(txRet.pb.HashSHA256)); err != nil {
|
||||
log.Error("Error deleting package blob from content store: %v", err)
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
pd, err := packages_model.GetPackageDescriptor(ctx, txRet.pv)
|
||||
if err != nil {
|
||||
log.Error("Error getting package descriptor: %v", err) // ignore this error
|
||||
} else {
|
||||
notify_service.PackageCreate(ctx, mci.Creator, pd)
|
||||
}
|
||||
return txRet.digest, nil
|
||||
}
|
||||
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
func processOciImageManifest(ctx context.Context, mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (manifestDigest string, errRet error) {
|
||||
manifest, configDescriptor, metadata, err := container_service.ParseManifestMetadata(ctx, buf, mci.Owner.ID, mci.Image)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err = buf.Seek(0, io.SeekStart); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
contentStore := packages_module.NewContentStore()
|
||||
var txRet processManifestTxRet
|
||||
err = db.WithTx(ctx, func(ctx context.Context) (err error) {
|
||||
blobReferences := make([]*blobReference, 0, 1+len(manifest.Layers))
|
||||
blobReferences = append(blobReferences, &blobReference{
|
||||
Digest: manifest.Config.Digest,
|
||||
@@ -127,7 +142,7 @@ func processOciImageManifest(ctx context.Context, mci *manifestCreationInfo, buf
|
||||
}
|
||||
|
||||
uploadVersion, err := packages_model.GetInternalVersionByNameAndVersion(ctx, mci.Owner.ID, packages_model.TypeContainer, mci.Image, container_module.UploadVersion)
|
||||
if err != nil && err != packages_model.ErrPackageNotExist {
|
||||
if err != nil && !errors.Is(err, packages_model.ErrPackageNotExist) {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -136,61 +151,26 @@ func processOciImageManifest(ctx context.Context, mci *manifestCreationInfo, buf
|
||||
return err
|
||||
}
|
||||
}
|
||||
txRet.pv = pv
|
||||
txRet.pb, txRet.created, txRet.digest, err = createManifestBlob(ctx, contentStore, mci, pv, buf)
|
||||
return err
|
||||
})
|
||||
|
||||
pb, created, digest, err := createManifestBlob(ctx, mci, pv, buf)
|
||||
removeBlob := false
|
||||
defer func() {
|
||||
if removeBlob {
|
||||
contentStore := packages_module.NewContentStore()
|
||||
if err := contentStore.Delete(packages_module.BlobHash256Key(pb.HashSHA256)); err != nil {
|
||||
log.Error("Error deleting package blob from content store: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
removeBlob = created
|
||||
return err
|
||||
}
|
||||
return handleCreateManifestResult(ctx, err, mci, contentStore, &txRet)
|
||||
}
|
||||
|
||||
if err := committer.Commit(); err != nil {
|
||||
removeBlob = created
|
||||
return err
|
||||
}
|
||||
|
||||
if err := notifyPackageCreate(ctx, mci.Creator, pv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
manifestDigest = digest
|
||||
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
func processOciImageIndex(ctx context.Context, mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (manifestDigest string, errRet error) {
|
||||
var index oci.Index
|
||||
if err := json.NewDecoder(buf).Decode(&index); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err := buf.Seek(0, io.SeekStart); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return manifestDigest, nil
|
||||
}
|
||||
|
||||
func processOciImageIndex(ctx context.Context, mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (string, error) {
|
||||
manifestDigest := ""
|
||||
|
||||
err := func() error {
|
||||
var index oci.Index
|
||||
if err := json.NewDecoder(buf).Decode(&index); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := buf.Seek(0, io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
contentStore := packages_module.NewContentStore()
|
||||
var txRet processManifestTxRet
|
||||
err := db.WithTx(ctx, func(ctx context.Context) (err error) {
|
||||
metadata := &container_module.Metadata{
|
||||
Type: container_module.TypeOCI,
|
||||
Manifests: make([]*container_module.Manifest, 0, len(index.Manifests)),
|
||||
@@ -241,50 +221,12 @@ func processOciImageIndex(ctx context.Context, mci *manifestCreationInfo, buf *p
|
||||
return err
|
||||
}
|
||||
|
||||
pb, created, digest, err := createManifestBlob(ctx, mci, pv, buf)
|
||||
removeBlob := false
|
||||
defer func() {
|
||||
if removeBlob {
|
||||
contentStore := packages_module.NewContentStore()
|
||||
if err := contentStore.Delete(packages_module.BlobHash256Key(pb.HashSHA256)); err != nil {
|
||||
log.Error("Error deleting package blob from content store: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
removeBlob = created
|
||||
return err
|
||||
}
|
||||
|
||||
if err := committer.Commit(); err != nil {
|
||||
removeBlob = created
|
||||
return err
|
||||
}
|
||||
|
||||
if err := notifyPackageCreate(ctx, mci.Creator, pv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
manifestDigest = digest
|
||||
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return manifestDigest, nil
|
||||
}
|
||||
|
||||
func notifyPackageCreate(ctx context.Context, doer *user_model.User, pv *packages_model.PackageVersion) error {
|
||||
pd, err := packages_model.GetPackageDescriptor(ctx, pv)
|
||||
if err != nil {
|
||||
txRet.pv = pv
|
||||
txRet.pb, txRet.created, txRet.digest, err = createManifestBlob(ctx, contentStore, mci, pv, buf)
|
||||
return err
|
||||
}
|
||||
})
|
||||
|
||||
notify_service.PackageCreate(ctx, doer, pd)
|
||||
|
||||
return nil
|
||||
return handleCreateManifestResult(ctx, err, mci, contentStore, &txRet)
|
||||
}
|
||||
|
||||
func createPackageAndVersion(ctx context.Context, mci *manifestCreationInfo, metadata *container_module.Metadata) (*packages_model.PackageVersion, error) {
|
||||
@@ -437,7 +379,7 @@ func createFileFromBlobReference(ctx context.Context, pv, uploadVersion *package
|
||||
return pf, nil
|
||||
}
|
||||
|
||||
func createManifestBlob(ctx context.Context, mci *manifestCreationInfo, pv *packages_model.PackageVersion, buf *packages_module.HashedBuffer) (*packages_model.PackageBlob, bool, string, error) {
|
||||
func createManifestBlob(ctx context.Context, contentStore *packages_module.ContentStore, mci *manifestCreationInfo, pv *packages_model.PackageVersion, buf *packages_module.HashedBuffer) (_ *packages_model.PackageBlob, created bool, manifestDigest string, _ error) {
|
||||
pb, exists, err := packages_model.GetOrInsertBlob(ctx, packages_service.NewPackageBlob(buf))
|
||||
if err != nil {
|
||||
log.Error("Error inserting package blob: %v", err)
|
||||
@@ -446,21 +388,20 @@ func createManifestBlob(ctx context.Context, mci *manifestCreationInfo, pv *pack
|
||||
// FIXME: Workaround to be removed in v1.20
|
||||
// https://github.com/go-gitea/gitea/issues/19586
|
||||
if exists {
|
||||
err = packages_module.NewContentStore().Has(packages_module.BlobHash256Key(pb.HashSHA256))
|
||||
err = contentStore.Has(packages_module.BlobHash256Key(pb.HashSHA256))
|
||||
if err != nil && (errors.Is(err, util.ErrNotExist) || errors.Is(err, os.ErrNotExist)) {
|
||||
log.Debug("Package registry inconsistent: blob %s does not exist on file system", pb.HashSHA256)
|
||||
exists = false
|
||||
}
|
||||
}
|
||||
if !exists {
|
||||
contentStore := packages_module.NewContentStore()
|
||||
if err := contentStore.Save(packages_module.BlobHash256Key(pb.HashSHA256), buf, buf.Size()); err != nil {
|
||||
log.Error("Error saving package blob in content store: %v", err)
|
||||
return nil, false, "", err
|
||||
}
|
||||
}
|
||||
|
||||
manifestDigest := digestFromHashSummer(buf)
|
||||
manifestDigest = digestFromHashSummer(buf)
|
||||
pf, err := createFileFromBlobReference(ctx, pv, nil, &blobReference{
|
||||
Digest: digest.Digest(manifestDigest),
|
||||
MediaType: mci.MediaType,
|
||||
|
||||
@@ -53,15 +53,23 @@ type RegistrationIndexPageItem struct {
|
||||
// https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#catalog-entry
|
||||
type CatalogEntry struct {
|
||||
CatalogLeafURL string `json:"@id"`
|
||||
PackageContentURL string `json:"packageContent"`
|
||||
ID string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Description string `json:"description"`
|
||||
ReleaseNotes string `json:"releaseNotes"`
|
||||
Authors string `json:"authors"`
|
||||
RequireLicenseAcceptance bool `json:"requireLicenseAcceptance"`
|
||||
ProjectURL string `json:"projectURL"`
|
||||
Copyright string `json:"copyright"`
|
||||
DependencyGroups []*PackageDependencyGroup `json:"dependencyGroups"`
|
||||
Description string `json:"description"`
|
||||
IconURL string `json:"iconUrl"`
|
||||
ID string `json:"id"`
|
||||
IsPrerelease bool `json:"isPrerelease"`
|
||||
Language string `json:"language"`
|
||||
LicenseURL string `json:"licenseUrl"`
|
||||
PackageContentURL string `json:"packageContent"`
|
||||
ProjectURL string `json:"projectUrl"`
|
||||
RequireLicenseAcceptance bool `json:"requireLicenseAcceptance"`
|
||||
Summary string `json:"summary"`
|
||||
Tags string `json:"tags"`
|
||||
Version string `json:"version"`
|
||||
ReleaseNotes string `json:"releaseNotes"`
|
||||
Published time.Time `json:"published"`
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#package-dependency-group
|
||||
@@ -109,15 +117,24 @@ func createRegistrationIndexPageItem(l *linkBuilder, pd *packages_model.PackageD
|
||||
RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
|
||||
PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version),
|
||||
CatalogEntry: &CatalogEntry{
|
||||
CatalogLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
|
||||
PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version),
|
||||
ID: pd.Package.Name,
|
||||
Version: pd.Version.Version,
|
||||
Description: metadata.Description,
|
||||
ReleaseNotes: metadata.ReleaseNotes,
|
||||
Authors: metadata.Authors,
|
||||
ProjectURL: metadata.ProjectURL,
|
||||
DependencyGroups: createDependencyGroups(pd),
|
||||
CatalogLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
|
||||
Authors: metadata.Authors,
|
||||
Copyright: metadata.Copyright,
|
||||
DependencyGroups: createDependencyGroups(pd),
|
||||
Description: metadata.Description,
|
||||
IconURL: metadata.IconURL,
|
||||
ID: pd.Package.Name,
|
||||
IsPrerelease: pd.Version.IsPrerelease(),
|
||||
Language: metadata.Language,
|
||||
LicenseURL: metadata.LicenseURL,
|
||||
PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version),
|
||||
ProjectURL: metadata.ProjectURL,
|
||||
RequireLicenseAcceptance: metadata.RequireLicenseAcceptance,
|
||||
Summary: metadata.Summary,
|
||||
Tags: metadata.Tags,
|
||||
Version: pd.Version.Version,
|
||||
ReleaseNotes: metadata.ReleaseNotes,
|
||||
Published: pd.Version.CreatedUnix.AsLocalTime(),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -145,22 +162,42 @@ func createDependencyGroups(pd *packages_model.PackageDescriptor) []*PackageDepe
|
||||
|
||||
// https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-leaf
|
||||
type RegistrationLeafResponse struct {
|
||||
RegistrationLeafURL string `json:"@id"`
|
||||
Type []string `json:"@type"`
|
||||
Listed bool `json:"listed"`
|
||||
PackageContentURL string `json:"packageContent"`
|
||||
Published time.Time `json:"published"`
|
||||
RegistrationIndexURL string `json:"registration"`
|
||||
RegistrationLeafURL string `json:"@id"`
|
||||
Type []string `json:"@type"`
|
||||
PackageContentURL string `json:"packageContent"`
|
||||
RegistrationIndexURL string `json:"registration"`
|
||||
CatalogEntry CatalogEntry `json:"catalogEntry"`
|
||||
}
|
||||
|
||||
func createRegistrationLeafResponse(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationLeafResponse {
|
||||
registrationLeafURL := l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version)
|
||||
packageDownloadURL := l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version)
|
||||
metadata := pd.Metadata.(*nuget_module.Metadata)
|
||||
return &RegistrationLeafResponse{
|
||||
Type: []string{"Package", "http://schema.nuget.org/catalog#Permalink"},
|
||||
Listed: true,
|
||||
Published: pd.Version.CreatedUnix.AsLocalTime(),
|
||||
RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
|
||||
PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version),
|
||||
RegistrationLeafURL: registrationLeafURL,
|
||||
RegistrationIndexURL: l.GetRegistrationIndexURL(pd.Package.Name),
|
||||
PackageContentURL: packageDownloadURL,
|
||||
Type: []string{"Package", "http://schema.nuget.org/catalog#Permalink"},
|
||||
CatalogEntry: CatalogEntry{
|
||||
CatalogLeafURL: registrationLeafURL,
|
||||
Authors: metadata.Authors,
|
||||
Copyright: metadata.Copyright,
|
||||
DependencyGroups: createDependencyGroups(pd),
|
||||
Description: metadata.Description,
|
||||
IconURL: metadata.IconURL,
|
||||
ID: pd.Package.Name,
|
||||
IsPrerelease: pd.Version.IsPrerelease(),
|
||||
Language: metadata.Language,
|
||||
LicenseURL: metadata.LicenseURL,
|
||||
PackageContentURL: packageDownloadURL,
|
||||
ProjectURL: metadata.ProjectURL,
|
||||
RequireLicenseAcceptance: metadata.RequireLicenseAcceptance,
|
||||
Summary: metadata.Summary,
|
||||
Tags: metadata.Tags,
|
||||
Version: pd.Version.Version,
|
||||
ReleaseNotes: metadata.ReleaseNotes,
|
||||
Published: pd.Version.CreatedUnix.AsLocalTime(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,13 +225,24 @@ type SearchResultResponse struct {
|
||||
|
||||
// https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result
|
||||
type SearchResult struct {
|
||||
ID string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Versions []*SearchResultVersion `json:"versions"`
|
||||
Description string `json:"description"`
|
||||
Authors string `json:"authors"`
|
||||
ProjectURL string `json:"projectURL"`
|
||||
RegistrationIndexURL string `json:"registration"`
|
||||
Authors string `json:"authors"`
|
||||
Copyright string `json:"copyright"`
|
||||
DependencyGroups []*PackageDependencyGroup `json:"dependencyGroups"`
|
||||
Description string `json:"description"`
|
||||
IconURL string `json:"iconUrl"`
|
||||
ID string `json:"id"`
|
||||
IsPrerelease bool `json:"isPrerelease"`
|
||||
Language string `json:"language"`
|
||||
LicenseURL string `json:"licenseUrl"`
|
||||
ProjectURL string `json:"projectUrl"`
|
||||
RequireLicenseAcceptance bool `json:"requireLicenseAcceptance"`
|
||||
Summary string `json:"summary"`
|
||||
Tags string `json:"tags"`
|
||||
Title string `json:"title"`
|
||||
TotalDownloads int64 `json:"totalDownloads"`
|
||||
Version string `json:"version"`
|
||||
Versions []*SearchResultVersion `json:"versions"`
|
||||
RegistrationIndexURL string `json:"registration"`
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result
|
||||
@@ -230,11 +278,12 @@ func createSearchResultResponse(l *linkBuilder, totalHits int64, pds []*packages
|
||||
func createSearchResult(l *linkBuilder, pds []*packages_model.PackageDescriptor) *SearchResult {
|
||||
latest := pds[0]
|
||||
versions := make([]*SearchResultVersion, 0, len(pds))
|
||||
totalDownloads := int64(0)
|
||||
for _, pd := range pds {
|
||||
if latest.SemVer.LessThan(pd.SemVer) {
|
||||
latest = pd
|
||||
}
|
||||
|
||||
totalDownloads += pd.Version.DownloadCount
|
||||
versions = append(versions, &SearchResultVersion{
|
||||
RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
|
||||
Version: pd.Version.Version,
|
||||
@@ -244,12 +293,23 @@ func createSearchResult(l *linkBuilder, pds []*packages_model.PackageDescriptor)
|
||||
metadata := latest.Metadata.(*nuget_module.Metadata)
|
||||
|
||||
return &SearchResult{
|
||||
ID: latest.Package.Name,
|
||||
Version: latest.Version.Version,
|
||||
Versions: versions,
|
||||
Description: metadata.Description,
|
||||
Authors: metadata.Authors,
|
||||
ProjectURL: metadata.ProjectURL,
|
||||
RegistrationIndexURL: l.GetRegistrationIndexURL(latest.Package.Name),
|
||||
Authors: metadata.Authors,
|
||||
Copyright: metadata.Copyright,
|
||||
Description: metadata.Description,
|
||||
DependencyGroups: createDependencyGroups(latest),
|
||||
IconURL: metadata.IconURL,
|
||||
ID: latest.Package.Name,
|
||||
IsPrerelease: latest.Version.IsPrerelease(),
|
||||
Language: metadata.Language,
|
||||
LicenseURL: metadata.LicenseURL,
|
||||
ProjectURL: metadata.ProjectURL,
|
||||
RequireLicenseAcceptance: metadata.RequireLicenseAcceptance,
|
||||
Summary: metadata.Summary,
|
||||
Tags: metadata.Tags,
|
||||
Title: metadata.Title,
|
||||
TotalDownloads: totalDownloads,
|
||||
Version: latest.Version.Version,
|
||||
Versions: versions,
|
||||
RegistrationIndexURL: l.GetRegistrationIndexURL(latest.Package.Name),
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ func apiError(ctx *context.Context, status int, obj any) {
|
||||
})
|
||||
}
|
||||
|
||||
func xmlResponse(ctx *context.Context, status int, obj any) { //nolint:unparam
|
||||
func xmlResponse(ctx *context.Context, status int, obj any) { //nolint:unparam // status is always StatusOK
|
||||
ctx.Resp.Header().Set("Content-Type", "application/atom+xml; charset=utf-8")
|
||||
ctx.Resp.WriteHeader(status)
|
||||
if _, err := ctx.Resp.Write([]byte(xml.Header)); err != nil {
|
||||
|
||||
@@ -29,7 +29,7 @@ func CreateOrg(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user that will own the created organization
|
||||
// description: username of the user who will own the created organization
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: organization
|
||||
|
||||
@@ -22,7 +22,7 @@ func CreateRepo(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user. This user will own the created repository
|
||||
// description: username of the user who will own the created repository
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: repository
|
||||
|
||||
@@ -175,7 +175,7 @@ func EditUser(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user to edit
|
||||
// description: username of the user whose data is to be edited
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: body
|
||||
@@ -240,7 +240,7 @@ func EditUser(ctx *context.APIContext) {
|
||||
Description: optional.FromPtr(form.Description),
|
||||
IsActive: optional.FromPtr(form.Active),
|
||||
IsAdmin: user_service.UpdateOptionFieldFromPtr(form.Admin),
|
||||
Visibility: optional.FromNonDefault(api.VisibilityModes[form.Visibility]),
|
||||
Visibility: optional.FromMapLookup(api.VisibilityModes, form.Visibility),
|
||||
AllowGitHook: optional.FromPtr(form.AllowGitHook),
|
||||
AllowImportLocal: optional.FromPtr(form.AllowImportLocal),
|
||||
MaxRepoCreation: optional.FromPtr(form.MaxRepoCreation),
|
||||
@@ -272,7 +272,7 @@ func DeleteUser(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user to delete
|
||||
// description: username of the user to delete
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: purge
|
||||
@@ -328,7 +328,7 @@ func CreatePublicKey(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user
|
||||
// description: username of the user who is to receive a public key
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: key
|
||||
@@ -358,7 +358,7 @@ func DeleteUserPublicKey(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose public key is to be deleted
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: id
|
||||
@@ -405,7 +405,7 @@ func SearchUsers(ctx *context.APIContext) {
|
||||
// format: int64
|
||||
// - name: login_name
|
||||
// in: query
|
||||
// description: user's login name to search for
|
||||
// description: identifier of the user, provided by the external authenticator
|
||||
// type: string
|
||||
// - name: page
|
||||
// in: query
|
||||
@@ -456,7 +456,7 @@ func RenameUser(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: existing username of user
|
||||
// description: current username of the user
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: body
|
||||
|
||||
@@ -22,7 +22,7 @@ func ListUserBadges(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose badges are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -53,7 +53,7 @@ func AddUserBadges(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user to whom a badge is to be added
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: body
|
||||
@@ -87,7 +87,7 @@ func DeleteUserBadges(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose badge is to be deleted
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: body
|
||||
|
||||
@@ -145,7 +145,7 @@ func repoAssignment() func(ctx *context.APIContext) {
|
||||
)
|
||||
|
||||
// Check if the user is the same as the repository owner.
|
||||
if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) {
|
||||
if ctx.IsSigned && strings.EqualFold(ctx.Doer.LowerName, userName) {
|
||||
owner = ctx.Doer
|
||||
} else {
|
||||
owner, err = user_model.GetUserByName(ctx, userName)
|
||||
|
||||
@@ -42,7 +42,7 @@ func Markup(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck
|
||||
mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck // form.Wiki is deprecated
|
||||
common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, form.FilePath)
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func Markdown(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck
|
||||
mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck // form.Wiki is deprecated
|
||||
common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, "")
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ func CheckUserBlock(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: user to check
|
||||
// description: username of the user to check
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -71,7 +71,7 @@ func BlockUser(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: user to block
|
||||
// description: username of the user to block
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: note
|
||||
@@ -101,7 +101,7 @@ func UnblockUser(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: user to unblock
|
||||
// description: username of the user to unblock
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
|
||||
@@ -133,7 +133,7 @@ func IsMember(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user
|
||||
// description: username of the user to check for an organization membership
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -186,7 +186,7 @@ func IsPublicMember(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user
|
||||
// description: username of the user to check for a public organization membership
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -240,7 +240,7 @@ func PublicizeMember(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user
|
||||
// description: username of the user whose membership is to be publicized
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -282,7 +282,7 @@ func ConcealMember(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user
|
||||
// description: username of the user whose membership is to be concealed
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -324,7 +324,7 @@ func DeleteMember(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user
|
||||
// description: username of the user to remove from the organization
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
|
||||
@@ -82,7 +82,7 @@ func ListUserOrgs(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose organizations are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: page
|
||||
@@ -112,7 +112,7 @@ func GetUserOrgsPermissions(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose permissions are to be obtained
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: org
|
||||
@@ -391,7 +391,7 @@ func Edit(ctx *context.APIContext) {
|
||||
Description: optional.Some(form.Description),
|
||||
Website: optional.Some(form.Website),
|
||||
Location: optional.Some(form.Location),
|
||||
Visibility: optional.FromNonDefault(api.VisibilityModes[form.Visibility]),
|
||||
Visibility: optional.FromMapLookup(api.VisibilityModes, form.Visibility),
|
||||
RepoAdminChangeTeamAccess: optional.FromPtr(form.RepoAdminChangeTeamAccess),
|
||||
}
|
||||
if err := user_service.UpdateUser(ctx, ctx.Org.Organization.AsUser(), opts); err != nil {
|
||||
|
||||
@@ -426,7 +426,7 @@ func GetTeamMember(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the member to list
|
||||
// description: username of the user whose data is to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -467,7 +467,7 @@ func AddTeamMember(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user to add
|
||||
// description: username of the user to add to a team
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -509,7 +509,7 @@ func RemoveTeamMember(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of the user to remove
|
||||
// description: username of the user to remove from a team
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
|
||||
@@ -747,7 +747,7 @@ func (Action) ListWorkflowRuns(ctx *context.APIContext) {
|
||||
// type: integer
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/ArtifactsList"
|
||||
// "$ref": "#/responses/WorkflowRunsList"
|
||||
// "400":
|
||||
// "$ref": "#/responses/error"
|
||||
// "404":
|
||||
|
||||
@@ -93,7 +93,7 @@ func IsCollaborator(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: collaborator
|
||||
// in: path
|
||||
// description: username of the collaborator
|
||||
// description: username of the user to check for being a collaborator
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -145,7 +145,7 @@ func AddOrUpdateCollaborator(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: collaborator
|
||||
// in: path
|
||||
// description: username of the collaborator to add
|
||||
// description: username of the user to add or update as a collaborator
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: body
|
||||
@@ -264,7 +264,7 @@ func GetRepoPermissions(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: collaborator
|
||||
// in: path
|
||||
// description: username of the collaborator
|
||||
// description: username of the collaborator whose permissions are to be obtained
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -276,7 +276,7 @@ func GetRepoPermissions(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/forbidden"
|
||||
|
||||
collaboratorUsername := ctx.PathParam("collaborator")
|
||||
if !ctx.Doer.IsAdmin && ctx.Doer.LowerName != strings.ToLower(collaboratorUsername) && !ctx.IsUserRepoAdmin() {
|
||||
if !ctx.Doer.IsAdmin && !strings.EqualFold(ctx.Doer.LowerName, collaboratorUsername) && !ctx.IsUserRepoAdmin() {
|
||||
ctx.APIError(http.StatusForbidden, "Only admins can query all permissions, repo admins can query all repo permissions, collaborators can query only their own")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -812,7 +812,8 @@ func GetContentsExt(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: filepath
|
||||
// in: path
|
||||
// description: path of the dir, file, symlink or submodule in the repo
|
||||
// description: path of the dir, file, symlink or submodule in the repo. Swagger requires path parameter to be "required",
|
||||
// you can leave it empty or pass a single dot (".") to get the root directory.
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: ref
|
||||
@@ -823,7 +824,8 @@ func GetContentsExt(ctx *context.APIContext) {
|
||||
// - name: includes
|
||||
// in: query
|
||||
// description: By default this API's response only contains file's metadata. Use comma-separated "includes" options to retrieve more fields.
|
||||
// Option "file_content" will try to retrieve the file content, option "lfs_metadata" will try to retrieve LFS metadata.
|
||||
// Option "file_content" will try to retrieve the file content, "lfs_metadata" will try to retrieve LFS metadata,
|
||||
// "commit_metadata" will try to retrieve commit metadata, and "commit_message" will try to retrieve commit message.
|
||||
// type: string
|
||||
// required: false
|
||||
// responses:
|
||||
@@ -832,6 +834,9 @@ func GetContentsExt(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
if treePath := ctx.PathParam("*"); treePath == "." || treePath == "/" {
|
||||
ctx.SetPathParam("*", "") // workaround for swagger, it requires path parameter to be "required", but we need to list root directory
|
||||
}
|
||||
opts := files_service.GetContentsOrListOptions{TreePath: ctx.PathParam("*")}
|
||||
for includeOpt := range strings.SplitSeq(ctx.FormString("includes"), ",") {
|
||||
if includeOpt == "" {
|
||||
@@ -842,6 +847,10 @@ func GetContentsExt(ctx *context.APIContext) {
|
||||
opts.IncludeSingleFileContent = true
|
||||
case "lfs_metadata":
|
||||
opts.IncludeLfsMetadata = true
|
||||
case "commit_metadata":
|
||||
opts.IncludeCommitMetadata = true
|
||||
case "commit_message":
|
||||
opts.IncludeCommitMessage = true
|
||||
default:
|
||||
ctx.APIError(http.StatusBadRequest, fmt.Sprintf("unknown include option %q", includeOpt))
|
||||
return
|
||||
@@ -883,7 +892,11 @@ func GetContents(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/ContentsResponse"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
ret := getRepoContents(ctx, files_service.GetContentsOrListOptions{TreePath: ctx.PathParam("*"), IncludeSingleFileContent: true})
|
||||
ret := getRepoContents(ctx, files_service.GetContentsOrListOptions{
|
||||
TreePath: ctx.PathParam("*"),
|
||||
IncludeSingleFileContent: true,
|
||||
IncludeCommitMetadata: true,
|
||||
})
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ func AddIssueSubscription(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: user
|
||||
// in: path
|
||||
// description: user to subscribe
|
||||
// description: username of the user to subscribe the issue to
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -87,7 +87,7 @@ func DelIssueSubscription(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: user
|
||||
// in: path
|
||||
// description: user witch unsubscribe
|
||||
// description: username of the user to unsubscribe from an issue
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
|
||||
@@ -405,7 +405,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
|
||||
// required: true
|
||||
// - name: user
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose tracked times are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
|
||||
@@ -669,7 +669,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
|
||||
newRepoName = *opts.Name
|
||||
}
|
||||
// Check if repository name has been changed and not just a case change
|
||||
if repo.LowerName != strings.ToLower(newRepoName) {
|
||||
if !strings.EqualFold(repo.LowerName, newRepoName) {
|
||||
if err := repo_service.ChangeRepositoryName(ctx, ctx.Doer, repo, newRepoName); err != nil {
|
||||
switch {
|
||||
case repo_model.IsErrRepoAlreadyExist(err):
|
||||
|
||||
@@ -44,5 +44,5 @@ type swaggerResponseActionWorkflow struct {
|
||||
// swagger:response ActionWorkflowList
|
||||
type swaggerResponseActionWorkflowList struct {
|
||||
// in:body
|
||||
Body []api.ActionWorkflow `json:"body"`
|
||||
Body api.ActionWorkflowResponse `json:"body"`
|
||||
}
|
||||
@@ -30,7 +30,7 @@ func ListAccessTokens(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of to user whose access tokens are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: page
|
||||
@@ -83,7 +83,7 @@ func CreateAccessToken(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose token is to be created
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: body
|
||||
@@ -149,7 +149,7 @@ func DeleteAccessToken(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose token is to be deleted
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: token
|
||||
|
||||
@@ -37,7 +37,7 @@ func CheckUserBlock(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: user to check
|
||||
// description: username of the user to check
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -56,7 +56,7 @@ func BlockUser(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: user to block
|
||||
// description: username of the user to block
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: note
|
||||
@@ -81,7 +81,7 @@ func UnblockUser(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: user to unblock
|
||||
// description: username of the user to unblock
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
|
||||
@@ -67,7 +67,7 @@ func ListFollowers(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose followers are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: page
|
||||
@@ -131,7 +131,7 @@ func ListFollowing(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose followed users are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: page
|
||||
@@ -167,7 +167,7 @@ func CheckMyFollowing(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of followed user
|
||||
// description: username of the user to check for authenticated followers
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -187,12 +187,12 @@ func CheckFollowing(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of following user
|
||||
// description: username of the following user
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: target
|
||||
// in: path
|
||||
// description: username of followed user
|
||||
// description: username of the followed user
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -216,7 +216,7 @@ func Follow(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user to follow
|
||||
// description: username of the user to follow
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -246,7 +246,7 @@ func Unfollow(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user to unfollow
|
||||
// description: username of the user to unfollow
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
|
||||
@@ -53,7 +53,7 @@ func ListGPGKeys(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose GPG key list is to be obtained
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: page
|
||||
|
||||
@@ -136,7 +136,7 @@ func ListPublicKeys(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose public keys are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: fingerprint
|
||||
|
||||
@@ -62,7 +62,7 @@ func ListUserRepos(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose owned repos are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: page
|
||||
|
||||
@@ -50,7 +50,7 @@ func GetStarredRepos(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose starred repos are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: page
|
||||
|
||||
@@ -110,7 +110,7 @@ func GetInfo(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user to get
|
||||
// description: username of the user whose data is to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -151,7 +151,7 @@ func GetUserHeatmapData(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user to get
|
||||
// description: username of the user whose heatmap is to be obtained
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
@@ -177,7 +177,7 @@ func ListUserActivityFeeds(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// description: username of the user whose activity feeds are to be listed
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: only-performed-by
|
||||
|
||||
@@ -49,7 +49,7 @@ func GetWatchedRepos(ctx *context.APIContext) {
|
||||
// - name: username
|
||||
// type: string
|
||||
// in: path
|
||||
// description: username of the user
|
||||
// description: username of the user whose watched repos are to be listed
|
||||
// required: true
|
||||
// - name: page
|
||||
// in: query
|
||||
|
||||
Reference in new issue
Block a user