All checks were successful
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 2m35s
Test / Hakurei (push) Successful in 3m53s
Test / ShareFS (push) Successful in 3m51s
Test / Sandbox (race detector) (push) Successful in 4m58s
Test / Hakurei (race detector) (push) Successful in 5m56s
Test / Flake checks (push) Successful in 1m30s
These have confusing names. Signed-off-by: Ophestra <cat@gensokyo.uk>
255 lines
5.1 KiB
Go
255 lines
5.1 KiB
Go
package rosa
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"errors"
|
||
"net/http"
|
||
"strconv"
|
||
"sync"
|
||
|
||
"hakurei.app/internal/pkg"
|
||
)
|
||
|
||
// PArtifact is a lazily-initialised [pkg.Artifact] preset.
|
||
type PArtifact int
|
||
|
||
const (
|
||
LLVMCompilerRT PArtifact = iota
|
||
LLVMRuntimes
|
||
LLVMClang
|
||
|
||
// ImageInitramfs is the Rosa OS initramfs archive.
|
||
ImageInitramfs
|
||
|
||
// Kernel is the generic Rosa OS Linux kernel.
|
||
Kernel
|
||
// KernelHeaders is an installation of kernel headers for [Kernel].
|
||
KernelHeaders
|
||
// KernelSource is a writable kernel source tree installed to [AbsUsrSrc].
|
||
KernelSource
|
||
|
||
ACL
|
||
ArgpStandalone
|
||
Attr
|
||
Autoconf
|
||
Automake
|
||
BC
|
||
Bash
|
||
Binutils
|
||
Bison
|
||
Bzip2
|
||
CMake
|
||
Coreutils
|
||
Curl
|
||
DTC
|
||
Diffutils
|
||
Elfutils
|
||
Fakeroot
|
||
Findutils
|
||
Flex
|
||
Fuse
|
||
GMP
|
||
GLib
|
||
Gawk
|
||
GenInitCPIO
|
||
Gettext
|
||
Git
|
||
Go
|
||
Gperf
|
||
Grep
|
||
Gzip
|
||
Hakurei
|
||
HakureiDist
|
||
Kmod
|
||
LibXau
|
||
Libcap
|
||
Libexpat
|
||
Libiconv
|
||
Libpsl
|
||
Libffi
|
||
Libgd
|
||
Libtool
|
||
Libseccomp
|
||
Libucontext
|
||
Libxml2
|
||
Libxslt
|
||
M4
|
||
MPC
|
||
MPFR
|
||
Make
|
||
Meson
|
||
Mksh
|
||
MuslFts
|
||
MuslObstack
|
||
NSS
|
||
NSSCACert
|
||
Ncurses
|
||
Ninja
|
||
OpenSSL
|
||
PCRE2
|
||
Patch
|
||
Perl
|
||
PerlLocaleGettext
|
||
PerlMIMECharset
|
||
PerlModuleBuild
|
||
PerlPodParser
|
||
PerlSGMLS
|
||
PerlTermReadKey
|
||
PerlTextCharWidth
|
||
PerlTextWrapI18N
|
||
PerlUnicodeGCString
|
||
PerlYAMLTiny
|
||
PkgConfig
|
||
Procps
|
||
Python
|
||
PythonIniConfig
|
||
PythonPackaging
|
||
PythonPluggy
|
||
PythonPyTest
|
||
PythonPygments
|
||
QEMU
|
||
Rsync
|
||
Sed
|
||
Setuptools
|
||
SquashfsTools
|
||
TamaGo
|
||
Tar
|
||
Texinfo
|
||
Toybox
|
||
toyboxEarly
|
||
Unzip
|
||
UtilLinux
|
||
Wayland
|
||
WaylandProtocols
|
||
XCB
|
||
XCBProto
|
||
Xproto
|
||
XZ
|
||
Zlib
|
||
Zstd
|
||
|
||
// PresetUnexportedStart is the first unexported preset.
|
||
PresetUnexportedStart
|
||
|
||
buildcatrust = iota - 1
|
||
utilMacros
|
||
|
||
// Musl is a standalone libc that does not depend on the toolchain.
|
||
Musl
|
||
|
||
// gcc is a hacked-to-pieces GCC toolchain meant for use in intermediate
|
||
// stages only. This preset and its direct output must never be exposed.
|
||
gcc
|
||
|
||
// Stage0 is a tarball containing all compile-time dependencies of artifacts
|
||
// part of the [Std] toolchain.
|
||
Stage0
|
||
|
||
// PresetEnd is the total number of presets and does not denote a preset.
|
||
PresetEnd
|
||
)
|
||
|
||
// Metadata is stage-agnostic information of a [PArtifact] not directly
|
||
// representable in the resulting [pkg.Artifact].
|
||
type Metadata struct {
|
||
f func(t Toolchain) (a pkg.Artifact, version string)
|
||
|
||
// Unique package name.
|
||
Name string `json:"name"`
|
||
// Short user-facing description.
|
||
Description string `json:"description"`
|
||
// Project home page.
|
||
Website string `json:"website,omitempty"`
|
||
|
||
// Project identifier on [Anitya].
|
||
//
|
||
// [Anitya]: https://release-monitoring.org/
|
||
ID int `json:"-"`
|
||
}
|
||
|
||
// Unversioned denotes an unversioned [PArtifact].
|
||
const Unversioned = "\x00"
|
||
|
||
// UnpopulatedIDError is returned by [Metadata.GetLatest] for an instance of
|
||
// [Metadata] where ID is not populated.
|
||
type UnpopulatedIDError struct{}
|
||
|
||
func (UnpopulatedIDError) Unwrap() error { return errors.ErrUnsupported }
|
||
func (UnpopulatedIDError) Error() string { return "Anitya ID is not populated" }
|
||
|
||
// Versions are package versions returned by Anitya.
|
||
type Versions struct {
|
||
// The latest version for the project, as determined by the version sorting algorithm.
|
||
Latest string `json:"latest_version"`
|
||
// List of all versions that aren’t flagged as pre-release.
|
||
Stable []string `json:"stable_versions"`
|
||
// List of all versions stored, sorted from newest to oldest.
|
||
All []string `json:"versions"`
|
||
}
|
||
|
||
// GetVersions returns versions fetched from Anitya.
|
||
func (meta *Metadata) GetVersions(ctx context.Context) (*Versions, error) {
|
||
if meta.ID == 0 {
|
||
return nil, UnpopulatedIDError{}
|
||
}
|
||
|
||
var resp *http.Response
|
||
if req, err := http.NewRequestWithContext(
|
||
ctx,
|
||
http.MethodGet,
|
||
"https://release-monitoring.org/api/v2/versions/?project_id="+
|
||
strconv.Itoa(meta.ID),
|
||
nil,
|
||
); err != nil {
|
||
return nil, err
|
||
} else if resp, err = http.DefaultClient.Do(req); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
var v Versions
|
||
err := json.NewDecoder(resp.Body).Decode(&v)
|
||
return &v, errors.Join(err, resp.Body.Close())
|
||
}
|
||
|
||
var (
|
||
// artifactsM is an array of [PArtifact] metadata.
|
||
artifactsM [PresetEnd]Metadata
|
||
|
||
// artifacts stores the result of Metadata.f.
|
||
artifacts [_toolchainEnd][len(artifactsM)]pkg.Artifact
|
||
// versions stores the version of [PArtifact].
|
||
versions [_toolchainEnd][len(artifactsM)]string
|
||
// artifactsOnce is for lazy initialisation of artifacts.
|
||
artifactsOnce [_toolchainEnd][len(artifactsM)]sync.Once
|
||
)
|
||
|
||
// GetMetadata returns [Metadata] of a [PArtifact].
|
||
func GetMetadata(p PArtifact) *Metadata { return &artifactsM[p] }
|
||
|
||
// Load returns the resulting [pkg.Artifact] of [PArtifact].
|
||
func (t Toolchain) Load(p PArtifact) pkg.Artifact {
|
||
artifactsOnce[t][p].Do(func() {
|
||
artifacts[t][p], versions[t][p] = artifactsM[p].f(t)
|
||
})
|
||
return artifacts[t][p]
|
||
}
|
||
|
||
// Version returns the version string of [PArtifact].
|
||
func (t Toolchain) Version(p PArtifact) string {
|
||
artifactsOnce[t][p].Do(func() {
|
||
artifacts[t][p], versions[t][p] = artifactsM[p].f(t)
|
||
})
|
||
return versions[t][p]
|
||
}
|
||
|
||
// ResolveName returns a [PArtifact] by name.
|
||
func ResolveName(name string) (p PArtifact, ok bool) {
|
||
for i := range PresetUnexportedStart {
|
||
if name == artifactsM[i].Name {
|
||
return i, true
|
||
}
|
||
}
|
||
return 0, false
|
||
}
|