github.com/wolfi-dev/wolfictl@v0.16.11/pkg/distro/detectv2.go (about)

     1  package distro
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"slices"
     7  
     8  	"github.com/go-git/go-git/v5"
     9  )
    10  
    11  // DetectV2 tries to detect which distro the user wants to operate on by seeing
    12  // if the current working directory is the distro's packages repo. No
    13  // advisory-related repositories are detected.
    14  func DetectV2() (Distro, error) {
    15  	cwd, err := os.Getwd()
    16  	if err != nil {
    17  		return Distro{}, err
    18  	}
    19  
    20  	d, err := DetectFromDirV2(cwd)
    21  	if err != nil {
    22  		return Distro{}, err
    23  	}
    24  
    25  	return d, nil
    26  }
    27  
    28  // DetectFromDirV2 tries to identify a Distro by inspecting the given directory
    29  // to see if it is a repository for a distro's packages.
    30  func DetectFromDirV2(dir string) (Distro, error) {
    31  	distro, err := identifyDistroFromLocalPackagesRepoDir(dir)
    32  	if err != nil {
    33  		return Distro{}, err
    34  	}
    35  
    36  	forkPoint, err := findRepoForkPoint(distro.Local.PackagesRepo.Dir, distro.Local.PackagesRepo.UpstreamName)
    37  	if err != nil {
    38  		return Distro{}, err
    39  	}
    40  	distro.Local.PackagesRepo.ForkPoint = forkPoint
    41  
    42  	return distro, nil
    43  }
    44  
    45  var ErrNotPackagesRepo = fmt.Errorf("directory is not a distro (packages) repository")
    46  
    47  func identifyDistroFromLocalPackagesRepoDir(dir string) (Distro, error) {
    48  	repo, err := git.PlainOpen(dir)
    49  	if err != nil {
    50  		return Distro{}, fmt.Errorf("unable to identify distro: couldn't open git repo: %v: %w", err, ErrNotDistroRepo)
    51  	}
    52  
    53  	config, err := repo.Config()
    54  	if err != nil {
    55  		return Distro{}, err
    56  	}
    57  
    58  	for _, remoteConfig := range config.Remotes {
    59  		urls := remoteConfig.URLs
    60  		if len(urls) == 0 {
    61  			continue
    62  		}
    63  
    64  		url := urls[0]
    65  
    66  		for _, d := range []AbsoluteProperties{wolfiDistro, chainguardDistro, extraPackagesDistro} {
    67  			// Fill in the local properties that we can cheaply here. We'll fill in the rest
    68  			// later, outside of this function call.
    69  
    70  			if slices.Contains(d.DistroRemoteURLs(), url) {
    71  				return Distro{
    72  					Absolute: d,
    73  					Local: LocalProperties{
    74  						PackagesRepo: LocalRepo{
    75  							Dir:          dir,
    76  							UpstreamName: remoteConfig.Name,
    77  							ForkPoint:    "", // This is slightly expensive to compute, so we do it later and only once per repo.
    78  						},
    79  					},
    80  				}, nil
    81  			}
    82  		}
    83  	}
    84  
    85  	return Distro{}, ErrNotPackagesRepo
    86  }