github.com/SAP/jenkins-library@v1.362.0/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  }