Something went wrong. Try again.
Maps Linux distribution source packages to their upstream repositories, and through them to each other
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293package arch
import ( "archive/tar" "bufio" "bytes" "compress/gzip" "context" "fmt" "io" "strings" "time"
"tangled.org/odd.computer/isomorph/internal/fetch")
// pacman's repository databases (core.db, extra.db, multilib.db) list every binary package of a// repository with its pkgbase, version and url in one small download, so they enumerate the// distribution without touching GitLab. They carry no source URLs; those come from .SRCINFO.
// DefaultMirror serves the repository databases.const DefaultMirror = "https://geo.mirror.pkgbuild.com"
// SyncRepos are the repositories of the released distribution.var SyncRepos = []string{"core", "extra", "multilib"}
// SyncPackage is one binary package entry of a repository database.type SyncPackage struct { Repo string Name string Base string Version string URL string}
// SyncDB downloads and parses the x86_64 database of repo.func (r *Resolver) SyncDB(ctx context.Context, repo string) ([]SyncPackage, error) { mirror := r.Mirror if mirror == "" { mirror = DefaultMirror } b, err := r.c.Get(ctx, mirror+"/"+repo+"/os/x86_64/"+repo+".db", fetch.WithTTL(6*time.Hour)) if err != nil { return nil, fmt.Errorf("arch: %s.db: %w", repo, err) } return ParseSyncDB(b, repo)}
// ParseSyncDB reads a gzip-compressed repository database.func ParseSyncDB(b []byte, repo string) ([]SyncPackage, error) { zr, err := gzip.NewReader(bytes.NewReader(b)) if err != nil { return nil, fmt.Errorf("arch: %s.db: %w", repo, err) } tr := tar.NewReader(zr) var out []SyncPackage for { h, err := tr.Next() if err == io.EOF { break } if err != nil { return nil, fmt.Errorf("arch: %s.db: %w", repo, err) } if h.Typeflag != tar.TypeReg || !strings.HasSuffix(h.Name, "/desc") { continue } fields := map[string]string{} sc := bufio.NewScanner(io.LimitReader(tr, 1<<20)) sc.Buffer(make([]byte, 64<<10), 1<<20) key := "" for sc.Scan() { line := sc.Text() switch { case strings.HasPrefix(line, "%") && strings.HasSuffix(line, "%"): key = strings.Trim(line, "%") case line == "": key = "" case key != "" && fields[key] == "": fields[key] = line } } p := SyncPackage{Repo: repo, Name: fields["NAME"], Base: fields["BASE"], Version: fields["VERSION"], URL: fields["URL"]} if p.Base == "" { p.Base = p.Name } if p.Name != "" { out = append(out, p) } } return out, nil}