internal/rosa: general helper abstraction
All checks were successful
Test / Create distribution (push) Successful in 1m30s
Test / Sandbox (push) Successful in 3m33s
Test / Hakurei (push) Successful in 4m41s
Test / ShareFS (push) Successful in 4m46s
Test / Hpkg (push) Successful in 5m21s
Test / Sandbox (race detector) (push) Successful in 5m40s
Test / Hakurei (race detector) (push) Successful in 7m9s
Test / Flake checks (push) Successful in 1m43s
All checks were successful
Test / Create distribution (push) Successful in 1m30s
Test / Sandbox (push) Successful in 3m33s
Test / Hakurei (push) Successful in 4m41s
Test / ShareFS (push) Successful in 4m46s
Test / Hpkg (push) Successful in 5m21s
Test / Sandbox (race detector) (push) Successful in 5m40s
Test / Hakurei (race detector) (push) Successful in 7m9s
Test / Flake checks (push) Successful in 1m43s
This greatly increases code sharing and makes implementations far simpler. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -392,3 +392,154 @@ cat /usr/src/` + name + `-patches/* | \
|
|||||||
t.Load(Patch),
|
t.Load(Patch),
|
||||||
), nil, nil, script, paths...)
|
), nil, nil, script, paths...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helperInPlace is a special directory value for omitting the cd statement.
|
||||||
|
const helperInPlace = "\x00"
|
||||||
|
|
||||||
|
// Helper is a build system helper for [Toolchain.NewPackage].
|
||||||
|
type Helper interface {
|
||||||
|
// name returns the value passed to the name argument of [Toolchain.New].
|
||||||
|
name(name, version string) string
|
||||||
|
// extra returns helper-specific dependencies.
|
||||||
|
extra(flag int) []PArtifact
|
||||||
|
|
||||||
|
// wantsChmod returns whether the source directory should be made writable.
|
||||||
|
wantsChmod() bool
|
||||||
|
// wantsWrite returns whether the source directory should be mounted writable.
|
||||||
|
wantsWrite() bool
|
||||||
|
// scriptEarly returns the helper-specific segment of cure script that goes
|
||||||
|
// before the cd statement.
|
||||||
|
scriptEarly() string
|
||||||
|
// createDir returns whether the path returned by wantsDir should be created.
|
||||||
|
createDir() bool
|
||||||
|
// wantsDir returns the directory to enter before script.
|
||||||
|
//
|
||||||
|
// The zero value implies source directory if [PackageAttr.ScriptEarly] is
|
||||||
|
// also empty. The special value helperInPlace omits the cd statement.
|
||||||
|
wantsDir() string
|
||||||
|
// script returns the helper-specific segment of cure script.
|
||||||
|
script(name string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// sourceTarXZ denotes a source tarball to be decompressed using [XZ].
|
||||||
|
sourceTarXZ = 1 + iota
|
||||||
|
)
|
||||||
|
|
||||||
|
// PackageAttr holds build-system-agnostic attributes.
|
||||||
|
type PackageAttr struct {
|
||||||
|
// Mount the source tree writable.
|
||||||
|
Writable bool
|
||||||
|
// Do not pass through [Toolchain.NewPatchedSource].
|
||||||
|
Chmod bool
|
||||||
|
// Unconditionally enter source directory early.
|
||||||
|
EnterSource bool
|
||||||
|
|
||||||
|
// Additional environment variables.
|
||||||
|
Env []string
|
||||||
|
// Runs before script emitted by [Helper]. Enters source if non-empty.
|
||||||
|
ScriptEarly string
|
||||||
|
|
||||||
|
// Passed to [Toolchain.NewPatchedSource].
|
||||||
|
Patches [][2]string
|
||||||
|
// Kind of source artifact.
|
||||||
|
SourceKind int
|
||||||
|
|
||||||
|
// Dependencies not provided by stage0.
|
||||||
|
NonStage0 []pkg.Artifact
|
||||||
|
|
||||||
|
// Passed through to [Toolchain.New], before source.
|
||||||
|
Paths []pkg.ExecPath
|
||||||
|
// Passed through to [Toolchain.New].
|
||||||
|
Flag int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPackage constructs a [pkg.Artifact] via a build system helper.
|
||||||
|
func (t Toolchain) NewPackage(
|
||||||
|
name, version string,
|
||||||
|
source pkg.Artifact,
|
||||||
|
attr *PackageAttr,
|
||||||
|
helper Helper,
|
||||||
|
extra ...PArtifact,
|
||||||
|
) pkg.Artifact {
|
||||||
|
if attr == nil {
|
||||||
|
attr = new(PackageAttr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "" || version == "" {
|
||||||
|
panic("name must be non-empty")
|
||||||
|
}
|
||||||
|
if source == nil {
|
||||||
|
panic("source must be non-nil")
|
||||||
|
}
|
||||||
|
wantsChmod, wantsWrite := helper.wantsChmod(), helper.wantsWrite()
|
||||||
|
if attr.SourceKind > 0 &&
|
||||||
|
(attr.Writable || attr.Chmod || wantsChmod || wantsWrite || len(attr.Patches) > 0) {
|
||||||
|
panic("source processing requested on a non-unpacked kind")
|
||||||
|
}
|
||||||
|
|
||||||
|
dc := len(attr.NonStage0)
|
||||||
|
if !t.isStage0() {
|
||||||
|
dc += 1<<3 + len(extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
extraRes := make([]pkg.Artifact, 0, dc)
|
||||||
|
extraRes = append(extraRes, attr.NonStage0...)
|
||||||
|
if !t.isStage0() {
|
||||||
|
for _, p := range helper.extra(attr.Flag) {
|
||||||
|
extraRes = append(extraRes, t.Load(p))
|
||||||
|
}
|
||||||
|
for _, p := range extra {
|
||||||
|
extraRes = append(extraRes, t.Load(p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var scriptEarly string
|
||||||
|
|
||||||
|
var sourceSuffix string
|
||||||
|
switch attr.SourceKind {
|
||||||
|
case sourceTarXZ:
|
||||||
|
sourceSuffix = ".tar.xz"
|
||||||
|
scriptEarly += `
|
||||||
|
tar -C /usr/src/ -xf '/usr/src/` + name + `.tar.xz'
|
||||||
|
mv '/usr/src/` + name + `-` + version + `' '/usr/src/` + name + `'
|
||||||
|
`
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
dir := helper.wantsDir()
|
||||||
|
helperScriptEarly := helper.scriptEarly()
|
||||||
|
if attr.EnterSource ||
|
||||||
|
dir == "" ||
|
||||||
|
attr.ScriptEarly != "" ||
|
||||||
|
helperScriptEarly != "" {
|
||||||
|
scriptEarly += `
|
||||||
|
cd '/usr/src/` + name + `/'
|
||||||
|
`
|
||||||
|
}
|
||||||
|
scriptEarly += attr.ScriptEarly + helperScriptEarly
|
||||||
|
if dir != "" && dir != helperInPlace {
|
||||||
|
if helper.createDir() {
|
||||||
|
scriptEarly += "\nmkdir -p " + dir
|
||||||
|
}
|
||||||
|
scriptEarly += "\ncd " + dir + "\n"
|
||||||
|
} else if !attr.EnterSource && attr.ScriptEarly == "" {
|
||||||
|
panic("cannot remain in root")
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.New(
|
||||||
|
helper.name(name, version),
|
||||||
|
attr.Flag,
|
||||||
|
extraRes,
|
||||||
|
nil,
|
||||||
|
attr.Env,
|
||||||
|
scriptEarly+helper.script(name),
|
||||||
|
slices.Concat(attr.Paths, []pkg.ExecPath{
|
||||||
|
pkg.Path(AbsUsrSrc.Append(
|
||||||
|
name+sourceSuffix,
|
||||||
|
), attr.Writable || wantsWrite, t.NewPatchedSource(
|
||||||
|
name, version, source, !attr.Chmod && !wantsChmod, attr.Patches...,
|
||||||
|
)),
|
||||||
|
})...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user