code.gitea.io/gitea@v1.21.7/models/packages/conan/references.go (about) 1 // Copyright 2022 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package conan 5 6 import ( 7 "context" 8 "strconv" 9 "strings" 10 11 "code.gitea.io/gitea/models/db" 12 "code.gitea.io/gitea/models/packages" 13 conan_module "code.gitea.io/gitea/modules/packages/conan" 14 "code.gitea.io/gitea/modules/timeutil" 15 "code.gitea.io/gitea/modules/util" 16 17 "xorm.io/builder" 18 ) 19 20 var ( 21 ErrRecipeReferenceNotExist = util.NewNotExistErrorf("recipe reference does not exist") 22 ErrPackageReferenceNotExist = util.NewNotExistErrorf("package reference does not exist") 23 ) 24 25 // RecipeExists checks if a recipe exists 26 func RecipeExists(ctx context.Context, ownerID int64, ref *conan_module.RecipeReference) (bool, error) { 27 revisions, err := GetRecipeRevisions(ctx, ownerID, ref) 28 if err != nil { 29 return false, err 30 } 31 32 return len(revisions) != 0, nil 33 } 34 35 type PropertyValue struct { 36 Value string 37 CreatedUnix timeutil.TimeStamp 38 } 39 40 func findPropertyValues(ctx context.Context, propertyName string, ownerID int64, name, version string, propertyFilter map[string]string) ([]*PropertyValue, error) { 41 var propsCond builder.Cond = builder.Eq{ 42 "package_property.ref_type": packages.PropertyTypeFile, 43 } 44 propsCond = propsCond.And(builder.Expr("package_property.ref_id = package_file.id")) 45 46 propsCondBlock := builder.NewCond() 47 for name, value := range propertyFilter { 48 propsCondBlock = propsCondBlock.Or(builder.Eq{ 49 "package_property.name": name, 50 "package_property.value": value, 51 }) 52 } 53 propsCond = propsCond.And(propsCondBlock) 54 55 var cond builder.Cond = builder.Eq{ 56 "package.type": packages.TypeConan, 57 "package.owner_id": ownerID, 58 "package.lower_name": strings.ToLower(name), 59 "package_version.lower_version": strings.ToLower(version), 60 "package_version.is_internal": false, 61 strconv.Itoa(len(propertyFilter)): builder.Select("COUNT(*)").Where(propsCond).From("package_property"), 62 } 63 64 in2 := builder. 65 Select("package_file.id"). 66 From("package_file"). 67 InnerJoin("package_version", "package_version.id = package_file.version_id"). 68 InnerJoin("package", "package.id = package_version.package_id"). 69 Where(cond) 70 71 query := builder. 72 Select("package_property.value, MAX(package_file.created_unix) AS created_unix"). 73 From("package_property"). 74 InnerJoin("package_file", "package_file.id = package_property.ref_id"). 75 Where(builder.Eq{"package_property.name": propertyName}.And(builder.In("package_property.ref_id", in2))). 76 GroupBy("package_property.value"). 77 OrderBy("created_unix DESC") 78 79 var values []*PropertyValue 80 return values, db.GetEngine(ctx).SQL(query).Find(&values) 81 } 82 83 // GetRecipeRevisions gets all revisions of a recipe 84 func GetRecipeRevisions(ctx context.Context, ownerID int64, ref *conan_module.RecipeReference) ([]*PropertyValue, error) { 85 values, err := findPropertyValues( 86 ctx, 87 conan_module.PropertyRecipeRevision, 88 ownerID, 89 ref.Name, 90 ref.Version, 91 map[string]string{ 92 conan_module.PropertyRecipeUser: ref.User, 93 conan_module.PropertyRecipeChannel: ref.Channel, 94 }, 95 ) 96 if err != nil { 97 return nil, err 98 } 99 100 return values, nil 101 } 102 103 // GetLastRecipeRevision gets the latest recipe revision 104 func GetLastRecipeRevision(ctx context.Context, ownerID int64, ref *conan_module.RecipeReference) (*PropertyValue, error) { 105 revisions, err := GetRecipeRevisions(ctx, ownerID, ref) 106 if err != nil { 107 return nil, err 108 } 109 110 if len(revisions) == 0 { 111 return nil, ErrRecipeReferenceNotExist 112 } 113 return revisions[0], nil 114 } 115 116 // GetPackageReferences gets all package references of a recipe 117 func GetPackageReferences(ctx context.Context, ownerID int64, ref *conan_module.RecipeReference) ([]*PropertyValue, error) { 118 values, err := findPropertyValues( 119 ctx, 120 conan_module.PropertyPackageReference, 121 ownerID, 122 ref.Name, 123 ref.Version, 124 map[string]string{ 125 conan_module.PropertyRecipeUser: ref.User, 126 conan_module.PropertyRecipeChannel: ref.Channel, 127 conan_module.PropertyRecipeRevision: ref.Revision, 128 }, 129 ) 130 if err != nil { 131 return nil, err 132 } 133 134 return values, nil 135 } 136 137 // GetPackageRevisions gets all revision of a package 138 func GetPackageRevisions(ctx context.Context, ownerID int64, ref *conan_module.PackageReference) ([]*PropertyValue, error) { 139 values, err := findPropertyValues( 140 ctx, 141 conan_module.PropertyPackageRevision, 142 ownerID, 143 ref.Recipe.Name, 144 ref.Recipe.Version, 145 map[string]string{ 146 conan_module.PropertyRecipeUser: ref.Recipe.User, 147 conan_module.PropertyRecipeChannel: ref.Recipe.Channel, 148 conan_module.PropertyRecipeRevision: ref.Recipe.Revision, 149 conan_module.PropertyPackageReference: ref.Reference, 150 }, 151 ) 152 if err != nil { 153 return nil, err 154 } 155 156 return values, nil 157 } 158 159 // GetLastPackageRevision gets the latest package revision 160 func GetLastPackageRevision(ctx context.Context, ownerID int64, ref *conan_module.PackageReference) (*PropertyValue, error) { 161 revisions, err := GetPackageRevisions(ctx, ownerID, ref) 162 if err != nil { 163 return nil, err 164 } 165 166 if len(revisions) == 0 { 167 return nil, ErrPackageReferenceNotExist 168 } 169 return revisions[0], nil 170 }