code.gitea.io/gitea@v1.19.3/modules/packages/conan/reference.go (about) 1 // Copyright 2022 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package conan 5 6 import ( 7 "fmt" 8 "regexp" 9 "strings" 10 11 "code.gitea.io/gitea/modules/log" 12 "code.gitea.io/gitea/modules/util" 13 ) 14 15 const ( 16 // taken from https://github.com/conan-io/conan/blob/develop/conans/model/ref.py 17 minChars = 2 18 maxChars = 51 19 20 // DefaultRevision if no revision is specified 21 DefaultRevision = "0" 22 ) 23 24 var ( 25 namePattern = regexp.MustCompile(fmt.Sprintf(`^[a-zA-Z0-9_][a-zA-Z0-9_\+\.-]{%d,%d}$`, minChars-1, maxChars-1)) 26 revisionPattern = regexp.MustCompile(fmt.Sprintf(`^[a-zA-Z0-9]{1,%d}$`, maxChars)) 27 28 ErrValidation = util.NewInvalidArgumentErrorf("could not validate one or more reference fields") 29 ) 30 31 // RecipeReference represents a recipe <Name>/<Version>@<User>/<Channel>#<Revision> 32 type RecipeReference struct { 33 Name string 34 Version string 35 User string 36 Channel string 37 Revision string 38 } 39 40 func NewRecipeReference(name, version, user, channel, revision string) (*RecipeReference, error) { 41 log.Trace("Conan Recipe: %s/%s(@%s/%s(#%s))", name, version, user, channel, revision) 42 43 if user == "_" { 44 user = "" 45 } 46 if channel == "_" { 47 channel = "" 48 } 49 50 if (user != "" && channel == "") || (user == "" && channel != "") { 51 return nil, ErrValidation 52 } 53 54 if !namePattern.MatchString(name) { 55 return nil, ErrValidation 56 } 57 58 v := strings.TrimSpace(version) 59 if v == "" { 60 return nil, ErrValidation 61 } 62 if user != "" && !namePattern.MatchString(user) { 63 return nil, ErrValidation 64 } 65 if channel != "" && !namePattern.MatchString(channel) { 66 return nil, ErrValidation 67 } 68 if revision != "" && !revisionPattern.MatchString(revision) { 69 return nil, ErrValidation 70 } 71 72 return &RecipeReference{name, v, user, channel, revision}, nil 73 } 74 75 func (r *RecipeReference) RevisionOrDefault() string { 76 if r.Revision == "" { 77 return DefaultRevision 78 } 79 return r.Revision 80 } 81 82 func (r *RecipeReference) String() string { 83 rev := "" 84 if r.Revision != "" { 85 rev = "#" + r.Revision 86 } 87 if r.User == "" || r.Channel == "" { 88 return fmt.Sprintf("%s/%s%s", r.Name, r.Version, rev) 89 } 90 return fmt.Sprintf("%s/%s@%s/%s%s", r.Name, r.Version, r.User, r.Channel, rev) 91 } 92 93 func (r *RecipeReference) LinkName() string { 94 user := r.User 95 if user == "" { 96 user = "_" 97 } 98 channel := r.Channel 99 if channel == "" { 100 channel = "_" 101 } 102 return fmt.Sprintf("%s/%s/%s/%s/%s", r.Name, r.Version, user, channel, r.RevisionOrDefault()) 103 } 104 105 func (r *RecipeReference) WithRevision(revision string) *RecipeReference { 106 return &RecipeReference{r.Name, r.Version, r.User, r.Channel, revision} 107 } 108 109 // AsKey builds the additional key for the package file 110 func (r *RecipeReference) AsKey() string { 111 return fmt.Sprintf("%s|%s|%s", r.User, r.Channel, r.RevisionOrDefault()) 112 } 113 114 // PackageReference represents a package of a recipe <Name>/<Version>@<User>/<Channel>#<Revision> <Reference>#<Revision> 115 type PackageReference struct { 116 Recipe *RecipeReference 117 Reference string 118 Revision string 119 } 120 121 func NewPackageReference(recipe *RecipeReference, reference, revision string) (*PackageReference, error) { 122 log.Trace("Conan Package: %v %s(#%s)", recipe, reference, revision) 123 124 if recipe == nil { 125 return nil, ErrValidation 126 } 127 if reference == "" || !revisionPattern.MatchString(reference) { 128 return nil, ErrValidation 129 } 130 if revision != "" && !revisionPattern.MatchString(revision) { 131 return nil, ErrValidation 132 } 133 134 return &PackageReference{recipe, reference, revision}, nil 135 } 136 137 func (r *PackageReference) RevisionOrDefault() string { 138 if r.Revision == "" { 139 return DefaultRevision 140 } 141 return r.Revision 142 } 143 144 func (r *PackageReference) LinkName() string { 145 return fmt.Sprintf("%s/%s", r.Reference, r.RevisionOrDefault()) 146 } 147 148 func (r *PackageReference) WithRevision(revision string) *PackageReference { 149 return &PackageReference{r.Recipe, r.Reference, revision} 150 } 151 152 // AsKey builds the additional key for the package file 153 func (r *PackageReference) AsKey() string { 154 return fmt.Sprintf("%s|%s|%s|%s|%s", r.Recipe.User, r.Recipe.Channel, r.Recipe.RevisionOrDefault(), r.Reference, r.RevisionOrDefault()) 155 }