164 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
// Copyright 2022 The Gitea Authors. All rights reserved.
 | 
						|
// SPDX-License-Identifier: MIT
 | 
						|
 | 
						|
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)
 | 
						|
}
 |