github.com/abemedia/appcast@v0.4.0/integrations/yum/build.go (about)

     1  package yum
     2  
     3  import (
     4  	"context"
     5  	"io/fs"
     6  	"log"
     7  	"os"
     8  	"path"
     9  	"strings"
    10  	"unsafe"
    11  
    12  	"github.com/abemedia/appcast/pkg/crypto/pgp"
    13  	"github.com/abemedia/appcast/source"
    14  	"github.com/abemedia/appcast/target"
    15  )
    16  
    17  type Config struct {
    18  	Source     *source.Source
    19  	Version    string
    20  	Prerelease bool
    21  	Target     target.Target
    22  	PGPKey     *pgp.PrivateKey
    23  }
    24  
    25  //nolint:funlen,gocognit
    26  func Build(ctx context.Context, c *Config) error {
    27  	repo, err := openRepo(ctx, c.Target)
    28  	if err != nil {
    29  		return err
    30  	}
    31  	defer os.RemoveAll(repo.dir)
    32  
    33  	version := c.Version
    34  	if v := getVersionConstraint(repo.primary.Package); v != "" {
    35  		version += "," + v
    36  	}
    37  
    38  	releases, err := c.Source.ListReleases(ctx, &source.ListOptions{
    39  		Version:    version,
    40  		Prerelease: c.Prerelease,
    41  	})
    42  	if err == source.ErrNoReleaseFound {
    43  		return nil
    44  	}
    45  	if err != nil {
    46  		return err
    47  	}
    48  
    49  	var hasReleases bool
    50  	for _, release := range releases {
    51  		for _, asset := range release.Assets {
    52  			if path.Ext(asset.Name) != ".rpm" {
    53  				continue
    54  			}
    55  			b, err := c.Source.DownloadAsset(ctx, release.Version, asset.Name)
    56  			if err != nil {
    57  				return err
    58  			}
    59  			if err = repo.Add(b); err != nil {
    60  				return err
    61  			}
    62  			hasReleases = true
    63  		}
    64  	}
    65  	if !hasReleases {
    66  		return nil
    67  	}
    68  
    69  	if err = repo.Write(c.PGPKey); err != nil {
    70  		return err
    71  	}
    72  
    73  	files := os.DirFS(repo.dir)
    74  	err = fs.WalkDir(files, ".", func(path string, d fs.DirEntry, err error) error {
    75  		if err != nil || d.IsDir() {
    76  			return err
    77  		}
    78  		b, err := fs.ReadFile(files, path)
    79  		if err != nil {
    80  			return err
    81  		}
    82  		w, err := c.Target.NewWriter(ctx, path)
    83  		if err != nil {
    84  			return err
    85  		}
    86  		if _, err = w.Write(b); err != nil {
    87  			return err
    88  		}
    89  		return w.Close()
    90  	})
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	for _, path := range repo.files {
    96  		if err = c.Target.Remove(ctx, path); err != nil {
    97  			log.Printf("Failed to delete %s: %s", path, err)
    98  		}
    99  	}
   100  
   101  	return nil
   102  }
   103  
   104  func getVersionConstraint(pkgs []Package) string {
   105  	if len(pkgs) == 0 {
   106  		return ""
   107  	}
   108  
   109  	v := make([]byte, 0, len(pkgs)*len("!=0.0.0,"))
   110  	for _, p := range pkgs {
   111  		v = append(v, '!', '=')
   112  		v = append(v, strings.Replace(p.Version.Ver, "~", "-", 1)...)
   113  		v = append(v, ',')
   114  	}
   115  
   116  	return unsafe.String(unsafe.SliceData(v), len(v)-1)
   117  }