2023-05-11 12:03:18 +00:00
|
|
|
package snapshot
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2023-05-11 13:20:36 +00:00
|
|
|
"fmt"
|
|
|
|
"net/url"
|
2023-05-11 12:03:18 +00:00
|
|
|
"regexp"
|
2023-05-11 13:20:36 +00:00
|
|
|
"strings"
|
2023-05-11 16:26:16 +00:00
|
|
|
|
|
|
|
"github.com/rs/zerolog/log"
|
2023-05-11 12:03:18 +00:00
|
|
|
|
|
|
|
"code.dumpstack.io/tools/out-of-tree/distro/debian/snapshot/mr"
|
|
|
|
)
|
|
|
|
|
2023-05-11 16:52:47 +00:00
|
|
|
const timeLayout = "20060102T150405Z"
|
|
|
|
|
2023-05-11 13:20:36 +00:00
|
|
|
const URL = "https://snapshot.debian.org"
|
|
|
|
|
2023-05-11 12:03:18 +00:00
|
|
|
func SourcePackageVersions(name string) (versions []string, err error) {
|
|
|
|
pkg, err := mr.GetPackage(name)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range pkg.Result {
|
|
|
|
versions = append(versions, res.Version)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
type Package struct {
|
|
|
|
Name string
|
|
|
|
Source string
|
|
|
|
Version string
|
|
|
|
Arch string
|
2023-05-11 13:20:36 +00:00
|
|
|
|
|
|
|
Deb struct {
|
2023-05-11 12:03:18 +00:00
|
|
|
Name string
|
|
|
|
Hash string
|
2023-05-11 13:20:36 +00:00
|
|
|
URL string
|
2023-05-11 12:03:18 +00:00
|
|
|
}
|
2023-05-11 13:20:36 +00:00
|
|
|
|
2023-05-11 12:03:18 +00:00
|
|
|
Repo struct {
|
2023-05-15 08:21:53 +00:00
|
|
|
Snapshot string
|
2023-05-11 16:52:47 +00:00
|
|
|
|
|
|
|
Archive string
|
2023-05-11 13:20:36 +00:00
|
|
|
|
|
|
|
Component string
|
2023-05-11 12:03:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-14 11:38:41 +00:00
|
|
|
func NewPackage(name, srcname, version string, archs []string) (
|
|
|
|
p Package, err error) {
|
|
|
|
|
2023-05-11 12:03:18 +00:00
|
|
|
p.Name = name
|
|
|
|
p.Source = srcname
|
|
|
|
p.Version = version
|
|
|
|
|
2023-05-14 11:38:41 +00:00
|
|
|
p.Arch, p.Deb.Hash, err = p.getHash(archs)
|
2023-05-11 12:03:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-11 13:20:36 +00:00
|
|
|
info, err := mr.GetInfo(p.Deb.Hash)
|
2023-05-11 12:03:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-11 13:20:36 +00:00
|
|
|
p.Deb.Name = info.Result[0].Name
|
2023-05-11 12:03:18 +00:00
|
|
|
|
|
|
|
p.Repo.Archive = info.Result[0].ArchiveName
|
|
|
|
p.Repo.Snapshot = info.Result[0].FirstSeen
|
|
|
|
|
2023-05-11 13:20:36 +00:00
|
|
|
p.Deb.URL, err = url.JoinPath(URL, "archive", p.Repo.Archive,
|
|
|
|
p.Repo.Snapshot, info.Result[0].Path, p.Deb.Name)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
split := strings.Split(info.Result[0].Path, "/")
|
|
|
|
if split[1] != "pool" || len(split) < 3 {
|
|
|
|
err = fmt.Errorf("incorrect path: %s", info.Result[0].Path)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
p.Repo.Component = split[2]
|
|
|
|
|
2023-05-11 12:03:18 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-14 11:38:41 +00:00
|
|
|
func (p Package) getHash(archs []string) (arch, hash string, err error) {
|
2023-05-11 12:03:18 +00:00
|
|
|
binfiles, err := mr.GetBinfiles(p.Name, p.Version)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range binfiles.Result {
|
2023-05-14 11:38:41 +00:00
|
|
|
for _, allowedArch := range archs {
|
|
|
|
if res.Architecture == allowedArch {
|
|
|
|
arch = res.Architecture
|
|
|
|
hash = res.Hash
|
|
|
|
return
|
|
|
|
}
|
2023-05-11 12:03:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-11 16:26:16 +00:00
|
|
|
err = errors.New("hash not found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-11 21:20:00 +00:00
|
|
|
func contains(pkgs []Package, pkg Package) bool {
|
|
|
|
for _, p := range pkgs {
|
|
|
|
if p.Name == pkg.Name {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-05-11 22:17:31 +00:00
|
|
|
func filtered(s string, filter []string) bool {
|
|
|
|
for _, f := range filter {
|
|
|
|
if strings.Contains(s, f) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-05-14 11:38:41 +00:00
|
|
|
func Packages(srcname, version, regex string, archs, filter []string) (
|
|
|
|
pkgs []Package, err error) {
|
2023-05-11 22:17:31 +00:00
|
|
|
|
2023-05-11 12:03:18 +00:00
|
|
|
binpkgs, err := mr.GetBinpackages(srcname, version)
|
2023-05-11 22:06:31 +00:00
|
|
|
if err == mr.ErrNotFound {
|
|
|
|
err = nil
|
|
|
|
return
|
|
|
|
}
|
2023-05-11 12:03:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
r := regexp.MustCompile(regex)
|
|
|
|
|
|
|
|
for _, res := range binpkgs.Result {
|
2023-05-14 19:48:15 +00:00
|
|
|
if res.Version != version {
|
|
|
|
continue
|
|
|
|
}
|
2023-05-11 22:17:31 +00:00
|
|
|
if !r.MatchString(res.Name) || filtered(res.Name, filter) {
|
2023-05-11 12:03:18 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-05-11 20:24:54 +00:00
|
|
|
log.Trace().Msgf("matched %v", res.Name)
|
|
|
|
|
2023-05-11 12:03:18 +00:00
|
|
|
var pkg Package
|
2023-05-14 11:38:41 +00:00
|
|
|
pkg, err = NewPackage(res.Name, srcname, version, archs)
|
2023-05-11 12:03:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-11 21:20:00 +00:00
|
|
|
if contains(pkgs, pkg) {
|
|
|
|
log.Trace().Msgf("%v already in slice O_o", pkg.Name)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-05-11 20:24:54 +00:00
|
|
|
log.Trace().Msgf("append %v", pkg.Name)
|
2023-05-11 12:03:18 +00:00
|
|
|
pkgs = append(pkgs, pkg)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|