github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/versioning/pip.go (about) 1 package versioning 2 3 import ( 4 "fmt" 5 "os" 6 "regexp" 7 "strings" 8 9 "github.com/pkg/errors" 10 ) 11 12 const ( 13 // NameRegex is used to match the pip descriptor artifact name 14 NameRegex = "(?s)(.*)name=['\"](.*?)['\"](.*)" 15 // VersionRegex is used to match the pip descriptor artifact version 16 VersionRegex = "(?s)(.*)version=['\"](.*?)['\"](.*)" 17 ) 18 19 // Pip utility to interact with Python specific versioning 20 type Pip struct { 21 path string 22 readFile func(string) ([]byte, error) 23 writeFile func(string, []byte, os.FileMode) error 24 fileExists func(string) (bool, error) 25 buildDescriptorContent string 26 } 27 28 func (p *Pip) init() error { 29 if p.readFile == nil { 30 p.readFile = os.ReadFile 31 } 32 33 if p.writeFile == nil { 34 p.writeFile = os.WriteFile 35 } 36 37 if len(p.buildDescriptorContent) == 0 { 38 content, err := p.readFile(p.path) 39 if err != nil { 40 return errors.Wrapf(err, "failed to read file '%v'", p.path) 41 } 42 p.buildDescriptorContent = string(content) 43 } 44 return nil 45 } 46 47 // GetVersion returns the Pip descriptor version property 48 func (p *Pip) GetVersion() (string, error) { 49 buildDescriptorFilePath := p.path 50 var err error 51 if strings.Contains(p.path, "setup.py") { 52 buildDescriptorFilePath, err = searchDescriptor([]string{"version.txt", "VERSION"}, p.fileExists) 53 if err != nil { 54 initErr := p.init() 55 if initErr != nil { 56 return "", errors.Wrapf(initErr, "failed to read file '%v'", p.path) 57 } 58 if evaluateResult(p.buildDescriptorContent, VersionRegex) { 59 compile := regexp.MustCompile(VersionRegex) 60 values := compile.FindStringSubmatch(p.buildDescriptorContent) 61 return values[2], nil 62 } 63 return "", errors.Wrap(err, "failed to retrieve version") 64 } 65 } 66 artifact := &Versionfile{ 67 path: buildDescriptorFilePath, 68 versioningScheme: p.VersioningScheme(), 69 readFile: p.readFile, 70 } 71 return artifact.GetVersion() 72 } 73 74 // SetVersion sets the Pip descriptor version property 75 func (p *Pip) SetVersion(v string) error { 76 buildDescriptorFilePath := p.path 77 var err error 78 if strings.Contains(p.path, "setup.py") { 79 buildDescriptorFilePath, err = searchDescriptor([]string{"version.txt", "VERSION"}, p.fileExists) 80 if err != nil { 81 initErr := p.init() 82 if initErr != nil { 83 return errors.Wrapf(initErr, "failed to read file '%v'", p.path) 84 } 85 if evaluateResult(p.buildDescriptorContent, VersionRegex) { 86 compile := regexp.MustCompile(VersionRegex) 87 values := compile.FindStringSubmatch(p.buildDescriptorContent) 88 p.buildDescriptorContent = strings.ReplaceAll(p.buildDescriptorContent, fmt.Sprintf("version='%v'", values[2]), fmt.Sprintf("version='%v'", v)) 89 p.buildDescriptorContent = strings.ReplaceAll(p.buildDescriptorContent, fmt.Sprintf("version=\"%v\"", values[2]), fmt.Sprintf("version=\"%v\"", v)) 90 p.writeFile(p.path, []byte(p.buildDescriptorContent), 0600) 91 } else { 92 return errors.Wrap(err, "failed to retrieve version") 93 } 94 } 95 } 96 artifact := &Versionfile{ 97 path: buildDescriptorFilePath, 98 versioningScheme: p.VersioningScheme(), 99 writeFile: p.writeFile, 100 } 101 return artifact.SetVersion(v) 102 } 103 104 // VersioningScheme returns the relevant versioning scheme 105 func (p *Pip) VersioningScheme() string { 106 return "pep440" 107 } 108 109 // GetCoordinates returns the pip build descriptor coordinates 110 func (p *Pip) GetCoordinates() (Coordinates, error) { 111 result := Coordinates{} 112 err := p.init() 113 if err != nil { 114 return result, err 115 } 116 117 if evaluateResult(p.buildDescriptorContent, NameRegex) { 118 compile := regexp.MustCompile(NameRegex) 119 values := compile.FindStringSubmatch(p.buildDescriptorContent) 120 result.ArtifactID = values[2] 121 } else { 122 result.ArtifactID = "" 123 } 124 125 result.Version, err = p.GetVersion() 126 if err != nil { 127 return result, errors.Wrap(err, "failed to retrieve coordinates") 128 } 129 130 return result, nil 131 } 132 133 func evaluateResult(value, regex string) bool { 134 if len(value) > 0 { 135 match, _ := regexp.MatchString(regex, value) 136 return match 137 } 138 return true 139 }