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