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),
|
||||
), 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