Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
4.5 KiB
164 lines
4.5 KiB
// Copyright 2022 The Gitea Authors. All rights reserved. |
|
// Use of this source code is governed by a MIT-style |
|
// license that can be found in the LICENSE file. |
|
|
|
package conan |
|
|
|
import ( |
|
"net/http" |
|
"strings" |
|
|
|
conan_model "code.gitea.io/gitea/models/packages/conan" |
|
user_model "code.gitea.io/gitea/models/user" |
|
"code.gitea.io/gitea/modules/context" |
|
"code.gitea.io/gitea/modules/json" |
|
conan_module "code.gitea.io/gitea/modules/packages/conan" |
|
) |
|
|
|
// SearchResult contains the found recipe names |
|
type SearchResult struct { |
|
Results []string `json:"results"` |
|
} |
|
|
|
// SearchRecipes searches all recipes matching the query |
|
func SearchRecipes(ctx *context.Context) { |
|
q := ctx.FormTrim("q") |
|
|
|
opts := parseQuery(ctx.Package.Owner, q) |
|
|
|
results, err := conan_model.SearchRecipes(ctx, opts) |
|
if err != nil { |
|
apiError(ctx, http.StatusInternalServerError, err) |
|
return |
|
} |
|
|
|
jsonResponse(ctx, http.StatusOK, &SearchResult{ |
|
Results: results, |
|
}) |
|
} |
|
|
|
// parseQuery creates search options for the given query |
|
func parseQuery(owner *user_model.User, query string) *conan_model.RecipeSearchOptions { |
|
opts := &conan_model.RecipeSearchOptions{ |
|
OwnerID: owner.ID, |
|
} |
|
|
|
if query != "" { |
|
parts := strings.Split(strings.ReplaceAll(query, "@", "/"), "/") |
|
|
|
opts.Name = parts[0] |
|
if len(parts) > 1 && parts[1] != "*" { |
|
opts.Version = parts[1] |
|
} |
|
if len(parts) > 2 && parts[2] != "*" { |
|
opts.User = parts[2] |
|
} |
|
if len(parts) > 3 && parts[3] != "*" { |
|
opts.Channel = parts[3] |
|
} |
|
} |
|
|
|
return opts |
|
} |
|
|
|
// SearchPackagesV1 searches all packages of a recipe (Conan v1 endpoint) |
|
func SearchPackagesV1(ctx *context.Context) { |
|
searchPackages(ctx, true) |
|
} |
|
|
|
// SearchPackagesV2 searches all packages of a recipe (Conan v2 endpoint) |
|
func SearchPackagesV2(ctx *context.Context) { |
|
searchPackages(ctx, false) |
|
} |
|
|
|
func searchPackages(ctx *context.Context, searchAllRevisions bool) { |
|
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) |
|
|
|
if !searchAllRevisions && rref.Revision == "" { |
|
lastRevision, err := conan_model.GetLastRecipeRevision(ctx, ctx.Package.Owner.ID, rref) |
|
if err != nil { |
|
if err == conan_model.ErrRecipeReferenceNotExist { |
|
apiError(ctx, http.StatusNotFound, err) |
|
} else { |
|
apiError(ctx, http.StatusInternalServerError, err) |
|
} |
|
return |
|
} |
|
rref = rref.WithRevision(lastRevision.Value) |
|
} else { |
|
has, err := conan_model.RecipeExists(ctx, ctx.Package.Owner.ID, rref) |
|
if err != nil { |
|
if err == conan_model.ErrRecipeReferenceNotExist { |
|
apiError(ctx, http.StatusNotFound, err) |
|
} else { |
|
apiError(ctx, http.StatusInternalServerError, err) |
|
} |
|
return |
|
} |
|
if !has { |
|
apiError(ctx, http.StatusNotFound, nil) |
|
return |
|
} |
|
} |
|
|
|
recipeRevisions := []*conan_model.PropertyValue{{Value: rref.Revision}} |
|
if searchAllRevisions { |
|
var err error |
|
recipeRevisions, err = conan_model.GetRecipeRevisions(ctx, ctx.Package.Owner.ID, rref) |
|
if err != nil { |
|
apiError(ctx, http.StatusInternalServerError, err) |
|
return |
|
} |
|
} |
|
|
|
result := make(map[string]*conan_module.Conaninfo) |
|
|
|
for _, recipeRevision := range recipeRevisions { |
|
currentRef := rref |
|
if recipeRevision.Value != "" { |
|
currentRef = rref.WithRevision(recipeRevision.Value) |
|
} |
|
packageReferences, err := conan_model.GetPackageReferences(ctx, ctx.Package.Owner.ID, currentRef) |
|
if err != nil { |
|
if err == conan_model.ErrRecipeReferenceNotExist { |
|
apiError(ctx, http.StatusNotFound, err) |
|
} else { |
|
apiError(ctx, http.StatusInternalServerError, err) |
|
} |
|
return |
|
} |
|
for _, packageReference := range packageReferences { |
|
if _, ok := result[packageReference.Value]; ok { |
|
continue |
|
} |
|
pref, _ := conan_module.NewPackageReference(currentRef, packageReference.Value, "") |
|
lastPackageRevision, err := conan_model.GetLastPackageRevision(ctx, ctx.Package.Owner.ID, pref) |
|
if err != nil { |
|
if err == conan_model.ErrPackageReferenceNotExist { |
|
apiError(ctx, http.StatusNotFound, err) |
|
} else { |
|
apiError(ctx, http.StatusInternalServerError, err) |
|
} |
|
return |
|
} |
|
pref = pref.WithRevision(lastPackageRevision.Value) |
|
infoRaw, err := conan_model.GetPackageInfo(ctx, ctx.Package.Owner.ID, pref) |
|
if err != nil { |
|
if err == conan_model.ErrPackageReferenceNotExist { |
|
apiError(ctx, http.StatusNotFound, err) |
|
} else { |
|
apiError(ctx, http.StatusInternalServerError, err) |
|
} |
|
return |
|
} |
|
var info *conan_module.Conaninfo |
|
if err := json.Unmarshal([]byte(infoRaw), &info); err != nil { |
|
apiError(ctx, http.StatusInternalServerError, err) |
|
return |
|
} |
|
result[pref.Reference] = info |
|
} |
|
} |
|
|
|
jsonResponse(ctx, http.StatusOK, result) |
|
}
|
|
|