Compare commits
113 Commits
v0.4.1
...
6f50811dc9
| Author | SHA1 | Date | |
|---|---|---|---|
|
6f50811dc9
|
|||
|
6b87bac401
|
|||
|
a967aa3b6e
|
|||
|
38bc2c7508
|
|||
|
30eb0d6a61
|
|||
|
c2ff9c9fa5
|
|||
|
d38d306147
|
|||
|
c32c06b2e8
|
|||
|
61199f734c
|
|||
|
87cf0d4e6b
|
|||
|
cf0dffa0f5
|
|||
|
686d7ec63a
|
|||
|
4c653b1151
|
|||
|
0b0a63d151
|
|||
|
6231cfe2aa
|
|||
|
712e80890b
|
|||
|
3fe7d48014
|
|||
|
16f9d39427
|
|||
|
c1cd5ba07b
|
|||
|
7b0cd2e472
|
|||
|
e580307528
|
|||
|
ee1dffb676
|
|||
|
f095fcf181
|
|||
|
ca8a130130
|
|||
|
0ad6b00e41
|
|||
|
ad0f1cf36b
|
|||
|
b12d924fa2
|
|||
|
c31d8ae41a
|
|||
|
6dbbf15c0e
|
|||
|
be7de68a42
|
|||
|
a759cf3666
|
|||
|
8c2dd3e984
|
|||
|
67038d5af4
|
|||
|
53d8d12e7f
|
|||
|
7997d79e56
|
|||
|
f2f1726190
|
|||
|
f63203cb0a
|
|||
|
19555c7670
|
|||
|
a3beab8959
|
|||
|
2ea786d6a9
|
|||
|
747d4ec4b0
|
|||
|
b76e6f6519
|
|||
|
840d8f68bf
|
|||
|
4bede7ecdd
|
|||
|
487a03b5a3
|
|||
|
8f3c22896a
|
|||
|
a167c1aba5
|
|||
|
a6008ef68b
|
|||
|
5228b27362
|
|||
|
f00d3a07ad
|
|||
|
f9538bc21b
|
|||
|
6ae5efec56
|
|||
|
14f4c59c8c
|
|||
|
688d43417b
|
|||
|
9f8fafa39b
|
|||
|
6643cfbeee
|
|||
|
dcde38f2e9
|
|||
|
deebbf6b1a
|
|||
|
0c557798bc
|
|||
|
327e6ed5a2
|
|||
|
76c7a423a9
|
|||
|
6e113b8836
|
|||
|
ce9f4b5f71
|
|||
|
8f727273ef
|
|||
|
d0a63b942e
|
|||
|
7f2126df32
|
|||
|
0cf0e18e35
|
|||
|
ee5c0dd135
|
|||
|
92c48d82e2
|
|||
|
c79a4fe7f8
|
|||
|
0aeb2bccfb
|
|||
|
50e079b99f
|
|||
|
fb2cb5005a
|
|||
|
6e73c28a92
|
|||
|
2c08aa3674
|
|||
|
1af73ae7b4
|
|||
|
c9aa5e04b1
|
|||
|
70a38bd3b0
|
|||
|
533b15da89
|
|||
|
a890e1d0e5
|
|||
|
e3520835bb
|
|||
|
0e56847754
|
|||
|
145d03b366
|
|||
|
2886228d40
|
|||
|
e1e499b79e
|
|||
|
65b7dd8b37
|
|||
|
8d72b9e5bd
|
|||
|
8a3c3d145a
|
|||
|
575ef307ad
|
|||
|
d4144fcf7f
|
|||
|
bad66facbc
|
|||
|
4aba014eac
|
|||
|
779ba994ce
|
|||
|
917be2de93
|
|||
|
9aad98d409
|
|||
|
b0d06b67dc
|
|||
|
089100f29d
|
|||
|
dfd26abf6c
|
|||
|
617ee21647
|
|||
|
15cdb37ec2
|
|||
|
1f0bdc7aca
|
|||
|
e3ffe85670
|
|||
|
f4403ba5cd
|
|||
|
5a26895a22
|
|||
|
09d9f766a9
|
|||
|
6558169666
|
|||
|
cccf970c57
|
|||
|
57ffb21690
|
|||
|
9c560b455a
|
|||
|
4c7c0fbfc6
|
|||
|
18b3b7904e
|
|||
|
fefefdf734
|
|||
|
b84bb09a80
|
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
# go generate
|
# go generate
|
||||||
/cmd/hakurei/LICENSE
|
/cmd/hakurei/LICENSE
|
||||||
/cmd/mbf/internal/pkgserver/ui/static
|
/cmd/mbf/internal/pkgserver/ui/static
|
||||||
/internal/pkg/testdata/testtool
|
/internal/pkg/internal/testtool/testtool
|
||||||
/internal/rosa/hakurei_current.tar.gz
|
/internal/rosa/hakurei_current.tar.gz
|
||||||
|
|
||||||
# cmd/dist default destination
|
# cmd/dist default destination
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/sh -e
|
||||||
|
|
||||||
TOOLCHAIN_VERSION="$(go version)"
|
HAKUREI_DIST_MAKE='' exec "$(dirname -- "$0")/cmd/dist/dist.sh"
|
||||||
cd "$(dirname -- "$0")/"
|
|
||||||
echo "Building cmd/dist using ${TOOLCHAIN_VERSION}."
|
|
||||||
FLAGS=''
|
|
||||||
if test -n "$VERBOSE"; then
|
|
||||||
FLAGS="$FLAGS -v"
|
|
||||||
fi
|
|
||||||
go run $FLAGS --tags=dist ./cmd/dist
|
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
TOOLCHAIN_VERSION="$(go version)"
|
||||||
|
cd "$(dirname -- "$0")/../.."
|
||||||
|
echo "Building cmd/dist using ${TOOLCHAIN_VERSION}."
|
||||||
|
FLAGS=''
|
||||||
|
if test -n "$VERBOSE"; then
|
||||||
|
FLAGS="$FLAGS -v"
|
||||||
|
fi
|
||||||
|
go run $FLAGS --tags=dist ./cmd/dist
|
||||||
Vendored
+10
-7
@@ -46,6 +46,7 @@ func main() {
|
|||||||
log.SetPrefix("")
|
log.SetPrefix("")
|
||||||
|
|
||||||
verbose := os.Getenv("VERBOSE") != ""
|
verbose := os.Getenv("VERBOSE") != ""
|
||||||
|
runTests := os.Getenv("HAKUREI_DIST_MAKE") == ""
|
||||||
version := getenv("HAKUREI_VERSION", "untagged")
|
version := getenv("HAKUREI_VERSION", "untagged")
|
||||||
prefix := getenv("PREFIX", "/usr")
|
prefix := getenv("PREFIX", "/usr")
|
||||||
destdir := getenv("DESTDIR", "dist")
|
destdir := getenv("DESTDIR", "dist")
|
||||||
@@ -101,13 +102,15 @@ func main() {
|
|||||||
)
|
)
|
||||||
log.Println()
|
log.Println()
|
||||||
|
|
||||||
log.Println("##### Testing Hakurei.")
|
if runTests {
|
||||||
mustRun(
|
log.Println("##### Testing Hakurei.")
|
||||||
ctx, "go", "test",
|
mustRun(
|
||||||
"-ldflags=-buildid= -linkmode external -extldflags=-static",
|
ctx, "go", "test",
|
||||||
"./...",
|
"-ldflags=-buildid= -linkmode external -extldflags=-static",
|
||||||
)
|
"./...",
|
||||||
log.Println()
|
)
|
||||||
|
log.Println()
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("##### Creating distribution.")
|
log.Println("##### Creating distribution.")
|
||||||
const suffix = ".tar.gz"
|
const suffix = ".tar.gz"
|
||||||
|
|||||||
+46
-2
@@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/check"
|
"hakurei.app/check"
|
||||||
|
"hakurei.app/container"
|
||||||
"hakurei.app/internal/pkg"
|
"hakurei.app/internal/pkg"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
@@ -19,8 +20,15 @@ type cache struct {
|
|||||||
// Should generally not be used directly.
|
// Should generally not be used directly.
|
||||||
c *pkg.Cache
|
c *pkg.Cache
|
||||||
|
|
||||||
cures, jobs int
|
cures, jobs int
|
||||||
hostAbstract, idle bool
|
// Primarily to work around missing landlock LSM.
|
||||||
|
hostAbstract bool
|
||||||
|
// Set SCHED_IDLE.
|
||||||
|
idle bool
|
||||||
|
// Unset [pkg.CSuppressInit].
|
||||||
|
verboseInit bool
|
||||||
|
// Loaded artifact of [rosa.QEMU].
|
||||||
|
qemu pkg.Artifact
|
||||||
|
|
||||||
base string
|
base string
|
||||||
}
|
}
|
||||||
@@ -45,6 +53,9 @@ func (cache *cache) open() (err error) {
|
|||||||
if cache.hostAbstract {
|
if cache.hostAbstract {
|
||||||
flags |= pkg.CHostAbstract
|
flags |= pkg.CHostAbstract
|
||||||
}
|
}
|
||||||
|
if !cache.verboseInit {
|
||||||
|
flags |= pkg.CSuppressInit
|
||||||
|
}
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
defer close(done)
|
defer close(done)
|
||||||
@@ -70,6 +81,39 @@ func (cache *cache) open() (err error) {
|
|||||||
cache.jobs,
|
cache.jobs,
|
||||||
base,
|
base,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
done <- struct{}{}
|
||||||
|
|
||||||
|
if cache.qemu != nil {
|
||||||
|
var pathname *check.Absolute
|
||||||
|
pathname, _, err = cache.c.Cure(cache.qemu)
|
||||||
|
if err != nil {
|
||||||
|
cache.c.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg.RegisterArch("riscv64", container.BinfmtEntry{
|
||||||
|
Offset: 0,
|
||||||
|
Magic: "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00",
|
||||||
|
Mask: "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff",
|
||||||
|
Interpreter: pathname.Append(
|
||||||
|
"system/bin",
|
||||||
|
"qemu-riscv64",
|
||||||
|
),
|
||||||
|
})
|
||||||
|
pkg.RegisterArch("arm64", container.BinfmtEntry{
|
||||||
|
Offset: 0,
|
||||||
|
Magic: "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00",
|
||||||
|
Mask: "\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff",
|
||||||
|
Interpreter: pathname.Append(
|
||||||
|
"system/bin",
|
||||||
|
"qemu-aarch64",
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-8
@@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unique"
|
||||||
|
|
||||||
"hakurei.app/internal/pkg"
|
"hakurei.app/internal/pkg"
|
||||||
"hakurei.app/internal/rosa"
|
"hakurei.app/internal/rosa"
|
||||||
@@ -35,17 +36,20 @@ func commandInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t := rosa.Native().Std()
|
||||||
for i, name := range args {
|
for i, name := range args {
|
||||||
if p, ok := rosa.ResolveName(name); !ok {
|
handle := rosa.ArtifactH(unique.Make(name))
|
||||||
|
if meta := rosa.Native().Get(handle); meta == nil {
|
||||||
return fmt.Errorf("unknown artifact %q", name)
|
return fmt.Errorf("unknown artifact %q", name)
|
||||||
} else {
|
} else {
|
||||||
var suffix string
|
var suffix string
|
||||||
if version := rosa.Std.Version(p); version != rosa.Unversioned {
|
|
||||||
|
a, version := t.MustLoad(handle)
|
||||||
|
if version != rosa.Unversioned {
|
||||||
suffix += "-" + version
|
suffix += "-" + version
|
||||||
}
|
}
|
||||||
mustPrintln("name : " + name + suffix)
|
mustPrintln("name : " + name + suffix)
|
||||||
|
|
||||||
meta := rosa.GetMetadata(p)
|
|
||||||
mustPrintln("description : " + meta.Description)
|
mustPrintln("description : " + meta.Description)
|
||||||
if meta.Website != "" {
|
if meta.Website != "" {
|
||||||
mustPrintln("website : " +
|
mustPrintln("website : " +
|
||||||
@@ -54,9 +58,9 @@ func commandInfo(
|
|||||||
if len(meta.Dependencies) > 0 {
|
if len(meta.Dependencies) > 0 {
|
||||||
mustPrint("depends on :")
|
mustPrint("depends on :")
|
||||||
for _, d := range meta.Dependencies {
|
for _, d := range meta.Dependencies {
|
||||||
s := rosa.GetMetadata(d).Name
|
s := rosa.Native().MustGet(d).Name
|
||||||
if version := rosa.Std.Version(d); version != rosa.Unversioned {
|
if _, _version := t.Load(d); _version != rosa.Unversioned {
|
||||||
s += "-" + version
|
s += "-" + _version
|
||||||
}
|
}
|
||||||
mustPrint(" " + s)
|
mustPrint(" " + s)
|
||||||
}
|
}
|
||||||
@@ -68,7 +72,7 @@ func commandInfo(
|
|||||||
if r == nil {
|
if r == nil {
|
||||||
var f io.ReadSeekCloser
|
var f io.ReadSeekCloser
|
||||||
err = cm.Do(func(cache *pkg.Cache) (err error) {
|
err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||||
f, err = cache.OpenStatus(rosa.Std.Load(p))
|
f, err = cache.OpenStatus(a)
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -87,7 +91,7 @@ func commandInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
} else if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||||
status, n := r.ArtifactOf(cache.Ident(rosa.Std.Load(p)))
|
status, n := r.ArtifactOf(cache.Ident(a))
|
||||||
if status == nil {
|
if status == nil {
|
||||||
mustPrintln(
|
mustPrintln(
|
||||||
statusPrefix + "not in report",
|
statusPrefix + "not in report",
|
||||||
|
|||||||
+22
-13
@@ -10,6 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
"unique"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"hakurei.app/internal/pkg"
|
"hakurei.app/internal/pkg"
|
||||||
@@ -20,6 +21,14 @@ import (
|
|||||||
func TestInfo(t *testing.T) {
|
func TestInfo(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
_t := rosa.Native().Std()
|
||||||
|
_, qemuVersion := _t.Load(rosa.QEMU)
|
||||||
|
_, glibVersion := _t.Load(rosa.GLib)
|
||||||
|
zlib, zlibVersion := _t.Load(rosa.Zlib)
|
||||||
|
_, zstdVersion := _t.Load(rosa.Zstd)
|
||||||
|
_, hakureiVersion := _t.Load(rosa.Hakurei)
|
||||||
|
_, hakureiDistVersion := _t.Load(rosa.HakureiDist)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
args []string
|
args []string
|
||||||
@@ -29,24 +38,24 @@ func TestInfo(t *testing.T) {
|
|||||||
wantErr any
|
wantErr any
|
||||||
}{
|
}{
|
||||||
{"qemu", []string{"qemu"}, nil, "", `
|
{"qemu", []string{"qemu"}, nil, "", `
|
||||||
name : qemu-` + rosa.Std.Version(rosa.QEMU) + `
|
name : qemu-` + qemuVersion + `
|
||||||
description : a generic and open source machine emulator and virtualizer
|
description : a generic and open source machine emulator and virtualizer
|
||||||
website : https://www.qemu.org
|
website : https://www.qemu.org
|
||||||
depends on : glib-` + rosa.Std.Version(rosa.GLib) + ` zstd-` + rosa.Std.Version(rosa.Zstd) + `
|
depends on : glib-` + glibVersion + ` zstd-` + zstdVersion + `
|
||||||
`, nil},
|
`, nil},
|
||||||
|
|
||||||
{"multi", []string{"hakurei", "hakurei-dist"}, nil, "", `
|
{"multi", []string{"hakurei", "hakurei-dist"}, nil, "", `
|
||||||
name : hakurei-` + rosa.Std.Version(rosa.Hakurei) + `
|
name : hakurei-` + hakureiVersion + `
|
||||||
description : low-level userspace tooling for Rosa OS
|
description : low-level userspace tooling for Rosa OS
|
||||||
website : https://hakurei.app
|
website : https://hakurei.app
|
||||||
|
|
||||||
name : hakurei-dist-` + rosa.Std.Version(rosa.HakureiDist) + `
|
name : hakurei-dist-` + hakureiDistVersion + `
|
||||||
description : low-level userspace tooling for Rosa OS (distribution tarball)
|
description : low-level userspace tooling for Rosa OS (distribution tarball)
|
||||||
website : https://hakurei.app
|
website : https://hakurei.app
|
||||||
`, nil},
|
`, nil},
|
||||||
|
|
||||||
{"nonexistent", []string{"zlib", "\x00"}, nil, "", `
|
{"nonexistent", []string{"zlib", "\x00"}, nil, "", `
|
||||||
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
|
name : zlib-` + zlibVersion + `
|
||||||
description : lossless data-compression library
|
description : lossless data-compression library
|
||||||
website : https://zlib.net
|
website : https://zlib.net
|
||||||
|
|
||||||
@@ -56,12 +65,12 @@ website : https://zlib.net
|
|||||||
"zstd": "internal/pkg (amd64) on satori\n",
|
"zstd": "internal/pkg (amd64) on satori\n",
|
||||||
"hakurei": "internal/pkg (amd64) on satori\n\n",
|
"hakurei": "internal/pkg (amd64) on satori\n\n",
|
||||||
}, "", `
|
}, "", `
|
||||||
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
|
name : zlib-` + zlibVersion + `
|
||||||
description : lossless data-compression library
|
description : lossless data-compression library
|
||||||
website : https://zlib.net
|
website : https://zlib.net
|
||||||
status : not yet cured
|
status : not yet cured
|
||||||
|
|
||||||
name : zstd-` + rosa.Std.Version(rosa.Zstd) + `
|
name : zstd-` + zstdVersion + `
|
||||||
description : a fast compression algorithm
|
description : a fast compression algorithm
|
||||||
website : https://facebook.github.io/zstd
|
website : https://facebook.github.io/zstd
|
||||||
status : internal/pkg (amd64) on satori
|
status : internal/pkg (amd64) on satori
|
||||||
@@ -70,19 +79,19 @@ status : internal/pkg (amd64) on satori
|
|||||||
{"status cache perm", []string{"zlib"}, map[string]string{
|
{"status cache perm", []string{"zlib"}, map[string]string{
|
||||||
"zlib": "\x00",
|
"zlib": "\x00",
|
||||||
}, "", `
|
}, "", `
|
||||||
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
|
name : zlib-` + zlibVersion + `
|
||||||
description : lossless data-compression library
|
description : lossless data-compression library
|
||||||
website : https://zlib.net
|
website : https://zlib.net
|
||||||
`, func(cm *cache) error {
|
`, func(cm *cache) error {
|
||||||
return &os.PathError{
|
return &os.PathError{
|
||||||
Op: "open",
|
Op: "open",
|
||||||
Path: filepath.Join(cm.base, "status", pkg.Encode(cm.c.Ident(rosa.Std.Load(rosa.Zlib)).Value())),
|
Path: filepath.Join(cm.base, "status", pkg.Encode(cm.c.Ident(zlib).Value())),
|
||||||
Err: syscall.EACCES,
|
Err: syscall.EACCES,
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
|
|
||||||
{"status report", []string{"zlib"}, nil, strings.Repeat("\x00", len(pkg.Checksum{})+8), `
|
{"status report", []string{"zlib"}, nil, strings.Repeat("\x00", len(pkg.Checksum{})+8), `
|
||||||
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
|
name : zlib-` + zlibVersion + `
|
||||||
description : lossless data-compression library
|
description : lossless data-compression library
|
||||||
website : https://zlib.net
|
website : https://zlib.net
|
||||||
status : not in report
|
status : not in report
|
||||||
@@ -131,8 +140,8 @@ status : not in report
|
|||||||
|
|
||||||
if tc.status != nil {
|
if tc.status != nil {
|
||||||
for name, status := range tc.status {
|
for name, status := range tc.status {
|
||||||
p, ok := rosa.ResolveName(name)
|
a, _ := _t.Load(rosa.ArtifactH(unique.Make(name)))
|
||||||
if !ok {
|
if a == nil {
|
||||||
t.Fatalf("invalid name %q", name)
|
t.Fatalf("invalid name %q", name)
|
||||||
}
|
}
|
||||||
perm := os.FileMode(0400)
|
perm := os.FileMode(0400)
|
||||||
@@ -143,7 +152,7 @@ status : not in report
|
|||||||
return os.WriteFile(filepath.Join(
|
return os.WriteFile(filepath.Join(
|
||||||
cm.base,
|
cm.base,
|
||||||
"status",
|
"status",
|
||||||
pkg.Encode(cache.Ident(rosa.Std.Load(p)).Value()),
|
pkg.Encode(cache.Ident(a).Value()),
|
||||||
), unsafe.Slice(unsafe.StringData(status), len(status)), perm)
|
), unsafe.Slice(unsafe.StringData(status), len(status)), perm)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
t.Fatalf("Do: error = %v", err)
|
t.Fatalf("Do: error = %v", err)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ var (
|
|||||||
// handleInfo writes constant system information.
|
// handleInfo writes constant system information.
|
||||||
func handleInfo(w http.ResponseWriter, _ *http.Request) {
|
func handleInfo(w http.ResponseWriter, _ *http.Request) {
|
||||||
infoPayloadOnce.Do(func() {
|
infoPayloadOnce.Do(func() {
|
||||||
infoPayload.Count = int(rosa.PresetUnexportedStart)
|
infoPayload.Count = int(rosa.Native().Count())
|
||||||
infoPayload.HakureiVersion = info.Version()
|
infoPayload.HakureiVersion = info.Version()
|
||||||
})
|
})
|
||||||
// TODO(mae): cache entire response if no additional fields are planned
|
// TODO(mae): cache entire response if no additional fields are planned
|
||||||
@@ -91,7 +91,7 @@ func (index *packageIndex) handleGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
if err != nil || i >= len(index.sorts[0]) || i < 0 {
|
if err != nil || i >= len(index.sorts[0]) || i < 0 {
|
||||||
http.Error(
|
http.Error(
|
||||||
w, "index must be an integer between 0 and "+
|
w, "index must be an integer between 0 and "+
|
||||||
strconv.Itoa(int(rosa.PresetUnexportedStart-1)),
|
strconv.Itoa(len(index.sorts[0])-1),
|
||||||
http.StatusBadRequest,
|
http.StatusBadRequest,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
@@ -125,7 +125,7 @@ func (index *packageIndex) handleSearch(w http.ResponseWriter, r *http.Request)
|
|||||||
if err != nil || i >= len(index.sorts[0]) || i < 0 {
|
if err != nil || i >= len(index.sorts[0]) || i < 0 {
|
||||||
http.Error(
|
http.Error(
|
||||||
w, "index must be an integer between 0 and "+
|
w, "index must be an integer between 0 and "+
|
||||||
strconv.Itoa(int(rosa.PresetUnexportedStart-1)),
|
strconv.Itoa(len(index.sorts[0])-1),
|
||||||
http.StatusBadRequest,
|
http.StatusBadRequest,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package pkgserver
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"slices"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ func TestAPIInfo(t *testing.T) {
|
|||||||
checkPayload(t, resp, struct {
|
checkPayload(t, resp, struct {
|
||||||
Count int `json:"count"`
|
Count int `json:"count"`
|
||||||
HakureiVersion string `json:"hakurei_version"`
|
HakureiVersion string `json:"hakurei_version"`
|
||||||
}{int(rosa.PresetUnexportedStart), info.Version()})
|
}{rosa.Native().Count(), info.Version()})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPIGet(t *testing.T) {
|
func TestAPIGet(t *testing.T) {
|
||||||
@@ -96,8 +95,8 @@ func TestAPIGet(t *testing.T) {
|
|||||||
t.Run("index", func(t *testing.T) {
|
t.Run("index", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
checkValidate(
|
checkValidate(
|
||||||
t, "limit=1&sort=0&index", 0, int(rosa.PresetUnexportedStart-1),
|
t, "limit=1&sort=0&index", 0, rosa.Native().Count()-1,
|
||||||
"index must be an integer between 0 and "+strconv.Itoa(int(rosa.PresetUnexportedStart-1)),
|
"index must be an integer between 0 and "+strconv.Itoa(rosa.Native().Count()-1),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -108,74 +107,4 @@ func TestAPIGet(t *testing.T) {
|
|||||||
"sort must be an integer between 0 and "+strconv.Itoa(int(sortOrderEnd)),
|
"sort must be an integer between 0 and "+strconv.Itoa(int(sortOrderEnd)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
checkWithSuffix := func(name, suffix string, want []*metadata) {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
w := newRequest(suffix)
|
|
||||||
resp := w.Result()
|
|
||||||
checkStatus(t, resp, http.StatusOK)
|
|
||||||
checkAPIHeader(t, w.Header())
|
|
||||||
checkPayloadFunc(t, resp, func(got *struct {
|
|
||||||
Values []*metadata `json:"values"`
|
|
||||||
}) bool {
|
|
||||||
return slices.EqualFunc(got.Values, want, func(a, b *metadata) bool {
|
|
||||||
return (a.Version == b.Version ||
|
|
||||||
a.Version == rosa.Unversioned ||
|
|
||||||
b.Version == rosa.Unversioned) &&
|
|
||||||
a.HasReport == b.HasReport &&
|
|
||||||
a.Name == b.Name &&
|
|
||||||
a.Description == b.Description &&
|
|
||||||
a.Website == b.Website
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
checkWithSuffix("declarationAscending", "?limit=2&index=1&sort=0", []*metadata{
|
|
||||||
{
|
|
||||||
Metadata: rosa.GetMetadata(1),
|
|
||||||
Version: rosa.Std.Version(1),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Metadata: rosa.GetMetadata(2),
|
|
||||||
Version: rosa.Std.Version(2),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
checkWithSuffix("declarationAscending offset", "?limit=3&index=5&sort=0", []*metadata{
|
|
||||||
{
|
|
||||||
Metadata: rosa.GetMetadata(5),
|
|
||||||
Version: rosa.Std.Version(5),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Metadata: rosa.GetMetadata(6),
|
|
||||||
Version: rosa.Std.Version(6),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Metadata: rosa.GetMetadata(7),
|
|
||||||
Version: rosa.Std.Version(7),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
checkWithSuffix("declarationDescending", "?limit=3&index=0&sort=1", []*metadata{
|
|
||||||
{
|
|
||||||
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 1),
|
|
||||||
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 1),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 2),
|
|
||||||
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 2),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 3),
|
|
||||||
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 3),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
checkWithSuffix("declarationDescending offset", "?limit=1&index=37&sort=1", []*metadata{
|
|
||||||
{
|
|
||||||
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 38),
|
|
||||||
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 38),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const (
|
|||||||
|
|
||||||
// packageIndex refers to metadata by name and various sort orders.
|
// packageIndex refers to metadata by name and various sort orders.
|
||||||
type packageIndex struct {
|
type packageIndex struct {
|
||||||
sorts [sortOrderEnd + 1][rosa.PresetUnexportedStart]*metadata
|
sorts [sortOrderEnd + 1][]*metadata
|
||||||
names map[string]*metadata
|
names map[string]*metadata
|
||||||
search searchCache
|
search searchCache
|
||||||
// Taken from [rosa.Report] if available.
|
// Taken from [rosa.Report] if available.
|
||||||
@@ -32,8 +32,8 @@ type packageIndex struct {
|
|||||||
|
|
||||||
// metadata holds [rosa.Metadata] extended with additional information.
|
// metadata holds [rosa.Metadata] extended with additional information.
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
p rosa.PArtifact
|
handle rosa.ArtifactH
|
||||||
*rosa.Metadata
|
*rosa.Artifact
|
||||||
|
|
||||||
// Populated via [rosa.Toolchain.Version], [rosa.Unversioned] is equivalent
|
// Populated via [rosa.Toolchain.Version], [rosa.Unversioned] is equivalent
|
||||||
// to the zero value. Otherwise, the zero value is invalid.
|
// to the zero value. Otherwise, the zero value is invalid.
|
||||||
@@ -56,15 +56,17 @@ func (index *packageIndex) populate(report *rosa.Report) (err error) {
|
|||||||
index.handleAccess = report.HandleAccess
|
index.handleAccess = report.HandleAccess
|
||||||
}
|
}
|
||||||
|
|
||||||
var work [rosa.PresetUnexportedStart]*metadata
|
handles := rosa.Native().Collect()
|
||||||
|
work := make([]*metadata, len(handles))
|
||||||
index.names = make(map[string]*metadata)
|
index.names = make(map[string]*metadata)
|
||||||
ir := pkg.NewIR()
|
ir := pkg.NewIR()
|
||||||
for p := range rosa.PresetUnexportedStart {
|
for i, handle := range handles {
|
||||||
|
a, version := rosa.Native().Std().MustLoad(handle)
|
||||||
m := metadata{
|
m := metadata{
|
||||||
p: p,
|
handle: handle,
|
||||||
|
|
||||||
Metadata: rosa.GetMetadata(p),
|
Artifact: rosa.Native().MustGet(handle),
|
||||||
Version: rosa.Std.Version(p),
|
Version: version,
|
||||||
}
|
}
|
||||||
if m.Version == "" {
|
if m.Version == "" {
|
||||||
return errors.New("invalid version from " + m.Name)
|
return errors.New("invalid version from " + m.Name)
|
||||||
@@ -74,32 +76,32 @@ func (index *packageIndex) populate(report *rosa.Report) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if report != nil {
|
if report != nil {
|
||||||
id := ir.Ident(rosa.Std.Load(p))
|
id := ir.Ident(a)
|
||||||
m.ids = pkg.Encode(id.Value())
|
m.ids = pkg.Encode(id.Value())
|
||||||
m.status, m.Size = report.ArtifactOf(id)
|
m.status, m.Size = report.ArtifactOf(id)
|
||||||
m.HasReport = m.Size >= 0
|
m.HasReport = m.Size >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
work[p] = &m
|
work[i] = &m
|
||||||
index.names[m.Name] = &m
|
index.names[m.Name] = &m
|
||||||
}
|
}
|
||||||
|
|
||||||
index.sorts[declarationAscending] = work
|
index.sorts[declarationAscending] = work
|
||||||
index.sorts[declarationDescending] = work
|
index.sorts[declarationDescending] = slices.Clone(work)
|
||||||
slices.Reverse(index.sorts[declarationDescending][:])
|
slices.Reverse(index.sorts[declarationDescending][:])
|
||||||
|
|
||||||
index.sorts[nameAscending] = work
|
index.sorts[nameAscending] = slices.Clone(work)
|
||||||
slices.SortFunc(index.sorts[nameAscending][:], func(a, b *metadata) int {
|
slices.SortFunc(index.sorts[nameAscending][:], func(a, b *metadata) int {
|
||||||
return strings.Compare(a.Name, b.Name)
|
return strings.Compare(a.Name, b.Name)
|
||||||
})
|
})
|
||||||
index.sorts[nameDescending] = index.sorts[nameAscending]
|
index.sorts[nameDescending] = slices.Clone(index.sorts[nameAscending])
|
||||||
slices.Reverse(index.sorts[nameDescending][:])
|
slices.Reverse(index.sorts[nameDescending][:])
|
||||||
|
|
||||||
index.sorts[sizeAscending] = work
|
index.sorts[sizeAscending] = slices.Clone(work)
|
||||||
slices.SortFunc(index.sorts[sizeAscending][:], func(a, b *metadata) int {
|
slices.SortFunc(index.sorts[sizeAscending][:], func(a, b *metadata) int {
|
||||||
return cmp.Compare(a.Size, b.Size)
|
return cmp.Compare(a.Size, b.Size)
|
||||||
})
|
})
|
||||||
index.sorts[sizeDescending] = index.sorts[sizeAscending]
|
index.sorts[sizeDescending] = slices.Clone(index.sorts[sizeAscending])
|
||||||
slices.Reverse(index.sorts[sizeDescending][:])
|
slices.Reverse(index.sorts[sizeDescending][:])
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<link rel="icon" href="https://hakurei.app/favicon.ico"/>
|
||||||
<title>Hakurei PkgServer</title>
|
<title>Hakurei PkgServer</title>
|
||||||
<script src="index.js"></script>
|
<script src="index.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
+143
-35
@@ -67,9 +67,13 @@ func main() {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
flagQuiet bool
|
flagQuiet bool
|
||||||
|
flagQEMU bool
|
||||||
|
flagArch string
|
||||||
flagCheck bool
|
flagCheck bool
|
||||||
flagLTO bool
|
flagLTO bool
|
||||||
|
|
||||||
|
flagCrossOverride int
|
||||||
|
|
||||||
addr net.UnixAddr
|
addr net.UnixAddr
|
||||||
)
|
)
|
||||||
c := command.New(os.Stderr, log.Printf, "mbf", func([]string) error {
|
c := command.New(os.Stderr, log.Printf, "mbf", func([]string) error {
|
||||||
@@ -93,13 +97,36 @@ func main() {
|
|||||||
if !flagLTO {
|
if !flagLTO {
|
||||||
flags |= rosa.OptLLVMNoLTO
|
flags |= rosa.OptLLVMNoLTO
|
||||||
}
|
}
|
||||||
rosa.DropCaches(flags)
|
rosa.Native().DropCaches("", flags)
|
||||||
|
cross := flagArch != "" && flagArch != runtime.GOARCH
|
||||||
|
if flagQEMU || cross {
|
||||||
|
cm.qemu, _ = rosa.Native().Std().Load(rosa.QEMU)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cross {
|
||||||
|
if flagCrossOverride != -1 {
|
||||||
|
flags = flagCrossOverride
|
||||||
|
}
|
||||||
|
|
||||||
|
rosa.Native().DropCaches(flagArch, flags)
|
||||||
|
if !rosa.HasStage0() {
|
||||||
|
return pkg.UnsupportedArchError(flagArch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}).Flag(
|
}).Flag(
|
||||||
&flagQuiet,
|
&flagQuiet,
|
||||||
"q", command.BoolFlag(false),
|
"q", command.BoolFlag(false),
|
||||||
"Do not print cure messages",
|
"Do not print cure messages",
|
||||||
|
).Flag(
|
||||||
|
&flagQEMU,
|
||||||
|
"register", command.BoolFlag(false),
|
||||||
|
"Enable additional target architectures",
|
||||||
|
).Flag(
|
||||||
|
&flagArch,
|
||||||
|
"arch", command.StringFlag(runtime.GOARCH),
|
||||||
|
"Target architecture",
|
||||||
).Flag(
|
).Flag(
|
||||||
&flagLTO,
|
&flagLTO,
|
||||||
"lto", command.BoolFlag(false),
|
"lto", command.BoolFlag(false),
|
||||||
@@ -108,6 +135,14 @@ func main() {
|
|||||||
&flagCheck,
|
&flagCheck,
|
||||||
"check", command.BoolFlag(true),
|
"check", command.BoolFlag(true),
|
||||||
"Run test suites",
|
"Run test suites",
|
||||||
|
).Flag(
|
||||||
|
&flagCrossOverride,
|
||||||
|
"cross-flags", command.IntFlag(-1),
|
||||||
|
"Override non-native target preset flags",
|
||||||
|
).Flag(
|
||||||
|
&cm.verboseInit,
|
||||||
|
"v", command.BoolFlag(false),
|
||||||
|
"Do not suppress verbose output from init",
|
||||||
).Flag(
|
).Flag(
|
||||||
&cm.cures,
|
&cm.cures,
|
||||||
"cures", command.IntFlag(0),
|
"cures", command.IntFlag(0),
|
||||||
@@ -296,12 +331,12 @@ func main() {
|
|||||||
n atomic.Uint64
|
n atomic.Uint64
|
||||||
)
|
)
|
||||||
|
|
||||||
w := make(chan rosa.PArtifact)
|
w := make(chan rosa.ArtifactH)
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for range max(flagJobs, 1) {
|
for range max(flagJobs, 1) {
|
||||||
wg.Go(func() {
|
wg.Go(func() {
|
||||||
for p := range w {
|
for p := range w {
|
||||||
meta := rosa.GetMetadata(p)
|
meta := rosa.Native().MustGet(p)
|
||||||
if meta.ID == 0 {
|
if meta.ID == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -314,8 +349,9 @@ func main() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, version := rosa.Native().Std().Load(p)
|
||||||
if current, latest :=
|
if current, latest :=
|
||||||
rosa.Std.Version(p),
|
version,
|
||||||
meta.GetLatest(v); current != latest {
|
meta.GetLatest(v); current != latest {
|
||||||
|
|
||||||
n.Add(1)
|
n.Add(1)
|
||||||
@@ -329,9 +365,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
for i := range rosa.PresetEnd {
|
for _, p := range rosa.Native().Collect() {
|
||||||
select {
|
select {
|
||||||
case w <- rosa.PArtifact(i):
|
case w <- p:
|
||||||
break
|
break
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
break done
|
break done
|
||||||
@@ -376,9 +412,9 @@ func main() {
|
|||||||
"stage3",
|
"stage3",
|
||||||
"Check for toolchain 3-stage non-determinism",
|
"Check for toolchain 3-stage non-determinism",
|
||||||
func(args []string) (err error) {
|
func(args []string) (err error) {
|
||||||
t := rosa.Std
|
s := rosa.Std
|
||||||
if flagGentoo != "" {
|
if flagGentoo != "" {
|
||||||
t -= 3 // magic number to discourage misuse
|
s -= 3 // magic number to discourage misuse
|
||||||
|
|
||||||
var checksum pkg.Checksum
|
var checksum pkg.Checksum
|
||||||
if len(flagChecksum) != 0 {
|
if len(flagChecksum) != 0 {
|
||||||
@@ -386,7 +422,7 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rosa.SetGentooStage3(flagGentoo, checksum)
|
rosa.Native().SetGentooStage3(flagGentoo, checksum)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -395,9 +431,8 @@ func main() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||||
pathname, _, err = cache.Cure(
|
llvm, _ := rosa.Native().New(s - 2).Load(rosa.LLVM)
|
||||||
(t - 2).Load(rosa.LLVM),
|
pathname, _, err = cache.Cure(llvm)
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return
|
return
|
||||||
@@ -405,18 +440,16 @@ func main() {
|
|||||||
log.Println("stage1:", pathname)
|
log.Println("stage1:", pathname)
|
||||||
|
|
||||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||||
pathname, checksum[0], err = cache.Cure(
|
llvm, _ := rosa.Native().New(s - 1).Load(rosa.LLVM)
|
||||||
(t - 1).Load(rosa.LLVM),
|
pathname, checksum[0], err = cache.Cure(llvm)
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Println("stage2:", pathname)
|
log.Println("stage2:", pathname)
|
||||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||||
pathname, checksum[1], err = cache.Cure(
|
llvm, _ := rosa.Native().New(s).Load(rosa.LLVM)
|
||||||
t.Load(rosa.LLVM),
|
pathname, checksum[1], err = cache.Cure(llvm)
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return
|
return
|
||||||
@@ -437,9 +470,8 @@ func main() {
|
|||||||
|
|
||||||
if flagStage0 {
|
if flagStage0 {
|
||||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||||
pathname, _, err = cache.Cure(
|
stage0, _ := rosa.Native().New(s).Load(rosa.Stage0)
|
||||||
t.Load(rosa.Stage0),
|
pathname, _, err = cache.Cure(stage0)
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return
|
return
|
||||||
@@ -471,6 +503,8 @@ func main() {
|
|||||||
flagExport string
|
flagExport string
|
||||||
flagRemote bool
|
flagRemote bool
|
||||||
flagNoReply bool
|
flagNoReply bool
|
||||||
|
flagFaults bool
|
||||||
|
flagPop bool
|
||||||
|
|
||||||
flagBoot bool
|
flagBoot bool
|
||||||
flagStd bool
|
flagStd bool
|
||||||
@@ -482,10 +516,6 @@ func main() {
|
|||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return errors.New("cure requires 1 argument")
|
return errors.New("cure requires 1 argument")
|
||||||
}
|
}
|
||||||
p, ok := rosa.ResolveName(args[0])
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("unknown artifact %q", args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
t := rosa.Std
|
t := rosa.Std
|
||||||
if flagBoot {
|
if flagBoot {
|
||||||
@@ -494,11 +524,16 @@ func main() {
|
|||||||
t -= 1
|
t -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a, _ := rosa.Native().New(t).Load(rosa.ArtifactH(unique.Make(args[0])))
|
||||||
|
if a == nil {
|
||||||
|
return fmt.Errorf("unknown artifact %q", args[0])
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
default:
|
default:
|
||||||
var pathname *check.Absolute
|
var pathname *check.Absolute
|
||||||
err := cm.Do(func(cache *pkg.Cache) (err error) {
|
err := cm.Do(func(cache *pkg.Cache) (err error) {
|
||||||
pathname, _, err = cache.Cure(t.Load(p))
|
pathname, _, err = cache.Cure(a)
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -540,7 +575,7 @@ func main() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = pkg.NewIR().EncodeAll(f, rosa.Std.Load(p)); err != nil {
|
if err = pkg.NewIR().EncodeAll(f, a); err != nil {
|
||||||
_ = f.Close()
|
_ = f.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -551,7 +586,7 @@ func main() {
|
|||||||
return cm.Do(func(cache *pkg.Cache) error {
|
return cm.Do(func(cache *pkg.Cache) error {
|
||||||
return cache.EnterExec(
|
return cache.EnterExec(
|
||||||
ctx,
|
ctx,
|
||||||
t.Load(p),
|
a,
|
||||||
true, os.Stdin, os.Stdout, os.Stderr,
|
true, os.Stdin, os.Stdout, os.Stderr,
|
||||||
rosa.AbsSystem.Append("bin", "mksh"),
|
rosa.AbsSystem.Append("bin", "mksh"),
|
||||||
"sh",
|
"sh",
|
||||||
@@ -563,7 +598,6 @@ func main() {
|
|||||||
if flagNoReply {
|
if flagNoReply {
|
||||||
flags |= remoteNoReply
|
flags |= remoteNoReply
|
||||||
}
|
}
|
||||||
a := t.Load(p)
|
|
||||||
pathname, err := cureRemote(ctx, &addr, a, flags)
|
pathname, err := cureRemote(ctx, &addr, a, flags)
|
||||||
if !flagNoReply && err == nil {
|
if !flagNoReply && err == nil {
|
||||||
log.Println(pathname)
|
log.Println(pathname)
|
||||||
@@ -579,6 +613,49 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
||||||
|
case flagFaults:
|
||||||
|
var faults []pkg.Fault
|
||||||
|
if err := cm.Do(func(cache *pkg.Cache) (err error) {
|
||||||
|
faults, err = cache.ReadFaults(a)
|
||||||
|
return
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fault := range faults {
|
||||||
|
log.Printf("%s: %s ago", fault.String(), time.Since(fault.Time()))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case flagPop:
|
||||||
|
var faults []pkg.Fault
|
||||||
|
if err := cm.Do(func(cache *pkg.Cache) (err error) {
|
||||||
|
faults, err = cache.ReadFaults(a)
|
||||||
|
return
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(faults) == 0 {
|
||||||
|
return errors.New("no fault entries found")
|
||||||
|
}
|
||||||
|
fault := faults[len(faults)-1]
|
||||||
|
r, err := fault.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err = io.Copy(os.Stdout, r); err != nil {
|
||||||
|
_ = r.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
if err = r.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("faulting cure terminated %s ago", time.Since(fault.Time()))
|
||||||
|
return fault.Destroy()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
).Flag(
|
).Flag(
|
||||||
@@ -609,9 +686,40 @@ func main() {
|
|||||||
&flagStd,
|
&flagStd,
|
||||||
"std", command.BoolFlag(false),
|
"std", command.BoolFlag(false),
|
||||||
"Build on the intermediate toolchain",
|
"Build on the intermediate toolchain",
|
||||||
|
).Flag(
|
||||||
|
&flagFaults,
|
||||||
|
"faults", command.BoolFlag(false),
|
||||||
|
"Display fault entries of the specified artifact",
|
||||||
|
).Flag(
|
||||||
|
&flagPop,
|
||||||
|
"pop", command.BoolFlag(false),
|
||||||
|
"Display and destroy the most recent fault entry",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.NewCommand(
|
||||||
|
"clear",
|
||||||
|
"Remove all fault entries from the cache",
|
||||||
|
func([]string) error {
|
||||||
|
return cm.Do(func(*pkg.Cache) error {
|
||||||
|
pathname := filepath.Join(cm.base, "fault")
|
||||||
|
dents, err := os.ReadDir(pathname)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dent := range dents {
|
||||||
|
msg.Verbosef("destroying entry %s", dent.Name())
|
||||||
|
if err = os.Remove(filepath.Join(pathname, dent.Name())); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Printf("destroyed %d fault entries", len(dents))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
c.NewCommand(
|
c.NewCommand(
|
||||||
"abort",
|
"abort",
|
||||||
"Abort all pending cures on the daemon",
|
"Abort all pending cures on the daemon",
|
||||||
@@ -629,27 +737,26 @@ func main() {
|
|||||||
"shell",
|
"shell",
|
||||||
"Interactive shell in the specified Rosa OS environment",
|
"Interactive shell in the specified Rosa OS environment",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
presets := make([]rosa.PArtifact, len(args)+3)
|
handles := make([]rosa.ArtifactH, len(args)+3)
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
p, ok := rosa.ResolveName(arg)
|
handles[i] = rosa.ArtifactH(unique.Make(arg))
|
||||||
if !ok {
|
if rosa.Native().Get(handles[i]) == nil {
|
||||||
return fmt.Errorf("unknown artifact %q", arg)
|
return fmt.Errorf("unknown artifact %q", arg)
|
||||||
}
|
}
|
||||||
presets[i] = p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
base := rosa.LLVM
|
base := rosa.LLVM
|
||||||
if !flagWithToolchain {
|
if !flagWithToolchain {
|
||||||
base = rosa.Musl
|
base = rosa.Musl
|
||||||
}
|
}
|
||||||
presets = append(presets,
|
handles = append(handles,
|
||||||
base,
|
base,
|
||||||
rosa.Mksh,
|
rosa.Mksh,
|
||||||
rosa.Toybox,
|
rosa.Toybox,
|
||||||
)
|
)
|
||||||
|
|
||||||
root := make(pkg.Collect, 0, 6+len(args))
|
root := make(pkg.Collect, 0, 6+len(args))
|
||||||
root = rosa.Std.AppendPresets(root, presets...)
|
root = rosa.Native().Std().Append(root, handles...)
|
||||||
|
|
||||||
if err := cm.Do(func(cache *pkg.Cache) error {
|
if err := cm.Do(func(cache *pkg.Cache) error {
|
||||||
_, _, err := cache.Cure(&root)
|
_, _, err := cache.Cure(&root)
|
||||||
@@ -710,6 +817,7 @@ func main() {
|
|||||||
z.Hostname = "localhost"
|
z.Hostname = "localhost"
|
||||||
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
||||||
z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr
|
z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
|
z.Quiet = !cm.verboseInit
|
||||||
if s, ok := os.LookupEnv("TERM"); ok {
|
if s, ok := os.LookupEnv("TERM"); ok {
|
||||||
z.Env = append(z.Env, "TERM="+s)
|
z.Env = append(z.Env, "TERM="+s)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
rosa.DropCaches(rosa.OptLLVMNoLTO)
|
rosa.Native().DropCaches("", rosa.OptLLVMNoLTO)
|
||||||
os.Exit(m.Run())
|
os.Exit(m.Run())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,10 +35,10 @@ func TestCureAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
for i := range rosa.PresetEnd {
|
for _, handle := range rosa.Native().Collect() {
|
||||||
p := rosa.PArtifact(i)
|
a, _ := rosa.Native().Std().MustLoad(handle)
|
||||||
t.Run(rosa.GetMetadata(p).Name, func(t *testing.T) {
|
t.Run(rosa.Native().MustGet(handle).Name, func(t *testing.T) {
|
||||||
_, err := cureRemote(t.Context(), &addr, rosa.Std.Load(p), 0)
|
_, err := cureRemote(t.Context(), &addr, a, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,14 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
virtualisation = {
|
virtualisation = {
|
||||||
|
# Hopefully reduces spurious test failures:
|
||||||
|
memorySize = if pkgs.stdenv.hostPlatform.is32bit then 2046 else 8192;
|
||||||
|
|
||||||
diskSize = 6 * 1024;
|
diskSize = 6 * 1024;
|
||||||
|
|
||||||
qemu.options = [
|
qemu.options = [
|
||||||
# Increase test performance:
|
# Increase test performance:
|
||||||
"-smp 8"
|
"-smp 16"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ testers.nixosTest {
|
|||||||
# For go tests:
|
# For go tests:
|
||||||
(pkgs.writeShellScriptBin "sharefs-workload-hakurei-tests" ''
|
(pkgs.writeShellScriptBin "sharefs-workload-hakurei-tests" ''
|
||||||
cp -r "${self.packages.${system}.hakurei.src}" "/sdcard/hakurei" && cd "/sdcard/hakurei"
|
cp -r "${self.packages.${system}.hakurei.src}" "/sdcard/hakurei" && cd "/sdcard/hakurei"
|
||||||
${fhs}/bin/hakurei-fhs -c 'CC="clang -O3 -Werror" go test ./...'
|
${fhs}/bin/hakurei-fhs -c 'ROSA_SKIP_BINFMT=1 CC="clang -O3 -Werror" go test ./...'
|
||||||
'')
|
'')
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package container
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"hakurei.app/check"
|
||||||
|
)
|
||||||
|
|
||||||
|
// escapeBinfmt escapes magic/mask sequences in a [BinfmtEntry].
|
||||||
|
func escapeBinfmt(buf *strings.Builder, s string) string {
|
||||||
|
const lowerhex = "0123456789abcdef"
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
for _, c := range unsafe.Slice(unsafe.StringData(s), len(s)) {
|
||||||
|
switch c {
|
||||||
|
case 0, '\\', ':':
|
||||||
|
buf.WriteString(`\x`)
|
||||||
|
buf.WriteByte(lowerhex[c>>4])
|
||||||
|
buf.WriteByte(lowerhex[c&0xf])
|
||||||
|
|
||||||
|
default:
|
||||||
|
buf.WriteByte(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// BinfmtEntry is an entry to be registered by the init process.
|
||||||
|
type BinfmtEntry struct {
|
||||||
|
// The offset of the magic/mask in the file, counted in bytes.
|
||||||
|
Offset byte
|
||||||
|
// The byte sequence binfmt_misc is matching for.
|
||||||
|
Magic string
|
||||||
|
// An (optional, defaults to all 0xff) mask.
|
||||||
|
Mask string
|
||||||
|
// The program that should be invoked with the binary as first argument.
|
||||||
|
Interpreter *check.Absolute
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid returns whether e can be registered into the kernel.
|
||||||
|
func (e *BinfmtEntry) Valid() bool {
|
||||||
|
return e != nil &&
|
||||||
|
int(e.Offset)+max(len(e.Magic), len(e.Mask)) < 128 &&
|
||||||
|
e.Interpreter != nil && len(e.Interpreter.String()) < 128
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package container
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"hakurei.app/fhs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEscapeBinfmt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
magic string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"packed DOS applications", "\x0eDEX", "\x0eDEX"},
|
||||||
|
|
||||||
|
{"riscv64 magic",
|
||||||
|
"\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00",
|
||||||
|
"\x7fELF\x02\x01\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\x02\\x00\xf3\\x00"},
|
||||||
|
{"riscv64 mask",
|
||||||
|
"\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff",
|
||||||
|
"\xff\xff\xff\xff\xff\xff\xff\\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
got := escapeBinfmt(new(strings.Builder), tc.magic)
|
||||||
|
if got != tc.want {
|
||||||
|
t.Errorf("escapeBinfmt: %q, want %q", got, tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinfmtEntry(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
e BinfmtEntry
|
||||||
|
valid bool
|
||||||
|
}{
|
||||||
|
{"zero", BinfmtEntry{}, false},
|
||||||
|
{"large offset", BinfmtEntry{Offset: 128}, false},
|
||||||
|
{"long magic", BinfmtEntry{Magic: strings.Repeat("\x00", 128)}, false},
|
||||||
|
{"long mask", BinfmtEntry{Mask: strings.Repeat("\x00", 128)}, false},
|
||||||
|
{"valid", BinfmtEntry{Interpreter: fhs.AbsRoot}, true},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if tc.e.Valid() != tc.valid {
|
||||||
|
t.Errorf("Valid: %v", !tc.valid)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ const (
|
|||||||
CAP_SETPCAP = 0x8
|
CAP_SETPCAP = 0x8
|
||||||
CAP_NET_ADMIN = 0xc
|
CAP_NET_ADMIN = 0xc
|
||||||
CAP_DAC_OVERRIDE = 0x1
|
CAP_DAC_OVERRIDE = 0x1
|
||||||
|
CAP_SETFCAP = 0x1f
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|||||||
+27
-6
@@ -67,6 +67,9 @@ type (
|
|||||||
// Copied to the underlying [exec.Cmd].
|
// Copied to the underlying [exec.Cmd].
|
||||||
WaitDelay time.Duration
|
WaitDelay time.Duration
|
||||||
|
|
||||||
|
// Suppress verbose output of init.
|
||||||
|
Quiet bool
|
||||||
|
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
msg message.Msg
|
msg message.Msg
|
||||||
@@ -88,12 +91,20 @@ type (
|
|||||||
// Time to wait for processes lingering after the initial process terminates.
|
// Time to wait for processes lingering after the initial process terminates.
|
||||||
AdoptWaitDelay time.Duration
|
AdoptWaitDelay time.Duration
|
||||||
|
|
||||||
|
// Map uid/gid 0 in the init process. Requires [FstypeProc] attached to
|
||||||
|
// [fhs.Proc] in the container filesystem.
|
||||||
|
InitAsRoot bool
|
||||||
// Mapped Uid in user namespace.
|
// Mapped Uid in user namespace.
|
||||||
Uid int
|
Uid int
|
||||||
// Mapped Gid in user namespace.
|
// Mapped Gid in user namespace.
|
||||||
Gid int
|
Gid int
|
||||||
// Hostname value in UTS namespace.
|
// Hostname value in UTS namespace.
|
||||||
Hostname string
|
Hostname string
|
||||||
|
// Register binfmt_misc entries.
|
||||||
|
Binfmt []BinfmtEntry
|
||||||
|
// Alternative pathname to attach binfmt_misc filesystem. The zero value
|
||||||
|
// requires [FstypeProc] to be made available at [fhs.Proc].
|
||||||
|
BinfmtPath *check.Absolute
|
||||||
// Sequential container setup ops.
|
// Sequential container setup ops.
|
||||||
*Ops
|
*Ops
|
||||||
|
|
||||||
@@ -213,6 +224,9 @@ func (p *Container) Start() error {
|
|||||||
if p.cmd.Process != nil {
|
if p.cmd.Process != nil {
|
||||||
return errors.New("container: already started")
|
return errors.New("container: already started")
|
||||||
}
|
}
|
||||||
|
if !p.InitAsRoot && len(p.Binfmt) > 0 {
|
||||||
|
return errors.New("container: init as root required, but not enabled")
|
||||||
|
}
|
||||||
|
|
||||||
if err := ensureCloseOnExec(); err != nil {
|
if err := ensureCloseOnExec(); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -283,6 +297,18 @@ func (p *Container) Start() error {
|
|||||||
if !p.HostNet {
|
if !p.HostNet {
|
||||||
p.cmd.SysProcAttr.Cloneflags |= CLONE_NEWNET
|
p.cmd.SysProcAttr.Cloneflags |= CLONE_NEWNET
|
||||||
}
|
}
|
||||||
|
if p.InitAsRoot {
|
||||||
|
p.cmd.SysProcAttr.AmbientCaps = append(p.cmd.SysProcAttr.AmbientCaps,
|
||||||
|
// mappings during init as root
|
||||||
|
CAP_SETFCAP,
|
||||||
|
)
|
||||||
|
|
||||||
|
if !p.SeccompDisable &&
|
||||||
|
len(p.SeccompRules) == 0 &&
|
||||||
|
p.SeccompPresets&std.PresetDenyNS != 0 {
|
||||||
|
return errors.New("container: as root requires late namespace creation")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// place setup pipe before user supplied extra files, this is later restored by init
|
// place setup pipe before user supplied extra files, this is later restored by init
|
||||||
if r, w, err := os.Pipe(); err != nil {
|
if r, w, err := os.Pipe(); err != nil {
|
||||||
@@ -342,8 +368,6 @@ func (p *Container) Start() error {
|
|||||||
Err: ENOSYS,
|
Err: ENOSYS,
|
||||||
Origin: true,
|
Origin: true,
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
p.msg.Verbosef("landlock abi version %d", abi)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if rulesetFd, err := rulesetAttr.Create(0); err != nil {
|
if rulesetFd, err := rulesetAttr.Create(0); err != nil {
|
||||||
@@ -353,7 +377,6 @@ func (p *Container) Start() error {
|
|||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.msg.Verbosef("enforcing landlock ruleset %s", rulesetAttr)
|
|
||||||
if err = landlock.RestrictSelf(rulesetFd, 0); err != nil {
|
if err = landlock.RestrictSelf(rulesetFd, 0); err != nil {
|
||||||
_ = Close(rulesetFd)
|
_ = Close(rulesetFd)
|
||||||
return &StartError{
|
return &StartError{
|
||||||
@@ -410,7 +433,6 @@ func (p *Container) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.msg.Verbose("starting container init")
|
|
||||||
if err := p.cmd.Start(); err != nil {
|
if err := p.cmd.Start(); err != nil {
|
||||||
return &StartError{
|
return &StartError{
|
||||||
Step: "start container init",
|
Step: "start container init",
|
||||||
@@ -481,7 +503,6 @@ func (p *Container) Serve() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case <-done:
|
case <-done:
|
||||||
p.msg.Verbose("setup payload took", time.Since(t))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}(p.setup[1])
|
}(p.setup[1])
|
||||||
@@ -491,7 +512,7 @@ func (p *Container) Serve() (err error) {
|
|||||||
Getuid(),
|
Getuid(),
|
||||||
Getgid(),
|
Getgid(),
|
||||||
len(p.ExtraFiles),
|
len(p.ExtraFiles),
|
||||||
p.msg.IsVerbose(),
|
p.msg.IsVerbose() && !p.Quiet,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+188
-74
@@ -16,7 +16,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
_ "unsafe" // for go:linkname
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"hakurei.app/check"
|
"hakurei.app/check"
|
||||||
"hakurei.app/command"
|
"hakurei.app/command"
|
||||||
@@ -408,39 +409,11 @@ var containerTestCases = []struct {
|
|||||||
func TestContainer(t *testing.T) {
|
func TestContainer(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
t.Run("cancel", testContainerCancel(nil, func(t *testing.T, c *container.Container) {
|
var suffix string
|
||||||
wantErr := context.Canceled
|
runTests:
|
||||||
wantExitCode := 0
|
|
||||||
if err := c.Wait(); !reflect.DeepEqual(err, wantErr) {
|
|
||||||
if m, ok := container.InternalMessageFromError(err); ok {
|
|
||||||
t.Error(m)
|
|
||||||
}
|
|
||||||
t.Errorf("Wait: error = %#v, want %#v", err, wantErr)
|
|
||||||
}
|
|
||||||
if ps := c.ProcessState(); ps == nil {
|
|
||||||
t.Errorf("ProcessState unexpectedly returned nil")
|
|
||||||
} else if code := ps.ExitCode(); code != wantExitCode {
|
|
||||||
t.Errorf("ExitCode: %d, want %d", code, wantExitCode)
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
t.Run("forward", testContainerCancel(func(c *container.Container) {
|
|
||||||
c.ForwardCancel = true
|
|
||||||
}, func(t *testing.T, c *container.Container) {
|
|
||||||
var exitError *exec.ExitError
|
|
||||||
if err := c.Wait(); !errors.As(err, &exitError) {
|
|
||||||
if m, ok := container.InternalMessageFromError(err); ok {
|
|
||||||
t.Error(m)
|
|
||||||
}
|
|
||||||
t.Errorf("Wait: error = %v", err)
|
|
||||||
}
|
|
||||||
if code := exitError.ExitCode(); code != blockExitCodeInterrupt {
|
|
||||||
t.Errorf("ExitCode: %d, want %d", code, blockExitCodeInterrupt)
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
for i, tc := range containerTestCases {
|
for i, tc := range containerTestCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
_suffix := suffix
|
||||||
|
t.Run(tc.name+_suffix, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
wantOps, wantOpsCtx := tc.ops(t)
|
wantOps, wantOpsCtx := tc.ops(t)
|
||||||
@@ -464,6 +437,8 @@ func TestContainer(t *testing.T) {
|
|||||||
c.SeccompDisable = !tc.filter
|
c.SeccompDisable = !tc.filter
|
||||||
c.RetainSession = tc.session
|
c.RetainSession = tc.session
|
||||||
c.HostNet = tc.net
|
c.HostNet = tc.net
|
||||||
|
c.InitAsRoot = _suffix != ""
|
||||||
|
c.Env = append(c.Env, "HAKUREI_TEST_SUFFIX="+_suffix)
|
||||||
if info.CanDegrade {
|
if info.CanDegrade {
|
||||||
if _, err := landlock.GetABI(); err != nil {
|
if _, err := landlock.GetABI(); err != nil {
|
||||||
if !errors.Is(err, syscall.ENOSYS) {
|
if !errors.Is(err, syscall.ENOSYS) {
|
||||||
@@ -473,6 +448,9 @@ func TestContainer(t *testing.T) {
|
|||||||
t.Log("Landlock LSM is unavailable, enabling HostAbstract")
|
t.Log("Landlock LSM is unavailable, enabling HostAbstract")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if c.InitAsRoot {
|
||||||
|
c.SeccompPresets &= ^std.PresetDenyNS
|
||||||
|
}
|
||||||
|
|
||||||
c.
|
c.
|
||||||
Readonly(check.MustAbs(pathReadonly), 0755).
|
Readonly(check.MustAbs(pathReadonly), 0755).
|
||||||
@@ -541,6 +519,11 @@ func TestContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if suffix == "" {
|
||||||
|
suffix = " as root"
|
||||||
|
goto runTests
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ent(root, target, vfsOptstr, fsType, source, fsOptstr string) *vfs.MountInfoEntry {
|
func ent(root, target, vfsOptstr, fsType, source, fsOptstr string) *vfs.MountInfoEntry {
|
||||||
@@ -563,49 +546,118 @@ func hostnameFromTestCase(name string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testContainerCancel(
|
func testContainerCancel(
|
||||||
|
t *testing.T,
|
||||||
containerExtra func(c *container.Container),
|
containerExtra func(c *container.Container),
|
||||||
waitCheck func(t *testing.T, c *container.Container),
|
waitCheck func(ps *os.ProcessState, waitErr error),
|
||||||
) func(t *testing.T) {
|
) {
|
||||||
return func(t *testing.T) {
|
ctx, cancel := context.WithCancel(t.Context())
|
||||||
t.Parallel()
|
|
||||||
ctx, cancel := context.WithCancel(t.Context())
|
|
||||||
|
|
||||||
c := helperNewContainer(ctx, "block")
|
c := helperNewContainer(ctx, "block")
|
||||||
c.Stdout, c.Stderr = os.Stdout, os.Stderr
|
c.Stdout, c.Stderr = os.Stdout, os.Stderr
|
||||||
if containerExtra != nil {
|
if containerExtra != nil {
|
||||||
containerExtra(c)
|
containerExtra(c)
|
||||||
}
|
|
||||||
|
|
||||||
ready := make(chan struct{})
|
|
||||||
if r, w, err := os.Pipe(); err != nil {
|
|
||||||
t.Fatalf("cannot pipe: %v", err)
|
|
||||||
} else {
|
|
||||||
c.ExtraFiles = append(c.ExtraFiles, w)
|
|
||||||
go func() {
|
|
||||||
defer close(ready)
|
|
||||||
if _, err = r.Read(make([]byte, 1)); err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.Start(); err != nil {
|
|
||||||
if m, ok := container.InternalMessageFromError(err); ok {
|
|
||||||
t.Fatal(m)
|
|
||||||
} else {
|
|
||||||
t.Fatalf("cannot start container: %v", err)
|
|
||||||
}
|
|
||||||
} else if err = c.Serve(); err != nil {
|
|
||||||
if m, ok := container.InternalMessageFromError(err); ok {
|
|
||||||
t.Error(m)
|
|
||||||
} else {
|
|
||||||
t.Errorf("cannot serve setup params: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
<-ready
|
|
||||||
cancel()
|
|
||||||
waitCheck(t, c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ready := make(chan struct{})
|
||||||
|
var waitErr error
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("cannot pipe: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ExtraFiles = append(c.ExtraFiles, w)
|
||||||
|
go func() {
|
||||||
|
defer close(ready)
|
||||||
|
if _, _err := r.Read(make([]byte, 1)); _err != nil {
|
||||||
|
panic(_err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err = c.Start(); err != nil {
|
||||||
|
if m, ok := container.InternalMessageFromError(err); ok {
|
||||||
|
t.Fatal(m)
|
||||||
|
} else {
|
||||||
|
t.Fatalf("cannot start container: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(done)
|
||||||
|
waitErr = c.Wait()
|
||||||
|
_ = r.SetReadDeadline(time.Now())
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err = c.Serve(); err != nil {
|
||||||
|
if m, ok := container.InternalMessageFromError(err); ok {
|
||||||
|
t.Error(m)
|
||||||
|
} else {
|
||||||
|
t.Errorf("cannot serve setup params: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<-ready
|
||||||
|
cancel()
|
||||||
|
<-done
|
||||||
|
waitCheck(c.ProcessState(), waitErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestForward(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
f := func(ps *os.ProcessState, waitErr error) {
|
||||||
|
var exitError *exec.ExitError
|
||||||
|
if !errors.As(waitErr, &exitError) {
|
||||||
|
if m, ok := container.InternalMessageFromError(waitErr); ok {
|
||||||
|
t.Error(m)
|
||||||
|
}
|
||||||
|
t.Errorf("Wait: error = %v", waitErr)
|
||||||
|
}
|
||||||
|
if code := exitError.ExitCode(); code != blockExitCodeInterrupt {
|
||||||
|
t.Errorf("ExitCode: %d, want %d", code, blockExitCodeInterrupt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Run("direct", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
testContainerCancel(t, func(c *container.Container) {
|
||||||
|
c.ForwardCancel = true
|
||||||
|
}, f)
|
||||||
|
})
|
||||||
|
t.Run("as root", func(t *testing.T) {
|
||||||
|
testContainerCancel(t, func(c *container.Container) {
|
||||||
|
c.ForwardCancel = true
|
||||||
|
c.InitAsRoot = true
|
||||||
|
c.Proc(fhs.AbsProc)
|
||||||
|
}, f)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCancel(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
f := func(ps *os.ProcessState, waitErr error) {
|
||||||
|
wantErr := context.Canceled
|
||||||
|
if !reflect.DeepEqual(waitErr, wantErr) {
|
||||||
|
if m, ok := container.InternalMessageFromError(waitErr); ok {
|
||||||
|
t.Error(m)
|
||||||
|
}
|
||||||
|
t.Errorf("Wait: error = %#v, want %#v", waitErr, wantErr)
|
||||||
|
}
|
||||||
|
if ps == nil {
|
||||||
|
t.Errorf("ProcessState unexpectedly returned nil")
|
||||||
|
} else if code := ps.ExitCode(); code != 0 {
|
||||||
|
t.Errorf("ExitCode: %d, want %d", code, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Run("direct", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
testContainerCancel(t, nil, f)
|
||||||
|
})
|
||||||
|
t.Run("as root", func(t *testing.T) {
|
||||||
|
testContainerCancel(t, func(c *container.Container) {
|
||||||
|
c.InitAsRoot = true
|
||||||
|
c.Proc(fhs.AbsProc)
|
||||||
|
}, f)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContainerString(t *testing.T) {
|
func TestContainerString(t *testing.T) {
|
||||||
@@ -641,6 +693,8 @@ func init() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
c.Command("container", command.UsageInternal, func(args []string) error {
|
c.Command("container", command.UsageInternal, func(args []string) error {
|
||||||
|
asRoot := os.Getenv("HAKUREI_TEST_SUFFIX") == " as root"
|
||||||
|
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
@@ -658,6 +712,66 @@ func init() {
|
|||||||
return fmt.Errorf("gid: %d, want %d", gid, tc.gid)
|
return fmt.Errorf("gid: %d, want %d", gid, tc.gid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no attack surface increase during as root due to no_new_privs
|
||||||
|
var wantBounding uintptr = 1
|
||||||
|
asRootNot := " not"
|
||||||
|
if !asRoot {
|
||||||
|
wantBounding = 0
|
||||||
|
asRootNot = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
PR_CAP_AMBIENT = 0x2f
|
||||||
|
PR_CAP_AMBIENT_IS_SET = 0x1
|
||||||
|
)
|
||||||
|
for i := range container.LastCap(nil) + 1 {
|
||||||
|
r, _, errno := syscall.Syscall(
|
||||||
|
syscall.SYS_PRCTL,
|
||||||
|
PR_CAP_AMBIENT,
|
||||||
|
PR_CAP_AMBIENT_IS_SET,
|
||||||
|
i,
|
||||||
|
)
|
||||||
|
if errno != 0 {
|
||||||
|
return os.NewSyscallError("prctl", errno)
|
||||||
|
}
|
||||||
|
if r != 0 {
|
||||||
|
return fmt.Errorf("capability %d in ambient set", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, _, errno = syscall.Syscall(
|
||||||
|
syscall.SYS_PRCTL,
|
||||||
|
syscall.PR_CAPBSET_READ,
|
||||||
|
i,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
if errno != 0 {
|
||||||
|
return os.NewSyscallError("prctl", errno)
|
||||||
|
}
|
||||||
|
if r != wantBounding {
|
||||||
|
return fmt.Errorf("capability %d%s in bounding set", i, asRootNot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const _LINUX_CAPABILITY_VERSION_3 = 0x20080522
|
||||||
|
var capData struct {
|
||||||
|
effective uint32
|
||||||
|
permitted uint32
|
||||||
|
inheritable uint32
|
||||||
|
}
|
||||||
|
if _, _, errno := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(&struct {
|
||||||
|
version uint32
|
||||||
|
pid int32
|
||||||
|
}{_LINUX_CAPABILITY_VERSION_3, 0})), uintptr(unsafe.Pointer(&capData)), 0); errno != 0 {
|
||||||
|
return os.NewSyscallError("capget", errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
if max(capData.effective, capData.permitted, capData.inheritable) != 0 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"effective = %d, permitted = %d, inheritable = %d",
|
||||||
|
capData.effective, capData.permitted, capData.inheritable,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
wantHost := hostnameFromTestCase(tc.name)
|
wantHost := hostnameFromTestCase(tc.name)
|
||||||
if host, err := os.Hostname(); err != nil {
|
if host, err := os.Hostname(); err != nil {
|
||||||
return fmt.Errorf("cannot get hostname: %v", err)
|
return fmt.Errorf("cannot get hostname: %v", err)
|
||||||
@@ -775,7 +889,7 @@ func TestMain(m *testing.M) {
|
|||||||
}
|
}
|
||||||
c.MustParse(os.Args[1:], func(err error) {
|
c.MustParse(os.Args[1:], func(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|||||||
+106
-23
@@ -11,11 +11,13 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
. "syscall"
|
. "syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"hakurei.app/check"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/ext"
|
"hakurei.app/ext"
|
||||||
"hakurei.app/fhs"
|
"hakurei.app/fhs"
|
||||||
@@ -182,23 +184,33 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
|||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uid, gid := param.Uid, param.Gid
|
||||||
|
if param.InitAsRoot {
|
||||||
|
uid, gid = 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
// write uid/gid map here so parent does not need to set dumpable
|
// write uid/gid map here so parent does not need to set dumpable
|
||||||
if err := k.setDumpable(ext.SUID_DUMP_USER); err != nil {
|
if err := k.setDumpable(ext.SUID_DUMP_USER); err != nil {
|
||||||
k.fatalf(msg, "cannot set SUID_DUMP_USER: %v", err)
|
k.fatalf(msg, "cannot set SUID_DUMP_USER: %v", err)
|
||||||
}
|
}
|
||||||
if err := k.writeFile(fhs.Proc+"self/uid_map",
|
if err := k.writeFile(
|
||||||
append([]byte{}, strconv.Itoa(param.Uid)+" "+strconv.Itoa(param.HostUid)+" 1\n"...),
|
fhs.Proc+"self/uid_map",
|
||||||
0); err != nil {
|
[]byte(strconv.Itoa(uid)+" "+strconv.Itoa(param.HostUid)+" 1\n"),
|
||||||
|
0,
|
||||||
|
); err != nil {
|
||||||
k.fatalf(msg, "%v", err)
|
k.fatalf(msg, "%v", err)
|
||||||
}
|
}
|
||||||
if err := k.writeFile(fhs.Proc+"self/setgroups",
|
if err := k.writeFile(
|
||||||
|
fhs.Proc+"self/setgroups",
|
||||||
[]byte("deny\n"),
|
[]byte("deny\n"),
|
||||||
0); err != nil && !os.IsNotExist(err) {
|
0,
|
||||||
|
); err != nil && !os.IsNotExist(err) {
|
||||||
k.fatalf(msg, "%v", err)
|
k.fatalf(msg, "%v", err)
|
||||||
}
|
}
|
||||||
if err := k.writeFile(fhs.Proc+"self/gid_map",
|
if err := k.writeFile(fhs.Proc+"self/gid_map",
|
||||||
append([]byte{}, strconv.Itoa(param.Gid)+" "+strconv.Itoa(param.HostGid)+" 1\n"...),
|
[]byte(strconv.Itoa(gid)+" "+strconv.Itoa(param.HostGid)+" 1\n"),
|
||||||
0); err != nil {
|
0,
|
||||||
|
); err != nil {
|
||||||
k.fatalf(msg, "%v", err)
|
k.fatalf(msg, "%v", err)
|
||||||
}
|
}
|
||||||
if err := k.setDumpable(ext.SUID_DUMP_DISABLE); err != nil {
|
if err := k.setDumpable(ext.SUID_DUMP_DISABLE); err != nil {
|
||||||
@@ -223,6 +235,23 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
|||||||
state := &setupState{process: make(map[int]WaitStatus), Params: ¶m.Params, Msg: msg, Context: ctx}
|
state := &setupState{process: make(map[int]WaitStatus), Params: ¶m.Params, Msg: msg, Context: ctx}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
if err := k.mount(SourceTmpfsRootfs, intermediateHostPath, FstypeTmpfs, MS_NODEV|MS_NOSUID, zeroString); err != nil {
|
||||||
|
k.fatalf(msg, "cannot mount intermediate root: %v", optionalErrorUnwrap(err))
|
||||||
|
}
|
||||||
|
if err := k.chdir(intermediateHostPath); err != nil {
|
||||||
|
k.fatalf(msg, "cannot enter intermediate host path: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(param.Binfmt) > 0 {
|
||||||
|
for i, e := range param.Binfmt {
|
||||||
|
if pathname, err := k.evalSymlinks(e.Interpreter.String()); err != nil {
|
||||||
|
k.fatal(msg, err)
|
||||||
|
} else if param.Binfmt[i].Interpreter, err = check.NewAbs(pathname); err != nil {
|
||||||
|
k.fatal(msg, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* early is called right before pivot_root into intermediate root;
|
/* early is called right before pivot_root into intermediate root;
|
||||||
this step is mostly for gathering information that would otherwise be
|
this step is mostly for gathering information that would otherwise be
|
||||||
difficult to obtain via library functions after pivot_root, and
|
difficult to obtain via library functions after pivot_root, and
|
||||||
@@ -242,13 +271,6 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := k.mount(SourceTmpfsRootfs, intermediateHostPath, FstypeTmpfs, MS_NODEV|MS_NOSUID, zeroString); err != nil {
|
|
||||||
k.fatalf(msg, "cannot mount intermediate root: %v", optionalErrorUnwrap(err))
|
|
||||||
}
|
|
||||||
if err := k.chdir(intermediateHostPath); err != nil {
|
|
||||||
k.fatalf(msg, "cannot enter intermediate host path: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := k.mkdir(sysrootDir, 0755); err != nil {
|
if err := k.mkdir(sysrootDir, 0755); err != nil {
|
||||||
k.fatalf(msg, "%v", err)
|
k.fatalf(msg, "%v", err)
|
||||||
}
|
}
|
||||||
@@ -285,6 +307,48 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(param.Binfmt) > 0 {
|
||||||
|
const interpreter = "/interpreter"
|
||||||
|
|
||||||
|
if param.BinfmtPath == nil {
|
||||||
|
param.BinfmtPath = fhs.AbsProcSys.Append("fs/binfmt_misc")
|
||||||
|
}
|
||||||
|
binfmt := sysrootPath + param.BinfmtPath.String()
|
||||||
|
if err := k.mkdirAll(binfmt, 0); err != nil {
|
||||||
|
k.fatal(msg, err)
|
||||||
|
}
|
||||||
|
if err := k.mount(
|
||||||
|
SourceBinfmtMisc,
|
||||||
|
binfmt,
|
||||||
|
FstypeBinfmtMisc,
|
||||||
|
MS_NOSUID|MS_NOEXEC|MS_NODEV,
|
||||||
|
zeroString,
|
||||||
|
); err != nil {
|
||||||
|
k.fatal(msg, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf strings.Builder
|
||||||
|
buf.Grow(1920)
|
||||||
|
|
||||||
|
register := binfmt + "/register"
|
||||||
|
for i, e := range param.Binfmt {
|
||||||
|
if err := k.symlink(hostPath+e.Interpreter.String(), interpreter); err != nil {
|
||||||
|
k.fatal(msg, err)
|
||||||
|
} else if err = k.writeFile(register, []byte(":"+
|
||||||
|
strconv.Itoa(i)+":"+
|
||||||
|
"M:"+
|
||||||
|
strconv.Itoa(int(e.Offset))+":"+
|
||||||
|
escapeBinfmt(&buf, e.Magic)+":"+
|
||||||
|
escapeBinfmt(&buf, e.Mask)+":"+
|
||||||
|
interpreter+":"+
|
||||||
|
"F"), 0); err != nil {
|
||||||
|
k.fatal(msg, err)
|
||||||
|
} else if err = k.remove(interpreter); err != nil {
|
||||||
|
k.fatal(msg, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// setup requiring host root complete at this point
|
// setup requiring host root complete at this point
|
||||||
if err := k.mount(hostDir, hostDir, zeroString, MS_SILENT|MS_REC|MS_PRIVATE, zeroString); err != nil {
|
if err := k.mount(hostDir, hostDir, zeroString, MS_SILENT|MS_REC|MS_PRIVATE, zeroString); err != nil {
|
||||||
k.fatalf(msg, "cannot make host root rprivate: %v", optionalErrorUnwrap(err))
|
k.fatalf(msg, "cannot make host root rprivate: %v", optionalErrorUnwrap(err))
|
||||||
@@ -323,11 +387,19 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var keepCaps []uintptr
|
||||||
|
if param.Privileged {
|
||||||
|
keepCaps = append(keepCaps, CAP_SYS_ADMIN, CAP_SETPCAP)
|
||||||
|
}
|
||||||
|
if param.InitAsRoot {
|
||||||
|
keepCaps = append(keepCaps, CAP_SETFCAP)
|
||||||
|
}
|
||||||
|
|
||||||
if err := k.capAmbientClearAll(); err != nil {
|
if err := k.capAmbientClearAll(); err != nil {
|
||||||
k.fatalf(msg, "cannot clear the ambient capability set: %v", err)
|
k.fatalf(msg, "cannot clear the ambient capability set: %v", err)
|
||||||
}
|
}
|
||||||
for i := uintptr(0); i <= lastcap; i++ {
|
for i := range lastcap + 1 {
|
||||||
if param.Privileged && i == CAP_SYS_ADMIN {
|
if slices.Contains(keepCaps, i) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := k.capBoundingSetDrop(i); err != nil {
|
if err := k.capBoundingSetDrop(i); err != nil {
|
||||||
@@ -336,20 +408,23 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var keep [2]uint32
|
var keep [2]uint32
|
||||||
if param.Privileged {
|
for _, c := range keepCaps {
|
||||||
keep[capToIndex(CAP_SYS_ADMIN)] |= capToMask(CAP_SYS_ADMIN)
|
keep[capToIndex(c)] |= capToMask(c)
|
||||||
|
|
||||||
if err := k.capAmbientRaise(CAP_SYS_ADMIN); err != nil {
|
|
||||||
k.fatalf(msg, "cannot raise CAP_SYS_ADMIN: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := k.capset(
|
if err := k.capset(
|
||||||
&capHeader{_LINUX_CAPABILITY_VERSION_3, 0},
|
&capHeader{_LINUX_CAPABILITY_VERSION_3, 0},
|
||||||
&[2]capData{{0, keep[0], keep[0]}, {0, keep[1], keep[1]}},
|
&[2]capData{{keep[0], keep[0], keep[0]}, {keep[1], keep[1], keep[1]}},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
k.fatalf(msg, "cannot capset: %v", err)
|
k.fatalf(msg, "cannot capset: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, c := range keepCaps {
|
||||||
|
if err := k.capAmbientRaise(c); err != nil {
|
||||||
|
k.fatalf(msg, "cannot raise %#x: %v", c, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !param.SeccompDisable {
|
if !param.SeccompDisable {
|
||||||
rules := param.SeccompRules
|
rules := param.SeccompRules
|
||||||
if len(rules) == 0 { // non-empty rules slice always overrides presets
|
if len(rules) == 0 { // non-empty rules slice always overrides presets
|
||||||
@@ -474,6 +549,14 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
|||||||
cmd.ExtraFiles = extraFiles
|
cmd.ExtraFiles = extraFiles
|
||||||
cmd.Dir = param.Dir.String()
|
cmd.Dir = param.Dir.String()
|
||||||
|
|
||||||
|
if param.InitAsRoot {
|
||||||
|
cmd.SysProcAttr = &SysProcAttr{
|
||||||
|
Cloneflags: CLONE_NEWUSER,
|
||||||
|
UidMappings: []SysProcIDMap{{ContainerID: param.Uid, HostID: 0, Size: 1}},
|
||||||
|
GidMappings: []SysProcIDMap{{ContainerID: param.Gid, HostID: 0, Size: 1}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
msg.Verbosef("starting initial process %s", param.Path)
|
msg.Verbosef("starting initial process %s", param.Path)
|
||||||
if err := k.start(cmd); err != nil {
|
if err := k.start(cmd); err != nil {
|
||||||
k.fatalf(msg, "%v", err)
|
k.fatalf(msg, "%v", err)
|
||||||
|
|||||||
+73
-73
@@ -332,6 +332,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("fatalf", stub.ExpectArgs{"invalid op at index %d", []any{0}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"invalid op at index %d", []any{0}}, nil, nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
@@ -370,6 +372,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("fatalf", stub.ExpectArgs{"invalid op at index %d", []any{0}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"invalid op at index %d", []any{0}}, nil, nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
@@ -408,6 +412,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", stub.UniqueError(61)),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", stub.UniqueError(61)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot prepare op at index %d: %v", []any{0, stub.UniqueError(61)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot prepare op at index %d: %v", []any{0, stub.UniqueError(61)}}, nil, nil),
|
||||||
@@ -447,6 +453,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", &os.PathError{Op: "readlink", Path: "/", Err: stub.UniqueError(60)}),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", &os.PathError{Op: "readlink", Path: "/", Err: stub.UniqueError(60)}),
|
||||||
call("fatal", stub.ExpectArgs{[]any{"cannot readlink /: unique error 60 injected by the test suite"}}, nil, nil),
|
call("fatal", stub.ExpectArgs{[]any{"cannot readlink /: unique error 60 injected by the test suite"}}, nil, nil),
|
||||||
@@ -486,9 +494,6 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
/* begin early */
|
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
|
||||||
/* end early */
|
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, stub.UniqueError(58)),
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, stub.UniqueError(58)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot mount intermediate root: %v", []any{stub.UniqueError(58)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot mount intermediate root: %v", []any{stub.UniqueError(58)}}, nil, nil),
|
||||||
},
|
},
|
||||||
@@ -526,9 +531,6 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
/* begin early */
|
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
|
||||||
/* end early */
|
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, stub.UniqueError(56)),
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, stub.UniqueError(56)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot enter intermediate host path: %v", []any{stub.UniqueError(56)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot enter intermediate host path: %v", []any{stub.UniqueError(56)}}, nil, nil),
|
||||||
@@ -567,11 +569,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, stub.UniqueError(54)),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, stub.UniqueError(54)),
|
||||||
call("fatalf", stub.ExpectArgs{"%v", []any{stub.UniqueError(54)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"%v", []any{stub.UniqueError(54)}}, nil, nil),
|
||||||
},
|
},
|
||||||
@@ -609,11 +611,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, stub.UniqueError(52)),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, stub.UniqueError(52)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot bind sysroot: %v", []any{stub.UniqueError(52)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot bind sysroot: %v", []any{stub.UniqueError(52)}}, nil, nil),
|
||||||
@@ -652,11 +654,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, stub.UniqueError(50)),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, stub.UniqueError(50)),
|
||||||
@@ -696,11 +698,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -741,11 +743,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -787,11 +789,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -842,11 +844,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -897,11 +899,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -953,11 +955,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1010,11 +1012,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1069,11 +1071,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1129,11 +1131,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1190,11 +1192,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1252,11 +1254,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1315,11 +1317,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1379,11 +1381,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1444,11 +1446,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1510,11 +1512,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1584,11 +1586,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1622,7 +1624,6 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
||||||
@@ -1654,8 +1655,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||||
|
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0x200100, 0x200100, 0x200100}, {0, 0, 0}}}, nil, nil),
|
||||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, stub.UniqueError(19)),
|
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, stub.UniqueError(19)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot raise CAP_SYS_ADMIN: %v", []any{stub.UniqueError(19)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot raise %#x: %v", []any{uintptr(0x15), stub.UniqueError(19)}}, nil, nil),
|
||||||
},
|
},
|
||||||
}, nil},
|
}, nil},
|
||||||
|
|
||||||
@@ -1691,11 +1693,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1729,7 +1731,6 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
||||||
@@ -1761,8 +1762,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0x200100, 0x200100, 0x200100}, {0, 0, 0}}}, nil, stub.UniqueError(17)),
|
||||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, stub.UniqueError(17)),
|
|
||||||
call("fatalf", stub.ExpectArgs{"cannot capset: %v", []any{stub.UniqueError(17)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot capset: %v", []any{stub.UniqueError(17)}}, nil, nil),
|
||||||
},
|
},
|
||||||
}, nil},
|
}, nil},
|
||||||
@@ -1799,11 +1799,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -1837,7 +1837,6 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
||||||
@@ -1869,8 +1868,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||||
|
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0x200100, 0x200100, 0x200100}, {0, 0, 0}}}, nil, nil),
|
||||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
||||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil),
|
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
||||||
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{std.FilterPreset(0xf)}}, nil, nil),
|
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{std.FilterPreset(0xf)}}, nil, nil),
|
||||||
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, stub.UniqueError(15)),
|
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, stub.UniqueError(15)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot load syscall filter: %v", []any{stub.UniqueError(15)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot load syscall filter: %v", []any{stub.UniqueError(15)}}, nil, nil),
|
||||||
@@ -1908,11 +1908,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -2032,11 +2032,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -2132,11 +2132,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -2232,11 +2232,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -2323,11 +2323,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -2418,11 +2418,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -2520,11 +2520,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -2659,11 +2659,11 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||||
|
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||||
|
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||||
/* begin early */
|
/* begin early */
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||||
/* end early */
|
/* end early */
|
||||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
|
||||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
|
||||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||||
@@ -2697,7 +2697,6 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
||||||
@@ -2729,8 +2728,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||||
|
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0x200100, 0x200100, 0x200100}, {0, 0, 0}}}, nil, nil),
|
||||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
||||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil),
|
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
||||||
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{std.FilterPreset(0xf)}}, nil, nil),
|
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{std.FilterPreset(0xf)}}, nil, nil),
|
||||||
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, nil),
|
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, nil),
|
||||||
call("verbosef", stub.ExpectArgs{"%d filter rules loaded", []any{73}}, nil, nil),
|
call("verbosef", stub.ExpectArgs{"%d filter rules loaded", []any{73}}, nil, nil),
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ const (
|
|||||||
// SourceMqueue is used when mounting mqueue.
|
// SourceMqueue is used when mounting mqueue.
|
||||||
// Note that any source value is allowed when fstype is [FstypeMqueue].
|
// Note that any source value is allowed when fstype is [FstypeMqueue].
|
||||||
SourceMqueue = "mqueue"
|
SourceMqueue = "mqueue"
|
||||||
|
// SourceBinfmtMisc is used when mounting binfmt_misc.
|
||||||
|
// Note that any source value is allowed when fstype is [SourceBinfmtMisc].
|
||||||
|
SourceBinfmtMisc = "binfmt_misc"
|
||||||
// SourceOverlay is used when mounting overlay.
|
// SourceOverlay is used when mounting overlay.
|
||||||
// Note that any source value is allowed when fstype is [FstypeOverlay].
|
// Note that any source value is allowed when fstype is [FstypeOverlay].
|
||||||
SourceOverlay = "overlay"
|
SourceOverlay = "overlay"
|
||||||
@@ -70,6 +73,9 @@ const (
|
|||||||
// FstypeMqueue represents the mqueue pseudo-filesystem.
|
// FstypeMqueue represents the mqueue pseudo-filesystem.
|
||||||
// This filesystem type is usually mounted on /dev/mqueue.
|
// This filesystem type is usually mounted on /dev/mqueue.
|
||||||
FstypeMqueue = "mqueue"
|
FstypeMqueue = "mqueue"
|
||||||
|
// FstypeBinfmtMisc represents the binfmt_misc pseudo-filesystem.
|
||||||
|
// This filesystem type is usually mounted on /proc/sys/fs/binfmt_misc.
|
||||||
|
FstypeBinfmtMisc = "binfmt_misc"
|
||||||
// FstypeOverlay represents the overlay pseudo-filesystem.
|
// FstypeOverlay represents the overlay pseudo-filesystem.
|
||||||
// This filesystem type can be mounted anywhere in the container filesystem.
|
// This filesystem type can be mounted anywhere in the container filesystem.
|
||||||
FstypeOverlay = "overlay"
|
FstypeOverlay = "overlay"
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ var (
|
|||||||
AbsDevShm = unsafeAbs(DevShm)
|
AbsDevShm = unsafeAbs(DevShm)
|
||||||
// AbsProc is [Proc] as [check.Absolute].
|
// AbsProc is [Proc] as [check.Absolute].
|
||||||
AbsProc = unsafeAbs(Proc)
|
AbsProc = unsafeAbs(Proc)
|
||||||
|
// AbsProcSys is [ProcSys] as [check.Absolute].
|
||||||
|
AbsProcSys = unsafeAbs(ProcSys)
|
||||||
// AbsProcSelfExe is [ProcSelfExe] as [check.Absolute].
|
// AbsProcSelfExe is [ProcSelfExe] as [check.Absolute].
|
||||||
AbsProcSelfExe = unsafeAbs(ProcSelfExe)
|
AbsProcSelfExe = unsafeAbs(ProcSelfExe)
|
||||||
// AbsSys is [Sys] as [check.Absolute].
|
// AbsSys is [Sys] as [check.Absolute].
|
||||||
|
|||||||
@@ -64,78 +64,6 @@ func TestFlatten(t *testing.T) {
|
|||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C"), nil},
|
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C"), nil},
|
||||||
|
|
||||||
{"sample cache file", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0}},
|
|
||||||
"checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: 0400, Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
|
||||||
"identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
|
||||||
"identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
|
||||||
"identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
|
||||||
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: 0400, Path: "checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq", Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}},
|
|
||||||
{Mode: 0400, Path: "checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", Data: []byte{0}},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq", Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe", Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("St9rlE-mGZ5gXwiv_hzQ_B8bZP-UUvSNmf4nHUZzCMOumb6hKnheZSe0dmnuc4Q2"), nil},
|
|
||||||
|
|
||||||
{"sample http get cure", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU": {Mode: 0400, Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/oM-2pUlk-mOxK1t3aMWZer69UdOQlAXiAgMrpZ1476VoOqpYVP1aGFS9_HYy-D8_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
|
|
||||||
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: 0400, Path: "checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU", Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/oM-2pUlk-mOxK1t3aMWZer69UdOQlAXiAgMrpZ1476VoOqpYVP1aGFS9_HYy-D8_", Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("L_0RFHpr9JUS4Zp14rz2dESSRvfLzpvqsLhR1-YjQt8hYlmEdVl7vI3_-v8UNPKs"), nil},
|
|
||||||
|
|
||||||
{"sample directory step simple", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"check": {Mode: 0400, Data: []byte{0, 0}},
|
|
||||||
|
|
||||||
"lib": {Mode: fs.ModeDir | 0700},
|
|
||||||
"lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
|
|
||||||
"lib/pkgconfig": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
|
||||||
|
|
||||||
{Mode: 0400, Path: "check", Data: []byte{0, 0}},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "lib"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "lib/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "lib/pkgconfig"},
|
|
||||||
}, pkg.MustDecode("qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b"), nil},
|
|
||||||
|
|
||||||
{"sample directory step garbage", fstest.MapFS{
|
{"sample directory step garbage", fstest.MapFS{
|
||||||
".": {Mode: fs.ModeDir | 0500},
|
".": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
@@ -151,421 +79,6 @@ func TestFlatten(t *testing.T) {
|
|||||||
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "lib/pkgconfig"},
|
{Mode: fs.ModeDir | 0500, Path: "lib/pkgconfig"},
|
||||||
}, pkg.MustDecode("CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT"), nil},
|
}, pkg.MustDecode("CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT"), nil},
|
||||||
|
|
||||||
{"sample directory", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/check": {Mode: 0400, Data: []byte{0, 0}},
|
|
||||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/pkgconfig": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
|
||||||
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
|
||||||
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b"},
|
|
||||||
{Mode: 0400, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/check", Data: []byte{0, 0}},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/pkgconfig"},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY", Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa", Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("WVpvsVqVKg9Nsh744x57h51AuWUoUR2nnh8Md-EYBQpk6ziyTuUn6PLtF2e0Eu_d"), nil},
|
|
||||||
|
|
||||||
{"sample no assume checksum", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M/check": {Mode: 0400, Data: []byte{}},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
|
||||||
"identifier/_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
|
||||||
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M"},
|
|
||||||
{Mode: 0400, Path: "checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M/check", Data: []byte{}},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("OC290t23aimNo2Rp2pPwan5GI2KRLRdOwYxXQMD9jw0QROgHnNXWodoWdV0hwu2w"), nil},
|
|
||||||
|
|
||||||
{"sample tar step unpack", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check": {Mode: 0400, Data: []byte{0, 0}},
|
|
||||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0500},
|
|
||||||
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
|
||||||
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
|
||||||
|
|
||||||
"work": {Mode: fs.ModeDir | 0500},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP"},
|
|
||||||
{Mode: 0400, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check", Data: []byte{0, 0}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig"},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY", Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa", Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "work"},
|
|
||||||
}, pkg.MustDecode("cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM"), nil},
|
|
||||||
|
|
||||||
{"sample tar", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check": {Mode: 0400, Data: []byte{0, 0}},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
|
||||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/work": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM")},
|
|
||||||
"identifier/rg7F1D5hwv6o4xctjD5zDq4i5MD0mArTsUIWfhUbik8xC6Bsyt3mjXXOm3goojTz": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM")},
|
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP"},
|
|
||||||
{Mode: 0400, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check", Data: []byte{0, 0}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY", Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa", Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/work"},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw", Data: []byte("../checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/rg7F1D5hwv6o4xctjD5zDq4i5MD0mArTsUIWfhUbik8xC6Bsyt3mjXXOm3goojTz", Data: []byte("../checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("NQTlc466JmSVLIyWklm_u8_g95jEEb98PxJU-kjwxLpfdjwMWJq0G8ze9R4Vo1Vu"), nil},
|
|
||||||
|
|
||||||
{"sample tar expand step unpack", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
}, pkg.MustDecode("CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN"), nil},
|
|
||||||
|
|
||||||
{"sample tar expand", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")},
|
|
||||||
"identifier/_v1blm2h-_KA-dVaawdpLas6MjHc6rbhhFS8JWwx8iJxZGUu8EBbRrhr5AaZ9PJL": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")},
|
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw", Data: []byte("../checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_v1blm2h-_KA-dVaawdpLas6MjHc6rbhhFS8JWwx8iJxZGUu8EBbRrhr5AaZ9PJL", Data: []byte("../checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("hSoSSgCYTNonX3Q8FjvjD1fBl-E-BQyA6OTXro2OadXqbST4tZ-akGXszdeqphRe"), nil},
|
|
||||||
|
|
||||||
{"testtool", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"check": {Mode: 0400, Data: []byte{0}},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
|
||||||
|
|
||||||
{Mode: 0400, Path: "check", Data: []byte{0}},
|
|
||||||
}, pkg.MustDecode("GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"), nil},
|
|
||||||
|
|
||||||
{"sample exec container", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
|
||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
|
||||||
"identifier/dztPS6jRjiZtCF4_p8AzfnxGp6obkhrgFVsxdodbKWUoAEVtDz3MykepJB4kI_ks": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
|
||||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
|
||||||
{Mode: 0400, Path: "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb", Data: []byte{}},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/dztPS6jRjiZtCF4_p8AzfnxGp6obkhrgFVsxdodbKWUoAEVtDz3MykepJB4kI_ks", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("Q5DluWQCAeohLoiGRImurwFp3vdz9IfQCoj7Fuhh73s4KQPRHpEQEnHTdNHmB8Fx"), nil},
|
|
||||||
|
|
||||||
{"testtool net", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"check": {Mode: 0400, Data: []byte("net")},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
|
||||||
|
|
||||||
{Mode: 0400, Path: "check", Data: []byte("net")},
|
|
||||||
}, pkg.MustDecode("a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W"), nil},
|
|
||||||
|
|
||||||
{"sample exec net container", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
|
||||||
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check": {Mode: 0400, Data: []byte("net")},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/G8qPxD9puvvoOVV7lrT80eyDeIl3G_CCFoKw12c8mCjMdG1zF7NEPkwYpNubClK3": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
|
||||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
|
||||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
|
||||||
{Mode: 0400, Path: "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb", Data: []byte{}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W"},
|
|
||||||
{Mode: 0400, Path: "checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check", Data: []byte("net")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/G8qPxD9puvvoOVV7lrT80eyDeIl3G_CCFoKw12c8mCjMdG1zF7NEPkwYpNubClK3", Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("bPYvvqxpfV7xcC1EptqyKNK1klLJgYHMDkzBcoOyK6j_Aj5hb0mXNPwTwPSK5F6Z"), nil},
|
|
||||||
|
|
||||||
{"sample exec container overlay root", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
|
||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/RdMA-mubnrHuu3Ky1wWyxauSYCO0ZH_zCPUj3uDHqkfwv5sGcByoF_g5PjlGiClb": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
|
||||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/RdMA-mubnrHuu3Ky1wWyxauSYCO0ZH_zCPUj3uDHqkfwv5sGcByoF_g5PjlGiClb", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("PO2DSSCa4yoSgEYRcCSZfQfwow1yRigL3Ry-hI0RDI4aGuFBha-EfXeSJnG_5_Rl"), nil},
|
|
||||||
|
|
||||||
{"sample exec container overlay work", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
|
||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/5hlaukCirnXE4W_RSLJFOZN47Z5RiHnacXzdFp_70cLgiJUGR6cSb_HaFftkzi0-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
|
||||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/5hlaukCirnXE4W_RSLJFOZN47Z5RiHnacXzdFp_70cLgiJUGR6cSb_HaFftkzi0-", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("iaRt6l_Wm2n-h5UsDewZxQkCmjZjyL8r7wv32QT2kyV55-Lx09Dq4gfg9BiwPnKs"), nil},
|
|
||||||
|
|
||||||
{"sample exec container multiple layers", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
|
||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
|
||||||
"checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK/check": {Mode: 0400, Data: []byte("layers")},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
|
||||||
"identifier/B-kc5iJMx8GtlCua4dz6BiJHnDAOUfPjgpbKq4e-QEn0_CZkSYs3fOA1ve06qMs2": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK")},
|
|
||||||
"identifier/p1t_drXr34i-jZNuxDMLaMOdL6tZvQqhavNafGynGqxOZoXAUTSn7kqNh3Ovv3DT": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
|
||||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
|
||||||
{Mode: 0400, Path: "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb", Data: []byte{}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK"},
|
|
||||||
{Mode: 0400, Path: "checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK/check", Data: []byte("layers")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/B-kc5iJMx8GtlCua4dz6BiJHnDAOUfPjgpbKq4e-QEn0_CZkSYs3fOA1ve06qMs2", Data: []byte("../checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/p1t_drXr34i-jZNuxDMLaMOdL6tZvQqhavNafGynGqxOZoXAUTSn7kqNh3Ovv3DT", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("O2YzyR7IUGU5J2CADy0hUZ3A5NkP_Vwzs4UadEdn2oMZZVWRtH0xZGJ3HXiimTnZ"), nil},
|
|
||||||
|
|
||||||
{"sample exec container layer promotion", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
|
||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/kvJIqZo5DKFOxC2ZQ-8_nPaQzEAz9cIm3p6guO-uLqm-xaiPu7oRkSnsu411jd_U": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
"identifier/xXTIYcXmgJWNLC91c417RRrNM9cjELwEZHpGvf8Fk_GNP5agRJp_SicD0w9aMeLJ": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
|
||||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/kvJIqZo5DKFOxC2ZQ-8_nPaQzEAz9cIm3p6guO-uLqm-xaiPu7oRkSnsu411jd_U", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/xXTIYcXmgJWNLC91c417RRrNM9cjELwEZHpGvf8Fk_GNP5agRJp_SicD0w9aMeLJ", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("3EaW6WibLi9gl03_UieiFPaFcPy5p4x3JPxrnLJxGaTI-bh3HU9DK9IMx7c3rrNm"), nil},
|
|
||||||
|
|
||||||
{"sample file short", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0}},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
|
||||||
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
|
||||||
}, []pkg.FlatEntry{
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
|
||||||
{Mode: 0400, Path: "checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", Data: []byte{0}},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi", Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
|
||||||
}, pkg.MustDecode("iR6H5OIsyOW4EwEgtm9rGzGF6DVtyHLySEtwnFE8bnus9VJcoCbR4JIek7Lw-vwT"), nil},
|
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
|||||||
+105
-35
@@ -9,8 +9,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unique"
|
"unique"
|
||||||
@@ -94,6 +96,32 @@ func MustPath(pathname string, writable bool, a ...Artifact) ExecPath {
|
|||||||
return ExecPath{check.MustAbs(pathname), a, writable}
|
return ExecPath{check.MustAbs(pathname), a, writable}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
binfmt map[string]container.BinfmtEntry
|
||||||
|
binfmtMu sync.RWMutex
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisterArch arranges for [KindExec] and [KindExecNet] to support a new
|
||||||
|
// architecture via a binfmt_misc entry. Each architecture must be registered
|
||||||
|
// at most once.
|
||||||
|
func RegisterArch(arch string, e container.BinfmtEntry) {
|
||||||
|
if arch == "" {
|
||||||
|
panic(UnsupportedArchError(arch))
|
||||||
|
}
|
||||||
|
|
||||||
|
binfmtMu.Lock()
|
||||||
|
defer binfmtMu.Unlock()
|
||||||
|
|
||||||
|
if binfmt == nil {
|
||||||
|
binfmt = make(map[string]container.BinfmtEntry)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := binfmt[arch]; ok {
|
||||||
|
panic("attempting to register " + strconv.Quote(arch) + " twice")
|
||||||
|
}
|
||||||
|
binfmt[arch] = e
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ExecTimeoutDefault replaces out of range [NewExec] timeout values.
|
// ExecTimeoutDefault replaces out of range [NewExec] timeout values.
|
||||||
ExecTimeoutDefault = 15 * time.Minute
|
ExecTimeoutDefault = 15 * time.Minute
|
||||||
@@ -110,6 +138,8 @@ type execArtifact struct {
|
|||||||
// Caller-supplied user-facing reporting name, guaranteed to be nonzero
|
// Caller-supplied user-facing reporting name, guaranteed to be nonzero
|
||||||
// during initialisation.
|
// during initialisation.
|
||||||
name string
|
name string
|
||||||
|
// Target architecture.
|
||||||
|
arch string
|
||||||
// Caller-supplied inner mount points.
|
// Caller-supplied inner mount points.
|
||||||
paths []ExecPath
|
paths []ExecPath
|
||||||
|
|
||||||
@@ -132,28 +162,40 @@ type execArtifact struct {
|
|||||||
|
|
||||||
var _ fmt.Stringer = new(execArtifact)
|
var _ fmt.Stringer = new(execArtifact)
|
||||||
|
|
||||||
// execNetArtifact is like execArtifact but implements [KnownChecksum] and has
|
// execMeasuredArtifact is like execArtifact but implements [KnownChecksum] and
|
||||||
// its resulting container keep the host net namespace.
|
// has its resulting container optionally keep the host net namespace.
|
||||||
type execNetArtifact struct {
|
type execMeasuredArtifact struct {
|
||||||
checksum Checksum
|
checksum Checksum
|
||||||
|
|
||||||
|
// Whether to keep host net namespace.
|
||||||
|
hostNet bool
|
||||||
|
|
||||||
execArtifact
|
execArtifact
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ KnownChecksum = new(execNetArtifact)
|
var _ KnownChecksum = new(execMeasuredArtifact)
|
||||||
|
|
||||||
// Checksum returns the caller-supplied checksum.
|
// Checksum returns the caller-supplied checksum.
|
||||||
func (a *execNetArtifact) Checksum() Checksum { return a.checksum }
|
func (a *execMeasuredArtifact) Checksum() Checksum { return a.checksum }
|
||||||
|
|
||||||
// Kind returns the hardcoded [Kind] constant.
|
// Kind returns [KindExecNet], or [KindExec] if hostNet is false.
|
||||||
func (*execNetArtifact) Kind() Kind { return KindExecNet }
|
func (a *execMeasuredArtifact) Kind() Kind {
|
||||||
|
if a == nil || a.hostNet {
|
||||||
|
return KindExecNet
|
||||||
|
}
|
||||||
|
return KindExec
|
||||||
|
}
|
||||||
|
|
||||||
// Cure cures the [Artifact] in the container described by the caller. The
|
// Cure cures the [Artifact] in the container described by the caller. The
|
||||||
// container retains host networking.
|
// container optionally retains host networking.
|
||||||
func (a *execNetArtifact) Cure(f *FContext) error {
|
func (a *execMeasuredArtifact) Cure(f *FContext) error {
|
||||||
return a.cure(f, true)
|
return a.cure(f, a.hostNet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrNetChecksum is panicked by [NewExec] if host net namespace is requested
|
||||||
|
// with a nil checksum.
|
||||||
|
var ErrNetChecksum = errors.New("attempting to keep net namespace without checksum")
|
||||||
|
|
||||||
// NewExec returns a new [Artifact] that executes the program path in a
|
// NewExec returns a new [Artifact] that executes the program path in a
|
||||||
// container with specified paths bind mounted read-only in order. A private
|
// container with specified paths bind mounted read-only in order. A private
|
||||||
// instance of /proc and /dev is made available to the container.
|
// instance of /proc and /dev is made available to the container.
|
||||||
@@ -167,7 +209,7 @@ func (a *execNetArtifact) Cure(f *FContext) error {
|
|||||||
// regular or symlink.
|
// regular or symlink.
|
||||||
//
|
//
|
||||||
// If checksum is non-nil, the resulting [Artifact] implements [KnownChecksum]
|
// If checksum is non-nil, the resulting [Artifact] implements [KnownChecksum]
|
||||||
// and its container runs in the host net namespace.
|
// and its container optionally runs in the host net namespace.
|
||||||
//
|
//
|
||||||
// The container is allowed to run for the specified duration before the initial
|
// The container is allowed to run for the specified duration before the initial
|
||||||
// process and all processes originating from it is terminated. A zero or
|
// process and all processes originating from it is terminated. A zero or
|
||||||
@@ -178,10 +220,10 @@ func (a *execNetArtifact) Cure(f *FContext) error {
|
|||||||
// container and does not affect curing outcome. Because of this, it is omitted
|
// container and does not affect curing outcome. Because of this, it is omitted
|
||||||
// from parameter data for computing identifier.
|
// from parameter data for computing identifier.
|
||||||
func NewExec(
|
func NewExec(
|
||||||
name string,
|
name, arch string,
|
||||||
checksum *Checksum,
|
checksum *Checksum,
|
||||||
timeout time.Duration,
|
timeout time.Duration,
|
||||||
exclusive bool,
|
hostNet, exclusive bool,
|
||||||
|
|
||||||
dir *check.Absolute,
|
dir *check.Absolute,
|
||||||
env []string,
|
env []string,
|
||||||
@@ -193,17 +235,23 @@ func NewExec(
|
|||||||
if name == "" {
|
if name == "" {
|
||||||
name = "exec-" + filepath.Base(pathname.String())
|
name = "exec-" + filepath.Base(pathname.String())
|
||||||
}
|
}
|
||||||
|
if arch == "" {
|
||||||
|
arch = runtime.GOARCH
|
||||||
|
}
|
||||||
if timeout <= 0 {
|
if timeout <= 0 {
|
||||||
timeout = ExecTimeoutDefault
|
timeout = ExecTimeoutDefault
|
||||||
}
|
}
|
||||||
if timeout > ExecTimeoutMax {
|
if timeout > ExecTimeoutMax {
|
||||||
timeout = ExecTimeoutMax
|
timeout = ExecTimeoutMax
|
||||||
}
|
}
|
||||||
a := execArtifact{name, paths, dir, env, pathname, args, timeout, exclusive}
|
a := execArtifact{name, arch, paths, dir, env, pathname, args, timeout, exclusive}
|
||||||
if checksum == nil {
|
if checksum == nil {
|
||||||
|
if hostNet {
|
||||||
|
panic(ErrNetChecksum)
|
||||||
|
}
|
||||||
return &a
|
return &a
|
||||||
}
|
}
|
||||||
return &execNetArtifact{*checksum, a}
|
return &execMeasuredArtifact{*checksum, hostNet, a}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kind returns the hardcoded [Kind] constant.
|
// Kind returns the hardcoded [Kind] constant.
|
||||||
@@ -211,6 +259,7 @@ func (*execArtifact) Kind() Kind { return KindExec }
|
|||||||
|
|
||||||
// Params writes paths, executable pathname and args.
|
// Params writes paths, executable pathname and args.
|
||||||
func (a *execArtifact) Params(ctx *IContext) {
|
func (a *execArtifact) Params(ctx *IContext) {
|
||||||
|
ctx.WriteString(a.arch)
|
||||||
ctx.WriteString(a.name)
|
ctx.WriteString(a.name)
|
||||||
|
|
||||||
ctx.WriteUint32(uint32(len(a.paths)))
|
ctx.WriteUint32(uint32(len(a.paths)))
|
||||||
@@ -257,11 +306,26 @@ func (a *execArtifact) Params(ctx *IContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnsupportedArchError describes an unsupported or invalid architecture.
|
||||||
|
type UnsupportedArchError string
|
||||||
|
|
||||||
|
func (e UnsupportedArchError) Error() string {
|
||||||
|
if e == "" {
|
||||||
|
return "invalid architecture name"
|
||||||
|
}
|
||||||
|
return "unsupported architecture " + string(e)
|
||||||
|
}
|
||||||
|
|
||||||
// readExecArtifact interprets IR values and returns the address of execArtifact
|
// readExecArtifact interprets IR values and returns the address of execArtifact
|
||||||
// or execNetArtifact.
|
// or execNetArtifact.
|
||||||
func readExecArtifact(r *IRReader, net bool) Artifact {
|
func readExecArtifact(r *IRReader, net bool) Artifact {
|
||||||
r.DiscardAll()
|
r.DiscardAll()
|
||||||
|
|
||||||
|
arch := r.ReadString()
|
||||||
|
if arch == "" {
|
||||||
|
panic(UnsupportedArchError(arch))
|
||||||
|
}
|
||||||
|
|
||||||
name := r.ReadString()
|
name := r.ReadString()
|
||||||
|
|
||||||
sz := r.ReadUint32()
|
sz := r.ReadUint32()
|
||||||
@@ -312,22 +376,17 @@ func readExecArtifact(r *IRReader, net bool) Artifact {
|
|||||||
exclusive := r.ReadUint32() != 0
|
exclusive := r.ReadUint32() != 0
|
||||||
|
|
||||||
checksum, ok := r.Finalise()
|
checksum, ok := r.Finalise()
|
||||||
|
|
||||||
var checksumP *Checksum
|
var checksumP *Checksum
|
||||||
if net {
|
if ok {
|
||||||
if !ok {
|
checksumP = new(checksum.Value())
|
||||||
panic(ErrExpectedChecksum)
|
}
|
||||||
}
|
|
||||||
checksumVal := checksum.Value()
|
if net && !ok {
|
||||||
checksumP = &checksumVal
|
panic(ErrExpectedChecksum)
|
||||||
} else {
|
|
||||||
if ok {
|
|
||||||
panic(ErrUnexpectedChecksum)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewExec(
|
return NewExec(
|
||||||
name, checksumP, timeout, exclusive, dir, env, pathname, args, paths...,
|
name, arch, checksumP, timeout, net, exclusive, dir, env, pathname, args, paths...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,11 +495,23 @@ func (a *execArtifact) makeContainer(
|
|||||||
if z.HostNet {
|
if z.HostNet {
|
||||||
z.Hostname = "cure-net"
|
z.Hostname = "cure-net"
|
||||||
}
|
}
|
||||||
|
z.Quiet = flags&CSuppressInit != 0
|
||||||
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
||||||
z.Dir, z.Path, z.Args = a.dir, a.path, a.args
|
z.Dir, z.Path, z.Args = a.dir, a.path, a.args
|
||||||
z.Env = slices.Concat(a.env, []string{EnvJobs + "=" + strconv.Itoa(jobs)})
|
z.Env = slices.Concat(a.env, []string{EnvJobs + "=" + strconv.Itoa(jobs)})
|
||||||
z.Grow(len(a.paths) + 4)
|
z.Grow(len(a.paths) + 4)
|
||||||
|
|
||||||
|
if a.arch != runtime.GOARCH {
|
||||||
|
binfmtMu.RLock()
|
||||||
|
e, ok := binfmt[a.arch]
|
||||||
|
binfmtMu.RUnlock()
|
||||||
|
if !ok {
|
||||||
|
return nil, UnsupportedArchError(a.arch)
|
||||||
|
}
|
||||||
|
z.Binfmt = []container.BinfmtEntry{e}
|
||||||
|
z.InitAsRoot = true
|
||||||
|
}
|
||||||
|
|
||||||
for i, b := range a.paths {
|
for i, b := range a.paths {
|
||||||
if i == overlayWorkIndex {
|
if i == overlayWorkIndex {
|
||||||
if err = os.MkdirAll(work.String(), 0700); err != nil {
|
if err = os.MkdirAll(work.String(), 0700); err != nil {
|
||||||
@@ -527,9 +598,9 @@ func (c *Cache) EnterExec(
|
|||||||
case *execArtifact:
|
case *execArtifact:
|
||||||
e = f
|
e = f
|
||||||
|
|
||||||
case *execNetArtifact:
|
case *execMeasuredArtifact:
|
||||||
e = &f.execArtifact
|
e = &f.execArtifact
|
||||||
hostNet = true
|
hostNet = f.hostNet
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return ErrNotExec
|
return ErrNotExec
|
||||||
@@ -630,12 +701,6 @@ func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
|
|||||||
_ = stdout.Close()
|
_ = stdout.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
if err != nil && !errors.As(err, new(*exec.ExitError)) {
|
|
||||||
_ = stdout.Close()
|
|
||||||
_ = stderr.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
brStdout, brStderr := f.cache.getReader(stdout), f.cache.getReader(stderr)
|
brStdout, brStderr := f.cache.getReader(stdout), f.cache.getReader(stderr)
|
||||||
stdoutDone, stderrDone := make(chan struct{}), make(chan struct{})
|
stdoutDone, stderrDone := make(chan struct{}), make(chan struct{})
|
||||||
@@ -650,6 +715,11 @@ func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
|
|||||||
io.TeeReader(brStderr, status),
|
io.TeeReader(brStderr, status),
|
||||||
)
|
)
|
||||||
defer func() {
|
defer func() {
|
||||||
|
if err != nil && !errors.As(err, new(*exec.ExitError)) {
|
||||||
|
_ = stdout.Close()
|
||||||
|
_ = stderr.Close()
|
||||||
|
}
|
||||||
|
|
||||||
<-stdoutDone
|
<-stdoutDone
|
||||||
<-stderrDone
|
<-stderrDone
|
||||||
f.cache.putReader(brStdout)
|
f.cache.putReader(brStdout)
|
||||||
|
|||||||
+297
-50
@@ -1,44 +1,70 @@
|
|||||||
package pkg_test
|
package pkg_test
|
||||||
|
|
||||||
//go:generate env CGO_ENABLED=0 go build -tags testtool -o testdata/testtool ./testdata
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
|
"io/fs"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
"unique"
|
|
||||||
|
|
||||||
"hakurei.app/check"
|
"hakurei.app/check"
|
||||||
|
"hakurei.app/container"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/info"
|
||||||
"hakurei.app/internal/pkg"
|
"hakurei.app/internal/pkg"
|
||||||
"hakurei.app/internal/stub"
|
"hakurei.app/internal/stub"
|
||||||
|
|
||||||
|
"hakurei.app/internal/pkg/internal/testtool/expected"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testtoolBin is the container test tool binary made available to the
|
// testtoolBin is the container test tool binary made available to the
|
||||||
// execArtifact for testing its curing environment.
|
// execArtifact for testing its curing environment.
|
||||||
//
|
//
|
||||||
//go:embed testdata/testtool
|
//go:generate env CGO_ENABLED=0 go build -tags testtool -o internal/testtool ./internal/testtool
|
||||||
|
//go:embed internal/testtool/testtool
|
||||||
var testtoolBin []byte
|
var testtoolBin []byte
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
pathname, err := filepath.Abs("internal/testtool/testtool")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pkg.RegisterArch("cafe", container.BinfmtEntry{
|
||||||
|
Magic: expected.Magic,
|
||||||
|
Interpreter: check.MustAbs(pathname),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestExec(t *testing.T) {
|
func TestExec(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
wantChecksumOffline := pkg.MustDecode(
|
wantOffline := expectsFS{
|
||||||
"GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9",
|
".": {Mode: fs.ModeDir | 0500},
|
||||||
)
|
|
||||||
|
"check": {Mode: 0400, Data: []byte{0}},
|
||||||
|
}
|
||||||
|
wantOfflineEncode := pkg.Encode(wantOffline.hash())
|
||||||
|
failingArtifact := &stubArtifact{
|
||||||
|
kind: pkg.KindTar,
|
||||||
|
params: []byte("doomed artifact"),
|
||||||
|
cure: func(t *pkg.TContext) error {
|
||||||
|
return stub.UniqueError(0xcafe)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
checkWithCache(t, []cacheTestCase{
|
checkWithCache(t, []cacheTestCase{
|
||||||
{"offline", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"offline", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
testtool, testtoolDestroy := newTesttool()
|
testtool, testtoolDestroy := newTesttool()
|
||||||
|
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"container", pkg.NewExec(
|
{"container", pkg.NewExec(
|
||||||
"exec-offline", nil, 0, false,
|
"exec-offline", "", new(wantOffline.hash()), 0, false, false,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1"},
|
[]string{"HAKUREI_TEST=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -58,67 +84,128 @@ func TestExec(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
pkg.MustPath("/opt", false, testtool),
|
pkg.MustPath("/opt", false, testtool),
|
||||||
), ignorePathname, wantChecksumOffline, nil},
|
), ignorePathname, wantOffline, nil},
|
||||||
|
|
||||||
{"error passthrough", pkg.NewExec(
|
{"substitution", pkg.NewExec(
|
||||||
"", nil, 0, true,
|
"exec-offline", "", new(wantOffline.hash()), 0, false, false,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1"},
|
[]string{"HAKUREI_TEST=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
[]string{"testtool"},
|
[]string{"testtool"},
|
||||||
|
|
||||||
pkg.MustPath("/proc/nonexistent", false, &stubArtifact{
|
pkg.MustPath("/file", false, newStubFile(
|
||||||
|
pkg.KindHTTPGet,
|
||||||
|
pkg.ID{0xfe, 0},
|
||||||
|
nil,
|
||||||
|
nil, nil,
|
||||||
|
)),
|
||||||
|
// substitution miss fails in testtool due to differing idents
|
||||||
|
pkg.MustPath("/.hakurei", false, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
params: []byte("doomed artifact"),
|
params: []byte("empty directory (substituted)"),
|
||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
return stub.UniqueError(0xcafe)
|
return os.MkdirAll(t.GetWorkDir().String(), 0700)
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
), nil, pkg.Checksum{}, &pkg.DependencyCureError{
|
pkg.MustPath("/opt", false, testtool),
|
||||||
|
), ignorePathname, wantOffline, nil},
|
||||||
|
|
||||||
|
{"error passthrough", pkg.NewExec(
|
||||||
|
"", "", nil, 0, false, true,
|
||||||
|
pkg.AbsWork,
|
||||||
|
[]string{"HAKUREI_TEST=1"},
|
||||||
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
|
[]string{"testtool"},
|
||||||
|
|
||||||
|
pkg.MustPath("/proc/nonexistent", false, failingArtifact),
|
||||||
|
), nil, nil, &pkg.DependencyCureError{
|
||||||
{
|
{
|
||||||
Ident: unique.Make(pkg.ID(pkg.MustDecode(
|
A: failingArtifact,
|
||||||
"Sowo6oZRmG6xVtUaxB6bDWZhVsqAJsIJWUp0OPKlE103cY0lodx7dem8J-qQF0Z1",
|
|
||||||
))),
|
|
||||||
Err: stub.UniqueError(0xcafe),
|
Err: stub.UniqueError(0xcafe),
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
|
|
||||||
{"invalid paths", pkg.NewExec(
|
{"invalid paths", pkg.NewExec(
|
||||||
"", nil, 0, false,
|
"", "", nil, 0, false, false,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1"},
|
[]string{"HAKUREI_TEST=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
[]string{"testtool"},
|
[]string{"testtool"},
|
||||||
|
|
||||||
pkg.ExecPath{},
|
pkg.ExecPath{},
|
||||||
), nil, pkg.Checksum{}, pkg.ErrInvalidPaths},
|
), nil, nil, pkg.ErrInvalidPaths},
|
||||||
})
|
})
|
||||||
|
|
||||||
// check init failure passthrough
|
// check init failure passthrough
|
||||||
var exitError *exec.ExitError
|
initFailureArtifact := pkg.NewExec(
|
||||||
if _, _, err := c.Cure(pkg.NewExec(
|
"", "", nil, 0, false, false,
|
||||||
"", nil, 0, false,
|
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
nil,
|
nil,
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
[]string{"testtool"},
|
[]string{"testtool"},
|
||||||
)); !errors.As(err, &exitError) ||
|
)
|
||||||
|
var exitError *exec.ExitError
|
||||||
|
if _, _, err := c.Cure(initFailureArtifact); !errors.As(err, &exitError) ||
|
||||||
exitError.ExitCode() != hst.ExitFailure {
|
exitError.ExitCode() != hst.ExitFailure {
|
||||||
t.Fatalf("Cure: error = %v, want init exit status 1", err)
|
t.Fatalf("Cure: error = %v, want init exit status 1", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
testtoolDestroy(t, base, c)
|
var faultStatus []byte
|
||||||
}, pkg.MustDecode("Q5DluWQCAeohLoiGRImurwFp3vdz9IfQCoj7Fuhh73s4KQPRHpEQEnHTdNHmB8Fx")},
|
if faults, err := c.ReadFaults(initFailureArtifact); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if len(faults) != 1 {
|
||||||
|
t.Fatalf("ReadFaults: %v", faults)
|
||||||
|
} else if faultStatus, err = os.ReadFile(faults[0].String()); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if err = faults[0].Destroy(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
t.Logf("destroyed expected fault at %s", faults[0].Time().UTC())
|
||||||
|
}
|
||||||
|
|
||||||
{"net", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
if !bytes.HasPrefix(faultStatus, []byte(
|
||||||
|
"internal/pkg ",
|
||||||
|
)) || !bytes.Contains(faultStatus, []byte(
|
||||||
|
"\ninit: fork/exec /opt/bin/testtool: no such file or directory\n",
|
||||||
|
)) {
|
||||||
|
t.Errorf("unexpected status:\n%s", string(faultStatus))
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyStatus(t, base, 2, 1)
|
||||||
|
testtoolDestroy(t, base, c)
|
||||||
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||||
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/IY91PCtOpCYy21AaIK0c9f8-Z6fb2_2ewoHWkt4dxoLf0GOrWqS8yAGFLV84b1Dw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||||
|
"identifier/QwS7SmiatdqryQYgESdGw7Yw2PcpNf0vNfpvUA0t92BTlKiUjfCrXyMW17G2X77X": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||||
|
"identifier/" + expected.Offline: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||||
|
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"net", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
testtool, testtoolDestroy := newTesttool()
|
testtool, testtoolDestroy := newTesttool()
|
||||||
|
|
||||||
wantChecksum := pkg.MustDecode(
|
wantNet := expectsFS{
|
||||||
"a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W",
|
".": {Mode: fs.ModeDir | 0500},
|
||||||
)
|
|
||||||
|
"check": {Mode: 0400, Data: []byte("net")},
|
||||||
|
}
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"container", pkg.NewExec(
|
{"container", pkg.NewExec(
|
||||||
"exec-net", &wantChecksum, 0, false,
|
"exec-net", "", new(wantNet.hash()), 0, true, false,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1"},
|
[]string{"HAKUREI_TEST=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -138,18 +225,37 @@ func TestExec(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
pkg.MustPath("/opt", false, testtool),
|
pkg.MustPath("/opt", false, testtool),
|
||||||
), ignorePathname, wantChecksum, nil},
|
), ignorePathname, wantNet, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
destroyStatus(t, base, 2, 0)
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("bPYvvqxpfV7xcC1EptqyKNK1klLJgYHMDkzBcoOyK6j_Aj5hb0mXNPwTwPSK5F6Z")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
{"overlay root", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||||
|
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check": {Mode: 0400, Data: []byte("net")},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/" + expected.Net: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
||||||
|
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||||
|
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"overlay root", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
testtool, testtoolDestroy := newTesttool()
|
testtool, testtoolDestroy := newTesttool()
|
||||||
|
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"container", pkg.NewExec(
|
{"container", pkg.NewExec(
|
||||||
"exec-overlay-root", nil, 0, false,
|
"exec-overlay-root", "", nil, 0, false, false,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -163,18 +269,35 @@ func TestExec(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
pkg.MustPath("/opt", false, testtool),
|
pkg.MustPath("/opt", false, testtool),
|
||||||
), ignorePathname, wantChecksumOffline, nil},
|
), ignorePathname, wantOffline, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
destroyStatus(t, base, 2, 0)
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("PO2DSSCa4yoSgEYRcCSZfQfwow1yRigL3Ry-hI0RDI4aGuFBha-EfXeSJnG_5_Rl")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
{"overlay work", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||||
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/" + expected.OvlRoot: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||||
|
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"overlay work", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
testtool, testtoolDestroy := newTesttool()
|
testtool, testtoolDestroy := newTesttool()
|
||||||
|
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"container", pkg.NewExec(
|
{"container", pkg.NewExec(
|
||||||
"exec-overlay-work", nil, 0, false,
|
"exec-overlay-work", "", nil, 0, false, false,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||||
check.MustAbs("/work/bin/testtool"),
|
check.MustAbs("/work/bin/testtool"),
|
||||||
@@ -193,18 +316,35 @@ func TestExec(t *testing.T) {
|
|||||||
return os.MkdirAll(t.GetWorkDir().String(), 0700)
|
return os.MkdirAll(t.GetWorkDir().String(), 0700)
|
||||||
},
|
},
|
||||||
}), pkg.Path(pkg.AbsWork, false /* ignored */, testtool),
|
}), pkg.Path(pkg.AbsWork, false /* ignored */, testtool),
|
||||||
), ignorePathname, wantChecksumOffline, nil},
|
), ignorePathname, wantOffline, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
destroyStatus(t, base, 2, 0)
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("iaRt6l_Wm2n-h5UsDewZxQkCmjZjyL8r7wv32QT2kyV55-Lx09Dq4gfg9BiwPnKs")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
{"multiple layers", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||||
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/" + expected.Work: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||||
|
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"multiple layers", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
testtool, testtoolDestroy := newTesttool()
|
testtool, testtoolDestroy := newTesttool()
|
||||||
|
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"container", pkg.NewExec(
|
{"container", pkg.NewExec(
|
||||||
"exec-multiple-layers", nil, 0, false,
|
"exec-multiple-layers", "", nil, 0, false, false,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -245,18 +385,40 @@ func TestExec(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
pkg.MustPath("/opt", false, testtool),
|
pkg.MustPath("/opt", false, testtool),
|
||||||
), ignorePathname, wantChecksumOffline, nil},
|
), ignorePathname, wantOffline, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
destroyStatus(t, base, 2, 0)
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("O2YzyR7IUGU5J2CADy0hUZ3A5NkP_Vwzs4UadEdn2oMZZVWRtH0xZGJ3HXiimTnZ")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
{"overlay layer promotion", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||||
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||||
|
"checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK/check": {Mode: 0400, Data: []byte("layers")},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||||
|
"identifier/B-kc5iJMx8GtlCua4dz6BiJHnDAOUfPjgpbKq4e-QEn0_CZkSYs3fOA1ve06qMs2": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK")},
|
||||||
|
"identifier/" + expected.Layers: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||||
|
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"overlay layer promotion", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
testtool, testtoolDestroy := newTesttool()
|
testtool, testtoolDestroy := newTesttool()
|
||||||
|
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"container", pkg.NewExec(
|
{"container", pkg.NewExec(
|
||||||
"exec-layer-promotion", nil, 0, true,
|
"exec-layer-promotion", "", nil, 0, false, true,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -276,11 +438,96 @@ func TestExec(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
pkg.MustPath("/opt", false, testtool),
|
pkg.MustPath("/opt", false, testtool),
|
||||||
), ignorePathname, wantChecksumOffline, nil},
|
), ignorePathname, wantOffline, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
destroyStatus(t, base, 2, 0)
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("3EaW6WibLi9gl03_UieiFPaFcPy5p4x3JPxrnLJxGaTI-bh3HU9DK9IMx7c3rrNm")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||||
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/kvJIqZo5DKFOxC2ZQ-8_nPaQzEAz9cIm3p6guO-uLqm-xaiPu7oRkSnsu411jd_U": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
"identifier/" + expected.Promote: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"binfmt", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
|
if info.CanDegrade && os.Getenv("ROSA_SKIP_BINFMT") != "" {
|
||||||
|
t.Skip("binfmt_misc test explicitly skipped")
|
||||||
|
}
|
||||||
|
|
||||||
|
cureMany(t, c, []cureStep{
|
||||||
|
{"container", pkg.NewExec(
|
||||||
|
"exec-binfmt", "cafe", nil, 0, false, true,
|
||||||
|
pkg.AbsWork,
|
||||||
|
[]string{"HAKUREI_TEST=1", "HAKUREI_BINFMT=1"},
|
||||||
|
check.MustAbs("/opt/bin/sample"),
|
||||||
|
[]string{"sample"},
|
||||||
|
|
||||||
|
pkg.MustPath("/", true, &stubArtifact{
|
||||||
|
kind: pkg.KindTar,
|
||||||
|
params: []byte("empty directory"),
|
||||||
|
cure: func(t *pkg.TContext) error {
|
||||||
|
return os.MkdirAll(t.GetWorkDir().String(), 0700)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
pkg.MustPath("/opt", false, overrideIdent{pkg.ID{0xfe, 0xff}, &stubArtifact{
|
||||||
|
kind: pkg.KindTar,
|
||||||
|
cure: func(t *pkg.TContext) error {
|
||||||
|
work := t.GetWorkDir()
|
||||||
|
if err := os.MkdirAll(
|
||||||
|
work.Append("bin").String(),
|
||||||
|
0700,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.WriteFile(t.GetWorkDir().Append(
|
||||||
|
"bin",
|
||||||
|
"sample",
|
||||||
|
).String(), []byte(expected.Full), 0500)
|
||||||
|
},
|
||||||
|
}}),
|
||||||
|
), ignorePathname, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
|
"check": {Mode: 0400, Data: []byte("binfmt")},
|
||||||
|
}, nil},
|
||||||
|
})
|
||||||
|
|
||||||
|
destroyStatus(t, base, 2, 0)
|
||||||
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV/bin": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV/bin/sample": {Mode: 0500, Data: []byte("\xca\xfe\xba\xbe\xfd\xfd:3")},
|
||||||
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/UnDo4B5KneEUY5b4vRUk_y9MWgkWuw2N8f8a2XayO686xXur-aZmX2-7n_8tKMe3": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/UnDo4B5KneEUY5b4vRUk_y9MWgkWuw2N8f8a2XayO686xXur-aZmX2-7n_8tKMe3/check": {Mode: 0400, Data: []byte("binfmt")},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/6VQTJ1lI5BmVuI1YFYJ8ClO3MRORvTTrcWFDcUU-l5Ga8EofxCxGlSTYN-u8dKj_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UnDo4B5KneEUY5b4vRUk_y9MWgkWuw2N8f8a2XayO686xXur-aZmX2-7n_8tKMe3")},
|
||||||
|
"identifier/_v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV")},
|
||||||
|
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package pkg_test
|
package pkg_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/fs"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/check"
|
"hakurei.app/check"
|
||||||
@@ -10,18 +11,27 @@ import (
|
|||||||
func TestFile(t *testing.T) {
|
func TestFile(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
want := expectsFile{0}
|
||||||
checkWithCache(t, []cacheTestCase{
|
checkWithCache(t, []cacheTestCase{
|
||||||
{"file", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"file", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"short", pkg.NewFile("null", []byte{0}), base.Append(
|
{"short", pkg.NewFile("null", []byte{0}), base.Append(
|
||||||
"identifier",
|
"identifier",
|
||||||
"3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi",
|
"3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi",
|
||||||
), pkg.MustDecode(
|
), want, nil},
|
||||||
"vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX",
|
|
||||||
), nil},
|
|
||||||
})
|
})
|
||||||
}, pkg.MustDecode(
|
}, expectsFS{
|
||||||
"iR6H5OIsyOW4EwEgtm9rGzGF6DVtyHLySEtwnFE8bnus9VJcoCbR4JIek7Lw-vwT",
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
)},
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/" + pkg.Encode(want.hash()): {Mode: 0400, Data: []byte{0}},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Package expected contains data shared between test helper and test harness.
|
||||||
|
package expected
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Magic are magic bytes in the binfmt test case.
|
||||||
|
Magic = "\xca\xfe\xba\xbe\xfd\xfd"
|
||||||
|
// Full is the full content of the binfmt test case executable.
|
||||||
|
Full = Magic + ":3"
|
||||||
|
)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package expected
|
||||||
|
|
||||||
|
const (
|
||||||
|
Offline = "q5ktDTq0miP-VvB2blxqXQeaRXCUWgP_KbC18KNtUDtyoaI_h5mHmGuPMArVEBDs"
|
||||||
|
OvlRoot = "NacZGXwuRkTvcHaG08a22ujJ8qCWN0RSoFlRSR5FSt0ZcBbJ28FRvkYsHEtX7G8i"
|
||||||
|
Layers = "WBJDrATtX6rIE5yAu8ePX3WmDF0Tt9kFiue0m3cRnyRoVx1my8a67fh3CAW486oP"
|
||||||
|
Net = "CmYtj2sNB3LHtqiDuck_Lz3MjLLIiwyP8N4NDitQ1Icvv__LVP9p8tm-sHeQaKKp"
|
||||||
|
Promote = "TX3eCloaQFkV-SZIH6Jg6E5WKH--rcXY1P0jnZKmLFKWrNqnOzd4G9eIBh6i5ywN"
|
||||||
|
Work = "OuNiLSC68pZhAOr1YQ4WbV1tzASA0nxLEBcK7lO7MqxDY_j8dmP_C612RTuF23Lu"
|
||||||
|
)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package expected
|
||||||
|
|
||||||
|
const (
|
||||||
|
Offline = "WapqyoPxbWSnq07dWHt71mHaJXq99pAjJfFlELlJljSiZMhTFqqlzU1_mN86shSj"
|
||||||
|
OvlRoot = "V9anFOiRvjGfAeBhLl14AL8TKdWZyD0WTPYe4fS9mOBw8iW5Lmarvt6TG6MV8uWm"
|
||||||
|
Layers = "tKx7JNRoSBdK_7MdzI-nwTNV2wmiPzwYdcd17oLmXKL_iLmUzUiA79qTqdrTasrv"
|
||||||
|
Net = "aXyDLzBCJ9XltXZIfetEVsEkrqHfcXuD5XE_FcUnYbN3emwL55N6P8LlHzNfGnM5"
|
||||||
|
Promote = "3k4V16n96Lq04gjFSKmm4sFjyQ883FFBNXgTy9s_DjeTwxT3pg_iacEh8yMb_S4m"
|
||||||
|
Work = "6Q49MhFWRE3Ne6MycwAotgl1GtoU5WCHqJNWG2byYZCY-zX-IxPrWiKk7bKkNzhE"
|
||||||
|
)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package expected
|
||||||
|
|
||||||
|
const (
|
||||||
|
Offline = "Z6yXE5gOJScL3srmnVMWgCXccDiUNZ5snSrf6RkXuU1_U0rX_kGVwsfHUgNG_awd"
|
||||||
|
OvlRoot = "zYXJHFRLuxvUhuisZEXgGgVvdQd6piMfp5jmtT6jdVjvC2gICXquOq-UTwlrSD5I"
|
||||||
|
Layers = "_F8EDazHbcLeT0sVSQXRN_kn9IjduqJcDYgzXpsT-hpKU4EBcZ0PISN2zchpqMbm"
|
||||||
|
Net = "CA_FAaSIYJgapBEHV40doxpH23PdUEy_6s1TZc7wfSPN0XYqwGpMceXXDSabGveO"
|
||||||
|
Promote = "_3LPrLp--4h9k4GsNNApu9hHtAafq-GUhfU6d4hJKBDKT3bz_szOsvkXxc5sK53d"
|
||||||
|
Work = "FEgHeiCD_WT4wsfB-9kDH5n6cRWCEYtJmXdKZgmUUukAOoXumH_hLlosXREC-tqq"
|
||||||
|
)
|
||||||
@@ -16,12 +16,27 @@ import (
|
|||||||
|
|
||||||
"hakurei.app/fhs"
|
"hakurei.app/fhs"
|
||||||
"hakurei.app/vfs"
|
"hakurei.app/vfs"
|
||||||
|
|
||||||
|
"hakurei.app/internal/pkg/internal/testtool/expected"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
log.SetPrefix("testtool: ")
|
log.SetPrefix("testtool: ")
|
||||||
|
|
||||||
|
if os.Getenv("HAKUREI_BINFMT") == "1" {
|
||||||
|
wantArgs := []string{"/interpreter", "/opt/bin/sample"}
|
||||||
|
if !slices.Equal(os.Args, wantArgs) {
|
||||||
|
log.Fatalf("Args: %q, want %q", os.Args, wantArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.WriteFile("check", []byte("binfmt"), 0400); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
environ := slices.DeleteFunc(slices.Clone(os.Environ()), func(s string) bool {
|
environ := slices.DeleteFunc(slices.Clone(os.Environ()), func(s string) bool {
|
||||||
return s == "CURE_JOBS="+strconv.Itoa(runtime.NumCPU())
|
return s == "CURE_JOBS="+strconv.Itoa(runtime.NumCPU())
|
||||||
})
|
})
|
||||||
@@ -147,12 +162,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const checksumEmptyDir = "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"
|
const checksumEmptyDir = "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"
|
||||||
ident := "dztPS6jRjiZtCF4_p8AzfnxGp6obkhrgFVsxdodbKWUoAEVtDz3MykepJB4kI_ks"
|
ident := expected.Offline
|
||||||
log.Println(m)
|
log.Println(m)
|
||||||
next := func() { m = m.Next; log.Println(m) }
|
next := func() { m = m.Next; log.Println(m) }
|
||||||
|
|
||||||
if overlayRoot {
|
if overlayRoot {
|
||||||
ident = "RdMA-mubnrHuu3Ky1wWyxauSYCO0ZH_zCPUj3uDHqkfwv5sGcByoF_g5PjlGiClb"
|
ident = expected.OvlRoot
|
||||||
|
|
||||||
if m.Root != "/" || m.Target != "/" ||
|
if m.Root != "/" || m.Target != "/" ||
|
||||||
m.Source != "overlay" || m.FsType != "overlay" {
|
m.Source != "overlay" || m.FsType != "overlay" {
|
||||||
@@ -170,7 +185,7 @@ func main() {
|
|||||||
log.Fatal("unexpected artifact checksum")
|
log.Fatal("unexpected artifact checksum")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ident = "p1t_drXr34i-jZNuxDMLaMOdL6tZvQqhavNafGynGqxOZoXAUTSn7kqNh3Ovv3DT"
|
ident = expected.Layers
|
||||||
|
|
||||||
if len(lowerdir) != 2 ||
|
if len(lowerdir) != 2 ||
|
||||||
filepath.Base(lowerdir[0]) != "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU" ||
|
filepath.Base(lowerdir[0]) != "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU" ||
|
||||||
@@ -180,7 +195,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if hostNet {
|
if hostNet {
|
||||||
ident = "G8qPxD9puvvoOVV7lrT80eyDeIl3G_CCFoKw12c8mCjMdG1zF7NEPkwYpNubClK3"
|
ident = expected.Net
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.Root != "/sysroot" || m.Target != "/" {
|
if m.Root != "/sysroot" || m.Target != "/" {
|
||||||
@@ -199,14 +214,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if promote {
|
if promote {
|
||||||
ident = "xXTIYcXmgJWNLC91c417RRrNM9cjELwEZHpGvf8Fk_GNP5agRJp_SicD0w9aMeLJ"
|
ident = expected.Promote
|
||||||
}
|
}
|
||||||
|
|
||||||
next() // testtool artifact
|
next() // testtool artifact
|
||||||
|
|
||||||
next()
|
next()
|
||||||
if overlayWork {
|
if overlayWork {
|
||||||
ident = "5hlaukCirnXE4W_RSLJFOZN47Z5RiHnacXzdFp_70cLgiJUGR6cSb_HaFftkzi0-"
|
ident = expected.Work
|
||||||
if m.Root != "/" || m.Target != "/work" ||
|
if m.Root != "/" || m.Target != "/work" ||
|
||||||
m.Source != "overlay" || m.FsType != "overlay" {
|
m.Source != "overlay" || m.FsType != "overlay" {
|
||||||
log.Fatal("unexpected work mount entry")
|
log.Fatal("unexpected work mount entry")
|
||||||
+47
-11
@@ -76,6 +76,9 @@ type IContext struct {
|
|||||||
// Written to by various methods, should be zeroed after [Artifact.Params]
|
// Written to by various methods, should be zeroed after [Artifact.Params]
|
||||||
// returns and must not be exposed directly.
|
// returns and must not be exposed directly.
|
||||||
w io.Writer
|
w io.Writer
|
||||||
|
// Optional [Artifact] to cureRes cache, replaces [IRKindIdent] with
|
||||||
|
// checksum values if non-nil.
|
||||||
|
inputs map[Artifact]cureRes
|
||||||
}
|
}
|
||||||
|
|
||||||
// irZero is a zero IR word.
|
// irZero is a zero IR word.
|
||||||
@@ -163,7 +166,15 @@ func (i *IContext) WriteIdent(a Artifact) {
|
|||||||
defer i.ic.putIdentBuf(buf)
|
defer i.ic.putIdentBuf(buf)
|
||||||
|
|
||||||
IRKindIdent.encodeHeader(0).put(buf[:])
|
IRKindIdent.encodeHeader(0).put(buf[:])
|
||||||
*(*ID)(buf[wordSize:]) = i.ic.Ident(a).Value()
|
if i.inputs != nil {
|
||||||
|
res, ok := i.inputs[a]
|
||||||
|
if !ok {
|
||||||
|
panic(InvalidLookupError(i.ic.Ident(a).Value()))
|
||||||
|
}
|
||||||
|
*(*ID)(buf[wordSize:]) = res.checksum.Value()
|
||||||
|
} else {
|
||||||
|
*(*ID)(buf[wordSize:]) = i.ic.Ident(a).Value()
|
||||||
|
}
|
||||||
i.mustWrite(buf[:])
|
i.mustWrite(buf[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,19 +218,44 @@ func (i *IContext) WriteString(s string) {
|
|||||||
// Encode writes a deterministic, efficient representation of a to w and returns
|
// Encode writes a deterministic, efficient representation of a to w and returns
|
||||||
// the first non-nil error encountered while writing to w.
|
// the first non-nil error encountered while writing to w.
|
||||||
func (ic *irCache) Encode(w io.Writer, a Artifact) (err error) {
|
func (ic *irCache) Encode(w io.Writer, a Artifact) (err error) {
|
||||||
|
return ic.encode(w, a, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode implements Encode but replaces identifiers with their cured checksums
|
||||||
|
// for a non-nil ident. Caller must acquire Cache.identMu.
|
||||||
|
func (ic *irCache) encode(
|
||||||
|
w io.Writer,
|
||||||
|
a Artifact,
|
||||||
|
inputs map[Artifact]cureRes,
|
||||||
|
) (err error) {
|
||||||
deps := a.Dependencies()
|
deps := a.Dependencies()
|
||||||
idents := make([]*extIdent, len(deps))
|
idents := make([]*extIdent, len(deps))
|
||||||
for i, d := range deps {
|
if inputs == nil {
|
||||||
dbuf, did := ic.unsafeIdent(d, true)
|
for i, d := range deps {
|
||||||
if dbuf == nil {
|
dbuf, did := ic.unsafeIdent(d, true)
|
||||||
dbuf = ic.getIdentBuf()
|
if dbuf == nil {
|
||||||
|
dbuf = ic.getIdentBuf()
|
||||||
|
binary.LittleEndian.PutUint64(dbuf[:], uint64(d.Kind()))
|
||||||
|
*(*ID)(dbuf[wordSize:]) = did.Value()
|
||||||
|
} else {
|
||||||
|
ic.storeIdent(d, dbuf)
|
||||||
|
}
|
||||||
|
defer ic.putIdentBuf(dbuf)
|
||||||
|
idents[i] = dbuf
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i, d := range deps {
|
||||||
|
res, ok := inputs[d]
|
||||||
|
if !ok {
|
||||||
|
return InvalidLookupError(ic.Ident(d).Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
dbuf := ic.getIdentBuf()
|
||||||
binary.LittleEndian.PutUint64(dbuf[:], uint64(d.Kind()))
|
binary.LittleEndian.PutUint64(dbuf[:], uint64(d.Kind()))
|
||||||
*(*ID)(dbuf[wordSize:]) = did.Value()
|
*(*ID)(dbuf[wordSize:]) = res.checksum.Value()
|
||||||
} else {
|
defer ic.putIdentBuf(dbuf)
|
||||||
ic.storeIdent(d, dbuf)
|
idents[i] = dbuf
|
||||||
}
|
}
|
||||||
defer ic.putIdentBuf(dbuf)
|
|
||||||
idents[i] = dbuf
|
|
||||||
}
|
}
|
||||||
slices.SortFunc(idents, func(a, b *extIdent) int {
|
slices.SortFunc(idents, func(a, b *extIdent) int {
|
||||||
return bytes.Compare(a[:], b[:])
|
return bytes.Compare(a[:], b[:])
|
||||||
@@ -244,7 +280,7 @@ func (ic *irCache) Encode(w io.Writer, a Artifact) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
i := IContext{ic, w}
|
i := IContext{ic, w, inputs}
|
||||||
|
|
||||||
defer panicToError(&err)
|
defer panicToError(&err)
|
||||||
defer func() { i.ic, i.w = nil, nil }()
|
defer func() { i.ic, i.w = nil, nil }()
|
||||||
|
|||||||
+33
-6
@@ -3,6 +3,7 @@ package pkg_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ func TestIRRoundtrip(t *testing.T) {
|
|||||||
)},
|
)},
|
||||||
|
|
||||||
{"exec offline", pkg.NewExec(
|
{"exec offline", pkg.NewExec(
|
||||||
"exec-offline", nil, 0, false,
|
"exec-offline", "", nil, 0, false, false,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1"},
|
[]string{"HAKUREI_TEST=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -58,9 +59,9 @@ func TestIRRoundtrip(t *testing.T) {
|
|||||||
)},
|
)},
|
||||||
|
|
||||||
{"exec net", pkg.NewExec(
|
{"exec net", pkg.NewExec(
|
||||||
"exec-net",
|
"exec-net", "",
|
||||||
(*pkg.Checksum)(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))),
|
(*pkg.Checksum)(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))),
|
||||||
0, false,
|
0, false, false,
|
||||||
pkg.AbsWork,
|
pkg.AbsWork,
|
||||||
[]string{"HAKUREI_TEST=1"},
|
[]string{"HAKUREI_TEST=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -79,6 +80,28 @@ func TestIRRoundtrip(t *testing.T) {
|
|||||||
)),
|
)),
|
||||||
)},
|
)},
|
||||||
|
|
||||||
|
{"exec measured", pkg.NewExec(
|
||||||
|
"exec-measured", "",
|
||||||
|
(*pkg.Checksum)(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))),
|
||||||
|
0, false, false,
|
||||||
|
pkg.AbsWork,
|
||||||
|
[]string{"HAKUREI_TEST=1"},
|
||||||
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
|
[]string{"testtool", "measured"},
|
||||||
|
|
||||||
|
pkg.MustPath("/file", false, pkg.NewFile("file", []byte(
|
||||||
|
"stub file",
|
||||||
|
))), pkg.MustPath("/.hakurei", false, pkg.NewHTTPGetTar(
|
||||||
|
nil, "file:///hakurei.tar",
|
||||||
|
pkg.Checksum(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))),
|
||||||
|
pkg.TarUncompressed,
|
||||||
|
)), pkg.MustPath("/opt", false, pkg.NewHTTPGetTar(
|
||||||
|
nil, "file:///testtool.tar.gz",
|
||||||
|
pkg.Checksum(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))),
|
||||||
|
pkg.TarGzip,
|
||||||
|
)),
|
||||||
|
)},
|
||||||
|
|
||||||
{"file anonymous", pkg.NewFile("", []byte{0})},
|
{"file anonymous", pkg.NewFile("", []byte{0})},
|
||||||
{"file", pkg.NewFile("stub", []byte("stub"))},
|
{"file", pkg.NewFile("stub", []byte("stub"))},
|
||||||
}
|
}
|
||||||
@@ -105,9 +128,13 @@ func TestIRRoundtrip(t *testing.T) {
|
|||||||
if err := <-done; err != nil {
|
if err := <-done; err != nil {
|
||||||
t.Fatalf("EncodeAll: error = %v", err)
|
t.Fatalf("EncodeAll: error = %v", err)
|
||||||
}
|
}
|
||||||
}, pkg.MustDecode(
|
}, expectsFS{
|
||||||
"E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C",
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
),
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkWithCache(t, testCasesCache)
|
checkWithCache(t, testCasesCache)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package pkg_test
|
|||||||
import (
|
import (
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -85,7 +86,13 @@ func TestHTTPGet(t *testing.T) {
|
|||||||
if _, err := f.Cure(r); !reflect.DeepEqual(err, wantErrNotFound) {
|
if _, err := f.Cure(r); !reflect.DeepEqual(err, wantErrNotFound) {
|
||||||
t.Fatalf("Cure: error = %#v, want %#v", err, wantErrNotFound)
|
t.Fatalf("Cure: error = %#v, want %#v", err, wantErrNotFound)
|
||||||
}
|
}
|
||||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
{"cure", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"cure", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
r := newRContext(t, c)
|
r := newRContext(t, c)
|
||||||
@@ -144,6 +151,18 @@ func TestHTTPGet(t *testing.T) {
|
|||||||
if _, _, err := c.Cure(f); !reflect.DeepEqual(err, wantErrNotFound) {
|
if _, _, err := c.Cure(f); !reflect.DeepEqual(err, wantErrNotFound) {
|
||||||
t.Fatalf("Pathname: error = %#v, want %#v", err, wantErrNotFound)
|
t.Fatalf("Pathname: error = %#v, want %#v", err, wantErrNotFound)
|
||||||
}
|
}
|
||||||
}, pkg.MustDecode("L_0RFHpr9JUS4Zp14rz2dESSRvfLzpvqsLhR1-YjQt8hYlmEdVl7vI3_-v8UNPKs")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU": {Mode: 0400, Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/oM-2pUlk-mOxK1t3aMWZer69UdOQlAXiAgMrpZ1476VoOqpYVP1aGFS9_HYy-D8_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+316
-77
@@ -4,6 +4,7 @@ package pkg
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
@@ -15,6 +16,7 @@ import (
|
|||||||
"io/fs"
|
"io/fs"
|
||||||
"maps"
|
"maps"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -24,6 +26,7 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
"unique"
|
"unique"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -247,7 +250,14 @@ func (t *TContext) destroy(errP *error) {
|
|||||||
*errP = errors.Join(*errP, err)
|
*errP = errors.Join(*errP, err)
|
||||||
}
|
}
|
||||||
if *errP != nil {
|
if *errP != nil {
|
||||||
*errP = errors.Join(*errP, os.Remove(t.statusPath.String()))
|
*errP = errors.Join(*errP, os.Rename(
|
||||||
|
t.statusPath.String(), t.cache.base.Append(
|
||||||
|
dirFault,
|
||||||
|
t.ids+"."+strconv.FormatUint(uint64(
|
||||||
|
time.Now().UnixNano(),
|
||||||
|
), 10),
|
||||||
|
).String(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
t.status = nil
|
t.status = nil
|
||||||
}
|
}
|
||||||
@@ -508,33 +518,34 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// fileLock is the file name appended to Cache.base for guaranteeing
|
// fileLock is the lock file for exclusive access to the cache directory.
|
||||||
// exclusive access to the cache directory.
|
|
||||||
fileLock = "lock"
|
fileLock = "lock"
|
||||||
// fileVariant is the file name appended to Cache.base holding the variant
|
// fileVariant is a file holding the variant identification string set by a
|
||||||
// identification string set by a prior call to [SetExtension].
|
// prior call to [SetExtension].
|
||||||
fileVariant = "variant"
|
fileVariant = "variant"
|
||||||
|
|
||||||
// dirIdentifier is the directory name appended to Cache.base for storing
|
// dirSubstitute holds symlinks to artifacts by checksum, named after their
|
||||||
// artifacts named after their [ID].
|
// substitute identifier.
|
||||||
|
dirSubstitute = "substitute"
|
||||||
|
// dirIdentifier holds symlinks to artifacts by checksum, named after their
|
||||||
|
// IR-based identifier.
|
||||||
dirIdentifier = "identifier"
|
dirIdentifier = "identifier"
|
||||||
// dirChecksum is the directory name appended to Cache.base for storing
|
// dirChecksum holds artifacts named after their [Checksum].
|
||||||
// artifacts named after their [Checksum].
|
|
||||||
dirChecksum = "checksum"
|
dirChecksum = "checksum"
|
||||||
// dirStatus is the directory name appended to Cache.base for storing
|
// dirStatus holds artifact metadata and logs named after their IR-based
|
||||||
// artifact metadata and logs named after their [ID].
|
// identifier. For [FloodArtifact], the same file is also available under
|
||||||
|
// its substitute identifier.
|
||||||
dirStatus = "status"
|
dirStatus = "status"
|
||||||
|
// dirFault holds status files of faulted cures.
|
||||||
|
dirFault = "fault"
|
||||||
|
|
||||||
// dirWork is the directory name appended to Cache.base for working
|
// dirWork holds working pathnames set up during [Cache.Cure].
|
||||||
// pathnames set up during [Cache.Cure].
|
|
||||||
dirWork = "work"
|
dirWork = "work"
|
||||||
// dirTemp is the directory name appended to Cache.base for scratch space
|
// dirTemp holds scratch space allocated during [Cache.Cure].
|
||||||
// pathnames allocated during [Cache.Cure].
|
|
||||||
dirTemp = "temp"
|
dirTemp = "temp"
|
||||||
|
|
||||||
// dirExecScratch is the directory name appended to Cache.base for scratch
|
// dirExecScratch is scratch space set up for the container started by
|
||||||
// space setting up the container started by [Cache.EnterExec]. Exclusivity
|
// [Cache.EnterExec]. Exclusivity via Cache.inExec.
|
||||||
// via Cache.inExec.
|
|
||||||
dirExecScratch = "scratch"
|
dirExecScratch = "scratch"
|
||||||
|
|
||||||
// checksumLinknamePrefix is prepended to the encoded [Checksum] value
|
// checksumLinknamePrefix is prepended to the encoded [Checksum] value
|
||||||
@@ -617,6 +628,13 @@ const (
|
|||||||
// CPromoteVariant allows [pkg.Open] to promote an unextended on-disk cache
|
// CPromoteVariant allows [pkg.Open] to promote an unextended on-disk cache
|
||||||
// to the current extension variant. This is a one-way operation.
|
// to the current extension variant. This is a one-way operation.
|
||||||
CPromoteVariant
|
CPromoteVariant
|
||||||
|
|
||||||
|
// CSuppressInit arranges for verbose output of the container init to be
|
||||||
|
// suppressed regardless of [message.Msg] state.
|
||||||
|
CSuppressInit
|
||||||
|
|
||||||
|
// CIgnoreSubstitutes disables content-based dependency substitution.
|
||||||
|
CIgnoreSubstitutes
|
||||||
)
|
)
|
||||||
|
|
||||||
// toplevel holds [context.WithCancel] over caller-supplied context, where all
|
// toplevel holds [context.WithCancel] over caller-supplied context, where all
|
||||||
@@ -672,6 +690,11 @@ type Cache struct {
|
|||||||
// Synchronises access to dirChecksum.
|
// Synchronises access to dirChecksum.
|
||||||
checksumMu sync.RWMutex
|
checksumMu sync.RWMutex
|
||||||
|
|
||||||
|
// Presence of an alternative in the cache. Keys are not valid identifiers
|
||||||
|
// and must not be used as such.
|
||||||
|
substitute map[unique.Handle[ID]]unique.Handle[Checksum]
|
||||||
|
// Synchronises access to substitute and corresponding filesystem entries.
|
||||||
|
substituteMu sync.RWMutex
|
||||||
// Identifier to content pair cache.
|
// Identifier to content pair cache.
|
||||||
ident map[unique.Handle[ID]]unique.Handle[Checksum]
|
ident map[unique.Handle[ID]]unique.Handle[Checksum]
|
||||||
// Identifier to error pair for unrecoverably faulted [Artifact].
|
// Identifier to error pair for unrecoverably faulted [Artifact].
|
||||||
@@ -882,11 +905,14 @@ func (c *Cache) Scrub(checks int) error {
|
|||||||
checks = runtime.NumCPU()
|
checks = runtime.NumCPU()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.substituteMu.Lock()
|
||||||
|
defer c.substituteMu.Unlock()
|
||||||
c.identMu.Lock()
|
c.identMu.Lock()
|
||||||
defer c.identMu.Unlock()
|
defer c.identMu.Unlock()
|
||||||
c.checksumMu.Lock()
|
c.checksumMu.Lock()
|
||||||
defer c.checksumMu.Unlock()
|
defer c.checksumMu.Unlock()
|
||||||
|
|
||||||
|
c.substitute = make(map[unique.Handle[ID]]unique.Handle[Checksum])
|
||||||
c.ident = make(map[unique.Handle[ID]]unique.Handle[Checksum])
|
c.ident = make(map[unique.Handle[ID]]unique.Handle[Checksum])
|
||||||
c.identErr = make(map[unique.Handle[ID]]error)
|
c.identErr = make(map[unique.Handle[ID]]error)
|
||||||
c.artifact.Clear()
|
c.artifact.Clear()
|
||||||
@@ -994,47 +1020,52 @@ func (c *Cache) Scrub(checks int) error {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = c.base.Append(dirIdentifier)
|
for _, suffix := range []string{
|
||||||
if entries, readdirErr := os.ReadDir(dir.String()); readdirErr != nil {
|
dirSubstitute,
|
||||||
addErr(dir, readdirErr)
|
dirIdentifier,
|
||||||
} else {
|
} {
|
||||||
wg.Add(len(entries))
|
dir = c.base.Append(suffix)
|
||||||
for _, ent := range entries {
|
if entries, readdirErr := os.ReadDir(dir.String()); readdirErr != nil {
|
||||||
w <- checkEntry{ent, func(ent os.DirEntry, want *Checksum) bool {
|
addErr(dir, readdirErr)
|
||||||
got := p.Get().(*Checksum)
|
} else {
|
||||||
defer p.Put(got)
|
wg.Add(len(entries))
|
||||||
|
for _, ent := range entries {
|
||||||
|
w <- checkEntry{ent, func(ent os.DirEntry, want *Checksum) bool {
|
||||||
|
got := p.Get().(*Checksum)
|
||||||
|
defer p.Put(got)
|
||||||
|
|
||||||
pathname := dir.Append(ent.Name())
|
pathname := dir.Append(ent.Name())
|
||||||
if linkname, err := os.Readlink(
|
if linkname, err := os.Readlink(
|
||||||
pathname.String(),
|
pathname.String(),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
seMu.Lock()
|
seMu.Lock()
|
||||||
se.Errs[pathname.Handle()] = append(se.Errs[pathname.Handle()], err)
|
se.Errs[pathname.Handle()] = append(se.Errs[pathname.Handle()], err)
|
||||||
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
||||||
seMu.Unlock()
|
seMu.Unlock()
|
||||||
return false
|
return false
|
||||||
} else if err = Decode(got, filepath.Base(linkname)); err != nil {
|
} else if err = Decode(got, filepath.Base(linkname)); err != nil {
|
||||||
seMu.Lock()
|
seMu.Lock()
|
||||||
lnp := dir.Append(linkname)
|
lnp := dir.Append(linkname)
|
||||||
se.Errs[lnp.Handle()] = append(se.Errs[lnp.Handle()], err)
|
se.Errs[lnp.Handle()] = append(se.Errs[lnp.Handle()], err)
|
||||||
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
||||||
seMu.Unlock()
|
seMu.Unlock()
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Stat(pathname.String()); err != nil {
|
|
||||||
if !errors.Is(err, os.ErrNotExist) {
|
|
||||||
addErr(pathname, err)
|
|
||||||
}
|
}
|
||||||
seMu.Lock()
|
|
||||||
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
if _, err := os.Stat(pathname.String()); err != nil {
|
||||||
seMu.Unlock()
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
return false
|
addErr(pathname, err)
|
||||||
}
|
}
|
||||||
return true
|
seMu.Lock()
|
||||||
}}
|
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
||||||
|
seMu.Unlock()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
}
|
}
|
||||||
wg.Wait()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = c.base.Append(dirStatus)
|
dir = c.base.Append(dirStatus)
|
||||||
@@ -1182,6 +1213,52 @@ func (c *Cache) finaliseIdent(
|
|||||||
close(done)
|
close(done)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zeroChecksum is a zero [Checksum] handle, used for comparison only.
|
||||||
|
var zeroChecksum unique.Handle[Checksum]
|
||||||
|
|
||||||
|
// loadSubstitute returns a checksum corresponding to a substitute identifier,
|
||||||
|
// or zeroChecksum if an alternative is not available.
|
||||||
|
func (c *Cache) loadSubstitute(
|
||||||
|
substitute unique.Handle[ID],
|
||||||
|
) (unique.Handle[Checksum], error) {
|
||||||
|
c.substituteMu.RLock()
|
||||||
|
if checksum, ok := c.substitute[substitute]; ok {
|
||||||
|
c.substituteMu.RUnlock()
|
||||||
|
return checksum, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
linkname, err := os.Readlink(c.base.Append(
|
||||||
|
dirSubstitute,
|
||||||
|
Encode(substitute.Value()),
|
||||||
|
).String())
|
||||||
|
c.substituteMu.RUnlock()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return zeroChecksum, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.substituteMu.Lock()
|
||||||
|
c.substitute[substitute] = zeroChecksum
|
||||||
|
c.substituteMu.Unlock()
|
||||||
|
return zeroChecksum, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var checksum unique.Handle[Checksum]
|
||||||
|
buf := c.getIdentBuf()
|
||||||
|
err = Decode((*Checksum)(buf[:]), filepath.Base(linkname))
|
||||||
|
if err == nil {
|
||||||
|
checksum = unique.Make(Checksum(buf[:]))
|
||||||
|
|
||||||
|
c.substituteMu.Lock()
|
||||||
|
c.substitute[substitute] = checksum
|
||||||
|
c.substituteMu.Unlock()
|
||||||
|
}
|
||||||
|
c.putIdentBuf(buf)
|
||||||
|
|
||||||
|
return checksum, err
|
||||||
|
}
|
||||||
|
|
||||||
// Done returns a channel that is closed when the ongoing cure of an [Artifact]
|
// Done returns a channel that is closed when the ongoing cure of an [Artifact]
|
||||||
// referred to by the specified identifier completes. Done may return nil if
|
// referred to by the specified identifier completes. Done may return nil if
|
||||||
// no ongoing cure of the specified identifier exists.
|
// no ongoing cure of the specified identifier exists.
|
||||||
@@ -1416,8 +1493,8 @@ func (c *Cache) Cure(a Artifact) (
|
|||||||
|
|
||||||
// CureError wraps a non-nil error returned attempting to cure an [Artifact].
|
// CureError wraps a non-nil error returned attempting to cure an [Artifact].
|
||||||
type CureError struct {
|
type CureError struct {
|
||||||
Ident unique.Handle[ID]
|
A Artifact
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwrap returns the underlying error.
|
// Unwrap returns the underlying error.
|
||||||
@@ -1430,40 +1507,63 @@ func (e *CureError) Error() string { return e.Err.Error() }
|
|||||||
type DependencyCureError []*CureError
|
type DependencyCureError []*CureError
|
||||||
|
|
||||||
// unwrapM recursively expands underlying errors into a caller-supplied map.
|
// unwrapM recursively expands underlying errors into a caller-supplied map.
|
||||||
func (e *DependencyCureError) unwrapM(me map[unique.Handle[ID]]*CureError) {
|
func (e *DependencyCureError) unwrapM(
|
||||||
|
ctx context.Context,
|
||||||
|
ir *IRCache,
|
||||||
|
me map[unique.Handle[ID]]*CureError,
|
||||||
|
) {
|
||||||
for _, err := range *e {
|
for _, err := range *e {
|
||||||
if _, ok := me[err.Ident]; ok {
|
if ctx.Err() != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
id := ir.Ident(err.A)
|
||||||
|
if _, ok := me[id]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _e, ok := err.Err.(*DependencyCureError); ok {
|
if _e, ok := err.Err.(*DependencyCureError); ok {
|
||||||
_e.unwrapM(me)
|
_e.unwrapM(ctx, ir, me)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
me[err.Ident] = err
|
me[id] = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unwrap recursively expands and deduplicates underlying errors.
|
// unwrap recursively expands and deduplicates underlying errors.
|
||||||
func (e *DependencyCureError) unwrap() DependencyCureError {
|
func (e *DependencyCureError) unwrap(
|
||||||
|
ctx context.Context,
|
||||||
|
ir *IRCache,
|
||||||
|
) DependencyCureError {
|
||||||
me := make(map[unique.Handle[ID]]*CureError)
|
me := make(map[unique.Handle[ID]]*CureError)
|
||||||
e.unwrapM(me)
|
e.unwrapM(ctx, ir, me)
|
||||||
errs := slices.AppendSeq(
|
type ent struct {
|
||||||
make(DependencyCureError, 0, len(me)),
|
id unique.Handle[ID]
|
||||||
maps.Values(me),
|
err *CureError
|
||||||
)
|
}
|
||||||
|
errs := make([]*ent, 0, len(me))
|
||||||
|
for id, err := range me {
|
||||||
|
errs = append(errs, &ent{id, err})
|
||||||
|
}
|
||||||
|
|
||||||
var identBuf [2]ID
|
var identBuf [2]ID
|
||||||
slices.SortFunc(errs, func(a, b *CureError) int {
|
slices.SortFunc(errs, func(a, b *ent) int {
|
||||||
identBuf[0], identBuf[1] = a.Ident.Value(), b.Ident.Value()
|
identBuf[0], identBuf[1] = a.id.Value(), b.id.Value()
|
||||||
return slices.Compare(identBuf[0][:], identBuf[1][:])
|
return slices.Compare(identBuf[0][:], identBuf[1][:])
|
||||||
})
|
})
|
||||||
|
|
||||||
return errs
|
_errs := make(DependencyCureError, len(errs))
|
||||||
|
for i, v := range errs {
|
||||||
|
_errs[i] = v.err
|
||||||
|
}
|
||||||
|
return _errs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwrap returns a deduplicated slice of underlying errors.
|
// Unwrap returns a deduplicated slice of underlying errors.
|
||||||
func (e *DependencyCureError) Unwrap() []error {
|
func (e *DependencyCureError) Unwrap() []error {
|
||||||
errs := e.unwrap()
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
errs := e.unwrap(ctx, NewIR())
|
||||||
_errs := make([]error, len(errs))
|
_errs := make([]error, len(errs))
|
||||||
for i, err := range errs {
|
for i, err := range errs {
|
||||||
_errs[i] = err
|
_errs[i] = err
|
||||||
@@ -1473,14 +1573,23 @@ func (e *DependencyCureError) Unwrap() []error {
|
|||||||
|
|
||||||
// Error returns a user-facing multiline error message.
|
// Error returns a user-facing multiline error message.
|
||||||
func (e *DependencyCureError) Error() string {
|
func (e *DependencyCureError) Error() string {
|
||||||
errs := e.unwrap()
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
ir := NewIR()
|
||||||
|
errs := e.unwrap(ctx, ir)
|
||||||
if len(errs) == 0 {
|
if len(errs) == 0 {
|
||||||
return "invalid dependency cure outcome"
|
return "invalid dependency cure outcome"
|
||||||
}
|
}
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
buf.WriteString("errors curing dependencies:")
|
buf.WriteString("errors curing dependencies:")
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
buf.WriteString("\n\t" + Encode(err.Ident.Value()) + ": " + err.Error())
|
buf.WriteString("\n\t" +
|
||||||
|
reportName(err.A, ir.Ident(err.A)) + ": " +
|
||||||
|
err.Error())
|
||||||
|
}
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
buf.WriteString("\nerror resolution cancelled")
|
||||||
}
|
}
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
@@ -1650,16 +1759,44 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var checksums string
|
var (
|
||||||
|
checksums string
|
||||||
|
substitute unique.Handle[ID]
|
||||||
|
alternative *check.Absolute
|
||||||
|
)
|
||||||
defer func() {
|
defer func() {
|
||||||
if err == nil && checksums != "" {
|
if err == nil && checksums != "" {
|
||||||
|
linkname := checksumLinknamePrefix + checksums
|
||||||
|
|
||||||
err = os.Symlink(
|
err = os.Symlink(
|
||||||
checksumLinknamePrefix+checksums,
|
linkname,
|
||||||
pathname.String(),
|
pathname.String(),
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = zeroTimes(pathname.String())
|
err = zeroTimes(pathname.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err == nil && alternative != nil {
|
||||||
|
c.substituteMu.Lock()
|
||||||
|
err = os.Symlink(
|
||||||
|
linkname,
|
||||||
|
alternative.String(),
|
||||||
|
)
|
||||||
|
if errors.Is(err, os.ErrExist) {
|
||||||
|
c.msg.Verbosef(
|
||||||
|
"creating alternative over %s for artifact %s",
|
||||||
|
Encode(substitute.Value()), ids,
|
||||||
|
)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
err = zeroTimes(alternative.String())
|
||||||
|
}
|
||||||
|
if err == nil && checksum != zeroChecksum {
|
||||||
|
c.substitute[substitute] = checksum
|
||||||
|
}
|
||||||
|
c.substituteMu.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -1856,11 +1993,64 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
|||||||
f.deps[deps[i]] = p
|
f.deps[deps[i]] = p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sh := sha512.New384()
|
||||||
|
err = c.encode(sh, a, f.deps)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := c.getIdentBuf()
|
||||||
|
sh.Sum(buf[wordSize:wordSize])
|
||||||
|
substitute = unique.Make(ID(buf[wordSize:]))
|
||||||
|
substitutes := Encode(substitute.Value())
|
||||||
|
c.putIdentBuf(buf)
|
||||||
|
alternative = c.base.Append(
|
||||||
|
dirSubstitute,
|
||||||
|
substitutes,
|
||||||
|
)
|
||||||
|
|
||||||
|
if c.flags&CIgnoreSubstitutes == 0 {
|
||||||
|
var substituteChecksum unique.Handle[Checksum]
|
||||||
|
substituteChecksum, err = c.loadSubstitute(substitute)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if substituteChecksum != zeroChecksum {
|
||||||
|
checksum = substituteChecksum
|
||||||
|
checksums = Encode(checksum.Value())
|
||||||
|
checksumPathname = c.base.Append(
|
||||||
|
dirChecksum,
|
||||||
|
checksums,
|
||||||
|
)
|
||||||
|
if _, err = os.Lstat(c.base.Append(
|
||||||
|
dirStatus,
|
||||||
|
substitutes,
|
||||||
|
).String()); err == nil {
|
||||||
|
err = os.Symlink(substitutes, c.base.Append(
|
||||||
|
dirStatus,
|
||||||
|
ids,
|
||||||
|
).String())
|
||||||
|
} else if errors.Is(err, os.ErrNotExist) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
defer f.destroy(&err)
|
defer f.destroy(&err)
|
||||||
if err = c.enterCure(a, curesExempt); err != nil {
|
if err = c.enterCure(a, curesExempt); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = ca.Cure(&f)
|
err = ca.Cure(&f)
|
||||||
|
if err == nil && f.status != nil {
|
||||||
|
err = os.Link(c.base.Append(
|
||||||
|
dirStatus,
|
||||||
|
ids,
|
||||||
|
).String(), c.base.Append(
|
||||||
|
dirStatus,
|
||||||
|
substitutes,
|
||||||
|
).String())
|
||||||
|
}
|
||||||
c.exitCure(a, curesExempt)
|
c.exitCure(a, curesExempt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -1953,7 +2143,7 @@ func (pending *pendingArtifactDep) cure(c *Cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pending.errsMu.Lock()
|
pending.errsMu.Lock()
|
||||||
*pending.errs = append(*pending.errs, &CureError{c.Ident(pending.a), err})
|
*pending.errs = append(*pending.errs, &CureError{pending.a, err})
|
||||||
pending.errsMu.Unlock()
|
pending.errsMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1969,6 +2159,52 @@ func (c *Cache) OpenStatus(a Artifact) (r io.ReadSeekCloser, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fault holds the pathname and termination time of an [Artifact] fault entry.
|
||||||
|
type Fault struct {
|
||||||
|
*check.Absolute
|
||||||
|
t uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time returns the instant in time where the fault occurred.
|
||||||
|
func (f Fault) Time() time.Time { return time.Unix(0, int64(f.t)) }
|
||||||
|
|
||||||
|
// Open opens the underlying entry for reading.
|
||||||
|
func (f Fault) Open() (io.ReadCloser, error) { return os.Open(f.Absolute.String()) }
|
||||||
|
|
||||||
|
// Destroy removes the underlying fault entry.
|
||||||
|
func (f Fault) Destroy() error { return os.Remove(f.Absolute.String()) }
|
||||||
|
|
||||||
|
// ReadFaults returns fault entries for an [Artifact].
|
||||||
|
func (c *Cache) ReadFaults(a Artifact) (faults []Fault, err error) {
|
||||||
|
prefix := Encode(c.Ident(a).Value()) + "."
|
||||||
|
var dents []os.DirEntry
|
||||||
|
if dents, err = os.ReadDir(c.base.Append(dirFault).String()); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dent := range dents {
|
||||||
|
name := dent.Name()
|
||||||
|
if !strings.HasPrefix(name, prefix) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var t uint64
|
||||||
|
t, err = strconv.ParseUint(name[len(prefix):], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
faults = append(faults, Fault{c.base.Append(
|
||||||
|
dirFault,
|
||||||
|
name,
|
||||||
|
), t})
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.SortFunc(faults, func(a, b Fault) int {
|
||||||
|
return cmp.Compare(a.t, b.t)
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Abort cancels all pending cures and waits for them to clean up, but does not
|
// Abort cancels all pending cures and waits for them to clean up, but does not
|
||||||
// close the cache.
|
// close the cache.
|
||||||
func (c *Cache) Abort() {
|
func (c *Cache) Abort() {
|
||||||
@@ -2068,9 +2304,11 @@ func open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range []string{
|
for _, name := range []string{
|
||||||
|
dirSubstitute,
|
||||||
dirIdentifier,
|
dirIdentifier,
|
||||||
dirChecksum,
|
dirChecksum,
|
||||||
dirStatus,
|
dirStatus,
|
||||||
|
dirFault,
|
||||||
dirWork,
|
dirWork,
|
||||||
} {
|
} {
|
||||||
if err := os.MkdirAll(
|
if err := os.MkdirAll(
|
||||||
@@ -2093,6 +2331,7 @@ func open(
|
|||||||
|
|
||||||
irCache: zeroIRCache(),
|
irCache: zeroIRCache(),
|
||||||
|
|
||||||
|
substitute: make(map[unique.Handle[ID]]unique.Handle[Checksum]),
|
||||||
ident: make(map[unique.Handle[ID]]unique.Handle[Checksum]),
|
ident: make(map[unique.Handle[ID]]unique.Handle[Checksum]),
|
||||||
identErr: make(map[unique.Handle[ID]]error),
|
identErr: make(map[unique.Handle[ID]]error),
|
||||||
identPending: make(map[unique.Handle[ID]]*pendingCure),
|
identPending: make(map[unique.Handle[ID]]*pendingCure),
|
||||||
|
|||||||
+484
-125
@@ -16,9 +16,12 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
"testing/fstest"
|
||||||
|
"time"
|
||||||
"unique"
|
"unique"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -242,6 +245,41 @@ func newDestroyArtifactFunc(a pkg.Artifact) func(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// destroyStatus counts non-substitution status entries and destroys them.
|
||||||
|
func destroyStatus(t *testing.T, base *check.Absolute, c, s int) {
|
||||||
|
dents, err := os.ReadDir(base.Append("status").String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var gotC, gotS int
|
||||||
|
for _, dent := range dents {
|
||||||
|
if err = os.Remove(base.Append(
|
||||||
|
"status",
|
||||||
|
dent.Name(),
|
||||||
|
).String()); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dent.Type().IsRegular() {
|
||||||
|
gotC++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if dent.Type()&fs.ModeSymlink == fs.ModeSymlink {
|
||||||
|
gotS++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Errorf("%s: %s", dent.Name(), dent.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
if gotC != c {
|
||||||
|
t.Errorf("status: c = %d, want %d", gotC, c)
|
||||||
|
}
|
||||||
|
if gotS != s {
|
||||||
|
t.Errorf("status: s = %d, want %d", gotS, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIdent(t *testing.T) {
|
func TestIdent(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@@ -286,6 +324,99 @@ func TestIdent(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An expectsKnown describes an expected file or directory.
|
||||||
|
type expectsKnown interface {
|
||||||
|
// hash returns the checksum of the represented data.
|
||||||
|
hash() (checksum pkg.Checksum)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An expectsChecksum is a prepared checksum value.
|
||||||
|
type expectsChecksum pkg.Checksum
|
||||||
|
|
||||||
|
// hash returns e.
|
||||||
|
func (e expectsChecksum) hash() pkg.Checksum { return e }
|
||||||
|
|
||||||
|
// An expectsFile is the contents of a file expected by the test suite.
|
||||||
|
type expectsFile []byte
|
||||||
|
|
||||||
|
// hash computes the checksum of e.
|
||||||
|
func (e expectsFile) hash() (checksum pkg.Checksum) {
|
||||||
|
h := sha512.New384()
|
||||||
|
h.Write(e)
|
||||||
|
h.Sum(checksum[:0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// An expectsFS describes the state of a filesystem expected by the test suite.
|
||||||
|
type expectsFS fstest.MapFS
|
||||||
|
|
||||||
|
// hash computes the checksum of e.
|
||||||
|
func (e expectsFS) hash() (checksum pkg.Checksum) {
|
||||||
|
if err := pkg.HashFS(&checksum, fstest.MapFS(e), "."); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// expectsFrom generates expectsFS for a filesystem directory.
|
||||||
|
func expectsFrom(pathname string) string {
|
||||||
|
var buf strings.Builder
|
||||||
|
buf.WriteString("expectsFS{\n")
|
||||||
|
if err := filepath.WalkDir(pathname, func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var rel string
|
||||||
|
if rel, err = filepath.Rel(pathname, path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buf.WriteString("\t" + strconv.Quote(rel) + ": {Mode: ")
|
||||||
|
|
||||||
|
var fi fs.FileInfo
|
||||||
|
if fi, err = d.Info(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mode := fi.Mode()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case mode.IsDir():
|
||||||
|
buf.WriteString("fs.ModeDir | 0" +
|
||||||
|
strconv.FormatInt(int64(mode&^fs.ModeDir), 8))
|
||||||
|
|
||||||
|
case mode&fs.ModeSymlink != 0:
|
||||||
|
buf.WriteString("fs.ModeSymlink | 0" +
|
||||||
|
strconv.FormatInt(int64(mode&^fs.ModeSymlink), 8) +
|
||||||
|
", Data: []byte(")
|
||||||
|
var linkname string
|
||||||
|
if linkname, err = os.Readlink(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buf.WriteString(strconv.Quote(linkname))
|
||||||
|
buf.WriteByte(')')
|
||||||
|
|
||||||
|
case mode.IsRegular():
|
||||||
|
buf.WriteString("0" + strconv.FormatInt(int64(mode), 8))
|
||||||
|
var p []byte
|
||||||
|
if p, err = os.ReadFile(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p) > 0 {
|
||||||
|
buf.WriteString(", Data: []byte(")
|
||||||
|
buf.WriteString(strconv.Quote(unsafe.String(unsafe.SliceData(p), len(p))))
|
||||||
|
buf.WriteByte(')')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.WriteString("},\n")
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
buf.WriteString("}")
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
// cacheTestCase is a test case passed to checkWithCache where a new instance
|
// cacheTestCase is a test case passed to checkWithCache where a new instance
|
||||||
// of [pkg.Cache] is prepared for the test case, and is validated and removed
|
// of [pkg.Cache] is prepared for the test case, and is validated and removed
|
||||||
// on test completion.
|
// on test completion.
|
||||||
@@ -294,9 +425,15 @@ type cacheTestCase struct {
|
|||||||
flags int
|
flags int
|
||||||
early func(t *testing.T, base *check.Absolute)
|
early func(t *testing.T, base *check.Absolute)
|
||||||
f func(t *testing.T, base *check.Absolute, c *pkg.Cache)
|
f func(t *testing.T, base *check.Absolute, c *pkg.Cache)
|
||||||
want pkg.Checksum
|
want expectsFS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// checkDestroySubstitutes arranges for substitutes to be destroyed before
|
||||||
|
// measurement during checkWithCache.
|
||||||
|
checkDestroySubstitutes = 1 << (iota + 32)
|
||||||
|
)
|
||||||
|
|
||||||
// checkWithCache runs a slice of cacheTestCase.
|
// checkWithCache runs a slice of cacheTestCase.
|
||||||
func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
@@ -328,7 +465,7 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
|||||||
msg := message.New(log.New(os.Stderr, "cache: ", 0))
|
msg := message.New(log.New(os.Stderr, "cache: ", 0))
|
||||||
msg.SwapVerbose(testing.Verbose())
|
msg.SwapVerbose(testing.Verbose())
|
||||||
|
|
||||||
flags := tc.flags
|
flags := tc.flags | pkg.CSuppressInit
|
||||||
|
|
||||||
if info.CanDegrade {
|
if info.CanDegrade {
|
||||||
if _, err := landlock.GetABI(); err != nil {
|
if _, err := landlock.GetABI(); err != nil {
|
||||||
@@ -377,19 +514,34 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy non-deterministic status files
|
// destroy non-deterministic substitutes
|
||||||
if err := os.RemoveAll(base.Append("status").String()); err != nil {
|
if tc.flags&checkDestroySubstitutes != 0 {
|
||||||
|
substitute := base.Append("substitute")
|
||||||
|
if err := os.RemoveAll(substitute.String()); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if err = os.Mkdir(substitute.String(), 0700); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// destroy empty status directory
|
||||||
|
if err := syscall.Rmdir(base.Append("status").String()); err != nil {
|
||||||
|
t.Error(expectsFrom(base.Append("status").String()))
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// destroy empty fault directory
|
||||||
|
if err := os.Remove(base.Append("fault").String()); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := tc.want.hash()
|
||||||
|
|
||||||
var checksum pkg.Checksum
|
var checksum pkg.Checksum
|
||||||
if err := pkg.HashDir(&checksum, base); err != nil {
|
if err := pkg.HashDir(&checksum, base); err != nil {
|
||||||
t.Fatalf("HashDir: error = %v", err)
|
t.Fatalf("HashDir: error = %v", err)
|
||||||
} else if checksum != tc.want {
|
} else if checksum != want {
|
||||||
t.Fatalf("HashDir: %v", &pkg.ChecksumMismatchError{
|
t.Fatal(expectsFrom(base.String()))
|
||||||
Got: checksum,
|
|
||||||
Want: tc.want,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scrubFunc(); err != nil {
|
if err := scrubFunc(); err != nil {
|
||||||
@@ -408,10 +560,10 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
|||||||
// validate again to make sure scrub did not condemn anything
|
// validate again to make sure scrub did not condemn anything
|
||||||
if err := pkg.HashDir(&checksum, base); err != nil {
|
if err := pkg.HashDir(&checksum, base); err != nil {
|
||||||
t.Fatalf("HashDir: error = %v", err)
|
t.Fatalf("HashDir: error = %v", err)
|
||||||
} else if checksum != tc.want {
|
} else if checksum != want {
|
||||||
t.Fatalf("(scrubbed) HashDir: %v", &pkg.ChecksumMismatchError{
|
t.Fatalf("(scrubbed) HashDir: %v", &pkg.ChecksumMismatchError{
|
||||||
Got: checksum,
|
Got: checksum,
|
||||||
Want: tc.want,
|
Want: want,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -425,7 +577,7 @@ type cureStep struct {
|
|||||||
a pkg.Artifact
|
a pkg.Artifact
|
||||||
|
|
||||||
pathname *check.Absolute
|
pathname *check.Absolute
|
||||||
checksum pkg.Checksum
|
output expectsKnown
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,17 +598,34 @@ func cureMany(t *testing.T, c *pkg.Cache, steps []cureStep) {
|
|||||||
for _, step := range steps {
|
for _, step := range steps {
|
||||||
t.Log("cure step:", step.name)
|
t.Log("cure step:", step.name)
|
||||||
if pathname, checksum, err := c.Cure(step.a); !reflect.DeepEqual(err, step.err) {
|
if pathname, checksum, err := c.Cure(step.a); !reflect.DeepEqual(err, step.err) {
|
||||||
|
faults, _err := c.ReadFaults(step.a)
|
||||||
|
if _err != nil {
|
||||||
|
t.Errorf("ReadFaults: error = %v", _err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var p []byte
|
||||||
|
for _, fault := range faults {
|
||||||
|
p, _err = os.ReadFile(fault.String())
|
||||||
|
if _err != nil {
|
||||||
|
t.Error(_err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Log(string(p))
|
||||||
|
t.Logf("faulting cure terminated %s ago", time.Since(faults[0].Time()))
|
||||||
|
}
|
||||||
t.Fatalf("Cure: error = %v, want %v", err, step.err)
|
t.Fatalf("Cure: error = %v, want %v", err, step.err)
|
||||||
} else if step.pathname != ignorePathname && !pathname.Is(step.pathname) {
|
} else if step.pathname != ignorePathname && !pathname.Is(step.pathname) {
|
||||||
t.Fatalf("Cure: pathname = %q, want %q", pathname, step.pathname)
|
t.Fatalf("Cure: pathname = %q, want %q", pathname, step.pathname)
|
||||||
} else if checksum != makeChecksumH(step.checksum) {
|
} else if step.output == nil || checksum != makeChecksumH(step.output.hash()) {
|
||||||
if checksum == (unique.Handle[pkg.Checksum]{}) {
|
if pathname != nil {
|
||||||
checksum = unique.Make(pkg.Checksum{})
|
if name, _err := filepath.EvalSymlinks(pathname.String()); _err != nil {
|
||||||
|
t.Fatal(_err)
|
||||||
|
} else {
|
||||||
|
t.Fatal(expectsFrom(name))
|
||||||
|
}
|
||||||
|
} else if checksum != (unique.Handle[pkg.Checksum]{}) {
|
||||||
|
t.Fatalf("Cure: unexpected checksum %s", pkg.Encode(checksum.Value()))
|
||||||
}
|
}
|
||||||
t.Fatalf(
|
|
||||||
"Cure: checksum = %s, want %s",
|
|
||||||
pkg.Encode(checksum.Value()), pkg.Encode(step.checksum),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
v := any(err)
|
v := any(err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -517,18 +686,12 @@ func newWantScrubError(base *check.Absolute) *pkg.ScrubError {
|
|||||||
func TestCache(t *testing.T) {
|
func TestCache(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
const testdata = "" +
|
testdata := expectsFile("" +
|
||||||
"\x00\x00\x00\x00" +
|
"\x00\x00\x00\x00" +
|
||||||
"\xad\x0b\x00" +
|
"\xad\x0b\x00" +
|
||||||
"\x04" +
|
"\x04" +
|
||||||
"\xfe\xfe\x00\x00" +
|
"\xfe\xfe\x00\x00" +
|
||||||
"\xfe\xca\x00\x00"
|
"\xfe\xca\x00\x00")
|
||||||
|
|
||||||
testdataChecksum := func() pkg.Checksum {
|
|
||||||
h := sha512.New384()
|
|
||||||
h.Write([]byte(testdata))
|
|
||||||
return (pkg.Checksum)(h.Sum(nil))
|
|
||||||
}()
|
|
||||||
|
|
||||||
testCases := []cacheTestCase{
|
testCases := []cacheTestCase{
|
||||||
{"file", pkg.CValidateKnown | pkg.CAssumeChecksum, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"file", pkg.CValidateKnown | pkg.CAssumeChecksum, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
@@ -546,36 +709,45 @@ func TestCache(t *testing.T) {
|
|||||||
"identifier",
|
"identifier",
|
||||||
"cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe",
|
"cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe",
|
||||||
)
|
)
|
||||||
|
failingFile := newStubFile(
|
||||||
|
pkg.KindHTTPGet,
|
||||||
|
pkg.ID{0xff, 3},
|
||||||
|
nil,
|
||||||
|
nil, struct {
|
||||||
|
_ []byte
|
||||||
|
stub.UniqueError
|
||||||
|
}{UniqueError: 0xbad},
|
||||||
|
)
|
||||||
|
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"initial file", newStubFile(
|
{"initial file", newStubFile(
|
||||||
pkg.KindHTTPGet,
|
pkg.KindHTTPGet,
|
||||||
identifier,
|
identifier,
|
||||||
&testdataChecksum,
|
new(testdata.hash()),
|
||||||
[]byte(testdata), nil,
|
testdata, nil,
|
||||||
), wantPathname, testdataChecksum, nil},
|
), wantPathname, testdata, nil},
|
||||||
|
|
||||||
{"identical content", newStubFile(
|
{"identical content", newStubFile(
|
||||||
pkg.KindHTTPGet,
|
pkg.KindHTTPGet,
|
||||||
identifier0,
|
identifier0,
|
||||||
&testdataChecksum,
|
new(testdata.hash()),
|
||||||
[]byte(testdata), nil,
|
testdata, nil,
|
||||||
), wantPathname0, testdataChecksum, nil},
|
), wantPathname0, testdata, nil},
|
||||||
|
|
||||||
{"existing entry", newStubFile(
|
{"existing entry", newStubFile(
|
||||||
pkg.KindHTTPGet,
|
pkg.KindHTTPGet,
|
||||||
identifier,
|
identifier,
|
||||||
&testdataChecksum,
|
new(testdata.hash()),
|
||||||
[]byte(testdata), nil,
|
testdata, nil,
|
||||||
), wantPathname, testdataChecksum, nil},
|
), wantPathname, testdata, nil},
|
||||||
|
|
||||||
{"checksum mismatch", newStubFile(
|
{"checksum mismatch", newStubFile(
|
||||||
pkg.KindHTTPGet,
|
pkg.KindHTTPGet,
|
||||||
pkg.ID{0xff, 0},
|
pkg.ID{0xff, 0},
|
||||||
new(pkg.Checksum),
|
new(pkg.Checksum),
|
||||||
[]byte(testdata), nil,
|
testdata, nil,
|
||||||
), nil, pkg.Checksum{}, &pkg.ChecksumMismatchError{
|
), nil, nil, &pkg.ChecksumMismatchError{
|
||||||
Got: testdataChecksum,
|
Got: testdata.hash(),
|
||||||
}},
|
}},
|
||||||
|
|
||||||
{"store without validation", newStubFile(
|
{"store without validation", newStubFile(
|
||||||
@@ -586,7 +758,7 @@ func TestCache(t *testing.T) {
|
|||||||
), base.Append(
|
), base.Append(
|
||||||
"identifier",
|
"identifier",
|
||||||
"vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX",
|
"vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX",
|
||||||
), pkg.Checksum{
|
), expectsChecksum{
|
||||||
0xbe, 0xc0, 0x21, 0xb4, 0xf3, 0x68,
|
0xbe, 0xc0, 0x21, 0xb4, 0xf3, 0x68,
|
||||||
0xe3, 0x06, 0x91, 0x34, 0xe0, 0x12,
|
0xe3, 0x06, 0x91, 0x34, 0xe0, 0x12,
|
||||||
0xc2, 0xb4, 0x30, 0x70, 0x83, 0xd3,
|
0xc2, 0xb4, 0x30, 0x70, 0x83, 0xd3,
|
||||||
@@ -600,7 +772,7 @@ func TestCache(t *testing.T) {
|
|||||||
{"incomplete implementation", struct{ pkg.Artifact }{&stubArtifact{
|
{"incomplete implementation", struct{ pkg.Artifact }{&stubArtifact{
|
||||||
kind: pkg.KindExec,
|
kind: pkg.KindExec,
|
||||||
params: []byte("artifact overridden to be incomplete"),
|
params: []byte("artifact overridden to be incomplete"),
|
||||||
}}, nil, pkg.Checksum{}, pkg.InvalidArtifactError(pkg.MustDecode(
|
}}, nil, nil, pkg.InvalidArtifactError(pkg.MustDecode(
|
||||||
"E__uZ1sLIvb84vzSm5Uezb03RogsiaeTt1nfIVv8TKnnf4LqwtSi-smdHhlkZrUJ",
|
"E__uZ1sLIvb84vzSm5Uezb03RogsiaeTt1nfIVv8TKnnf4LqwtSi-smdHhlkZrUJ",
|
||||||
))},
|
))},
|
||||||
|
|
||||||
@@ -609,40 +781,32 @@ func TestCache(t *testing.T) {
|
|||||||
pkg.ID{0xff, 1},
|
pkg.ID{0xff, 1},
|
||||||
nil,
|
nil,
|
||||||
nil, stub.UniqueError(0xcafe),
|
nil, stub.UniqueError(0xcafe),
|
||||||
), nil, pkg.Checksum{}, stub.UniqueError(0xcafe)},
|
), nil, nil, stub.UniqueError(0xcafe)},
|
||||||
|
|
||||||
{"error caching", newStubFile(
|
{"error caching", newStubFile(
|
||||||
pkg.KindHTTPGet,
|
pkg.KindHTTPGet,
|
||||||
pkg.ID{0xff, 1},
|
pkg.ID{0xff, 1},
|
||||||
nil,
|
nil,
|
||||||
nil, nil,
|
nil, nil,
|
||||||
), nil, pkg.Checksum{}, stub.UniqueError(0xcafe)},
|
), nil, nil, stub.UniqueError(0xcafe)},
|
||||||
|
|
||||||
{"cache hit bad type", overrideChecksum{testdataChecksum, overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
|
{"cache hit bad type", overrideChecksum{testdata.hash(), overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
}}}, nil, pkg.Checksum{}, pkg.InvalidFileModeError(
|
}}}, nil, nil, pkg.InvalidFileModeError(
|
||||||
0400,
|
0400,
|
||||||
)},
|
)},
|
||||||
|
|
||||||
{"noncomparable error", &stubArtifactF{
|
{"noncomparable error", &stubArtifactF{
|
||||||
kind: pkg.KindExec,
|
kind: pkg.KindExec,
|
||||||
params: []byte("artifact with dependency returning noncomparable error"),
|
params: []byte("artifact with dependency returning noncomparable error"),
|
||||||
deps: []pkg.Artifact{newStubFile(
|
deps: []pkg.Artifact{failingFile},
|
||||||
pkg.KindHTTPGet,
|
|
||||||
pkg.ID{0xff, 3},
|
|
||||||
nil,
|
|
||||||
nil, struct {
|
|
||||||
_ []byte
|
|
||||||
stub.UniqueError
|
|
||||||
}{UniqueError: 0xbad},
|
|
||||||
)},
|
|
||||||
|
|
||||||
cure: func(f *pkg.FContext) error {
|
cure: func(f *pkg.FContext) error {
|
||||||
panic("attempting to cure impossible artifact")
|
panic("attempting to cure impossible artifact")
|
||||||
},
|
},
|
||||||
}, nil, pkg.Checksum{}, &pkg.DependencyCureError{
|
}, nil, nil, &pkg.DependencyCureError{
|
||||||
{
|
{
|
||||||
Ident: unique.Make(pkg.ID{0xff, 3}),
|
A: failingFile,
|
||||||
Err: struct {
|
Err: struct {
|
||||||
_ []byte
|
_ []byte
|
||||||
stub.UniqueError
|
stub.UniqueError
|
||||||
@@ -662,18 +826,18 @@ func TestCache(t *testing.T) {
|
|||||||
cureMany(t, c0, []cureStep{
|
cureMany(t, c0, []cureStep{
|
||||||
{"cache hit ident", overrideIdent{
|
{"cache hit ident", overrideIdent{
|
||||||
id: identifier,
|
id: identifier,
|
||||||
}, wantPathname, testdataChecksum, nil},
|
}, wantPathname, testdata, nil},
|
||||||
|
|
||||||
{"cache miss checksum match", newStubFile(
|
{"cache miss checksum match", newStubFile(
|
||||||
pkg.KindHTTPGet,
|
pkg.KindHTTPGet,
|
||||||
testdataChecksum,
|
testdata.hash(),
|
||||||
nil,
|
nil,
|
||||||
[]byte(testdata),
|
testdata,
|
||||||
nil,
|
nil,
|
||||||
), base.Append(
|
), base.Append(
|
||||||
"identifier",
|
"identifier",
|
||||||
pkg.Encode(testdataChecksum),
|
pkg.Encode(testdata.hash()),
|
||||||
), testdataChecksum, nil},
|
), testdata, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
// cure after close
|
// cure after close
|
||||||
@@ -686,7 +850,23 @@ func TestCache(t *testing.T) {
|
|||||||
t.Fatalf("(closed) Cure: error = %v", err)
|
t.Fatalf("(closed) Cure: error = %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, pkg.MustDecode("St9rlE-mGZ5gXwiv_hzQ_B8bZP-UUvSNmf4nHUZzCMOumb6hKnheZSe0dmnuc4Q2")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0}},
|
||||||
|
"checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: 0400, Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
||||||
|
"identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||||
|
"identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||||
|
"identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
{"directory", pkg.CAssumeChecksum, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"directory", pkg.CAssumeChecksum, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
id := pkg.MustDecode(
|
id := pkg.MustDecode(
|
||||||
@@ -721,9 +901,16 @@ func TestCache(t *testing.T) {
|
|||||||
).String(),
|
).String(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
wantChecksum := pkg.MustDecode(
|
want := expectsFS{
|
||||||
"qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b",
|
".": {Mode: fs.ModeDir | 0500},
|
||||||
)
|
|
||||||
|
"check": {Mode: 0400, Data: []byte{0, 0}},
|
||||||
|
|
||||||
|
"lib": {Mode: fs.ModeDir | 0700},
|
||||||
|
"lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||||
|
|
||||||
|
"lib/pkgconfig": {Mode: fs.ModeDir | 0700},
|
||||||
|
}
|
||||||
wantPathname := base.Append(
|
wantPathname := base.Append(
|
||||||
"identifier",
|
"identifier",
|
||||||
pkg.Encode(id),
|
pkg.Encode(id),
|
||||||
@@ -777,33 +964,33 @@ func TestCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"initial directory", overrideChecksum{wantChecksum, overrideIdent{id, &stubArtifact{
|
{"initial directory", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
cure: makeSample,
|
cure: makeSample,
|
||||||
}}}, wantPathname, wantChecksum, nil},
|
}}}, wantPathname, want, nil},
|
||||||
|
|
||||||
{"identical identifier", overrideChecksum{wantChecksum, overrideIdent{id, &stubArtifact{
|
{"identical identifier", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
}}}, wantPathname, wantChecksum, nil},
|
}}}, wantPathname, want, nil},
|
||||||
|
|
||||||
{"identical checksum", overrideIdent{id0, &stubArtifact{
|
{"identical checksum", overrideIdent{id0, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
cure: makeSample,
|
cure: makeSample,
|
||||||
}}, wantPathname0, wantChecksum, nil},
|
}}, wantPathname0, want, nil},
|
||||||
|
|
||||||
{"cure fault", overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{
|
{"cure fault", overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xcafe))
|
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xcafe))
|
||||||
},
|
},
|
||||||
}}, nil, pkg.Checksum{}, stub.UniqueError(0xcafe)},
|
}}, nil, nil, stub.UniqueError(0xcafe)},
|
||||||
|
|
||||||
{"checksum mismatch", overrideChecksum{pkg.Checksum{}, overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
|
{"checksum mismatch", overrideChecksum{pkg.Checksum{}, overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
return makeGarbage(t.GetWorkDir(), nil)
|
return makeGarbage(t.GetWorkDir(), nil)
|
||||||
},
|
},
|
||||||
}}}, nil, pkg.Checksum{}, &pkg.ChecksumMismatchError{
|
}}}, nil, nil, &pkg.ChecksumMismatchError{
|
||||||
Got: pkg.MustDecode(
|
Got: pkg.MustDecode(
|
||||||
"CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT",
|
"CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT",
|
||||||
),
|
),
|
||||||
@@ -812,27 +999,27 @@ func TestCache(t *testing.T) {
|
|||||||
{"cache hit bad type", newStubFile(
|
{"cache hit bad type", newStubFile(
|
||||||
pkg.KindHTTPGet,
|
pkg.KindHTTPGet,
|
||||||
pkg.ID{0xff, 2},
|
pkg.ID{0xff, 2},
|
||||||
&wantChecksum,
|
new(want.hash()),
|
||||||
[]byte(testdata), nil,
|
testdata, nil,
|
||||||
), nil, pkg.Checksum{}, pkg.InvalidFileModeError(
|
), nil, nil, pkg.InvalidFileModeError(
|
||||||
fs.ModeDir | 0500,
|
fs.ModeDir | 0500,
|
||||||
)},
|
)},
|
||||||
|
|
||||||
{"openFile directory", overrideIdent{pkg.ID{0xff, 3}, &stubArtifact{
|
{"openFile directory", overrideIdent{pkg.ID{0xff, 3}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
r, err := t.Open(overrideChecksumFile{checksum: wantChecksum})
|
r, err := t.Open(overrideChecksumFile{checksum: want.hash()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
_, err = io.ReadAll(r)
|
_, err = io.ReadAll(r)
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
}}, nil, pkg.Checksum{}, &os.PathError{
|
}}, nil, nil, &os.PathError{
|
||||||
Op: "read",
|
Op: "read",
|
||||||
Path: base.Append(
|
Path: base.Append(
|
||||||
"checksum",
|
"checksum",
|
||||||
pkg.Encode(wantChecksum),
|
pkg.Encode(want.hash()),
|
||||||
).String(),
|
).String(),
|
||||||
Err: syscall.EISDIR,
|
Err: syscall.EISDIR,
|
||||||
}},
|
}},
|
||||||
@@ -842,14 +1029,14 @@ func TestCache(t *testing.T) {
|
|||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}}, nil, pkg.Checksum{}, pkg.NoOutputError{}},
|
}}, nil, nil, pkg.NoOutputError{}},
|
||||||
|
|
||||||
{"file output", overrideIdent{pkg.ID{0xff, 5}, &stubArtifact{
|
{"file output", overrideIdent{pkg.ID{0xff, 5}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
return os.WriteFile(t.GetWorkDir().String(), []byte{0}, 0400)
|
return os.WriteFile(t.GetWorkDir().String(), []byte{0}, 0400)
|
||||||
},
|
},
|
||||||
}}, nil, pkg.Checksum{}, errors.New("non-file artifact produced regular file")},
|
}}, nil, nil, errors.New("non-file artifact produced regular file")},
|
||||||
|
|
||||||
{"symlink output", overrideIdent{pkg.ID{0xff, 6}, &stubArtifact{
|
{"symlink output", overrideIdent{pkg.ID{0xff, 6}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
@@ -859,11 +1046,111 @@ func TestCache(t *testing.T) {
|
|||||||
t.GetWorkDir().String(),
|
t.GetWorkDir().String(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}}, nil, pkg.Checksum{}, pkg.InvalidFileModeError(
|
}}, nil, nil, pkg.InvalidFileModeError(
|
||||||
fs.ModeSymlink | 0777,
|
fs.ModeSymlink | 0777,
|
||||||
)},
|
)},
|
||||||
|
|
||||||
|
{"alternative", &stubArtifactF{
|
||||||
|
kind: pkg.KindExec,
|
||||||
|
params: []byte("substitutable artifact"),
|
||||||
|
deps: []pkg.Artifact{newStubFile(
|
||||||
|
pkg.KindHTTPGet,
|
||||||
|
pkg.ID{0xff, 8},
|
||||||
|
nil,
|
||||||
|
[]byte("substitutable dependency"),
|
||||||
|
nil,
|
||||||
|
)},
|
||||||
|
|
||||||
|
cure: func(f *pkg.FContext) error {
|
||||||
|
return makeSample(&f.TContext)
|
||||||
|
},
|
||||||
|
}, base.Append(
|
||||||
|
"identifier",
|
||||||
|
"xMDWovje7OfyIaDy_2VnjpKxRqSOQ_LoeD946t-3WsS2V2SeMJ7nDGrNfpa4Pbc-",
|
||||||
|
), want, nil},
|
||||||
|
|
||||||
|
{"substitutable", &stubArtifactF{
|
||||||
|
kind: pkg.KindExec,
|
||||||
|
params: []byte("substitutable artifact"),
|
||||||
|
deps: []pkg.Artifact{newStubFile(
|
||||||
|
pkg.KindHTTPGet,
|
||||||
|
pkg.ID{0xff, 10},
|
||||||
|
nil,
|
||||||
|
[]byte("substitutable dependency"),
|
||||||
|
nil,
|
||||||
|
)},
|
||||||
|
|
||||||
|
cure: func(f *pkg.FContext) error {
|
||||||
|
panic("substitution missed")
|
||||||
|
},
|
||||||
|
}, base.Append(
|
||||||
|
"identifier",
|
||||||
|
"k2ilgG5KQ9NXnMoT2oB6NdwOnSPRn_H24oXQc4l6qOYIxIG9XfuEczeyrR8UEv_f",
|
||||||
|
), want, nil},
|
||||||
})
|
})
|
||||||
}, pkg.MustDecode("WVpvsVqVKg9Nsh744x57h51AuWUoUR2nnh8Md-EYBQpk6ziyTuUn6PLtF2e0Eu_d")},
|
|
||||||
|
if c0, err := unsafeOpen(
|
||||||
|
t.Context(),
|
||||||
|
message.New(nil),
|
||||||
|
0, 0, 0, base, false,
|
||||||
|
); err != nil {
|
||||||
|
t.Fatalf("open: error = %v", err)
|
||||||
|
} else {
|
||||||
|
t.Cleanup(c.Close)
|
||||||
|
cureMany(t, c0, []cureStep{
|
||||||
|
{"substitutable", &stubArtifactF{
|
||||||
|
kind: pkg.KindExec,
|
||||||
|
params: []byte("substitutable artifact"),
|
||||||
|
deps: []pkg.Artifact{newStubFile(
|
||||||
|
pkg.KindHTTPGet,
|
||||||
|
pkg.ID{0xff, 0xff, 0xfd, 0xfd},
|
||||||
|
nil,
|
||||||
|
[]byte("substitutable dependency"),
|
||||||
|
nil,
|
||||||
|
)},
|
||||||
|
|
||||||
|
cure: func(f *pkg.FContext) error {
|
||||||
|
panic("substitution missed")
|
||||||
|
},
|
||||||
|
}, base.Append(
|
||||||
|
"identifier",
|
||||||
|
"_EmV5nsYZ2UWHgRmLDMU8i-rJWDx-kv5_1pFrzQI7vMMCM5mAXivO8UZtVfOqMR_",
|
||||||
|
), want, nil},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if dents, err := os.ReadDir(base.Append("status").String()); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if len(dents) > 0 {
|
||||||
|
t.Errorf("ReadDir: %v", dents)
|
||||||
|
}
|
||||||
|
|
||||||
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO": {Mode: 0400, Data: []byte("substitutable dependency")},
|
||||||
|
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||||
|
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/pkgconfig": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||||
|
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||||
|
"identifier/_EmV5nsYZ2UWHgRmLDMU8i-rJWDx-kv5_1pFrzQI7vMMCM5mAXivO8UZtVfOqMR_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||||
|
"identifier/___9_QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")},
|
||||||
|
"identifier/_wgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")},
|
||||||
|
"identifier/_woAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")},
|
||||||
|
"identifier/k2ilgG5KQ9NXnMoT2oB6NdwOnSPRn_H24oXQc4l6qOYIxIG9XfuEczeyrR8UEv_f": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||||
|
"identifier/xMDWovje7OfyIaDy_2VnjpKxRqSOQ_LoeD946t-3WsS2V2SeMJ7nDGrNfpa4Pbc-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
"substitute/OyBGorh72Z9kVw35JUa8FbqDbpR4DqT-MX1jic0uKN5PdYmUBiAF38BRsIRnBigf": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||||
|
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
{"pending", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"pending", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
wantErr := stub.UniqueError(0xcafe)
|
wantErr := stub.UniqueError(0xcafe)
|
||||||
@@ -899,7 +1186,7 @@ func TestCache(t *testing.T) {
|
|||||||
pkg.ID{0xff, 1},
|
pkg.ID{0xff, 1},
|
||||||
nil,
|
nil,
|
||||||
nil, stub.UniqueError(0xbad),
|
nil, stub.UniqueError(0xbad),
|
||||||
), nil, pkg.Checksum{}, stub.UniqueError(0xbad)},
|
), nil, nil, stub.UniqueError(0xbad)},
|
||||||
|
|
||||||
{"file output", overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
|
{"file output", overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
@@ -910,7 +1197,7 @@ func TestCache(t *testing.T) {
|
|||||||
0400,
|
0400,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}}, nil, pkg.Checksum{}, errors.New(
|
}}, nil, nil, errors.New(
|
||||||
"non-file artifact produced regular file",
|
"non-file artifact produced regular file",
|
||||||
)},
|
)},
|
||||||
})
|
})
|
||||||
@@ -932,7 +1219,13 @@ func TestCache(t *testing.T) {
|
|||||||
for c.Done(unique.Make(pkg.ID{0xff})) != nil {
|
for c.Done(unique.Make(pkg.ID{0xff})) != nil {
|
||||||
}
|
}
|
||||||
<-wCureDone
|
<-wCureDone
|
||||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
{"cancel abort block", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"cancel abort block", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
@@ -985,7 +1278,13 @@ func TestCache(t *testing.T) {
|
|||||||
|
|
||||||
c.Close()
|
c.Close()
|
||||||
c.Abort()
|
c.Abort()
|
||||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
{"no assume checksum", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"no assume checksum", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
makeGarbage := func(work *check.Absolute, wantErr error) error {
|
makeGarbage := func(work *check.Absolute, wantErr error) error {
|
||||||
@@ -1002,10 +1301,12 @@ func TestCache(t *testing.T) {
|
|||||||
return wantErr
|
return wantErr
|
||||||
}
|
}
|
||||||
|
|
||||||
wantChecksum := pkg.MustDecode("Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")
|
want := expectsChecksum(pkg.MustDecode(
|
||||||
|
"Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M",
|
||||||
|
))
|
||||||
|
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
{"create", overrideChecksum{wantChecksum, overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{
|
{"create", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
return makeGarbage(t.GetWorkDir(), nil)
|
return makeGarbage(t.GetWorkDir(), nil)
|
||||||
@@ -1013,16 +1314,16 @@ func TestCache(t *testing.T) {
|
|||||||
}}}, base.Append(
|
}}}, base.Append(
|
||||||
"identifier",
|
"identifier",
|
||||||
pkg.Encode(pkg.ID{0xff, 0}),
|
pkg.Encode(pkg.ID{0xff, 0}),
|
||||||
), wantChecksum, nil},
|
), want, nil},
|
||||||
|
|
||||||
{"reject", overrideChecksum{wantChecksum, overrideIdent{pkg.ID{0xfe, 1}, &stubArtifact{
|
{"reject", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xfe, 1}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xbad))
|
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xbad))
|
||||||
},
|
},
|
||||||
}}}, nil, pkg.Checksum{}, stub.UniqueError(0xbad)},
|
}}}, nil, nil, stub.UniqueError(0xbad)},
|
||||||
|
|
||||||
{"match", overrideChecksum{wantChecksum, overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
|
{"match", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
return makeGarbage(t.GetWorkDir(), nil)
|
return makeGarbage(t.GetWorkDir(), nil)
|
||||||
@@ -1030,9 +1331,23 @@ func TestCache(t *testing.T) {
|
|||||||
}}}, base.Append(
|
}}}, base.Append(
|
||||||
"identifier",
|
"identifier",
|
||||||
pkg.Encode(pkg.ID{0xff, 1}),
|
pkg.Encode(pkg.ID{0xff, 1}),
|
||||||
), wantChecksum, nil},
|
), want, nil},
|
||||||
})
|
})
|
||||||
}, pkg.MustDecode("OC290t23aimNo2Rp2pPwan5GI2KRLRdOwYxXQMD9jw0QROgHnNXWodoWdV0hwu2w")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M/check": {Mode: 0400, Data: []byte{}},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||||
|
"identifier/_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
{"scrub", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"scrub", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
cureMany(t, c, []cureStep{
|
cureMany(t, c, []cureStep{
|
||||||
@@ -1044,7 +1359,7 @@ func TestCache(t *testing.T) {
|
|||||||
), base.Append(
|
), base.Append(
|
||||||
"identifier",
|
"identifier",
|
||||||
pkg.Encode(pkg.Checksum{0xfe, 0}),
|
pkg.Encode(pkg.Checksum{0xfe, 0}),
|
||||||
), pkg.Checksum{0xff, 0}, nil},
|
), expectsChecksum{0xff, 0}, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, p := range [][]string{
|
for _, p := range [][]string{
|
||||||
@@ -1077,7 +1392,13 @@ func TestCache(t *testing.T) {
|
|||||||
if err := c.Scrub(1 << 6); !reflect.DeepEqual(err, wantErr) {
|
if err := c.Scrub(1 << 6); !reflect.DeepEqual(err, wantErr) {
|
||||||
t.Fatalf("Scrub: error =\n%s\nwant\n%s", err, wantErr)
|
t.Fatalf("Scrub: error =\n%s\nwant\n%s", err, wantErr)
|
||||||
}
|
}
|
||||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
checkWithCache(t, testCases)
|
checkWithCache(t, testCases)
|
||||||
}
|
}
|
||||||
@@ -1135,6 +1456,11 @@ func TestErrors(t *testing.T) {
|
|||||||
{"UnsupportedVariantError", pkg.UnsupportedVariantError(
|
{"UnsupportedVariantError", pkg.UnsupportedVariantError(
|
||||||
"rosa",
|
"rosa",
|
||||||
), `unsupported variant "rosa"`},
|
), `unsupported variant "rosa"`},
|
||||||
|
|
||||||
|
{"UnsupportedArchError zero", pkg.UnsupportedArchError(""),
|
||||||
|
"invalid architecture name"},
|
||||||
|
{"UnsupportedArchError", pkg.UnsupportedArchError("riscv64"),
|
||||||
|
"unsupported architecture riscv64"},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
@@ -1250,6 +1576,14 @@ errors during scrub:
|
|||||||
func TestDependencyCureError(t *testing.T) {
|
func TestDependencyCureError(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
makeIdent := func(ident ...byte) pkg.Artifact {
|
||||||
|
var a overrideIdent
|
||||||
|
copy(a.id[:], ident)
|
||||||
|
// does not compare equal
|
||||||
|
a.TrivialArtifact = new(stubArtifact)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
err pkg.DependencyCureError
|
err pkg.DependencyCureError
|
||||||
@@ -1257,51 +1591,51 @@ func TestDependencyCureError(t *testing.T) {
|
|||||||
unwrap []error
|
unwrap []error
|
||||||
}{
|
}{
|
||||||
{"simple", pkg.DependencyCureError{
|
{"simple", pkg.DependencyCureError{
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 1}), Err: stub.UniqueError(0xbad01)},
|
{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
|
||||||
}, `errors curing dependencies:
|
}, `errors curing dependencies:
|
||||||
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
|
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
|
||||||
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
|
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
|
||||||
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
|
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
|
||||||
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
|
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
|
||||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 1}), Err: stub.UniqueError(0xbad01)},
|
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
|
||||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||||
}},
|
}},
|
||||||
|
|
||||||
{"dedup", pkg.DependencyCureError{
|
{"dedup", pkg.DependencyCureError{
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0xfd}), Err: &pkg.DependencyCureError{
|
{A: makeIdent(0xff, 0xfd), Err: &pkg.DependencyCureError{
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0xc}), Err: &pkg.DependencyCureError{
|
{A: makeIdent(0xff, 0xc), Err: &pkg.DependencyCureError{
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||||
}},
|
}},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||||
}},
|
}},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0xff}), Err: &pkg.DependencyCureError{
|
{A: makeIdent(0xff, 0xff), Err: &pkg.DependencyCureError{
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0xc}), Err: &pkg.DependencyCureError{
|
{A: makeIdent(0xff, 0xc), Err: &pkg.DependencyCureError{
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||||
}},
|
}},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||||
}},
|
}},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||||
{Ident: unique.Make(pkg.ID{0xff, 1}), Err: stub.UniqueError(0xbad01)},
|
{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
|
||||||
}, `errors curing dependencies:
|
}, `errors curing dependencies:
|
||||||
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
|
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
|
||||||
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
|
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
|
||||||
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
|
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
|
||||||
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
|
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
|
||||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 1}), Err: stub.UniqueError(0xbad01)},
|
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
|
||||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
@@ -1342,6 +1676,25 @@ func (a earlyFailureF) Cure(*pkg.FContext) error {
|
|||||||
return stub.UniqueError(0xcafe)
|
return stub.UniqueError(0xcafe)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkEarlyDCE(b *testing.B) {
|
||||||
|
msg := message.New(log.New(os.Stderr, "dce: ", 0))
|
||||||
|
msg.SwapVerbose(testing.Verbose())
|
||||||
|
c, err := pkg.Open(b.Context(), msg, 0, 0, 0, check.MustAbs(b.TempDir()))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
_, _, err = c.Cure(earlyFailureF(8))
|
||||||
|
if !errors.Is(err, stub.UniqueError(0xcafe)) {
|
||||||
|
b.Fatalf("Cure: error = %v", err)
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
|
dce := err.(*pkg.DependencyCureError)
|
||||||
|
|
||||||
|
for b.Loop() {
|
||||||
|
dce.Unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDependencyCureErrorEarly(t *testing.T) {
|
func TestDependencyCureErrorEarly(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@@ -1351,7 +1704,13 @@ func TestDependencyCureErrorEarly(t *testing.T) {
|
|||||||
if !errors.Is(err, stub.UniqueError(0xcafe)) {
|
if !errors.Is(err, stub.UniqueError(0xcafe)) {
|
||||||
t.Fatalf("Cure: error = %v", err)
|
t.Fatalf("Cure: error = %v", err)
|
||||||
}
|
}
|
||||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
}, expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+74
-14
@@ -20,6 +20,31 @@ import (
|
|||||||
func TestTar(t *testing.T) {
|
func TestTar(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
want := expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||||
|
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0500},
|
||||||
|
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||||
|
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||||
|
|
||||||
|
"work": {Mode: fs.ModeDir | 0500},
|
||||||
|
}
|
||||||
|
wantEncode := pkg.Encode(want.hash())
|
||||||
|
|
||||||
|
wantExpand := expectsFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
|
"libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||||
|
}
|
||||||
|
wantExpandEncode := pkg.Encode(wantExpand.hash())
|
||||||
|
|
||||||
checkWithCache(t, []cacheTestCase{
|
checkWithCache(t, []cacheTestCase{
|
||||||
{"http", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"http", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
checkTarHTTP(t, base, c, fstest.MapFS{
|
checkTarHTTP(t, base, c, fstest.MapFS{
|
||||||
@@ -37,10 +62,32 @@ func TestTar(t *testing.T) {
|
|||||||
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||||
|
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
}, pkg.MustDecode(
|
}, want)
|
||||||
"cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM",
|
}, expectsFS{
|
||||||
))
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
}, pkg.MustDecode("NQTlc466JmSVLIyWklm_u8_g95jEEb98PxJU-kjwxLpfdjwMWJq0G8ze9R4Vo1Vu")},
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/" + wantEncode: {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantEncode + "/checksum": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||||
|
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||||
|
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantEncode + "/identifier": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantEncode + "/identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||||
|
"checksum/" + wantEncode + "/identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||||
|
"checksum/" + wantEncode + "/work": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
|
||||||
|
"identifier/rg7F1D5hwv6o4xctjD5zDq4i5MD0mArTsUIWfhUbik8xC6Bsyt3mjXXOm3goojTz": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
|
|
||||||
{"http expand", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"http expand", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
checkTarHTTP(t, base, c, fstest.MapFS{
|
checkTarHTTP(t, base, c, fstest.MapFS{
|
||||||
@@ -48,10 +95,23 @@ func TestTar(t *testing.T) {
|
|||||||
|
|
||||||
"lib": {Mode: fs.ModeDir | 0700},
|
"lib": {Mode: fs.ModeDir | 0700},
|
||||||
"lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
"lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||||
}, pkg.MustDecode(
|
}, wantExpand)
|
||||||
"CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN",
|
}, expectsFS{
|
||||||
))
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
}, pkg.MustDecode("hSoSSgCYTNonX3Q8FjvjD1fBl-E-BQyA6OTXro2OadXqbST4tZ-akGXszdeqphRe")},
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/" + wantExpandEncode: {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/" + wantExpandEncode + "/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
|
||||||
|
"identifier/_v1blm2h-_KA-dVaawdpLas6MjHc6rbhhFS8JWwx8iJxZGUu8EBbRrhr5AaZ9PJL": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
|
||||||
|
|
||||||
|
"substitute": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +120,7 @@ func checkTarHTTP(
|
|||||||
base *check.Absolute,
|
base *check.Absolute,
|
||||||
c *pkg.Cache,
|
c *pkg.Cache,
|
||||||
testdataFsys fs.FS,
|
testdataFsys fs.FS,
|
||||||
wantChecksum pkg.Checksum,
|
want expectsKnown,
|
||||||
) {
|
) {
|
||||||
var testdata string
|
var testdata string
|
||||||
{
|
{
|
||||||
@@ -194,24 +254,24 @@ func checkTarHTTP(
|
|||||||
{"file", a, base.Append(
|
{"file", a, base.Append(
|
||||||
"identifier",
|
"identifier",
|
||||||
pkg.Encode(wantIdent),
|
pkg.Encode(wantIdent),
|
||||||
), wantChecksum, nil},
|
), want, nil},
|
||||||
|
|
||||||
{"directory", pkg.NewTar(
|
{"directory", pkg.NewTar(
|
||||||
&tarDir,
|
&tarDir,
|
||||||
pkg.TarGzip,
|
pkg.TarGzip,
|
||||||
), ignorePathname, wantChecksum, nil},
|
), ignorePathname, want, nil},
|
||||||
|
|
||||||
{"multiple entries", pkg.NewTar(
|
{"multiple entries", pkg.NewTar(
|
||||||
&tarDirMulti,
|
&tarDirMulti,
|
||||||
pkg.TarGzip,
|
pkg.TarGzip,
|
||||||
), nil, pkg.Checksum{}, errors.New(
|
), nil, nil, errors.New(
|
||||||
"input directory does not contain a single regular file",
|
"input directory does not contain a single regular file",
|
||||||
)},
|
)},
|
||||||
|
|
||||||
{"bad type", pkg.NewTar(
|
{"bad type", pkg.NewTar(
|
||||||
&tarDirType,
|
&tarDirType,
|
||||||
pkg.TarGzip,
|
pkg.TarGzip,
|
||||||
), nil, pkg.Checksum{}, errors.New(
|
), nil, nil, errors.New(
|
||||||
"input directory does not contain a single regular file",
|
"input directory does not contain a single regular file",
|
||||||
)},
|
)},
|
||||||
|
|
||||||
@@ -221,6 +281,6 @@ func checkTarHTTP(
|
|||||||
cure: func(t *pkg.TContext) error {
|
cure: func(t *pkg.TContext) error {
|
||||||
return stub.UniqueError(0xcafe)
|
return stub.UniqueError(0xcafe)
|
||||||
},
|
},
|
||||||
}, pkg.TarGzip), nil, pkg.Checksum{}, stub.UniqueError(0xcafe)},
|
}, pkg.TarGzip), nil, nil, stub.UniqueError(0xcafe)},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ ln -s ../../system/bin/perl /usr/bin
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Attr] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newAttr,
|
f: Toolchain.newAttr,
|
||||||
|
|
||||||
Name: "attr",
|
Name: "attr",
|
||||||
@@ -73,7 +73,7 @@ func init() {
|
|||||||
Website: "https://savannah.nongnu.org/projects/attr/",
|
Website: "https://savannah.nongnu.org/projects/attr/",
|
||||||
|
|
||||||
ID: 137,
|
ID: 137,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newACL() (pkg.Artifact, string) {
|
func (t Toolchain) newACL() (pkg.Artifact, string) {
|
||||||
@@ -94,7 +94,7 @@ func (t Toolchain) newACL() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[ACL] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newACL,
|
f: Toolchain.newACL,
|
||||||
|
|
||||||
Name: "acl",
|
Name: "acl",
|
||||||
@@ -106,5 +106,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 16,
|
ID: 16,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,401 +0,0 @@
|
|||||||
package rosa
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"hakurei.app/internal/pkg"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PArtifact is a lazily-initialised [pkg.Artifact] preset.
|
|
||||||
type PArtifact int
|
|
||||||
|
|
||||||
const (
|
|
||||||
LLVM PArtifact = iota
|
|
||||||
|
|
||||||
// EarlyInit is the Rosa OS init program.
|
|
||||||
EarlyInit
|
|
||||||
// ImageSystem is the Rosa OS /system image.
|
|
||||||
ImageSystem
|
|
||||||
// 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
|
|
||||||
// Firmware is firmware blobs for use with the Linux kernel.
|
|
||||||
Firmware
|
|
||||||
|
|
||||||
ACL
|
|
||||||
ArgpStandalone
|
|
||||||
Attr
|
|
||||||
Autoconf
|
|
||||||
Automake
|
|
||||||
BC
|
|
||||||
Bash
|
|
||||||
Binutils
|
|
||||||
Bison
|
|
||||||
Bzip2
|
|
||||||
CMake
|
|
||||||
Connman
|
|
||||||
Coreutils
|
|
||||||
Curl
|
|
||||||
DBus
|
|
||||||
DTC
|
|
||||||
Diffutils
|
|
||||||
Elfutils
|
|
||||||
Fakeroot
|
|
||||||
Findutils
|
|
||||||
Flex
|
|
||||||
Fuse
|
|
||||||
GMP
|
|
||||||
GLib
|
|
||||||
Gawk
|
|
||||||
GenInitCPIO
|
|
||||||
Gettext
|
|
||||||
Git
|
|
||||||
Glslang
|
|
||||||
GnuTLS
|
|
||||||
Go
|
|
||||||
Gperf
|
|
||||||
Grep
|
|
||||||
Gzip
|
|
||||||
Hakurei
|
|
||||||
HakureiDist
|
|
||||||
IPTables
|
|
||||||
Kmod
|
|
||||||
LIT
|
|
||||||
LibX11
|
|
||||||
LibXau
|
|
||||||
LibXext
|
|
||||||
Libbsd
|
|
||||||
Libcap
|
|
||||||
Libdrm
|
|
||||||
Libev
|
|
||||||
Libexpat
|
|
||||||
Libffi
|
|
||||||
Libgd
|
|
||||||
Libglvnd
|
|
||||||
Libiconv
|
|
||||||
Libmd
|
|
||||||
Libmnl
|
|
||||||
Libpciaccess
|
|
||||||
Libnftnl
|
|
||||||
Libpsl
|
|
||||||
Libseccomp
|
|
||||||
Libtasn1
|
|
||||||
Libtool
|
|
||||||
Libucontext
|
|
||||||
Libunistring
|
|
||||||
Libxshmfence
|
|
||||||
Libxml2
|
|
||||||
Libxslt
|
|
||||||
Libxtrans
|
|
||||||
M4
|
|
||||||
MPC
|
|
||||||
MPFR
|
|
||||||
Make
|
|
||||||
Meson
|
|
||||||
Mksh
|
|
||||||
MuslFts
|
|
||||||
MuslObstack
|
|
||||||
NSS
|
|
||||||
NSSCACert
|
|
||||||
Ncurses
|
|
||||||
Nettle
|
|
||||||
Ninja
|
|
||||||
OpenSSL
|
|
||||||
P11Kit
|
|
||||||
PCRE2
|
|
||||||
Parallel
|
|
||||||
Patch
|
|
||||||
Perl
|
|
||||||
PerlLocaleGettext
|
|
||||||
PerlMIMECharset
|
|
||||||
PerlModuleBuild
|
|
||||||
PerlPodParser
|
|
||||||
PerlSGMLS
|
|
||||||
PerlTermReadKey
|
|
||||||
PerlTextCharWidth
|
|
||||||
PerlTextWrapI18N
|
|
||||||
PerlUnicodeLineBreak
|
|
||||||
PerlYAMLTiny
|
|
||||||
PkgConfig
|
|
||||||
Procps
|
|
||||||
Python
|
|
||||||
PythonFlitCore
|
|
||||||
PythonHatchling
|
|
||||||
PythonIniConfig
|
|
||||||
PythonMako
|
|
||||||
PythonMarkupSafe
|
|
||||||
PythonPackaging
|
|
||||||
PythonPathspec
|
|
||||||
PythonPluggy
|
|
||||||
PythonPyTest
|
|
||||||
PythonPyYAML
|
|
||||||
PythonPygments
|
|
||||||
PythonSetuptools
|
|
||||||
PythonSetuptoolsSCM
|
|
||||||
PythonTroveClassifiers
|
|
||||||
PythonVCSVersioning
|
|
||||||
PythonWheel
|
|
||||||
QEMU
|
|
||||||
Rdfind
|
|
||||||
Readline
|
|
||||||
Rsync
|
|
||||||
Sed
|
|
||||||
SPIRVHeaders
|
|
||||||
SPIRVLLVMTranslator
|
|
||||||
SPIRVTools
|
|
||||||
SquashfsTools
|
|
||||||
Strace
|
|
||||||
TamaGo
|
|
||||||
Tar
|
|
||||||
Texinfo
|
|
||||||
Toybox
|
|
||||||
toyboxEarly
|
|
||||||
Unzip
|
|
||||||
UtilLinux
|
|
||||||
Wayland
|
|
||||||
WaylandProtocols
|
|
||||||
XCB
|
|
||||||
XCBProto
|
|
||||||
XDGDBusProxy
|
|
||||||
XZ
|
|
||||||
XorgProto
|
|
||||||
Zlib
|
|
||||||
Zstd
|
|
||||||
|
|
||||||
// PresetUnexportedStart is the first unexported preset.
|
|
||||||
PresetUnexportedStart
|
|
||||||
|
|
||||||
llvmSource = iota - 1
|
|
||||||
// earlyCompilerRT is an early, standalone compiler-rt installation for the
|
|
||||||
// standalone runtimes build.
|
|
||||||
//
|
|
||||||
// earlyCompilerRT must only be loaded by [LLVM].
|
|
||||||
earlyCompilerRT
|
|
||||||
// earlyRuntimes is an early, standalone installation of LLVM runtimes to
|
|
||||||
// work around the cmake build system leaking the system LLVM installation
|
|
||||||
// when invoking the newly built toolchain.
|
|
||||||
//
|
|
||||||
// earlyRuntimes must only be loaded by [LLVM].
|
|
||||||
earlyRuntimes
|
|
||||||
|
|
||||||
buildcatrust
|
|
||||||
utilMacros
|
|
||||||
|
|
||||||
// Musl is a standalone libc that does not depend on the toolchain.
|
|
||||||
Musl
|
|
||||||
// muslHeaders is a system installation of [Musl] headers.
|
|
||||||
muslHeaders
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// nettle3 is an older version of [Nettle].
|
|
||||||
nettle3
|
|
||||||
|
|
||||||
// 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
|
|
||||||
)
|
|
||||||
|
|
||||||
// P represents multiple [PArtifact] and is stable through JSON.
|
|
||||||
type P []PArtifact
|
|
||||||
|
|
||||||
// MarshalJSON represents [PArtifact] by their [Metadata.Name].
|
|
||||||
func (s P) MarshalJSON() ([]byte, error) {
|
|
||||||
names := make([]string, len(s))
|
|
||||||
for i, p := range s {
|
|
||||||
names[i] = GetMetadata(p).Name
|
|
||||||
}
|
|
||||||
return json.Marshal(names)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON resolves the value created by MarshalJSON back to [P].
|
|
||||||
func (s *P) UnmarshalJSON(data []byte) error {
|
|
||||||
var names []string
|
|
||||||
if err := json.Unmarshal(data, &names); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*s = make(P, len(names))
|
|
||||||
for i, name := range names {
|
|
||||||
if p, ok := ResolveName(name); !ok {
|
|
||||||
return fmt.Errorf("unknown artifact %q", name)
|
|
||||||
} else {
|
|
||||||
(*s)[i] = p
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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"`
|
|
||||||
|
|
||||||
// Runtime dependencies.
|
|
||||||
Dependencies P `json:"dependencies"`
|
|
||||||
|
|
||||||
// Project identifier on [Anitya].
|
|
||||||
//
|
|
||||||
// [Anitya]: https://release-monitoring.org/
|
|
||||||
ID int `json:"-"`
|
|
||||||
|
|
||||||
// Optional custom version checking behaviour.
|
|
||||||
latest func(v *Versions) string
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLatest returns the latest version described by v.
|
|
||||||
func (meta *Metadata) GetLatest(v *Versions) string {
|
|
||||||
if meta.latest != nil {
|
|
||||||
return meta.latest(v)
|
|
||||||
}
|
|
||||||
return v.Latest
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// getStable returns the first Stable version, or Latest if that is unavailable.
|
|
||||||
func (v *Versions) getStable() string {
|
|
||||||
if len(v.Stable) == 0 {
|
|
||||||
return v.Latest
|
|
||||||
}
|
|
||||||
return v.Stable[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
|
||||||
req.Header.Set("User-Agent", "Rosa/1.1")
|
|
||||||
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)]struct {
|
|
||||||
a pkg.Artifact
|
|
||||||
v string
|
|
||||||
}
|
|
||||||
// artifactsOnce is for lazy initialisation of artifacts.
|
|
||||||
artifactsOnce [_toolchainEnd][len(artifactsM)]sync.Once
|
|
||||||
|
|
||||||
// presetOpts globally modifies behaviour of presets.
|
|
||||||
presetOpts int
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// OptSkipCheck skips running all test suites.
|
|
||||||
OptSkipCheck = 1 << iota
|
|
||||||
// OptLLVMNoLTO disables LTO in all [LLVM] stages.
|
|
||||||
OptLLVMNoLTO
|
|
||||||
)
|
|
||||||
|
|
||||||
// Flags returns the current preset flags
|
|
||||||
func Flags() int { return presetOpts }
|
|
||||||
|
|
||||||
// zero zeros the value pointed to by p.
|
|
||||||
func zero[T any](p *T) { var v T; *p = v }
|
|
||||||
|
|
||||||
// DropCaches arranges for all cached [pkg.Artifact] to be freed some time after
|
|
||||||
// it returns. Must not be used concurrently with any other function from this
|
|
||||||
// package.
|
|
||||||
func DropCaches(flags int) {
|
|
||||||
presetOpts = flags
|
|
||||||
zero(&artifacts)
|
|
||||||
zero(&artifactsOnce)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMetadata returns [Metadata] of a [PArtifact].
|
|
||||||
func GetMetadata(p PArtifact) *Metadata { return &artifactsM[p] }
|
|
||||||
|
|
||||||
// construct constructs a [pkg.Artifact] corresponding to a [PArtifact] once.
|
|
||||||
func (t Toolchain) construct(p PArtifact) {
|
|
||||||
artifactsOnce[t][p].Do(func() {
|
|
||||||
artifacts[t][p].a, artifacts[t][p].v = artifactsM[p].f(t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load returns the resulting [pkg.Artifact] of [PArtifact].
|
|
||||||
func (t Toolchain) Load(p PArtifact) pkg.Artifact {
|
|
||||||
t.construct(p)
|
|
||||||
return artifacts[t][p].a
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version returns the version string of [PArtifact].
|
|
||||||
func (t Toolchain) Version(p PArtifact) string {
|
|
||||||
t.construct(p)
|
|
||||||
return artifacts[t][p].v
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package rosa_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"hakurei.app/internal/rosa"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLoad(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
for i := range rosa.PresetEnd {
|
|
||||||
p := rosa.PArtifact(i)
|
|
||||||
t.Run(rosa.GetMetadata(p).Name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
rosa.Std.Load(p)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkAll(b *testing.B) {
|
|
||||||
flags := rosa.Flags()
|
|
||||||
b.Cleanup(func() { rosa.DropCaches(flags) })
|
|
||||||
|
|
||||||
for b.Loop() {
|
|
||||||
for i := range rosa.PresetEnd {
|
|
||||||
rosa.Std.Load(rosa.PArtifact(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
rosa.DropCaches(0)
|
|
||||||
b.StartTimer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestResolveName(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
for i := range rosa.PresetUnexportedStart {
|
|
||||||
p := i
|
|
||||||
name := rosa.GetMetadata(p).Name
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
if got, ok := rosa.ResolveName(name); !ok {
|
|
||||||
t.Fatal("ResolveName: ok = false")
|
|
||||||
} else if got != p {
|
|
||||||
t.Fatalf("ResolveName: %d, want %d", got, p)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func TestResolveNameUnexported(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
for i := rosa.PresetUnexportedStart; i < rosa.PresetEnd; i++ {
|
|
||||||
p := i
|
|
||||||
name := rosa.GetMetadata(p).Name
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
if got, ok := rosa.ResolveName(name); ok {
|
|
||||||
t.Fatalf("ResolveName: resolved unexported preset %d", got)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnique(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
names := make(map[string]struct{})
|
|
||||||
for i := range rosa.PresetEnd {
|
|
||||||
name := rosa.GetMetadata(rosa.PArtifact(i)).Name
|
|
||||||
if _, ok := names[name]; ok {
|
|
||||||
t.Fatalf("name %s is not unique", name)
|
|
||||||
}
|
|
||||||
names[name] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,11 +26,11 @@ install -D -m755 libargp.a /work/system/lib/libargp.a
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[ArgpStandalone] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newArgpStandalone,
|
f: Toolchain.newArgpStandalone,
|
||||||
|
|
||||||
Name: "argp-standalone",
|
Name: "argp-standalone",
|
||||||
Description: "hierarchical argument parsing library broken out from glibc",
|
Description: "hierarchical argument parsing library broken out from glibc",
|
||||||
Website: "http://www.lysator.liu.se/~nisse/misc/",
|
Website: "http://www.lysator.liu.se/~nisse/misc/",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,348 @@
|
|||||||
|
// Package azalea implements a proof-of-concept, domain-specific language for
|
||||||
|
// Rosa OS software packaging.
|
||||||
|
package azalea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"text/scanner"
|
||||||
|
)
|
||||||
|
|
||||||
|
// idents are runes accepted in an identifier.
|
||||||
|
var idents = [...]bool{
|
||||||
|
'0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true,
|
||||||
|
'7': true, '8': true, '9': true,
|
||||||
|
|
||||||
|
'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true,
|
||||||
|
'H': true, 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true,
|
||||||
|
'O': true, 'P': true, 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true,
|
||||||
|
'V': true, 'W': true, 'X': true, 'Y': true, 'Z': true,
|
||||||
|
|
||||||
|
'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true,
|
||||||
|
'h': true, 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true,
|
||||||
|
'o': true, 'p': true, 'q': true, 'r': true, 's': true, 't': true, 'u': true,
|
||||||
|
'v': true, 'w': true, 'x': true, 'y': true, 'z': true,
|
||||||
|
|
||||||
|
'-': true, '_': true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TokenError describes an unexpected token.
|
||||||
|
type TokenError [2]rune
|
||||||
|
|
||||||
|
func (e TokenError) Error() string {
|
||||||
|
return "expected " + scanner.TokenString(e[0]) +
|
||||||
|
", found " + scanner.TokenString(e[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExprError is an unexpected token encountered while parsing an expression.
|
||||||
|
type ExprError rune
|
||||||
|
|
||||||
|
func (e ExprError) Error() string {
|
||||||
|
return "unexpected token " + scanner.TokenString(rune(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
// must1 returns v, or panics if err is not nil.
|
||||||
|
func must1[T any](v T, err error) T {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// parser retains the current token.
|
||||||
|
type parser struct {
|
||||||
|
s scanner.Scanner
|
||||||
|
tok rune
|
||||||
|
}
|
||||||
|
|
||||||
|
// scan advances the underlying scanner to the next token, storing its result.
|
||||||
|
func (p *parser) scan() rune { p.tok = p.s.Scan(); return p.tok }
|
||||||
|
|
||||||
|
// expects panics with [TokenError] for an unexpected tok.
|
||||||
|
func (p *parser) expects(expects rune) {
|
||||||
|
if p.tok != expects {
|
||||||
|
panic(TokenError{expects, p.tok})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// scanAs advances the scanner for an expected token.
|
||||||
|
func (p *parser) scanAs(expects rune) { p.scan(); p.expects(expects) }
|
||||||
|
|
||||||
|
// An Int is the value represented by an integer literal.
|
||||||
|
type Int int64
|
||||||
|
|
||||||
|
func (v Int) GoString() string {
|
||||||
|
return "azalea.Int(" + strconv.FormatInt(int64(v), 10) + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseInt parses the current token as a base 10 representation of a 64-bit
|
||||||
|
// signed integer.
|
||||||
|
func (p *parser) parseInt() Int {
|
||||||
|
v, err := strconv.ParseInt(p.s.TokenText(), 10, 64)
|
||||||
|
return must1(Int(v), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A String holds the unquoted content of a string literal.
|
||||||
|
type String string
|
||||||
|
|
||||||
|
func (v String) GoString() string {
|
||||||
|
return "azalea.String(" + strconv.Quote(string(v)) + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseString parses the current token as a string.
|
||||||
|
func (p *parser) parseString() String {
|
||||||
|
s, err := strconv.Unquote(p.s.TokenText())
|
||||||
|
return must1(String(s), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Ident holds the name of an identifier.
|
||||||
|
type Ident string
|
||||||
|
|
||||||
|
func (v Ident) GoString() string {
|
||||||
|
return "azalea.Ident(" + strconv.Quote(string(v)) + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Val are statements joined by the '+' operator. Only the [String] type
|
||||||
|
// supports concatenation.
|
||||||
|
type Val []any
|
||||||
|
|
||||||
|
// parseVal parses until the end of the [Val].
|
||||||
|
func (p *parser) parseVal() (v Val) {
|
||||||
|
v = append(v, p.parseExpr())
|
||||||
|
for p.tok == '+' {
|
||||||
|
p.scan()
|
||||||
|
v = append(v, p.parseExpr())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Array holds statements in an array.
|
||||||
|
type Array []Val
|
||||||
|
|
||||||
|
// A KV holds a key/value pair.
|
||||||
|
type KV struct {
|
||||||
|
K String
|
||||||
|
V Val
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Arg represents an argument of [Func].
|
||||||
|
type Arg struct {
|
||||||
|
K []Ident
|
||||||
|
V Val
|
||||||
|
R bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func is a function call or package declaration.
|
||||||
|
type Func struct {
|
||||||
|
// Function or package identifier.
|
||||||
|
Ident Ident
|
||||||
|
// Whether this is a package declaration.
|
||||||
|
Package bool
|
||||||
|
// Key-value arguments.
|
||||||
|
Args []Arg
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseExpr parses the current expression.
|
||||||
|
func (p *parser) parseExpr() any {
|
||||||
|
switch p.tok {
|
||||||
|
case scanner.Int:
|
||||||
|
v := p.parseInt()
|
||||||
|
p.scan()
|
||||||
|
return v
|
||||||
|
|
||||||
|
case scanner.String, scanner.RawString:
|
||||||
|
v := p.parseString()
|
||||||
|
p.scan()
|
||||||
|
return v
|
||||||
|
|
||||||
|
case scanner.Ident:
|
||||||
|
var v Func
|
||||||
|
v.Ident = Ident(p.s.TokenText())
|
||||||
|
if v.Package = v.Ident == "package"; v.Package {
|
||||||
|
p.scanAs(scanner.Ident)
|
||||||
|
v.Ident = Ident(p.s.TokenText())
|
||||||
|
}
|
||||||
|
|
||||||
|
p.scan()
|
||||||
|
switch p.tok {
|
||||||
|
case '{':
|
||||||
|
for {
|
||||||
|
p.scan()
|
||||||
|
switch p.tok {
|
||||||
|
case '}':
|
||||||
|
p.scan()
|
||||||
|
return v
|
||||||
|
|
||||||
|
case scanner.Ident:
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(TokenError{scanner.Ident, p.tok})
|
||||||
|
}
|
||||||
|
|
||||||
|
arg := Arg{K: []Ident{Ident(p.s.TokenText())}}
|
||||||
|
delim := true
|
||||||
|
arg:
|
||||||
|
for {
|
||||||
|
p.scan()
|
||||||
|
switch p.tok {
|
||||||
|
case ',':
|
||||||
|
if delim {
|
||||||
|
delim = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
panic(ExprError(p.tok))
|
||||||
|
|
||||||
|
case scanner.Ident:
|
||||||
|
if delim {
|
||||||
|
panic(TokenError{',', p.tok})
|
||||||
|
}
|
||||||
|
delim = true
|
||||||
|
arg.K = append(arg.K, Ident(p.s.TokenText()))
|
||||||
|
|
||||||
|
default:
|
||||||
|
break arg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch p.tok {
|
||||||
|
case '=':
|
||||||
|
break
|
||||||
|
|
||||||
|
case '*':
|
||||||
|
arg.R = true
|
||||||
|
p.scanAs('=')
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(TokenError{'=', p.tok})
|
||||||
|
}
|
||||||
|
p.scan()
|
||||||
|
arg.V = p.parseVal()
|
||||||
|
v.Args = append(v.Args, arg)
|
||||||
|
p.expects(';')
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return v.Ident
|
||||||
|
}
|
||||||
|
|
||||||
|
case '{':
|
||||||
|
var v []KV
|
||||||
|
for {
|
||||||
|
p.scan()
|
||||||
|
switch p.tok {
|
||||||
|
case '}':
|
||||||
|
p.scan()
|
||||||
|
return v
|
||||||
|
|
||||||
|
case scanner.String:
|
||||||
|
pair := KV{K: p.parseString()}
|
||||||
|
p.scan()
|
||||||
|
switch p.tok {
|
||||||
|
case ';':
|
||||||
|
break
|
||||||
|
|
||||||
|
case ':':
|
||||||
|
p.scan()
|
||||||
|
pair.V = p.parseVal()
|
||||||
|
p.expects(';')
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(ExprError(p.tok))
|
||||||
|
}
|
||||||
|
v = append(v, pair)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(ExprError(p.tok))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
var (
|
||||||
|
v Array
|
||||||
|
delim bool
|
||||||
|
)
|
||||||
|
p.scan()
|
||||||
|
for {
|
||||||
|
switch p.tok {
|
||||||
|
case ',':
|
||||||
|
if delim {
|
||||||
|
p.scan()
|
||||||
|
delim = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
panic(ExprError(','))
|
||||||
|
case ']':
|
||||||
|
p.scan()
|
||||||
|
return v
|
||||||
|
case scanner.EOF:
|
||||||
|
panic(ExprError(scanner.EOF))
|
||||||
|
default:
|
||||||
|
if delim {
|
||||||
|
panic(TokenError{',', p.tok})
|
||||||
|
}
|
||||||
|
delim = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v = append(v, p.parseVal())
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(ExprError(p.tok))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScanError is the error count parsing all expressions.
|
||||||
|
type ScanError int
|
||||||
|
|
||||||
|
func (ScanError) Error() string {
|
||||||
|
return "aborting due to scanning errors"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses expressions from r.
|
||||||
|
func Parse(r io.Reader) (e []any, err error) {
|
||||||
|
var p parser
|
||||||
|
p.s.Init(r)
|
||||||
|
|
||||||
|
p.s.Mode = scanner.ScanIdents |
|
||||||
|
scanner.ScanInts |
|
||||||
|
scanner.ScanStrings |
|
||||||
|
scanner.ScanRawStrings |
|
||||||
|
scanner.ScanComments |
|
||||||
|
scanner.SkipComments
|
||||||
|
p.s.IsIdentRune = func(ch rune, i int) bool {
|
||||||
|
if i == 0 && ch >= '0' && ch <= '9' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return ch > 0 && ch < rune(len(idents)) && idents[ch]
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
v := recover()
|
||||||
|
if v == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_err, ok := v.(error)
|
||||||
|
if !ok {
|
||||||
|
panic(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
err = _err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = errors.Join(err, _err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
p.scan()
|
||||||
|
for p.tok != scanner.EOF {
|
||||||
|
e = append(e, p.parseExpr())
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.s.ErrorCount != 0 {
|
||||||
|
err = ScanError(p.s.ErrorCount)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
package azalea_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"text/scanner"
|
||||||
|
|
||||||
|
. "hakurei.app/internal/rosa/azalea"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed testdata/gcc.az
|
||||||
|
var sample string
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
data string
|
||||||
|
want []any
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{"invalid", "}", nil, ExprError('}')},
|
||||||
|
{"bad sep", "f{v?}", nil, TokenError{'=', '?'}},
|
||||||
|
{"bad ident", "f{9}", nil, TokenError{scanner.Ident, scanner.Int}},
|
||||||
|
{"share bad sep", "f { v,,v = v; }", nil, ExprError(',')},
|
||||||
|
{"share missing sep", "f { v v }", nil, TokenError{',', scanner.Ident}},
|
||||||
|
|
||||||
|
{"ident", `v`, []any{Ident("v")}, nil},
|
||||||
|
{"concat", `f { v = v+"\xfd"+p{}+9; }`, []any{Func{
|
||||||
|
Ident: "f",
|
||||||
|
|
||||||
|
Args: []Arg{{K: []Ident{"v"}, V: Val{
|
||||||
|
Ident("v"),
|
||||||
|
String("\xfd"),
|
||||||
|
Func{Ident: "p"},
|
||||||
|
Int(9),
|
||||||
|
}}},
|
||||||
|
}}, nil},
|
||||||
|
{"truncated string concat", `f { v = v+; }`, nil,
|
||||||
|
ExprError(';')},
|
||||||
|
|
||||||
|
{"empty pairs", `{}`, []any{[]KV(nil)}, nil},
|
||||||
|
{"short kv", `{"\x00":v;}`, []any{[]KV{
|
||||||
|
{K: "\x00", V: Val{Ident("v")}},
|
||||||
|
}}, nil},
|
||||||
|
{"truncated kv", `{"\x00"`, nil, ExprError(scanner.EOF)},
|
||||||
|
{"ident kv", `{v="";}`, nil, ExprError(scanner.Ident)},
|
||||||
|
|
||||||
|
{"empty array", `[]`, []any{Array(nil)}, nil},
|
||||||
|
{"integer array", `[9]`, []any{Array{{Int(9)}}}, nil},
|
||||||
|
{"short array", `[ "\x00" ]`, []any{
|
||||||
|
Array{{String("\x00")}},
|
||||||
|
}, nil},
|
||||||
|
{"short array delim", `[ "\x00", ]`, []any{
|
||||||
|
Array{{String("\x00")}},
|
||||||
|
}, nil},
|
||||||
|
{"missing array value", `[ "\x00", , v ]`, nil, ExprError(',')},
|
||||||
|
{"missing array delimiter", `[ v0 v1 ]`, nil, TokenError{',', scanner.Ident}},
|
||||||
|
{"truncated array", `[ "\x00"`, nil,
|
||||||
|
ExprError(scanner.EOF)},
|
||||||
|
|
||||||
|
{"gcc", sample, []any{Func{
|
||||||
|
Ident: Ident("gcc"),
|
||||||
|
Package: true,
|
||||||
|
|
||||||
|
Args: []Arg{
|
||||||
|
{K: []Ident{Ident("description")}, V: Val{String("The GNU Compiler Collection")}},
|
||||||
|
{K: []Ident{Ident("website")}, V: Val{String("https://www.gnu.org/software/gcc")}},
|
||||||
|
{K: []Ident{Ident("anitya")}, V: Val{Int(6502)}},
|
||||||
|
|
||||||
|
{K: []Ident{Ident("version")}, V: Val{String("16.1.0")}, R: true},
|
||||||
|
{K: []Ident{Ident("source")}, V: Val{Func{
|
||||||
|
Ident: Ident("remoteTar"),
|
||||||
|
|
||||||
|
Args: []Arg{
|
||||||
|
{K: []Ident{Ident("url")}, V: Val{
|
||||||
|
String("https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"),
|
||||||
|
String("gcc-"),
|
||||||
|
Ident("version"),
|
||||||
|
String("/gcc-"),
|
||||||
|
Ident("version"),
|
||||||
|
String(".tar.gz"),
|
||||||
|
}},
|
||||||
|
{K: []Ident{Ident("checksum")}, V: Val{String("4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K")}},
|
||||||
|
{K: []Ident{Ident("compress")}, V: Val{Ident("gzip")}},
|
||||||
|
},
|
||||||
|
}}},
|
||||||
|
{K: []Ident{Ident("patches")}, V: Val{Array{
|
||||||
|
{String("musl-off64_t-loff_t.patch")},
|
||||||
|
{String("musl-legacy-lfs.patch")},
|
||||||
|
}}},
|
||||||
|
|
||||||
|
{K: []Ident{Ident("exclusive")}, V: Val{Ident("true")}},
|
||||||
|
|
||||||
|
{K: []Ident{Ident("exec")}, V: Val{Func{
|
||||||
|
Ident: Ident("make"),
|
||||||
|
|
||||||
|
Args: []Arg{
|
||||||
|
{K: []Ident{Ident("configure")}, V: Val{[]KV{
|
||||||
|
{K: String("disable-multilib")},
|
||||||
|
{K: String("enable-default-pie")},
|
||||||
|
{K: String("disable-nls")},
|
||||||
|
{K: String("with-gnu-as")},
|
||||||
|
{K: String("with-gnu-ld")},
|
||||||
|
{K: String("with-system-zlib")},
|
||||||
|
{K: String("enable-languages"), V: Val{String("c,c++,go")}},
|
||||||
|
{K: String("with-native-system-header-dir"), V: Val{String("/system/include")}},
|
||||||
|
{K: String("with-multilib-list"), V: Val{Func{
|
||||||
|
Ident: Ident("arch"),
|
||||||
|
|
||||||
|
Args: []Arg{
|
||||||
|
{K: []Ident{Ident("amd64"), Ident("arm64")}, V: Val{String("''")}},
|
||||||
|
{K: []Ident{Ident("default")}, V: Val{Ident("unset")}},
|
||||||
|
},
|
||||||
|
}}},
|
||||||
|
}}},
|
||||||
|
{K: []Ident{Ident("make")}, V: Val{Array{
|
||||||
|
{String("BOOT_CFLAGS='-O2 -g'")},
|
||||||
|
{
|
||||||
|
Func{Ident: Ident("noop"), Args: []Arg{{K: []Ident{Ident("key")}, V: Val{Ident("value")}}}},
|
||||||
|
String("\x00"),
|
||||||
|
},
|
||||||
|
{String("bootstrap")},
|
||||||
|
}}},
|
||||||
|
|
||||||
|
{K: []Ident{Ident("skip-check")}, V: Val{Ident("true")}},
|
||||||
|
},
|
||||||
|
}}},
|
||||||
|
|
||||||
|
{K: []Ident{Ident("inputs")}, V: Val{Array{
|
||||||
|
{Ident("binutils")},
|
||||||
|
{Ident("mpc")},
|
||||||
|
{Ident("zlib")},
|
||||||
|
{Ident("libucontext")},
|
||||||
|
{Ident("kernel-headers")},
|
||||||
|
}}},
|
||||||
|
},
|
||||||
|
}}, nil},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p, err := Parse(strings.NewReader(tc.data))
|
||||||
|
if !reflect.DeepEqual(p, tc.want) {
|
||||||
|
t.Errorf("Parse: %#v, want %#v", p, tc.want)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(err, tc.err) {
|
||||||
|
t.Errorf("Parse: error = %v, want %v", err, tc.err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParse(b *testing.B) {
|
||||||
|
r := strings.NewReader(sample)
|
||||||
|
for b.Loop() {
|
||||||
|
if _, err := Parse(r); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
r.Reset(sample)
|
||||||
|
b.StartTimer()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
package azalea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"maps"
|
||||||
|
"reflect"
|
||||||
|
"unique"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Value are types supported by the language.
|
||||||
|
type Value interface {
|
||||||
|
bool | int64 | string | []string | [][2]string
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
// FArg is an argument passed to [F].
|
||||||
|
FArg struct {
|
||||||
|
K unique.Handle[Ident]
|
||||||
|
V any
|
||||||
|
R bool
|
||||||
|
}
|
||||||
|
// FArgs are arguments passed to [F].
|
||||||
|
FArgs []FArg
|
||||||
|
|
||||||
|
// F is the implementation of a [Func].
|
||||||
|
F struct {
|
||||||
|
F func(isPackage bool, args FArgs) (v any, set bool, err error)
|
||||||
|
V map[unique.Handle[Ident]]any
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Apply applies named arguments and rejects unused arguments.
|
||||||
|
func (args FArgs) Apply(v map[unique.Handle[Ident]]any) error {
|
||||||
|
for _, arg := range args {
|
||||||
|
if arg.V == nil {
|
||||||
|
// unset
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := v[arg.K]
|
||||||
|
if !ok {
|
||||||
|
if arg.R {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return UndefinedError(arg.K.Value())
|
||||||
|
}
|
||||||
|
err := storeE(r, arg.V)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Frame refers to local variables and debugging information.
|
||||||
|
type Frame struct {
|
||||||
|
// Local constants.
|
||||||
|
Val map[unique.Handle[Ident]]any
|
||||||
|
// Functions.
|
||||||
|
Func map[unique.Handle[Ident]]F
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsupportedExprError is an expression with invalid concrete type.
|
||||||
|
type UnsupportedExprError struct{ E any }
|
||||||
|
|
||||||
|
func (e UnsupportedExprError) Error() string {
|
||||||
|
return fmt.Sprintf("unsupported expression %#v", e.E)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UndefinedError is an identifier not defined in any stack frame visible to the
|
||||||
|
// expression containing it.
|
||||||
|
type UndefinedError Ident
|
||||||
|
|
||||||
|
func (e UndefinedError) Error() string {
|
||||||
|
return "undefined: " + string(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate is evaluateAny with a type parameter.
|
||||||
|
func evaluate[T Value](s []Frame, expr any, rp *T) bool {
|
||||||
|
return evaluateAny(s, expr, rp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeError is an unexpected type during evaluation.
|
||||||
|
type TypeError struct {
|
||||||
|
Concrete, Asserted reflect.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e TypeError) Error() string {
|
||||||
|
return "expected " + e.Asserted.String() + ", got " + e.Concrete.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e TypeError) Is(err error) bool {
|
||||||
|
var v TypeError
|
||||||
|
return errors.As(err, &v) &&
|
||||||
|
e.Asserted == v.Asserted &&
|
||||||
|
e.Concrete == v.Concrete
|
||||||
|
}
|
||||||
|
|
||||||
|
// storeE is a convenience function to set the value of a result pointer.
|
||||||
|
func storeE(rp any, r any) error {
|
||||||
|
pv := reflect.ValueOf(rp).Elem()
|
||||||
|
v := reflect.ValueOf(r)
|
||||||
|
pt, vt := pv.Type(), v.Type()
|
||||||
|
if !vt.AssignableTo(pt) {
|
||||||
|
return TypeError{vt, pt}
|
||||||
|
}
|
||||||
|
pv.Set(v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// store is like storeE, but panics if error is non-nil.
|
||||||
|
func store[T Value](rp any, r T) {
|
||||||
|
err := storeE(rp, r)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EvaluationError is an error and the expression it occurred in.
|
||||||
|
type EvaluationError struct {
|
||||||
|
Expr any
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap returns the underlying error.
|
||||||
|
func (e EvaluationError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
|
// Error returns a very long error description that should not be presented
|
||||||
|
// to the user directly.
|
||||||
|
func (e EvaluationError) Error() string {
|
||||||
|
return fmt.Sprintf("expression %#v: %v", e.Expr, e.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluateAny implements [Evaluate].
|
||||||
|
func evaluateAny(s []Frame, expr, rp any) bool {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
if r == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err, ok := r.(error)
|
||||||
|
if !ok {
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok = err.(EvaluationError); ok {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
panic(EvaluationError{expr, err})
|
||||||
|
}()
|
||||||
|
|
||||||
|
switch e := expr.(type) {
|
||||||
|
case Int:
|
||||||
|
store(rp, int64(e))
|
||||||
|
return true
|
||||||
|
|
||||||
|
case String:
|
||||||
|
store(rp, string(e))
|
||||||
|
return true
|
||||||
|
|
||||||
|
case Ident:
|
||||||
|
var (
|
||||||
|
v any
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
for i := range s {
|
||||||
|
v, ok = s[len(s)-1-i].Val[unique.Make(e)]
|
||||||
|
if ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
panic(UndefinedError(e))
|
||||||
|
}
|
||||||
|
if err := storeE(rp, v); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
case Val:
|
||||||
|
if len(e) == 1 {
|
||||||
|
switch v := e[0].(type) {
|
||||||
|
case Ident:
|
||||||
|
switch v {
|
||||||
|
case "unset":
|
||||||
|
return false
|
||||||
|
case "true":
|
||||||
|
store(rp, true)
|
||||||
|
return true
|
||||||
|
case "false":
|
||||||
|
store(rp, false)
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return evaluateAny(s, v, rp)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return evaluateAny(s, e[0], rp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var v string
|
||||||
|
for i := range e {
|
||||||
|
var _r string
|
||||||
|
if evaluate(s, e[i], &_r) {
|
||||||
|
v += _r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store(rp, v)
|
||||||
|
return true
|
||||||
|
|
||||||
|
case Array:
|
||||||
|
r := make([]string, 0, len(e))
|
||||||
|
for i := range e {
|
||||||
|
var _r string
|
||||||
|
if evaluate(s, e[i], &_r) {
|
||||||
|
r = append(r, _r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store(rp, r)
|
||||||
|
return true
|
||||||
|
|
||||||
|
case []KV:
|
||||||
|
r := make([][2]string, 0, len(e))
|
||||||
|
for i := range e {
|
||||||
|
var _r string
|
||||||
|
if e[i].V == nil || evaluate(s, e[i].V, &_r) {
|
||||||
|
r = append(r, [2]string{string(e[i].K), _r})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store(rp, r)
|
||||||
|
return true
|
||||||
|
|
||||||
|
case Func:
|
||||||
|
var (
|
||||||
|
f F
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
for i := range s {
|
||||||
|
f, ok = s[len(s)-1-i].Func[unique.Make(e.Ident)]
|
||||||
|
if ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
panic(UndefinedError(e.Ident))
|
||||||
|
}
|
||||||
|
|
||||||
|
argc := len(e.Args)
|
||||||
|
for _, arg := range e.Args {
|
||||||
|
argc += len(arg.K) - 1
|
||||||
|
}
|
||||||
|
fargs := make([]FArg, 0, len(e.Args))
|
||||||
|
s = append(s, Frame{Val: maps.Clone(f.V)})
|
||||||
|
fp := &s[len(s)-1]
|
||||||
|
|
||||||
|
for _, arg := range e.Args {
|
||||||
|
farg := FArg{R: arg.R}
|
||||||
|
if !evaluateAny(s, arg.V, &farg.V) {
|
||||||
|
farg.V = nil
|
||||||
|
}
|
||||||
|
for _, name := range arg.K {
|
||||||
|
h := unique.Make(name)
|
||||||
|
farg.K = h
|
||||||
|
fargs = append(fargs, farg)
|
||||||
|
|
||||||
|
if arg.R && farg.V != nil {
|
||||||
|
if fp.Val == nil {
|
||||||
|
fp.Val = make(map[unique.Handle[Ident]]any)
|
||||||
|
}
|
||||||
|
(*fp).Val[h] = farg.V
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v, set, err := f.F(e.Package, fargs)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else if v != nil {
|
||||||
|
if err = storeE(rp, v); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(UnsupportedExprError{expr})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate evaluates a statement and returns its value.
|
||||||
|
func Evaluate[T Value](s []Frame, expr any) (v T, set bool, err error) {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
if r == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_err, ok := r.(error)
|
||||||
|
if !ok {
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
err = _err
|
||||||
|
}()
|
||||||
|
set = evaluate[T](s, expr, &v)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,358 @@
|
|||||||
|
package azalea_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"unique"
|
||||||
|
|
||||||
|
. "hakurei.app/internal/rosa/azalea"
|
||||||
|
)
|
||||||
|
|
||||||
|
// makeStackCheck creates a stack with a single frame with a single function "f"
|
||||||
|
// which calls the check function internally.
|
||||||
|
func makeStackCheck(check func(args FArgs) (any, error)) []Frame {
|
||||||
|
return []Frame{{Func: map[unique.Handle[Ident]]F{
|
||||||
|
unique.Make(Ident("f")): {F: func(
|
||||||
|
isPackage bool,
|
||||||
|
args FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
set = true
|
||||||
|
v, err = check(args)
|
||||||
|
if isPackage {
|
||||||
|
err = errors.New("unexpected package")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
data string
|
||||||
|
s []Frame
|
||||||
|
want string
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{"apply unset", `f { v = unset; }`, makeStackCheck(func(
|
||||||
|
args FArgs,
|
||||||
|
) (v any, err error) {
|
||||||
|
v = "\xfd"
|
||||||
|
err = args.Apply(map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("v")): &v,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}), "\xfd", nil},
|
||||||
|
|
||||||
|
{"apply bad type", `f { v = 9; }`, makeStackCheck(func(
|
||||||
|
args FArgs,
|
||||||
|
) (v any, err error) {
|
||||||
|
v = "\xfd"
|
||||||
|
err = args.Apply(map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("v")): &v,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}), "", TypeError{
|
||||||
|
Concrete: reflect.TypeFor[int64](),
|
||||||
|
Asserted: reflect.TypeFor[string](),
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"apply undefined", `f { v = 9; }`, makeStackCheck(func(
|
||||||
|
args FArgs,
|
||||||
|
) (v any, err error) {
|
||||||
|
v = "\xfd"
|
||||||
|
err = args.Apply(map[unique.Handle[Ident]]any{})
|
||||||
|
return
|
||||||
|
}), "", EvaluationError{
|
||||||
|
Expr: Func{
|
||||||
|
Ident: Ident("f"),
|
||||||
|
Args: []Arg{
|
||||||
|
{K: []Ident{"v"}, V: Val{Int(9)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Err: UndefinedError("v"),
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"apply bound undefined", `f { _v* = "\x00"; v = _v; }`, makeStackCheck(func(
|
||||||
|
args FArgs,
|
||||||
|
) (v any, err error) {
|
||||||
|
v = "\xfd"
|
||||||
|
err = args.Apply(map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("v")): &v,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}), "\x00", nil},
|
||||||
|
|
||||||
|
{"undefined function", `f {}`, nil, "", EvaluationError{
|
||||||
|
Expr: Func{Ident: "f"},
|
||||||
|
Err: UndefinedError("f"),
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"error wrap deep", `f { v = nil; }`, makeStackCheck(func(
|
||||||
|
FArgs,
|
||||||
|
) (any, error) {
|
||||||
|
panic("unreachable")
|
||||||
|
}), "", EvaluationError{
|
||||||
|
Expr: Ident("nil"),
|
||||||
|
Err: UndefinedError("nil"),
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var expr Func
|
||||||
|
if e, err := Parse(strings.NewReader(tc.data)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if len(e) != 1 {
|
||||||
|
t.Fatalf("got expression %#v", e)
|
||||||
|
} else {
|
||||||
|
expr = e[0].(Func)
|
||||||
|
}
|
||||||
|
r, set, err := Evaluate[string](tc.s, expr)
|
||||||
|
if set != (err == nil) {
|
||||||
|
t.Error("Evaluate: unexpected unset")
|
||||||
|
}
|
||||||
|
|
||||||
|
if r != tc.want {
|
||||||
|
t.Errorf("Evaluate: %q, want %q", r, tc.want)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errEquals bool
|
||||||
|
if errors.As(err, new(TypeError)) {
|
||||||
|
errEquals = errors.Is(err, tc.err)
|
||||||
|
} else {
|
||||||
|
errEquals = reflect.DeepEqual(err, tc.err)
|
||||||
|
}
|
||||||
|
if !errEquals {
|
||||||
|
t.Errorf("Evaluate: error = %v, want %v", err, tc.err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateGCC(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var gcc Func
|
||||||
|
if e, err := Parse(strings.NewReader(sample)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
gcc = e[0].(Func)
|
||||||
|
}
|
||||||
|
|
||||||
|
var got [3]FArgs
|
||||||
|
if r, set, err := Evaluate[string]([]Frame{{
|
||||||
|
Func: map[unique.Handle[Ident]]F{
|
||||||
|
unique.Make(Ident("gcc")): {F: func(
|
||||||
|
isPackage bool,
|
||||||
|
args FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
v = "\x00"
|
||||||
|
if !isPackage {
|
||||||
|
err = errors.New("not a package")
|
||||||
|
}
|
||||||
|
set = true
|
||||||
|
got[0] = args
|
||||||
|
return
|
||||||
|
}, V: map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("binutils")): "binutils",
|
||||||
|
unique.Make(Ident("mpc")): "mpc",
|
||||||
|
unique.Make(Ident("zlib")): "zlib",
|
||||||
|
unique.Make(Ident("libucontext")): "libucontext",
|
||||||
|
unique.Make(Ident("kernel-headers")): "kernel-headers",
|
||||||
|
}},
|
||||||
|
|
||||||
|
unique.Make(Ident("remoteTar")): {F: func(
|
||||||
|
isPackage bool,
|
||||||
|
args FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
if isPackage {
|
||||||
|
err = errors.New("unexpected package")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var url, checksum string
|
||||||
|
var compress int
|
||||||
|
if err = args.Apply(map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("url")): &url,
|
||||||
|
unique.Make(Ident("checksum")): &checksum,
|
||||||
|
unique.Make(Ident("compress")): &compress,
|
||||||
|
}); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if compress != 0xcafe {
|
||||||
|
err = fmt.Errorf("unexpected compress %#v", compress)
|
||||||
|
}
|
||||||
|
set = true
|
||||||
|
v = url + "?checksum=" + checksum
|
||||||
|
return
|
||||||
|
}, V: map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("gzip")): 0xcafe,
|
||||||
|
}},
|
||||||
|
|
||||||
|
unique.Make(Ident("make")): {F: func(
|
||||||
|
isPackage bool,
|
||||||
|
args FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
v = args
|
||||||
|
if isPackage {
|
||||||
|
err = errors.New("unexpected package")
|
||||||
|
}
|
||||||
|
set = true
|
||||||
|
return
|
||||||
|
}},
|
||||||
|
|
||||||
|
unique.Make(Ident("arch")): {F: func(
|
||||||
|
isPackage bool,
|
||||||
|
args FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
set = false
|
||||||
|
if isPackage {
|
||||||
|
err = errors.New("unexpected package")
|
||||||
|
}
|
||||||
|
got[1] = args
|
||||||
|
return
|
||||||
|
}},
|
||||||
|
|
||||||
|
unique.Make(Ident("noop")): {F: func(
|
||||||
|
isPackage bool,
|
||||||
|
args FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
set = false
|
||||||
|
if isPackage {
|
||||||
|
err = errors.New("unexpected package")
|
||||||
|
}
|
||||||
|
set = true
|
||||||
|
got[2] = args
|
||||||
|
return
|
||||||
|
}, V: map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("value")): "\xfd",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}}, gcc); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if r != "\x00" {
|
||||||
|
t.Fatalf("package: %q", r)
|
||||||
|
} else if !set {
|
||||||
|
t.Fatal("package: unset")
|
||||||
|
}
|
||||||
|
|
||||||
|
want := [...]FArgs{
|
||||||
|
{
|
||||||
|
{K: unique.Make(Ident("description")), V: "The GNU Compiler Collection"},
|
||||||
|
{K: unique.Make(Ident("website")), V: "https://www.gnu.org/software/gcc"},
|
||||||
|
{K: unique.Make(Ident("anitya")), V: int64(6502)},
|
||||||
|
|
||||||
|
{K: unique.Make(Ident("version")), V: "16.1.0", R: true},
|
||||||
|
{K: unique.Make(Ident("source")), V: "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-16.1.0/gcc-16.1.0.tar.gz?checksum=4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K"},
|
||||||
|
{K: unique.Make(Ident("patches")), V: []string{"musl-off64_t-loff_t.patch", "musl-legacy-lfs.patch"}},
|
||||||
|
|
||||||
|
{K: unique.Make(Ident("exclusive")), V: true},
|
||||||
|
{K: unique.Make(Ident("exec")), V: FArgs{
|
||||||
|
{K: unique.Make(Ident("configure")), V: [][2]string{
|
||||||
|
{"disable-multilib", ""},
|
||||||
|
{"enable-default-pie", ""},
|
||||||
|
{"disable-nls", ""},
|
||||||
|
{"with-gnu-as", ""},
|
||||||
|
{"with-gnu-ld", ""},
|
||||||
|
{"with-system-zlib", ""},
|
||||||
|
{"enable-languages", "c,c++,go"},
|
||||||
|
{"with-native-system-header-dir", "/system/include"},
|
||||||
|
}},
|
||||||
|
{K: unique.Make(Ident("make")), V: []string{
|
||||||
|
"BOOT_CFLAGS='-O2 -g'",
|
||||||
|
"\x00",
|
||||||
|
"bootstrap",
|
||||||
|
}},
|
||||||
|
{K: unique.Make(Ident("skip-check")), V: true},
|
||||||
|
}},
|
||||||
|
|
||||||
|
{K: unique.Make(Ident("inputs")), V: []string{
|
||||||
|
"binutils",
|
||||||
|
"mpc",
|
||||||
|
"zlib",
|
||||||
|
"libucontext",
|
||||||
|
"kernel-headers",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{K: unique.Make(Ident("amd64")), V: "''"},
|
||||||
|
{K: unique.Make(Ident("arm64")), V: "''"},
|
||||||
|
{K: unique.Make(Ident("default"))},
|
||||||
|
},
|
||||||
|
{{K: unique.Make(Ident("key")), V: "\xfd"}},
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("package: args = %#v, want %#v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEvaluate(b *testing.B) {
|
||||||
|
var gcc Func
|
||||||
|
if e, err := Parse(strings.NewReader(sample)); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
} else {
|
||||||
|
gcc = e[0].(Func)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := []Frame{{
|
||||||
|
Func: map[unique.Handle[Ident]]F{
|
||||||
|
unique.Make(Ident("gcc")): {F: func(
|
||||||
|
bool,
|
||||||
|
FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
return
|
||||||
|
}, V: map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("binutils")): "binutils",
|
||||||
|
unique.Make(Ident("mpc")): "mpc",
|
||||||
|
unique.Make(Ident("zlib")): "zlib",
|
||||||
|
unique.Make(Ident("libucontext")): "libucontext",
|
||||||
|
unique.Make(Ident("kernel-headers")): "kernel-headers",
|
||||||
|
}},
|
||||||
|
|
||||||
|
unique.Make(Ident("remoteTar")): {F: func(
|
||||||
|
bool,
|
||||||
|
FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
return
|
||||||
|
}, V: map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("gzip")): 0xcafe,
|
||||||
|
}},
|
||||||
|
|
||||||
|
unique.Make(Ident("make")): {F: func(
|
||||||
|
bool,
|
||||||
|
FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
return
|
||||||
|
}},
|
||||||
|
|
||||||
|
unique.Make(Ident("arch")): {F: func(
|
||||||
|
bool,
|
||||||
|
FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
return
|
||||||
|
}},
|
||||||
|
|
||||||
|
unique.Make(Ident("noop")): {F: func(
|
||||||
|
bool,
|
||||||
|
FArgs,
|
||||||
|
) (v any, set bool, err error) {
|
||||||
|
return
|
||||||
|
}, V: map[unique.Handle[Ident]]any{
|
||||||
|
unique.Make(Ident("value")): "\xfd",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
for b.Loop() {
|
||||||
|
if _, _, err := Evaluate[string](s, gcc); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+57
@@ -0,0 +1,57 @@
|
|||||||
|
package gcc {
|
||||||
|
description = "The GNU Compiler Collection";
|
||||||
|
website = "https://www.gnu.org/software/gcc";
|
||||||
|
anitya = 6502;
|
||||||
|
|
||||||
|
version* = "16.1.0";
|
||||||
|
source = remoteTar {
|
||||||
|
url = "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"+
|
||||||
|
"gcc-"+version+"/gcc-"+version+".tar.gz";
|
||||||
|
checksum = "4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K";
|
||||||
|
compress = gzip;
|
||||||
|
};
|
||||||
|
patches = [
|
||||||
|
"musl-off64_t-loff_t.patch",
|
||||||
|
"musl-legacy-lfs.patch",
|
||||||
|
];
|
||||||
|
|
||||||
|
// GCC spends most of its time in its many configure scripts, however
|
||||||
|
// it also saturates the CPU for a consequential amount of time.
|
||||||
|
exclusive = true;
|
||||||
|
|
||||||
|
exec = make {
|
||||||
|
configure = {
|
||||||
|
"disable-multilib";
|
||||||
|
"enable-default-pie";
|
||||||
|
"disable-nls";
|
||||||
|
"with-gnu-as";
|
||||||
|
"with-gnu-ld";
|
||||||
|
"with-system-zlib";
|
||||||
|
"enable-languages": "c,c++,go";
|
||||||
|
"with-native-system-header-dir": "/system/include";
|
||||||
|
"with-multilib-list": arch {
|
||||||
|
amd64, arm64 = "''";
|
||||||
|
default = unset;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
make = [
|
||||||
|
"BOOT_CFLAGS='-O2 -g'",
|
||||||
|
noop { key = value; } + "\x00",
|
||||||
|
"bootstrap",
|
||||||
|
];
|
||||||
|
|
||||||
|
// This toolchain is hacked to pieces, it is not expected to ever work
|
||||||
|
// well in its current state. That does not matter as long as the
|
||||||
|
// toolchain it produces passes its own test suite.
|
||||||
|
skip-check = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
inputs = [
|
||||||
|
binutils,
|
||||||
|
|
||||||
|
mpc,
|
||||||
|
zlib,
|
||||||
|
libucontext,
|
||||||
|
kernel-headers,
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/fhs"
|
"hakurei.app/fhs"
|
||||||
@@ -86,13 +85,13 @@ func (a busyboxBin) Cure(t *pkg.TContext) (err error) {
|
|||||||
|
|
||||||
// newBusyboxBin returns a [pkg.Artifact] containing a busybox installation from
|
// newBusyboxBin returns a [pkg.Artifact] containing a busybox installation from
|
||||||
// the https://busybox.net/downloads/binaries/ binary release.
|
// the https://busybox.net/downloads/binaries/ binary release.
|
||||||
func newBusyboxBin() pkg.Artifact {
|
func (s *S) newBusyboxBin() pkg.Artifact {
|
||||||
var version, url, checksum string
|
var version, url, checksum string
|
||||||
switch runtime.GOARCH {
|
switch s.arch {
|
||||||
case "amd64":
|
case "amd64":
|
||||||
version = "1.35.0"
|
version = "1.35.0"
|
||||||
url = "https://busybox.net/downloads/binaries/" +
|
url = "https://busybox.net/downloads/binaries/" +
|
||||||
version + "-" + linuxArch() + "-linux-musl/busybox"
|
version + "-" + s.linuxArch() + "-linux-musl/busybox"
|
||||||
checksum = "L7OBIsPu9enNHn7FqpBT1kOg_mCLNmetSeNMA3i4Y60Z5jTgnlX3qX3zcQtLx5AB"
|
checksum = "L7OBIsPu9enNHn7FqpBT1kOg_mCLNmetSeNMA3i4Y60Z5jTgnlX3qX3zcQtLx5AB"
|
||||||
case "arm64":
|
case "arm64":
|
||||||
version = "1.31.0"
|
version = "1.31.0"
|
||||||
@@ -101,11 +100,11 @@ func newBusyboxBin() pkg.Artifact {
|
|||||||
checksum = "npJjBO7iwhjW6Kx2aXeSxf8kXhVgTCDChOZTTsI8ZfFfa3tbsklxRiidZQdrVERg"
|
checksum = "npJjBO7iwhjW6Kx2aXeSxf8kXhVgTCDChOZTTsI8ZfFfa3tbsklxRiidZQdrVERg"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("unsupported target " + runtime.GOARCH)
|
panic("unsupported target " + s.arch)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pkg.NewExec(
|
return pkg.NewExec(
|
||||||
"busybox-bin-"+version, nil, pkg.ExecTimeoutMax, false,
|
"busybox-bin-"+version, s.arch, nil, pkg.ExecTimeoutMax, false, false,
|
||||||
fhs.AbsRoot, []string{
|
fhs.AbsRoot, []string{
|
||||||
"PATH=/system/bin",
|
"PATH=/system/bin",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func (t Toolchain) newBzip2() (pkg.Artifact, string) {
|
|||||||
}), version
|
}), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Bzip2] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newBzip2,
|
f: Toolchain.newBzip2,
|
||||||
|
|
||||||
Name: "bzip2",
|
Name: "bzip2",
|
||||||
@@ -34,5 +34,5 @@ func init() {
|
|||||||
Website: "https://sourceware.org/bzip2/",
|
Website: "https://sourceware.org/bzip2/",
|
||||||
|
|
||||||
ID: 237,
|
ID: 237,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ index 2ead810437..f85cbb8b1c 100644
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[CMake] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newCMake,
|
f: Toolchain.newCMake,
|
||||||
|
|
||||||
Name: "cmake",
|
Name: "cmake",
|
||||||
@@ -114,7 +114,7 @@ func init() {
|
|||||||
Website: "https://cmake.org/",
|
Website: "https://cmake.org/",
|
||||||
|
|
||||||
ID: 306,
|
ID: 306,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// CMakeHelper is the [CMake] build system helper.
|
// CMakeHelper is the [CMake] build system helper.
|
||||||
@@ -164,7 +164,7 @@ func (*CMakeHelper) createDir() bool { return true }
|
|||||||
func (*CMakeHelper) wantsDir() string { return "/cure/" }
|
func (*CMakeHelper) wantsDir() string { return "/cure/" }
|
||||||
|
|
||||||
// script generates the cure script.
|
// script generates the cure script.
|
||||||
func (attr *CMakeHelper) script(name string) string {
|
func (attr *CMakeHelper) script(s *S, name string) string {
|
||||||
if attr == nil {
|
if attr == nil {
|
||||||
attr = new(CMakeHelper)
|
attr = new(CMakeHelper)
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ func (attr *CMakeHelper) script(name string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
script := attr.Script
|
script := attr.Script
|
||||||
if !attr.SkipTest && presetOpts&OptSkipCheck == 0 {
|
if !attr.SkipTest && s.opts&OptSkipCheck == 0 {
|
||||||
script += "\n" + test
|
script += "\n" + test
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ func (t Toolchain) newConnman() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Connman] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newConnman,
|
f: Toolchain.newConnman,
|
||||||
|
|
||||||
Name: "connman",
|
Name: "connman",
|
||||||
@@ -105,5 +105,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 337,
|
ID: 337,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import "hakurei.app/internal/pkg"
|
|||||||
|
|
||||||
func (t Toolchain) newCurl() (pkg.Artifact, string) {
|
func (t Toolchain) newCurl() (pkg.Artifact, string) {
|
||||||
const (
|
const (
|
||||||
version = "8.19.0"
|
version = "8.20.0"
|
||||||
checksum = "YHuVLVVp8q_Y7-JWpID5ReNjq2Zk6t7ArHB6ngQXilp_R5l3cubdxu3UKo-xDByv"
|
checksum = "xyHXwrngIRGMasuzhn-I5MSCOhktwINbsWt1f_LuR-5jRVvyx_g6U1EQfDLEbr9r"
|
||||||
)
|
)
|
||||||
return t.NewPackage("curl", version, newTar(
|
return t.NewPackage("curl", version, newTar(
|
||||||
"https://curl.se/download/curl-"+version+".tar.bz2",
|
"https://curl.se/download/curl-"+version+".tar.bz2",
|
||||||
@@ -39,7 +39,7 @@ chmod +w tests/data && rm -f tests/data/test459
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Curl] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newCurl,
|
f: Toolchain.newCurl,
|
||||||
|
|
||||||
Name: "curl",
|
Name: "curl",
|
||||||
@@ -52,5 +52,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 381,
|
ID: 381,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func (t Toolchain) newDBus() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[DBus] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newDBus,
|
f: Toolchain.newDBus,
|
||||||
|
|
||||||
Name: "dbus",
|
Name: "dbus",
|
||||||
@@ -42,7 +42,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 5356,
|
ID: 5356,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newXDGDBusProxy() (pkg.Artifact, string) {
|
func (t Toolchain) newXDGDBusProxy() (pkg.Artifact, string) {
|
||||||
@@ -65,7 +65,7 @@ func (t Toolchain) newXDGDBusProxy() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[XDGDBusProxy] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newXDGDBusProxy,
|
f: Toolchain.newXDGDBusProxy,
|
||||||
|
|
||||||
Name: "xdg-dbus-proxy",
|
Name: "xdg-dbus-proxy",
|
||||||
@@ -77,5 +77,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 58434,
|
ID: 58434,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func (t Toolchain) newDTC() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[DTC] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newDTC,
|
f: Toolchain.newDTC,
|
||||||
|
|
||||||
Name: "dtc",
|
Name: "dtc",
|
||||||
@@ -39,5 +39,5 @@ func init() {
|
|||||||
Website: "https://git.kernel.org/pub/scm/utils/dtc/dtc.git/",
|
Website: "https://git.kernel.org/pub/scm/utils/dtc/dtc.git/",
|
||||||
|
|
||||||
ID: 16911,
|
ID: 16911,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func (t Toolchain) newElfutils() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Elfutils] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newElfutils,
|
f: Toolchain.newElfutils,
|
||||||
|
|
||||||
Name: "elfutils",
|
Name: "elfutils",
|
||||||
@@ -55,5 +55,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 5679,
|
ID: 5679,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ index f135ad9..85c784c 100644
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Fakeroot] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newFakeroot,
|
f: Toolchain.newFakeroot,
|
||||||
|
|
||||||
Name: "fakeroot",
|
Name: "fakeroot",
|
||||||
@@ -54,5 +54,5 @@ func init() {
|
|||||||
Website: "https://salsa.debian.org/clint/fakeroot",
|
Website: "https://salsa.debian.org/clint/fakeroot",
|
||||||
|
|
||||||
ID: 12048,
|
ID: 12048,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func (t Toolchain) newFlex() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Flex] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newFlex,
|
f: Toolchain.newFlex,
|
||||||
|
|
||||||
Name: "flex",
|
Name: "flex",
|
||||||
@@ -28,5 +28,5 @@ func init() {
|
|||||||
Website: "https://github.com/westes/flex/",
|
Website: "https://github.com/westes/flex/",
|
||||||
|
|
||||||
ID: 819,
|
ID: 819,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package rosa
|
||||||
|
|
||||||
|
import "hakurei.app/internal/pkg"
|
||||||
|
|
||||||
|
func (t Toolchain) newFreetype() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "2.14.3"
|
||||||
|
checksum = "-WfLv8fVJNyCHpP_lriiDzOcVbBL9ajdQ3tl8AzIIUa9-8sVpU9irxOmSMgRHWYz"
|
||||||
|
)
|
||||||
|
return t.NewPackage("freetype", version, newTar(
|
||||||
|
"https://download.savannah.gnu.org/releases/freetype/"+
|
||||||
|
"freetype-"+version+".tar.gz",
|
||||||
|
checksum,
|
||||||
|
pkg.TarGzip,
|
||||||
|
), nil, (*MakeHelper)(nil)), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newFreetype,
|
||||||
|
|
||||||
|
Name: "freetype",
|
||||||
|
Description: "a freely available software library to render fonts",
|
||||||
|
Website: "http://www.freetype.org/",
|
||||||
|
|
||||||
|
ID: 854,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -31,7 +31,7 @@ func (t Toolchain) newFuse() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Fuse] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newFuse,
|
f: Toolchain.newFuse,
|
||||||
|
|
||||||
Name: "fuse",
|
Name: "fuse",
|
||||||
@@ -39,5 +39,5 @@ func init() {
|
|||||||
Website: "https://github.com/libfuse/libfuse/",
|
Website: "https://github.com/libfuse/libfuse/",
|
||||||
|
|
||||||
ID: 861,
|
ID: 861,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-3
@@ -55,6 +55,14 @@ disable_test t9300-fast-import
|
|||||||
disable_test t0211-trace2-perf
|
disable_test t0211-trace2-perf
|
||||||
disable_test t1517-outside-repo
|
disable_test t1517-outside-repo
|
||||||
disable_test t2200-add-update
|
disable_test t2200-add-update
|
||||||
|
disable_test t0027-auto-crlf
|
||||||
|
disable_test t7513-interpret-trailers
|
||||||
|
disable_test t7703-repack-geometric
|
||||||
|
disable_test t7002-mv-sparse-checkout
|
||||||
|
disable_test t1451-fsck-buffer
|
||||||
|
disable_test t4104-apply-boundary
|
||||||
|
disable_test t4200-rerere
|
||||||
|
disable_test t5515-fetch-merge-logic
|
||||||
`,
|
`,
|
||||||
Check: []string{
|
Check: []string{
|
||||||
"-C t",
|
"-C t",
|
||||||
@@ -80,7 +88,7 @@ disable_test t2200-add-update
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Git] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGit,
|
f: Toolchain.newGit,
|
||||||
|
|
||||||
Name: "git",
|
Name: "git",
|
||||||
@@ -94,7 +102,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 5350,
|
ID: 5350,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewViaGit returns a [pkg.Artifact] for cloning a git repository.
|
// NewViaGit returns a [pkg.Artifact] for cloning a git repository.
|
||||||
@@ -105,7 +113,7 @@ func (t Toolchain) NewViaGit(
|
|||||||
return t.New(strings.TrimSuffix(
|
return t.New(strings.TrimSuffix(
|
||||||
path.Base(url),
|
path.Base(url),
|
||||||
".git",
|
".git",
|
||||||
)+"-src-"+path.Base(rev), 0, t.AppendPresets(nil,
|
)+"-src-"+path.Base(rev), THostNet, t.Append(nil,
|
||||||
NSSCACert,
|
NSSCACert,
|
||||||
Git,
|
Git,
|
||||||
), &checksum, nil, `
|
), &checksum, nil, `
|
||||||
|
|||||||
+73
-15
@@ -22,7 +22,7 @@ func (t Toolchain) newSPIRVHeaders() (pkg.Artifact, string) {
|
|||||||
}), version
|
}), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[SPIRVHeaders] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newSPIRVHeaders,
|
f: Toolchain.newSPIRVHeaders,
|
||||||
|
|
||||||
Name: "spirv-headers",
|
Name: "spirv-headers",
|
||||||
@@ -49,7 +49,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
return v.Latest
|
return v.Latest
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
|
func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
|
||||||
@@ -72,7 +72,7 @@ func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[SPIRVTools] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newSPIRVTools,
|
f: Toolchain.newSPIRVTools,
|
||||||
|
|
||||||
Name: "spirv-tools",
|
Name: "spirv-tools",
|
||||||
@@ -86,13 +86,13 @@ func init() {
|
|||||||
ID: 14894,
|
ID: 14894,
|
||||||
|
|
||||||
latest: (*Versions).getStable,
|
latest: (*Versions).getStable,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGlslang() (pkg.Artifact, string) {
|
func (t Toolchain) newGlslang() (pkg.Artifact, string) {
|
||||||
const (
|
const (
|
||||||
version = "16.2.0"
|
version = "16.3.0"
|
||||||
checksum = "6_UuF9reLRDaVkgO-9IfB3kMwme3lQZM8LL8YsJwPdUFkrjzxJtf2A9X3w9nFxj2"
|
checksum = "xyqDf8k3-D0_BXHGi0uLgMglnJ05Rf3j73QgbDs3sGtKNdBIQhY8JfqX1NcNoJQN"
|
||||||
)
|
)
|
||||||
return t.NewPackage("glslang", version, newFromGitHub(
|
return t.NewPackage("glslang", version, newFromGitHub(
|
||||||
"KhronosGroup/glslang",
|
"KhronosGroup/glslang",
|
||||||
@@ -116,7 +116,7 @@ func (t Toolchain) newGlslang() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Glslang] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGlslang,
|
f: Toolchain.newGlslang,
|
||||||
|
|
||||||
Name: "glslang",
|
Name: "glslang",
|
||||||
@@ -124,7 +124,7 @@ func init() {
|
|||||||
Website: "https://github.com/KhronosGroup/glslang",
|
Website: "https://github.com/KhronosGroup/glslang",
|
||||||
|
|
||||||
ID: 205796,
|
ID: 205796,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
|
func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
|
||||||
@@ -132,15 +132,75 @@ func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
|
|||||||
version = "22.1.2"
|
version = "22.1.2"
|
||||||
checksum = "JZAaV5ewYcm-35YA_U2BM2IcsQouZtX1BLZR0zh2vSlfEXMsT5OCtY4Gh5RJkcGy"
|
checksum = "JZAaV5ewYcm-35YA_U2BM2IcsQouZtX1BLZR0zh2vSlfEXMsT5OCtY4Gh5RJkcGy"
|
||||||
)
|
)
|
||||||
|
skipChecks := []string{
|
||||||
|
// error: line 13: OpTypeCooperativeMatrixKHR Scope is limited to Workgroup and Subgroup
|
||||||
|
"cooperative_matrix_constant_null.spvasm",
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t.arch {
|
||||||
|
case "arm64":
|
||||||
|
skipChecks = append(skipChecks,
|
||||||
|
// LLVM ERROR: unsupported calling convention
|
||||||
|
"DebugInfo/COFF/no-cus.ll",
|
||||||
|
"DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll",
|
||||||
|
"DebugInfo/Generic/2009-11-10-CurrentFn.ll",
|
||||||
|
"DebugInfo/Generic/2010-01-05-DbgScope.ll",
|
||||||
|
"DebugInfo/Generic/2010-03-12-llc-crash.ll",
|
||||||
|
"DebugInfo/Generic/2010-03-24-MemberFn.ll",
|
||||||
|
"DebugInfo/Generic/2010-04-19-FramePtr.ll",
|
||||||
|
"DebugInfo/Generic/2010-06-29-InlinedFnLocalVar.ll",
|
||||||
|
"DebugInfo/Generic/2010-10-01-crash.ll",
|
||||||
|
"DebugInfo/Generic/PR20038.ll",
|
||||||
|
"DebugInfo/Generic/constant-pointers.ll",
|
||||||
|
"DebugInfo/Generic/dead-argument-order.ll",
|
||||||
|
"DebugInfo/Generic/debug-info-eis-option.ll",
|
||||||
|
"DebugInfo/Generic/def-line.ll",
|
||||||
|
"DebugInfo/Generic/discriminator.ll",
|
||||||
|
"DebugInfo/Generic/dwarf-public-names.ll",
|
||||||
|
"DebugInfo/Generic/enum.ll",
|
||||||
|
"DebugInfo/Generic/func-using-decl.ll",
|
||||||
|
"DebugInfo/Generic/global.ll",
|
||||||
|
"DebugInfo/Generic/imported-name-inlined.ll",
|
||||||
|
"DebugInfo/Generic/incorrect-variable-debugloc1.ll",
|
||||||
|
"DebugInfo/Generic/inline-scopes.ll",
|
||||||
|
"DebugInfo/Generic/inlined-arguments.ll",
|
||||||
|
"DebugInfo/Generic/inlined-vars.ll",
|
||||||
|
"DebugInfo/Generic/linear-dbg-value.ll",
|
||||||
|
"DebugInfo/Generic/linkage-name-abstract.ll",
|
||||||
|
"DebugInfo/Generic/member-order.ll",
|
||||||
|
"DebugInfo/Generic/missing-abstract-variable.ll",
|
||||||
|
"DebugInfo/Generic/multiline.ll",
|
||||||
|
"DebugInfo/Generic/namespace_function_definition.ll",
|
||||||
|
"DebugInfo/Generic/namespace_inline_function_definition.ll",
|
||||||
|
"DebugInfo/Generic/noscopes.ll",
|
||||||
|
"DebugInfo/Generic/ptrsize.ll",
|
||||||
|
"DebugInfo/Generic/restrict.ll",
|
||||||
|
"DebugInfo/Generic/two-cus-from-same-file.ll",
|
||||||
|
"DebugInfo/Generic/version.ll",
|
||||||
|
"DebugInfo/LocalAddressSpace.ll",
|
||||||
|
"DebugInfo/UnknownBaseType.ll",
|
||||||
|
"DebugInfo/expr-opcode.ll",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return t.NewPackage("spirv-llvm-translator", version, newFromGitHub(
|
return t.NewPackage("spirv-llvm-translator", version, newFromGitHub(
|
||||||
"KhronosGroup/SPIRV-LLVM-Translator",
|
"KhronosGroup/SPIRV-LLVM-Translator",
|
||||||
"v"+version, checksum,
|
"v"+version, checksum,
|
||||||
), &PackageAttr{
|
), &PackageAttr{
|
||||||
Patches: []KV{
|
Patches: []KV{
|
||||||
{"remove-early-prefix", `diff --git a/CMakeLists.txt b/CMakeLists.txt
|
{"remove-early-prefix", `diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
index c000a77e..86f79b03 100644
|
index c000a77e..f18f3fde 100644
|
||||||
--- a/CMakeLists.txt
|
--- a/CMakeLists.txt
|
||||||
+++ b/CMakeLists.txt
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -164,7 +164,7 @@ install(
|
||||||
|
${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVOpts.h
|
||||||
|
${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVExtensions.inc
|
||||||
|
DESTINATION
|
||||||
|
- ${CMAKE_INSTALL_PREFIX}/include/LLVMSPIRVLib
|
||||||
|
+ include/LLVMSPIRVLib
|
||||||
|
)
|
||||||
|
|
||||||
|
configure_file(LLVMSPIRVLib.pc.in ${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc @ONLY)
|
||||||
@@ -172,5 +172,5 @@ install(
|
@@ -172,5 +172,5 @@ install(
|
||||||
FILES
|
FILES
|
||||||
${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc
|
${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc
|
||||||
@@ -148,14 +208,12 @@ index c000a77e..86f79b03 100644
|
|||||||
- ${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
- ${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||||
+ lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
+ lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||||
)
|
)
|
||||||
`},
|
;`},
|
||||||
},
|
},
|
||||||
|
|
||||||
// litArgs emits shell syntax
|
// litArgs emits shell syntax
|
||||||
ScriptEarly: `
|
ScriptEarly: `
|
||||||
export LIT_OPTS=` + litArgs(true,
|
export LIT_OPTS=` + litArgs(true, skipChecks...) + `
|
||||||
// error: line 13: OpTypeCooperativeMatrixKHR Scope is limited to Workgroup and Subgroup
|
|
||||||
"cooperative_matrix_constant_null.spvasm") + `
|
|
||||||
`,
|
`,
|
||||||
}, &CMakeHelper{
|
}, &CMakeHelper{
|
||||||
Cache: []KV{
|
Cache: []KV{
|
||||||
@@ -174,7 +232,7 @@ export LIT_OPTS=` + litArgs(true,
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[SPIRVLLVMTranslator] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newSPIRVLLVMTranslator,
|
f: Toolchain.newSPIRVLLVMTranslator,
|
||||||
|
|
||||||
Name: "spirv-llvm-translator",
|
Name: "spirv-llvm-translator",
|
||||||
@@ -186,5 +244,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 227273,
|
ID: 227273,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+65
-66
@@ -1,7 +1,6 @@
|
|||||||
package rosa
|
package rosa
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -64,7 +63,7 @@ chmod +w tests/test-c32ispunct.sh && echo '#!/bin/sh' > tests/test-c32ispunct.sh
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[M4] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newM4,
|
f: Toolchain.newM4,
|
||||||
|
|
||||||
Name: "m4",
|
Name: "m4",
|
||||||
@@ -72,7 +71,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/m4/",
|
Website: "https://www.gnu.org/software/m4/",
|
||||||
|
|
||||||
ID: 1871,
|
ID: 1871,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newBison() (pkg.Artifact, string) {
|
func (t Toolchain) newBison() (pkg.Artifact, string) {
|
||||||
@@ -99,7 +98,7 @@ func (t Toolchain) newBison() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Bison] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newBison,
|
f: Toolchain.newBison,
|
||||||
|
|
||||||
Name: "bison",
|
Name: "bison",
|
||||||
@@ -107,7 +106,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/bison/",
|
Website: "https://www.gnu.org/software/bison/",
|
||||||
|
|
||||||
ID: 193,
|
ID: 193,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newSed() (pkg.Artifact, string) {
|
func (t Toolchain) newSed() (pkg.Artifact, string) {
|
||||||
@@ -126,7 +125,7 @@ func (t Toolchain) newSed() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Sed] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newSed,
|
f: Toolchain.newSed,
|
||||||
|
|
||||||
Name: "sed",
|
Name: "sed",
|
||||||
@@ -134,7 +133,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/sed/",
|
Website: "https://www.gnu.org/software/sed/",
|
||||||
|
|
||||||
ID: 4789,
|
ID: 4789,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newAutoconf() (pkg.Artifact, string) {
|
func (t Toolchain) newAutoconf() (pkg.Artifact, string) {
|
||||||
@@ -161,7 +160,7 @@ func (t Toolchain) newAutoconf() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Autoconf] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newAutoconf,
|
f: Toolchain.newAutoconf,
|
||||||
|
|
||||||
Name: "autoconf",
|
Name: "autoconf",
|
||||||
@@ -174,7 +173,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 141,
|
ID: 141,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newAutomake() (pkg.Artifact, string) {
|
func (t Toolchain) newAutomake() (pkg.Artifact, string) {
|
||||||
@@ -206,7 +205,7 @@ test_disable '#!/bin/sh' t/pr9.sh
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Automake] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newAutomake,
|
f: Toolchain.newAutomake,
|
||||||
|
|
||||||
Name: "automake",
|
Name: "automake",
|
||||||
@@ -218,7 +217,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 144,
|
ID: 144,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newLibtool() (pkg.Artifact, string) {
|
func (t Toolchain) newLibtool() (pkg.Artifact, string) {
|
||||||
@@ -232,7 +231,7 @@ func (t Toolchain) newLibtool() (pkg.Artifact, string) {
|
|||||||
pkg.TarGzip,
|
pkg.TarGzip,
|
||||||
), nil, &MakeHelper{
|
), nil, &MakeHelper{
|
||||||
// _Z2a2c: symbol not found
|
// _Z2a2c: symbol not found
|
||||||
SkipCheck: t.isStage0(),
|
SkipCheck: t.stage.isStage0(),
|
||||||
|
|
||||||
Check: []string{
|
Check: []string{
|
||||||
"TESTSUITEFLAGS=" + jobsFlagE,
|
"TESTSUITEFLAGS=" + jobsFlagE,
|
||||||
@@ -244,7 +243,7 @@ func (t Toolchain) newLibtool() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libtool] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibtool,
|
f: Toolchain.newLibtool,
|
||||||
|
|
||||||
Name: "libtool",
|
Name: "libtool",
|
||||||
@@ -252,7 +251,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/libtool/",
|
Website: "https://www.gnu.org/software/libtool/",
|
||||||
|
|
||||||
ID: 1741,
|
ID: 1741,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGzip() (pkg.Artifact, string) {
|
func (t Toolchain) newGzip() (pkg.Artifact, string) {
|
||||||
@@ -270,7 +269,7 @@ func (t Toolchain) newGzip() (pkg.Artifact, string) {
|
|||||||
}), version
|
}), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Gzip] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGzip,
|
f: Toolchain.newGzip,
|
||||||
|
|
||||||
Name: "gzip",
|
Name: "gzip",
|
||||||
@@ -278,7 +277,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/gzip/",
|
Website: "https://www.gnu.org/software/gzip/",
|
||||||
|
|
||||||
ID: 1290,
|
ID: 1290,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGettext() (pkg.Artifact, string) {
|
func (t Toolchain) newGettext() (pkg.Artifact, string) {
|
||||||
@@ -316,7 +315,7 @@ touch gettext-tools/autotools/archive.dir.tar
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Gettext] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGettext,
|
f: Toolchain.newGettext,
|
||||||
|
|
||||||
Name: "gettext",
|
Name: "gettext",
|
||||||
@@ -324,7 +323,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/gettext/",
|
Website: "https://www.gnu.org/software/gettext/",
|
||||||
|
|
||||||
ID: 898,
|
ID: 898,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newDiffutils() (pkg.Artifact, string) {
|
func (t Toolchain) newDiffutils() (pkg.Artifact, string) {
|
||||||
@@ -349,7 +348,7 @@ test_disable '#!/bin/sh' tests/cmp
|
|||||||
}, (*MakeHelper)(nil)), version
|
}, (*MakeHelper)(nil)), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Diffutils] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newDiffutils,
|
f: Toolchain.newDiffutils,
|
||||||
|
|
||||||
Name: "diffutils",
|
Name: "diffutils",
|
||||||
@@ -357,7 +356,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/diffutils/",
|
Website: "https://www.gnu.org/software/diffutils/",
|
||||||
|
|
||||||
ID: 436,
|
ID: 436,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newPatch() (pkg.Artifact, string) {
|
func (t Toolchain) newPatch() (pkg.Artifact, string) {
|
||||||
@@ -381,7 +380,7 @@ test_disable '#!/bin/sh' tests/need-filename
|
|||||||
}, (*MakeHelper)(nil)), version
|
}, (*MakeHelper)(nil)), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Patch] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newPatch,
|
f: Toolchain.newPatch,
|
||||||
|
|
||||||
Name: "patch",
|
Name: "patch",
|
||||||
@@ -389,7 +388,7 @@ func init() {
|
|||||||
Website: "https://savannah.gnu.org/projects/patch/",
|
Website: "https://savannah.gnu.org/projects/patch/",
|
||||||
|
|
||||||
ID: 2597,
|
ID: 2597,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newBash() (pkg.Artifact, string) {
|
func (t Toolchain) newBash() (pkg.Artifact, string) {
|
||||||
@@ -411,7 +410,7 @@ func (t Toolchain) newBash() (pkg.Artifact, string) {
|
|||||||
}), version
|
}), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Bash] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newBash,
|
f: Toolchain.newBash,
|
||||||
|
|
||||||
Name: "bash",
|
Name: "bash",
|
||||||
@@ -419,7 +418,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/bash/",
|
Website: "https://www.gnu.org/software/bash/",
|
||||||
|
|
||||||
ID: 166,
|
ID: 166,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newCoreutils() (pkg.Artifact, string) {
|
func (t Toolchain) newCoreutils() (pkg.Artifact, string) {
|
||||||
@@ -457,7 +456,7 @@ test_disable 'int main(){return 0;}' gnulib-tests/test-lchown.c
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Coreutils] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newCoreutils,
|
f: Toolchain.newCoreutils,
|
||||||
|
|
||||||
Name: "coreutils",
|
Name: "coreutils",
|
||||||
@@ -465,7 +464,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/coreutils/",
|
Website: "https://www.gnu.org/software/coreutils/",
|
||||||
|
|
||||||
ID: 343,
|
ID: 343,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newTexinfo() (pkg.Artifact, string) {
|
func (t Toolchain) newTexinfo() (pkg.Artifact, string) {
|
||||||
@@ -485,7 +484,7 @@ func (t Toolchain) newTexinfo() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Texinfo] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newTexinfo,
|
f: Toolchain.newTexinfo,
|
||||||
|
|
||||||
Name: "texinfo",
|
Name: "texinfo",
|
||||||
@@ -498,7 +497,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 4958,
|
ID: 4958,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGperf() (pkg.Artifact, string) {
|
func (t Toolchain) newGperf() (pkg.Artifact, string) {
|
||||||
@@ -515,7 +514,7 @@ func (t Toolchain) newGperf() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Gperf] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGperf,
|
f: Toolchain.newGperf,
|
||||||
|
|
||||||
Name: "gperf",
|
Name: "gperf",
|
||||||
@@ -523,7 +522,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/gperf/",
|
Website: "https://www.gnu.org/software/gperf/",
|
||||||
|
|
||||||
ID: 1237,
|
ID: 1237,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGawk() (pkg.Artifact, string) {
|
func (t Toolchain) newGawk() (pkg.Artifact, string) {
|
||||||
@@ -543,7 +542,7 @@ func (t Toolchain) newGawk() (pkg.Artifact, string) {
|
|||||||
}), version
|
}), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Gawk] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGawk,
|
f: Toolchain.newGawk,
|
||||||
|
|
||||||
Name: "gawk",
|
Name: "gawk",
|
||||||
@@ -551,7 +550,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/gawk/",
|
Website: "https://www.gnu.org/software/gawk/",
|
||||||
|
|
||||||
ID: 868,
|
ID: 868,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGrep() (pkg.Artifact, string) {
|
func (t Toolchain) newGrep() (pkg.Artifact, string) {
|
||||||
@@ -576,7 +575,7 @@ test_disable 'int main(){return 0;}' gnulib-tests/test-c32ispunct.c
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Grep] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGrep,
|
f: Toolchain.newGrep,
|
||||||
|
|
||||||
Name: "grep",
|
Name: "grep",
|
||||||
@@ -584,7 +583,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/grep/",
|
Website: "https://www.gnu.org/software/grep/",
|
||||||
|
|
||||||
ID: 1251,
|
ID: 1251,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newFindutils() (pkg.Artifact, string) {
|
func (t Toolchain) newFindutils() (pkg.Artifact, string) {
|
||||||
@@ -607,7 +606,7 @@ echo 'int main(){return 0;}' > tests/xargs/test-sigusr.c
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Findutils] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newFindutils,
|
f: Toolchain.newFindutils,
|
||||||
|
|
||||||
Name: "findutils",
|
Name: "findutils",
|
||||||
@@ -615,7 +614,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/findutils/",
|
Website: "https://www.gnu.org/software/findutils/",
|
||||||
|
|
||||||
ID: 812,
|
ID: 812,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newBC() (pkg.Artifact, string) {
|
func (t Toolchain) newBC() (pkg.Artifact, string) {
|
||||||
@@ -636,7 +635,7 @@ func (t Toolchain) newBC() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[BC] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newBC,
|
f: Toolchain.newBC,
|
||||||
|
|
||||||
Name: "bc",
|
Name: "bc",
|
||||||
@@ -644,7 +643,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/bc/",
|
Website: "https://www.gnu.org/software/bc/",
|
||||||
|
|
||||||
ID: 170,
|
ID: 170,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newLibiconv() (pkg.Artifact, string) {
|
func (t Toolchain) newLibiconv() (pkg.Artifact, string) {
|
||||||
@@ -659,7 +658,7 @@ func (t Toolchain) newLibiconv() (pkg.Artifact, string) {
|
|||||||
), nil, (*MakeHelper)(nil)), version
|
), nil, (*MakeHelper)(nil)), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libiconv] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibiconv,
|
f: Toolchain.newLibiconv,
|
||||||
|
|
||||||
Name: "libiconv",
|
Name: "libiconv",
|
||||||
@@ -667,7 +666,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/libiconv/",
|
Website: "https://www.gnu.org/software/libiconv/",
|
||||||
|
|
||||||
ID: 10656,
|
ID: 10656,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newTar() (pkg.Artifact, string) {
|
func (t Toolchain) newTar() (pkg.Artifact, string) {
|
||||||
@@ -701,7 +700,7 @@ func (t Toolchain) newTar() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Tar] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newTar,
|
f: Toolchain.newTar,
|
||||||
|
|
||||||
Name: "tar",
|
Name: "tar",
|
||||||
@@ -709,7 +708,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/tar/",
|
Website: "https://www.gnu.org/software/tar/",
|
||||||
|
|
||||||
ID: 4939,
|
ID: 4939,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newParallel() (pkg.Artifact, string) {
|
func (t Toolchain) newParallel() (pkg.Artifact, string) {
|
||||||
@@ -731,7 +730,7 @@ ln -s ../system/bin/bash /bin/
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Parallel] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newParallel,
|
f: Toolchain.newParallel,
|
||||||
|
|
||||||
Name: "parallel",
|
Name: "parallel",
|
||||||
@@ -743,7 +742,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 5448,
|
ID: 5448,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newLibunistring() (pkg.Artifact, string) {
|
func (t Toolchain) newLibunistring() (pkg.Artifact, string) {
|
||||||
@@ -768,7 +767,7 @@ test_disable 'int main(){return 0;}' tests/test-c32ispunct.c
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libunistring] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibunistring,
|
f: Toolchain.newLibunistring,
|
||||||
|
|
||||||
Name: "libunistring",
|
Name: "libunistring",
|
||||||
@@ -776,7 +775,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/libunistring/",
|
Website: "https://www.gnu.org/software/libunistring/",
|
||||||
|
|
||||||
ID: 1747,
|
ID: 1747,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newLibtasn1() (pkg.Artifact, string) {
|
func (t Toolchain) newLibtasn1() (pkg.Artifact, string) {
|
||||||
@@ -791,7 +790,7 @@ func (t Toolchain) newLibtasn1() (pkg.Artifact, string) {
|
|||||||
), nil, (*MakeHelper)(nil)), version
|
), nil, (*MakeHelper)(nil)), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libtasn1] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibtasn1,
|
f: Toolchain.newLibtasn1,
|
||||||
|
|
||||||
Name: "libtasn1",
|
Name: "libtasn1",
|
||||||
@@ -799,7 +798,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/libtasn1/",
|
Website: "https://www.gnu.org/software/libtasn1/",
|
||||||
|
|
||||||
ID: 1734,
|
ID: 1734,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newReadline() (pkg.Artifact, string) {
|
func (t Toolchain) newReadline() (pkg.Artifact, string) {
|
||||||
@@ -821,7 +820,7 @@ func (t Toolchain) newReadline() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Readline] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newReadline,
|
f: Toolchain.newReadline,
|
||||||
|
|
||||||
Name: "readline",
|
Name: "readline",
|
||||||
@@ -833,7 +832,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 4173,
|
ID: 4173,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGnuTLS() (pkg.Artifact, string) {
|
func (t Toolchain) newGnuTLS() (pkg.Artifact, string) {
|
||||||
@@ -843,7 +842,7 @@ func (t Toolchain) newGnuTLS() (pkg.Artifact, string) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
var configureExtra []KV
|
var configureExtra []KV
|
||||||
switch runtime.GOARCH {
|
switch t.arch {
|
||||||
case "arm64":
|
case "arm64":
|
||||||
configureExtra = []KV{
|
configureExtra = []KV{
|
||||||
{"disable-hardware-acceleration"},
|
{"disable-hardware-acceleration"},
|
||||||
@@ -998,7 +997,7 @@ index 1b78b8cf1..350156a86 100644
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[GnuTLS] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGnuTLS,
|
f: Toolchain.newGnuTLS,
|
||||||
|
|
||||||
Name: "gnutls",
|
Name: "gnutls",
|
||||||
@@ -1014,7 +1013,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 1221,
|
ID: 1221,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newBinutils() (pkg.Artifact, string) {
|
func (t Toolchain) newBinutils() (pkg.Artifact, string) {
|
||||||
@@ -1031,7 +1030,7 @@ func (t Toolchain) newBinutils() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Binutils] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newBinutils,
|
f: Toolchain.newBinutils,
|
||||||
|
|
||||||
Name: "binutils",
|
Name: "binutils",
|
||||||
@@ -1039,7 +1038,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/binutils/",
|
Website: "https://www.gnu.org/software/binutils/",
|
||||||
|
|
||||||
ID: 7981,
|
ID: 7981,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGMP() (pkg.Artifact, string) {
|
func (t Toolchain) newGMP() (pkg.Artifact, string) {
|
||||||
@@ -1061,7 +1060,7 @@ func (t Toolchain) newGMP() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[GMP] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGMP,
|
f: Toolchain.newGMP,
|
||||||
|
|
||||||
Name: "gmp",
|
Name: "gmp",
|
||||||
@@ -1069,7 +1068,7 @@ func init() {
|
|||||||
Website: "https://gmplib.org/",
|
Website: "https://gmplib.org/",
|
||||||
|
|
||||||
ID: 1186,
|
ID: 1186,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newMPFR() (pkg.Artifact, string) {
|
func (t Toolchain) newMPFR() (pkg.Artifact, string) {
|
||||||
@@ -1087,7 +1086,7 @@ func (t Toolchain) newMPFR() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[MPFR] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newMPFR,
|
f: Toolchain.newMPFR,
|
||||||
|
|
||||||
Name: "mpfr",
|
Name: "mpfr",
|
||||||
@@ -1099,7 +1098,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 2019,
|
ID: 2019,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newMPC() (pkg.Artifact, string) {
|
func (t Toolchain) newMPC() (pkg.Artifact, string) {
|
||||||
@@ -1126,7 +1125,7 @@ func (t Toolchain) newMPC() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[MPC] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newMPC,
|
f: Toolchain.newMPC,
|
||||||
|
|
||||||
Name: "mpc",
|
Name: "mpc",
|
||||||
@@ -1138,17 +1137,17 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 1667,
|
ID: 1667,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGCC() (pkg.Artifact, string) {
|
func (t Toolchain) newGCC() (pkg.Artifact, string) {
|
||||||
const (
|
const (
|
||||||
version = "15.2.0"
|
version = "16.1.0"
|
||||||
checksum = "TXJ5WrbXlGLzy1swghQTr4qxgDCyIZFgJry51XEPTBZ8QYbVmFeB4lZbSMtPJ-a1"
|
checksum = "4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K"
|
||||||
)
|
)
|
||||||
|
|
||||||
var configureExtra []KV
|
var configureExtra []KV
|
||||||
switch runtime.GOARCH {
|
switch t.arch {
|
||||||
case "amd64", "arm64":
|
case "amd64", "arm64":
|
||||||
configureExtra = append(configureExtra, KV{"with-multilib-list", "''"})
|
configureExtra = append(configureExtra, KV{"with-multilib-list", "''"})
|
||||||
}
|
}
|
||||||
@@ -1347,7 +1346,7 @@ ln -s system/lib /work/
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[gcc] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGCC,
|
f: Toolchain.newGCC,
|
||||||
|
|
||||||
Name: "gcc",
|
Name: "gcc",
|
||||||
@@ -1363,5 +1362,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 6502,
|
ID: 6502,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-21
@@ -1,7 +1,6 @@
|
|||||||
package rosa
|
package rosa
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"hakurei.app/internal/pkg"
|
"hakurei.app/internal/pkg"
|
||||||
@@ -10,7 +9,7 @@ import (
|
|||||||
// newGoBootstrap returns the Go bootstrap toolchain.
|
// newGoBootstrap returns the Go bootstrap toolchain.
|
||||||
func (t Toolchain) newGoBootstrap() pkg.Artifact {
|
func (t Toolchain) newGoBootstrap() pkg.Artifact {
|
||||||
const checksum = "8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23"
|
const checksum = "8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23"
|
||||||
return t.New("go1.4-bootstrap", 0, t.AppendPresets(nil,
|
return t.New("go1.4-bootstrap", 0, t.Append(nil,
|
||||||
Bash,
|
Bash,
|
||||||
), nil, []string{
|
), nil, []string{
|
||||||
"CGO_ENABLED=0",
|
"CGO_ENABLED=0",
|
||||||
@@ -35,7 +34,11 @@ func (t Toolchain) newGo(
|
|||||||
script string,
|
script string,
|
||||||
extra ...pkg.Artifact,
|
extra ...pkg.Artifact,
|
||||||
) pkg.Artifact {
|
) pkg.Artifact {
|
||||||
return t.New("go"+version, 0, t.AppendPresets(extra,
|
name := "all"
|
||||||
|
if t.opts&OptSkipCheck != 0 {
|
||||||
|
name = "make"
|
||||||
|
}
|
||||||
|
return t.New("go"+version, 0, t.Append(extra,
|
||||||
Bash,
|
Bash,
|
||||||
), nil, slices.Concat([]string{
|
), nil, slices.Concat([]string{
|
||||||
"CC=cc",
|
"CC=cc",
|
||||||
@@ -48,7 +51,7 @@ cp -r /usr/src/go /work/system
|
|||||||
cd /work/system/go/src
|
cd /work/system/go/src
|
||||||
chmod -R +w ..
|
chmod -R +w ..
|
||||||
`+script+`
|
`+script+`
|
||||||
./all.bash
|
./`+name+`.bash
|
||||||
|
|
||||||
mkdir /work/system/bin
|
mkdir /work/system/bin
|
||||||
ln -s \
|
ln -s \
|
||||||
@@ -69,17 +72,17 @@ func (t Toolchain) newGoLatest() (pkg.Artifact, string) {
|
|||||||
|
|
||||||
finalEnv []string
|
finalEnv []string
|
||||||
)
|
)
|
||||||
switch runtime.GOARCH {
|
switch t.arch {
|
||||||
case "amd64":
|
case "amd64":
|
||||||
bootstrapExtra = append(bootstrapExtra, t.newGoBootstrap())
|
bootstrapExtra = append(bootstrapExtra, t.newGoBootstrap())
|
||||||
|
|
||||||
case "arm64", "riscv64":
|
case "arm64", "riscv64":
|
||||||
bootstrapEnv = append(bootstrapEnv, "GOROOT_BOOTSTRAP=/system")
|
bootstrapEnv = append(bootstrapEnv, "GOROOT_BOOTSTRAP=/system")
|
||||||
bootstrapExtra = t.AppendPresets(bootstrapExtra, gcc)
|
bootstrapExtra = t.Append(bootstrapExtra, gcc)
|
||||||
finalEnv = append(finalEnv, "CGO_ENABLED=0")
|
finalEnv = append(finalEnv, "CGO_ENABLED=0")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("unsupported target " + runtime.GOARCH)
|
panic("unsupported target " + t.arch)
|
||||||
}
|
}
|
||||||
|
|
||||||
go119 := t.newGo(
|
go119 := t.newGo(
|
||||||
@@ -103,8 +106,8 @@ echo \
|
|||||||
"YtrDka402BOAEwywx03Vz4QlVwoBiguJHzG7PuythMCPHXS8CVMLvzmvgEbu4Tzu",
|
"YtrDka402BOAEwywx03Vz4QlVwoBiguJHzG7PuythMCPHXS8CVMLvzmvgEbu4Tzu",
|
||||||
[]string{"CGO_ENABLED=0"}, `
|
[]string{"CGO_ENABLED=0"}, `
|
||||||
sed -i \
|
sed -i \
|
||||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
cmd/link/internal/`+t.arch+`/obj.go
|
||||||
|
|
||||||
rm \
|
rm \
|
||||||
crypto/tls/handshake_client_test.go \
|
crypto/tls/handshake_client_test.go \
|
||||||
@@ -121,18 +124,18 @@ echo \
|
|||||||
"wcI32bl1tkqbgcelGtGWPI4RtlEddd-PTd76Eb-k7nXA5LbE9yTNdIL9QSOOxMOs",
|
"wcI32bl1tkqbgcelGtGWPI4RtlEddd-PTd76Eb-k7nXA5LbE9yTNdIL9QSOOxMOs",
|
||||||
[]string{"CGO_ENABLED=0"}, `
|
[]string{"CGO_ENABLED=0"}, `
|
||||||
sed -i \
|
sed -i \
|
||||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
cmd/link/internal/`+t.arch+`/obj.go
|
||||||
`, go121,
|
`, go121,
|
||||||
)
|
)
|
||||||
|
|
||||||
go125 := t.newGo(
|
go125 := t.newGo(
|
||||||
"1.25.9",
|
"1.25.10",
|
||||||
"gShJb9uOMk5AxqPSwvn53ZO56S6PyP6nfojzrHUiJ3krAvrgjJpYa6-DPA-jxbpN",
|
"TwKwatkpwal-j9U2sDSRPEdM3YesI4Gm88YgGV59wtU-L85K9gA7UPy9SCxn6PMb",
|
||||||
[]string{"CGO_ENABLED=0"}, `
|
[]string{"CGO_ENABLED=0"}, `
|
||||||
sed -i \
|
sed -i \
|
||||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
cmd/link/internal/`+t.arch+`/obj.go
|
||||||
|
|
||||||
rm \
|
rm \
|
||||||
os/root_unix_test.go \
|
os/root_unix_test.go \
|
||||||
@@ -141,16 +144,16 @@ rm \
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "1.26.2"
|
version = "1.26.3"
|
||||||
checksum = "v-6BE89_1g3xYf-9oIYpJKFXlo3xKHYJj2_VGkaUq8ZVkIVQmLwrto-xGG03OISH"
|
checksum = "lEiFocZFnN5fKvZzmwVdqc9pYUjAuhzqZGbuiOqxUP4XdcY8yECisKcqsQ_eNn1N"
|
||||||
)
|
)
|
||||||
return t.newGo(
|
return t.newGo(
|
||||||
version,
|
version,
|
||||||
checksum,
|
checksum,
|
||||||
finalEnv, `
|
finalEnv, `
|
||||||
sed -i \
|
sed -i \
|
||||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
cmd/link/internal/`+t.arch+`/obj.go
|
||||||
sed -i \
|
sed -i \
|
||||||
's/cpu.X86.HasAVX512VBMI/& \&\& cpu.X86.HasPOPCNT/' \
|
's/cpu.X86.HasAVX512VBMI/& \&\& cpu.X86.HasPOPCNT/' \
|
||||||
internal/runtime/gc/scan/scan_amd64.go
|
internal/runtime/gc/scan/scan_amd64.go
|
||||||
@@ -163,7 +166,7 @@ rm \
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Go] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGoLatest,
|
f: Toolchain.newGoLatest,
|
||||||
|
|
||||||
Name: "go",
|
Name: "go",
|
||||||
@@ -171,5 +174,5 @@ func init() {
|
|||||||
Website: "https://go.dev/",
|
Website: "https://go.dev/",
|
||||||
|
|
||||||
ID: 1227,
|
ID: 1227,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
|
|
||||||
func (t Toolchain) newGLib() (pkg.Artifact, string) {
|
func (t Toolchain) newGLib() (pkg.Artifact, string) {
|
||||||
const (
|
const (
|
||||||
version = "2.88.0"
|
version = "2.88.1"
|
||||||
checksum = "T79Cg4z6j-sDZ2yIwvbY4ccRv2-fbwbqgcw59F5NQ6qJT6z4v261vbYp3dHO6Ma3"
|
checksum = "Rkszn6W4RHjyspyqfXdVAVawdwDJCuS0Zu0f7qot7tbJhnw2fUDoUUJB40m-1MCX"
|
||||||
)
|
)
|
||||||
return t.NewPackage("glib", version, t.newTagRemote(
|
return t.NewPackage("glib", version, t.newTagRemote(
|
||||||
"https://gitlab.gnome.org/GNOME/glib.git",
|
"https://gitlab.gnome.org/GNOME/glib.git",
|
||||||
@@ -42,7 +42,7 @@ func (t Toolchain) newGLib() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[GLib] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGLib,
|
f: Toolchain.newGLib,
|
||||||
|
|
||||||
Name: "glib",
|
Name: "glib",
|
||||||
@@ -56,5 +56,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 10024,
|
ID: 10024,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-10
@@ -14,7 +14,7 @@ go build -o /bin/hostname /usr/src/hostname/main.go
|
|||||||
hostname = ""
|
hostname = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.New("hakurei"+suffix+"-"+hakureiVersion, 0, t.AppendPresets(nil,
|
return t.New("hakurei"+suffix+"-"+hakureiVersion, 0, t.Append(nil,
|
||||||
Go,
|
Go,
|
||||||
PkgConfig,
|
PkgConfig,
|
||||||
|
|
||||||
@@ -58,14 +58,14 @@ func main() {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Hakurei] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||||
return t.newHakurei("", `
|
return t.newHakurei("", `
|
||||||
mkdir -p /work/system/libexec/hakurei/
|
mkdir -p /work/system/libexec/hakurei/
|
||||||
|
|
||||||
echo '# Building hakurei.'
|
echo "Building hakurei for $(go env GOOS)/$(go env GOARCH)."
|
||||||
go generate -v ./...
|
go generate ./...
|
||||||
go build -trimpath -v -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
|
go build -trimpath -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
|
||||||
-buildid=
|
-buildid=
|
||||||
-linkmode external
|
-linkmode external
|
||||||
-extldflags=-static
|
-extldflags=-static
|
||||||
@@ -76,7 +76,7 @@ go build -trimpath -v -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
|
|||||||
" ./...
|
" ./...
|
||||||
echo
|
echo
|
||||||
|
|
||||||
echo '# Testing hakurei.'
|
echo '##### Testing hakurei.'
|
||||||
go test -ldflags='-buildid= -linkmode external -extldflags=-static' ./...
|
go test -ldflags='-buildid= -linkmode external -extldflags=-static' ./...
|
||||||
echo
|
echo
|
||||||
|
|
||||||
@@ -93,17 +93,21 @@ mkdir -p /work/system/bin/
|
|||||||
Website: "https://hakurei.app/",
|
Website: "https://hakurei.app/",
|
||||||
|
|
||||||
ID: 388834,
|
ID: 388834,
|
||||||
}
|
})
|
||||||
artifactsM[HakureiDist] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||||
|
name := "all"
|
||||||
|
if t.opts&OptSkipCheck != 0 {
|
||||||
|
name = "make"
|
||||||
|
}
|
||||||
return t.newHakurei("-dist", `
|
return t.newHakurei("-dist", `
|
||||||
export HAKUREI_VERSION
|
export HAKUREI_VERSION
|
||||||
DESTDIR=/work /usr/src/hakurei/all.sh
|
DESTDIR=/work /usr/src/hakurei/`+name+`.sh
|
||||||
`, true), hakureiVersion
|
`, true), hakureiVersion
|
||||||
},
|
},
|
||||||
|
|
||||||
Name: "hakurei-dist",
|
Name: "hakurei-dist",
|
||||||
Description: "low-level userspace tooling for Rosa OS (distribution tarball)",
|
Description: "low-level userspace tooling for Rosa OS (distribution tarball)",
|
||||||
Website: "https://hakurei.app/",
|
Website: "https://hakurei.app/",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ package rosa
|
|||||||
|
|
||||||
import "hakurei.app/internal/pkg"
|
import "hakurei.app/internal/pkg"
|
||||||
|
|
||||||
const hakureiVersion = "0.4.0"
|
const hakureiVersion = "0.4.2"
|
||||||
|
|
||||||
// hakureiSource is the source code of a hakurei release.
|
// hakureiSource is the source code of a hakurei release.
|
||||||
var hakureiSource = newTar(
|
var hakureiSource = newTar(
|
||||||
"https://git.gensokyo.uk/rosa/hakurei/archive/"+
|
"https://git.gensokyo.uk/rosa/hakurei/archive/"+
|
||||||
"v"+hakureiVersion+".tar.gz",
|
"v"+hakureiVersion+".tar.gz",
|
||||||
"wfQ9DqCW0Fw9o91wj-I55waoqzB-UqzzuC0_2h-P-1M78SgZ1WHSPCDJMth6EyC2",
|
"jadgaOrxv5ABGvzQ_Rk0aPGz7U8K-427TbMhQNQ32scSizEnlR44Pu7NoWYWVZWq",
|
||||||
pkg.TarGzip,
|
pkg.TarGzip,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package rosa
|
||||||
|
|
||||||
|
import "hakurei.app/internal/pkg"
|
||||||
|
|
||||||
|
func (t Toolchain) newHwdata() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "0.407"
|
||||||
|
checksum = "6p1XD0CRuzt6hLfjv4ShKBW934BexmoPkRrmwxD4J63fBVCzVBRHyF8pVJdW_Xjm"
|
||||||
|
)
|
||||||
|
return t.NewPackage("hwdata", version, newFromGitHub(
|
||||||
|
"vcrhonek/hwdata",
|
||||||
|
"v"+version, checksum,
|
||||||
|
), &PackageAttr{
|
||||||
|
Writable: true,
|
||||||
|
EnterSource: true,
|
||||||
|
}, &MakeHelper{
|
||||||
|
// awk: fatal: cannot open file `hwdata.spec' for reading: No such file or directory
|
||||||
|
InPlace: true,
|
||||||
|
|
||||||
|
// lspci: Unknown option 'A' (see "lspci --help")
|
||||||
|
SkipCheck: true,
|
||||||
|
}), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newHwdata,
|
||||||
|
|
||||||
|
Name: "hwdata",
|
||||||
|
Description: "contains various hardware identification and configuration data",
|
||||||
|
Website: "https://github.com/vcrhonek/hwdata",
|
||||||
|
|
||||||
|
ID: 5387,
|
||||||
|
})
|
||||||
|
}
|
||||||
+9
-11
@@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[EarlyInit] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
Name: "earlyinit",
|
Name: "earlyinit",
|
||||||
Description: "Rosa OS initramfs init program",
|
Description: "Rosa OS initramfs init program",
|
||||||
|
|
||||||
@@ -24,15 +24,14 @@ go build -trimpath -v -o /work/system/libexec/hakurei -ldflags="-s -w
|
|||||||
echo
|
echo
|
||||||
`, false), Unversioned
|
`, false), Unversioned
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newImageSystem() (pkg.Artifact, string) {
|
func (t Toolchain) newImageSystem() (pkg.Artifact, string) {
|
||||||
return t.New("system.img", TNoToolchain, t.AppendPresets(nil,
|
return t.New("system.img", TNoToolchain, t.Append(nil,
|
||||||
SquashfsTools,
|
SquashfsTools,
|
||||||
), nil, nil, `
|
), nil, nil, `
|
||||||
mksquashfs /mnt/system /work/system.img
|
mksquashfs /mnt/system /work/system.img
|
||||||
`, pkg.Path(fhs.AbsRoot.Append("mnt"), false, t.AppendPresets(nil,
|
`, pkg.Path(fhs.AbsRoot.Append("mnt"), false, t.Append(nil,
|
||||||
Musl,
|
Musl,
|
||||||
Mksh,
|
Mksh,
|
||||||
Toybox,
|
Toybox,
|
||||||
@@ -43,16 +42,15 @@ mksquashfs /mnt/system /work/system.img
|
|||||||
)...)), Unversioned
|
)...)), Unversioned
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[ImageSystem] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
Name: "system-image",
|
Name: "system-image",
|
||||||
Description: "Rosa OS system image",
|
Description: "Rosa OS system image",
|
||||||
|
|
||||||
f: Toolchain.newImageSystem,
|
f: Toolchain.newImageSystem,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newImageInitramfs() (pkg.Artifact, string) {
|
func (t Toolchain) newImageInitramfs() (pkg.Artifact, string) {
|
||||||
return t.New("initramfs", TNoToolchain, t.AppendPresets(nil,
|
return t.New("initramfs", TNoToolchain, t.Append(nil,
|
||||||
Zstd,
|
Zstd,
|
||||||
EarlyInit,
|
EarlyInit,
|
||||||
GenInitCPIO,
|
GenInitCPIO,
|
||||||
@@ -66,10 +64,10 @@ file /init /system/libexec/hakurei/earlyinit 0555 0 0
|
|||||||
`)))), Unversioned
|
`)))), Unversioned
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[ImageInitramfs] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
Name: "initramfs-image",
|
Name: "initramfs-image",
|
||||||
Description: "Rosa OS initramfs image",
|
Description: "Rosa OS initramfs image",
|
||||||
|
|
||||||
f: Toolchain.newImageInitramfs,
|
f: Toolchain.newImageInitramfs,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-14
@@ -2,12 +2,12 @@ package rosa
|
|||||||
|
|
||||||
import "hakurei.app/internal/pkg"
|
import "hakurei.app/internal/pkg"
|
||||||
|
|
||||||
const kernelVersion = "6.12.84"
|
const kernelVersion = "6.12.87"
|
||||||
|
|
||||||
var kernelSource = newTar(
|
var kernelSource = newTar(
|
||||||
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+
|
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+
|
||||||
"snapshot/linux-"+kernelVersion+".tar.gz",
|
"snapshot/linux-"+kernelVersion+".tar.gz",
|
||||||
"GJLUEu68r3DpLYoTcMl4wA_ThMBs_Zwc0gZsp82ii_3AOfcVxpI639IKfq2jAAY2",
|
"QTl5teIy0K5KsOLYGHQ3FbnPCZNRH2bySXVzghiOoHDdM3zAcSPUkmdly85lMzHx",
|
||||||
pkg.TarGzip,
|
pkg.TarGzip,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,18 +19,35 @@ chmod -R +w /work/usr/src/linux/
|
|||||||
`, pkg.Path(AbsUsrSrc.Append("linux"), false, kernelSource)), kernelVersion
|
`, pkg.Path(AbsUsrSrc.Append("linux"), false, kernelSource)), kernelVersion
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[KernelSource] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newKernelSource,
|
f: Toolchain.newKernelSource,
|
||||||
|
|
||||||
Name: "kernel-source",
|
Name: "kernel-source",
|
||||||
Description: "a writable kernel source tree installed to /usr/src/linux",
|
Description: "a writable kernel source tree installed to /usr/src/linux",
|
||||||
Website: "https://kernel.org/",
|
Website: "https://kernel.org/",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newKernelHeaders() (pkg.Artifact, string) {
|
func (t Toolchain) newKernelHeaders() (pkg.Artifact, string) {
|
||||||
|
checksum := perArch[string]{
|
||||||
|
"amd64": "lCmBNcMeUmXifg0vecKOPy3GAaFcJSmOPnf3wit9xYTDSTsFADPt1xxUFfmTn1fD",
|
||||||
|
"arm64": "PlRxp4JzZeMGx7CScRlT1NBzc2NVyJlb8Gm8sa3ofFght9ZT101ZJhcIXiCkHSHM",
|
||||||
|
}
|
||||||
return t.NewPackage("kernel-headers", kernelVersion, kernelSource, &PackageAttr{
|
return t.NewPackage("kernel-headers", kernelVersion, kernelSource, &PackageAttr{
|
||||||
Flag: TEarly,
|
Flag: TEarly,
|
||||||
|
KnownChecksum: new(mustDecode(checksum.unwrap(t.S))),
|
||||||
|
|
||||||
|
Paths: []pkg.ExecPath{
|
||||||
|
// updated manually for API changes
|
||||||
|
pkg.Path(AbsUsrSrc.Append("version.h"), false, pkg.NewFile(
|
||||||
|
"version.h", []byte(`#define LINUX_VERSION_CODE 396372
|
||||||
|
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
|
||||||
|
#define LINUX_VERSION_MAJOR 6
|
||||||
|
#define LINUX_VERSION_PATCHLEVEL 12
|
||||||
|
#define LINUX_VERSION_SUBLEVEL 84
|
||||||
|
`),
|
||||||
|
)),
|
||||||
|
},
|
||||||
}, &MakeHelper{
|
}, &MakeHelper{
|
||||||
SkipConfigure: true,
|
SkipConfigure: true,
|
||||||
|
|
||||||
@@ -43,19 +60,23 @@ func (t Toolchain) newKernelHeaders() (pkg.Artifact, string) {
|
|||||||
"INSTALL_HDR_PATH=/work/system",
|
"INSTALL_HDR_PATH=/work/system",
|
||||||
"headers_install",
|
"headers_install",
|
||||||
},
|
},
|
||||||
Install: "# headers installed during make",
|
Install: `
|
||||||
|
cat \
|
||||||
|
/usr/src/version.h > \
|
||||||
|
/work/system/include/linux/version.h
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
Rsync,
|
Rsync,
|
||||||
), kernelVersion
|
), kernelVersion
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[KernelHeaders] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newKernelHeaders,
|
f: Toolchain.newKernelHeaders,
|
||||||
|
|
||||||
Name: "kernel-headers",
|
Name: "kernel-headers",
|
||||||
Description: "an installation of kernel headers",
|
Description: "an installation of kernel headers",
|
||||||
Website: "https://kernel.org/",
|
Website: "https://kernel.org/",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newKernel() (pkg.Artifact, string) {
|
func (t Toolchain) newKernel() (pkg.Artifact, string) {
|
||||||
@@ -1254,7 +1275,7 @@ rm -v /work/system/lib/modules/` + kernelVersion + `/build
|
|||||||
), kernelVersion
|
), kernelVersion
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Kernel] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newKernel,
|
f: Toolchain.newKernel,
|
||||||
|
|
||||||
Name: "kernel",
|
Name: "kernel",
|
||||||
@@ -1262,7 +1283,7 @@ func init() {
|
|||||||
Website: "https://kernel.org/",
|
Website: "https://kernel.org/",
|
||||||
|
|
||||||
ID: 375621,
|
ID: 375621,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newGenInitCPIO() (pkg.Artifact, string) {
|
func (t Toolchain) newGenInitCPIO() (pkg.Artifact, string) {
|
||||||
@@ -1272,12 +1293,12 @@ cc -o /work/system/bin/gen_init_cpio /usr/src/linux/usr/gen_init_cpio.c
|
|||||||
`, pkg.Path(AbsUsrSrc.Append("linux"), false, kernelSource)), kernelVersion
|
`, pkg.Path(AbsUsrSrc.Append("linux"), false, kernelSource)), kernelVersion
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[GenInitCPIO] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newGenInitCPIO,
|
f: Toolchain.newGenInitCPIO,
|
||||||
|
|
||||||
Name: "gen_init_cpio",
|
Name: "gen_init_cpio",
|
||||||
Description: "a program in the kernel source tree for creating initramfs archive",
|
Description: "a program in the kernel source tree for creating initramfs archive",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newFirmware() (pkg.Artifact, string) {
|
func (t Toolchain) newFirmware() (pkg.Artifact, string) {
|
||||||
@@ -1319,7 +1340,7 @@ func (t Toolchain) newFirmware() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Firmware] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newFirmware,
|
f: Toolchain.newFirmware,
|
||||||
|
|
||||||
Name: "firmware",
|
Name: "firmware",
|
||||||
@@ -1327,5 +1348,5 @@ func init() {
|
|||||||
Website: "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/",
|
Website: "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/",
|
||||||
|
|
||||||
ID: 141464,
|
ID: 141464,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func (t Toolchain) newKmod() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Kmod] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newKmod,
|
f: Toolchain.newKmod,
|
||||||
|
|
||||||
Name: "kmod",
|
Name: "kmod",
|
||||||
@@ -46,5 +46,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 1517,
|
ID: 1517,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package rosa
|
||||||
|
|
||||||
|
import "hakurei.app/internal/pkg"
|
||||||
|
|
||||||
|
func (t Toolchain) newLibarchive() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "3.8.7"
|
||||||
|
checksum = "CUJK4MDQmZmATClgQBH2Wt-7Ts4iiSUlg1J_TVb6-5IK3rVUgVLIMc5k-bnWB9w3"
|
||||||
|
)
|
||||||
|
return t.NewPackage("libarchive", version, newFromGitHub(
|
||||||
|
"libarchive/libarchive",
|
||||||
|
"v"+version, checksum,
|
||||||
|
), &PackageAttr{
|
||||||
|
Paths: []pkg.ExecPath{
|
||||||
|
pkg.Path(AbsUsrSrc.Append(
|
||||||
|
"CTestCustom.cmake",
|
||||||
|
), false, pkg.NewFile("CTestCustom.cmake", []byte(`
|
||||||
|
list(APPEND CTEST_CUSTOM_TESTS_IGNORE
|
||||||
|
"libarchive_test_archive_string_conversion_fail_c"
|
||||||
|
"libarchive_test_archive_string_conversion_fail_latin1"
|
||||||
|
"libarchive_test_archive_string_update_utf8_koi8"
|
||||||
|
"libarchive_test_gnutar_filename_encoding_KOI8R_UTF8"
|
||||||
|
"libarchive_test_gnutar_filename_encoding_KOI8R_CP866"
|
||||||
|
"libarchive_test_gnutar_filename_encoding_CP1251_UTF8"
|
||||||
|
"libarchive_test_gnutar_filename_encoding_Russian_Russia"
|
||||||
|
"libarchive_test_gnutar_filename_encoding_EUCJP_UTF8"
|
||||||
|
"libarchive_test_gnutar_filename_encoding_EUCJP_CP932"
|
||||||
|
"libarchive_test_gnutar_filename_encoding_CP932_UTF8"
|
||||||
|
"libarchive_test_pax_filename_encoding_KOI8R"
|
||||||
|
"libarchive_test_pax_filename_encoding_CP1251"
|
||||||
|
"libarchive_test_pax_filename_encoding_EUCJP"
|
||||||
|
"libarchive_test_pax_filename_encoding_CP932"
|
||||||
|
"libarchive_test_read_format_cpio_filename_UTF8_eucJP"
|
||||||
|
"libarchive_test_read_format_cpio_filename_CP866_KOI8R"
|
||||||
|
"libarchive_test_read_format_cpio_filename_KOI8R_CP866"
|
||||||
|
"libarchive_test_read_format_cpio_filename_UTF8_KOI8R"
|
||||||
|
"libarchive_test_read_format_cpio_filename_UTF8_CP866"
|
||||||
|
"libarchive_test_read_format_cpio_filename_eucJP_CP932"
|
||||||
|
"libarchive_test_read_format_cpio_filename_UTF8_CP932"
|
||||||
|
"libarchive_test_read_format_cpio_filename_CP866_CP1251"
|
||||||
|
"libarchive_test_read_format_cpio_filename_CP866_CP1251_win"
|
||||||
|
"libarchive_test_read_format_cpio_filename_KOI8R_CP1251"
|
||||||
|
"libarchive_test_read_format_cpio_filename_UTF8_CP1251"
|
||||||
|
"libarchive_test_read_format_gtar_filename_CP866_KOI8R"
|
||||||
|
"libarchive_test_read_format_gtar_filename_KOI8R_CP866"
|
||||||
|
"libarchive_test_read_format_gtar_filename_eucJP_CP932"
|
||||||
|
"libarchive_test_read_format_gtar_filename_CP866_CP1251"
|
||||||
|
"libarchive_test_read_format_gtar_filename_CP866_CP1251_win"
|
||||||
|
"libarchive_test_read_format_gtar_filename_KOI8R_CP1251"
|
||||||
|
"libarchive_test_read_format_rar_unicode_CP932"
|
||||||
|
"libarchive_test_read_format_zip_filename_CP932_eucJP"
|
||||||
|
"libarchive_test_read_format_zip_filename_UTF8_eucJP"
|
||||||
|
"libarchive_test_read_format_zip_filename_CP866_KOI8R"
|
||||||
|
"libarchive_test_read_format_zip_filename_KOI8R_CP866"
|
||||||
|
"libarchive_test_read_format_zip_filename_UTF8_KOI8R"
|
||||||
|
"libarchive_test_read_format_zip_filename_UTF8_CP866"
|
||||||
|
"libarchive_test_read_format_zip_filename_CP932_CP932"
|
||||||
|
"libarchive_test_read_format_zip_filename_UTF8_CP932"
|
||||||
|
"libarchive_test_read_format_zip_filename_CP866_CP1251"
|
||||||
|
"libarchive_test_read_format_zip_filename_CP866_CP1251_win"
|
||||||
|
"libarchive_test_read_format_zip_filename_KOI8R_CP1251"
|
||||||
|
"libarchive_test_read_format_zip_filename_UTF8_CP1251"
|
||||||
|
"libarchive_test_ustar_filename_encoding_KOI8R_UTF8"
|
||||||
|
"libarchive_test_ustar_filename_encoding_KOI8R_CP866"
|
||||||
|
"libarchive_test_ustar_filename_encoding_CP1251_UTF8"
|
||||||
|
"libarchive_test_ustar_filename_encoding_Russian_Russia"
|
||||||
|
"libarchive_test_ustar_filename_encoding_EUCJP_UTF8"
|
||||||
|
"libarchive_test_ustar_filename_encoding_EUCJP_CP932"
|
||||||
|
"libarchive_test_ustar_filename_encoding_CP932_UTF8"
|
||||||
|
"libarchive_test_zip_filename_encoding_KOI8R"
|
||||||
|
"libarchive_test_zip_filename_encoding_ru_RU_CP1251"
|
||||||
|
"libarchive_test_zip_filename_encoding_Russian_Russia"
|
||||||
|
"libarchive_test_zip_filename_encoding_EUCJP"
|
||||||
|
"libarchive_test_zip_filename_encoding_CP932"
|
||||||
|
"libarchive_test_read_format_cab_filename"
|
||||||
|
"libarchive_test_read_format_lha_filename"
|
||||||
|
"libarchive_test_read_format_tar_filename"
|
||||||
|
"libarchive_test_read_format_ustar_filename"
|
||||||
|
"libarchive_test_read_append_wrong_filter"
|
||||||
|
)
|
||||||
|
`))),
|
||||||
|
},
|
||||||
|
|
||||||
|
Writable: true,
|
||||||
|
ScriptEarly: `
|
||||||
|
install -Dv /usr/src/CTestCustom.cmake /cure/
|
||||||
|
`,
|
||||||
|
}, (*CMakeHelper)(nil)), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newLibarchive,
|
||||||
|
|
||||||
|
Name: "libarchive",
|
||||||
|
Description: "multi-format archive and compression library",
|
||||||
|
Website: "https://www.libarchive.org/",
|
||||||
|
|
||||||
|
ID: 1558,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@ import "hakurei.app/internal/pkg"
|
|||||||
|
|
||||||
func (t Toolchain) newLibmd() (pkg.Artifact, string) {
|
func (t Toolchain) newLibmd() (pkg.Artifact, string) {
|
||||||
const (
|
const (
|
||||||
version = "1.1.0"
|
version = "1.2.0"
|
||||||
checksum = "9apYqPPZm0j5HQT8sCsVIhnVIqRD7XgN7kPIaTwTqnTuUq5waUAMq4M7ev8CODJ1"
|
checksum = "1rJ6joAO0wwMZvSfnRNkc1MOhywyAq7SM8VmF92NvDtv7Qdl1LRbjm5fg_DFFtGj"
|
||||||
)
|
)
|
||||||
return t.NewPackage("libmd", version, t.newTagRemote(
|
return t.NewPackage("libmd", version, t.newTagRemote(
|
||||||
"https://git.hadrons.org/git/libmd.git",
|
"https://git.hadrons.org/git/libmd.git",
|
||||||
@@ -21,7 +21,7 @@ install -D /usr/src/libmd/src/helper.c src/helper.c
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libmd] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibmd,
|
f: Toolchain.newLibmd,
|
||||||
|
|
||||||
Name: "libmd",
|
Name: "libmd",
|
||||||
@@ -29,7 +29,7 @@ func init() {
|
|||||||
Website: "https://www.hadrons.org/software/libmd/",
|
Website: "https://www.hadrons.org/software/libmd/",
|
||||||
|
|
||||||
ID: 15525,
|
ID: 15525,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newLibbsd() (pkg.Artifact, string) {
|
func (t Toolchain) newLibbsd() (pkg.Artifact, string) {
|
||||||
@@ -50,7 +50,7 @@ func (t Toolchain) newLibbsd() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libbsd] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibbsd,
|
f: Toolchain.newLibbsd,
|
||||||
|
|
||||||
Name: "libbsd",
|
Name: "libbsd",
|
||||||
@@ -58,5 +58,5 @@ func init() {
|
|||||||
Website: "https://libbsd.freedesktop.org/",
|
Website: "https://libbsd.freedesktop.org/",
|
||||||
|
|
||||||
ID: 1567,
|
ID: 1567,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ ln -s ../system/bin/bash /bin/
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libcap] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibcap,
|
f: Toolchain.newLibcap,
|
||||||
|
|
||||||
Name: "libcap",
|
Name: "libcap",
|
||||||
@@ -50,5 +50,5 @@ func init() {
|
|||||||
Website: "https://sites.google.com/site/fullycapable/",
|
Website: "https://sites.google.com/site/fullycapable/",
|
||||||
|
|
||||||
ID: 1569,
|
ID: 1569,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package rosa
|
||||||
|
|
||||||
|
import "hakurei.app/internal/pkg"
|
||||||
|
|
||||||
|
func (t Toolchain) newLibconfig() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "1.8.2"
|
||||||
|
checksum = "fD32hjeAZuTz98g6WYHRwsxphrgrEFqxi5Z1jlJemPckPBfxpS3i5HgshAuA6vmT"
|
||||||
|
)
|
||||||
|
return t.NewPackage("libconfig", version, newFromGitHub(
|
||||||
|
"hyperrealm/libconfig",
|
||||||
|
"v"+version,
|
||||||
|
checksum,
|
||||||
|
), &PackageAttr{
|
||||||
|
Patches: []KV{
|
||||||
|
{"disable-broken-tests", `diff --git a/tests/tests.c b/tests/tests.c
|
||||||
|
index eba7eae..f916d2e 100644
|
||||||
|
--- a/tests/tests.c
|
||||||
|
+++ b/tests/tests.c
|
||||||
|
@@ -753,7 +753,6 @@ int main(int argc, char **argv)
|
||||||
|
int failures;
|
||||||
|
|
||||||
|
TT_SUITE_START(LibConfigTests);
|
||||||
|
- TT_SUITE_TEST(LibConfigTests, ParsingAndFormatting);
|
||||||
|
TT_SUITE_TEST(LibConfigTests, ParseInvalidFiles);
|
||||||
|
TT_SUITE_TEST(LibConfigTests, ParseInvalidStrings);
|
||||||
|
TT_SUITE_TEST(LibConfigTests, BigInt1);
|
||||||
|
@@ -768,7 +767,6 @@ int main(int argc, char **argv)
|
||||||
|
TT_SUITE_TEST(LibConfigTests, OverrideSetting);
|
||||||
|
TT_SUITE_TEST(LibConfigTests, SettingLookups);
|
||||||
|
TT_SUITE_TEST(LibConfigTests, ReadStream);
|
||||||
|
- TT_SUITE_TEST(LibConfigTests, BinaryAndHex);
|
||||||
|
TT_SUITE_RUN(LibConfigTests);
|
||||||
|
failures = TT_SUITE_NUM_FAILURES(LibConfigTests);
|
||||||
|
TT_SUITE_END(LibConfigTests);
|
||||||
|
`},
|
||||||
|
},
|
||||||
|
}, (*CMakeHelper)(nil)), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newLibconfig,
|
||||||
|
|
||||||
|
Name: "libconfig",
|
||||||
|
Description: "a simple library for processing structured configuration files",
|
||||||
|
Website: "https://hyperrealm.github.io/libconfig/",
|
||||||
|
|
||||||
|
ID: 1580,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package rosa
|
||||||
|
|
||||||
|
import "hakurei.app/internal/pkg"
|
||||||
|
|
||||||
|
func (t Toolchain) newLibdisplayInfo() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "0.3.0"
|
||||||
|
checksum = "yjOqPUHHYgRtpqGw5RI1n2Q1_hO5j0LiFNMbjcRWV4Nf71XwwoC9fZMlKBDeLchT"
|
||||||
|
)
|
||||||
|
return t.NewPackage("libdisplay-info", version, newFromGitLab(
|
||||||
|
"gitlab.freedesktop.org",
|
||||||
|
"emersion/libdisplay-info",
|
||||||
|
version, checksum,
|
||||||
|
), nil, (*MesonHelper)(nil),
|
||||||
|
Diffutils,
|
||||||
|
|
||||||
|
Hwdata,
|
||||||
|
), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newLibdisplayInfo,
|
||||||
|
|
||||||
|
Name: "libdisplay-info",
|
||||||
|
Description: "EDID and DisplayID library",
|
||||||
|
Website: "https://gitlab.freedesktop.org/emersion/libdisplay-info",
|
||||||
|
|
||||||
|
ID: 326668,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package rosa
|
||||||
|
|
||||||
|
import "hakurei.app/internal/pkg"
|
||||||
|
|
||||||
|
func (t Toolchain) newLibepoxy() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "1.5.10"
|
||||||
|
checksum = "OHI8wshrlGw6BMGrmSyejJtwzM2gPhyFJrTsKxULyKMmYrfgcOe7Iw2ibVoUND_Q"
|
||||||
|
)
|
||||||
|
return t.NewPackage("libepoxy", version, newFromGitHub(
|
||||||
|
"anholt/libepoxy",
|
||||||
|
version,
|
||||||
|
checksum,
|
||||||
|
), nil, &MesonHelper{
|
||||||
|
Setup: []KV{
|
||||||
|
{"Dglx", "no"},
|
||||||
|
{"Degl", "no"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
LibX11,
|
||||||
|
), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newLibepoxy,
|
||||||
|
|
||||||
|
Name: "libepoxy",
|
||||||
|
Description: "a library for handling OpenGL function pointer management",
|
||||||
|
Website: "https://github.com/anholt/libepoxy",
|
||||||
|
|
||||||
|
ID: 6090,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ func (t Toolchain) newLibev() (pkg.Artifact, string) {
|
|||||||
), nil, (*MakeHelper)(nil)), version
|
), nil, (*MakeHelper)(nil)), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libev] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibev,
|
f: Toolchain.newLibev,
|
||||||
|
|
||||||
Name: "libev",
|
Name: "libev",
|
||||||
@@ -22,5 +22,5 @@ func init() {
|
|||||||
Website: "http://libev.schmorp.de/",
|
Website: "http://libev.schmorp.de/",
|
||||||
|
|
||||||
ID: 1605,
|
ID: 1605,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
|
|
||||||
func (t Toolchain) newLibexpat() (pkg.Artifact, string) {
|
func (t Toolchain) newLibexpat() (pkg.Artifact, string) {
|
||||||
const (
|
const (
|
||||||
version = "2.8.0"
|
version = "2.8.1"
|
||||||
checksum = "pnwZ_JSif-OfoWIwk2JYXWHagOWMA3Sh-Ea0p-4Rz9U9mDEeAebhyvnfD7OYOMCk"
|
checksum = "iMEtbOJhQfGof2GxSlxffQSI1va_NDDQ9VIuqcPbNZ0291Dr8wttD5QecYyjIQap"
|
||||||
)
|
)
|
||||||
return t.NewPackage("libexpat", version, newFromGitHubRelease(
|
return t.NewPackage("libexpat", version, newFromGitHubRelease(
|
||||||
"libexpat/libexpat",
|
"libexpat/libexpat",
|
||||||
@@ -22,7 +22,7 @@ func (t Toolchain) newLibexpat() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libexpat] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibexpat,
|
f: Toolchain.newLibexpat,
|
||||||
|
|
||||||
Name: "libexpat",
|
Name: "libexpat",
|
||||||
@@ -30,5 +30,5 @@ func init() {
|
|||||||
Website: "https://libexpat.github.io/",
|
Website: "https://libexpat.github.io/",
|
||||||
|
|
||||||
ID: 770,
|
ID: 770,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func (t Toolchain) newLibffi() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libffi] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibffi,
|
f: Toolchain.newLibffi,
|
||||||
|
|
||||||
Name: "libffi",
|
Name: "libffi",
|
||||||
@@ -26,5 +26,5 @@ func init() {
|
|||||||
Website: "https://sourceware.org/libffi/",
|
Website: "https://sourceware.org/libffi/",
|
||||||
|
|
||||||
ID: 1611,
|
ID: 1611,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ mkdir /dev/shm/gd
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libgd] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibgd,
|
f: Toolchain.newLibgd,
|
||||||
|
|
||||||
Name: "libgd",
|
Name: "libgd",
|
||||||
@@ -36,5 +36,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 880,
|
ID: 880,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package rosa
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"hakurei.app/internal/pkg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t Toolchain) newLibpng() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "1.6.58"
|
||||||
|
checksum = "m_a5lROJH7vmF3cMjqwTUqURuQLhV1JQx2ySPzcN3VPdgDB9pG3UINsIx_mtkr-t"
|
||||||
|
)
|
||||||
|
return t.NewPackage("libpng", version, newTar(
|
||||||
|
"https://downloads.sourceforge.net/project/libpng/libpng"+
|
||||||
|
strings.Join(strings.SplitN(version, ".", 3)[:2], "")+
|
||||||
|
"/"+version+"/libpng-"+version+".tar.gz",
|
||||||
|
checksum,
|
||||||
|
pkg.TarGzip,
|
||||||
|
), nil, (*MakeHelper)(nil),
|
||||||
|
Zlib,
|
||||||
|
), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newLibpng,
|
||||||
|
|
||||||
|
Name: "libpng",
|
||||||
|
Description: "the official PNG reference library",
|
||||||
|
Website: "https://www.libpng.org/pub/png/libpng.html",
|
||||||
|
|
||||||
|
Dependencies: P{
|
||||||
|
Zlib,
|
||||||
|
},
|
||||||
|
|
||||||
|
ID: 1705,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ test_disable 'int main(){return 0;}' tests/test-is-public-builtin.c
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libpsl] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibpsl,
|
f: Toolchain.newLibpsl,
|
||||||
|
|
||||||
Name: "libpsl",
|
Name: "libpsl",
|
||||||
@@ -33,5 +33,5 @@ func init() {
|
|||||||
Website: "https://rockdaboot.github.io/libpsl/",
|
Website: "https://rockdaboot.github.io/libpsl/",
|
||||||
|
|
||||||
ID: 7305,
|
ID: 7305,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ index adccef3..65a277a 100644
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libseccomp] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibseccomp,
|
f: Toolchain.newLibseccomp,
|
||||||
|
|
||||||
Name: "libseccomp",
|
Name: "libseccomp",
|
||||||
@@ -51,5 +51,5 @@ func init() {
|
|||||||
Website: "https://github.com/seccomp/libseccomp/",
|
Website: "https://github.com/seccomp/libseccomp/",
|
||||||
|
|
||||||
ID: 13823,
|
ID: 13823,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package rosa
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"hakurei.app/internal/pkg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t Toolchain) newLibtirpc() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "1.3.7"
|
||||||
|
checksum = "nzFfu7LNvnSNiNAryD1vtnNWnU-Xqee8KqfXUKoBf5yjb5-dkeRkYuRijdCoYLof"
|
||||||
|
)
|
||||||
|
return t.NewPackage("libtirpc", version, t.newTagRemote(
|
||||||
|
"git://linux-nfs.org/~steved/libtirpc",
|
||||||
|
"libtirpc-"+
|
||||||
|
strings.Join(strings.SplitN(version, ".", 3), "-"),
|
||||||
|
checksum,
|
||||||
|
), nil, &MakeHelper{
|
||||||
|
Generate: "sh -e ./bootstrap",
|
||||||
|
Configure: []KV{
|
||||||
|
{"CFLAGS", `"$(pkg-config --cflags libbsd-overlay) ${CFLAGS:-}"`},
|
||||||
|
{"disable-gssapi"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Automake,
|
||||||
|
Libtool,
|
||||||
|
PkgConfig,
|
||||||
|
|
||||||
|
Libbsd,
|
||||||
|
KernelHeaders,
|
||||||
|
), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newLibtirpc,
|
||||||
|
|
||||||
|
Name: "libtirpc",
|
||||||
|
Description: "a port of Suns Transport-Independent RPC library to Linux",
|
||||||
|
Website: "https://sourceforge.net/projects/libtirpc/",
|
||||||
|
|
||||||
|
ID: 1740,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@ import "hakurei.app/internal/pkg"
|
|||||||
|
|
||||||
func (t Toolchain) newLibucontext() (pkg.Artifact, string) {
|
func (t Toolchain) newLibucontext() (pkg.Artifact, string) {
|
||||||
const (
|
const (
|
||||||
version = "1.5"
|
version = "1.5.1"
|
||||||
checksum = "Ggk7FMmDNBdCx1Z9PcNWWW6LSpjGYssn2vU0GK5BLXJYw7ZxZbA2m_eSgT9TFnIG"
|
checksum = "mUgeyJknjMxT-5fORzz-rqhZfP3Y7EZGBhOwvhuX7MsF4Pk9wkuwtrLf5IML-jWu"
|
||||||
)
|
)
|
||||||
return t.NewPackage("libucontext", version, newFromGitHub(
|
return t.NewPackage("libucontext", version, newFromGitHub(
|
||||||
"kaniini/libucontext",
|
"kaniini/libucontext",
|
||||||
@@ -21,13 +21,13 @@ func (t Toolchain) newLibucontext() (pkg.Artifact, string) {
|
|||||||
SkipConfigure: true,
|
SkipConfigure: true,
|
||||||
InPlace: true,
|
InPlace: true,
|
||||||
Make: []string{
|
Make: []string{
|
||||||
"ARCH=" + linuxArch(),
|
"ARCH=" + t.linuxArch(),
|
||||||
},
|
},
|
||||||
Install: "make prefix=/system DESTDIR=/work install",
|
Install: "make prefix=/system DESTDIR=/work install",
|
||||||
}), version
|
}), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libucontext] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibucontext,
|
f: Toolchain.newLibucontext,
|
||||||
|
|
||||||
Name: "libucontext",
|
Name: "libucontext",
|
||||||
@@ -35,5 +35,5 @@ func init() {
|
|||||||
Website: "https://github.com/kaniini/libucontext/",
|
Website: "https://github.com/kaniini/libucontext/",
|
||||||
|
|
||||||
ID: 17085,
|
ID: 17085,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func (t Toolchain) newLibxml2() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libxml2] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibxml2,
|
f: Toolchain.newLibxml2,
|
||||||
|
|
||||||
Name: "libxml2",
|
Name: "libxml2",
|
||||||
@@ -28,5 +28,5 @@ func init() {
|
|||||||
Website: "https://gitlab.gnome.org/GNOME/libxml2/",
|
Website: "https://gitlab.gnome.org/GNOME/libxml2/",
|
||||||
|
|
||||||
ID: 1783,
|
ID: 1783,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func (t Toolchain) newLibxslt() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libxslt] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibxslt,
|
f: Toolchain.newLibxslt,
|
||||||
|
|
||||||
Name: "libxslt",
|
Name: "libxslt",
|
||||||
@@ -38,5 +38,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 13301,
|
ID: 13301,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-31
@@ -2,7 +2,6 @@ package rosa
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -31,24 +30,31 @@ func litArgs(verbose bool, skipChecks ...string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newEarlyCompilerRT() (pkg.Artifact, string) {
|
func (t Toolchain) newEarlyCompilerRT() (pkg.Artifact, string) {
|
||||||
version := t.Version(llvmSource)
|
source, version := t.Load(llvmSource)
|
||||||
major, _, _ := strings.Cut(version, ".")
|
major, _, _ := strings.Cut(version, ".")
|
||||||
return t.NewPackage("early-compiler-rt", version, t.Load(llvmSource), &PackageAttr{
|
return t.NewPackage("early-compiler-rt", version, source, &PackageAttr{
|
||||||
Flag: TExclusive,
|
Flag: TExclusive,
|
||||||
}, &CMakeHelper{
|
}, &CMakeHelper{
|
||||||
Append: []string{"compiler-rt"},
|
Append: []string{"compiler-rt"},
|
||||||
|
|
||||||
Cache: []KV{
|
Cache: []KV{
|
||||||
|
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||||
|
|
||||||
// libc++ not yet available
|
// libc++ not yet available
|
||||||
{"CMAKE_CXX_COMPILER_TARGET", ""},
|
{"CMAKE_CXX_COMPILER_TARGET", ""},
|
||||||
|
|
||||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||||
|
{"LLVM_ENABLE_RTTI", "ON"},
|
||||||
|
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||||
|
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||||
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
||||||
|
|
||||||
{"COMPILER_RT_BUILD_BUILTINS", "ON"},
|
{"COMPILER_RT_BUILD_BUILTINS", "ON"},
|
||||||
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "OFF"},
|
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"},
|
||||||
|
{"COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"},
|
||||||
{"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"},
|
{"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"},
|
||||||
|
{"COMPILER_RT_BUILD_GWP_ASAN", "OFF"},
|
||||||
|
|
||||||
// does not work without libunwind
|
// does not work without libunwind
|
||||||
{"COMPILER_RT_BUILD_CTX_PROFILE", "OFF"},
|
{"COMPILER_RT_BUILD_CTX_PROFILE", "OFF"},
|
||||||
@@ -65,10 +71,10 @@ ln -s \
|
|||||||
"/work/system/lib/clang/` + major + `/lib/"
|
"/work/system/lib/clang/` + major + `/lib/"
|
||||||
|
|
||||||
ln -s \
|
ln -s \
|
||||||
"clang_rt.crtbegin-` + linuxArch() + `.o" \
|
"clang_rt.crtbegin-` + t.linuxArch() + `.o" \
|
||||||
"/work/system/lib/${ROSA_TRIPLE}/crtbeginS.o"
|
"/work/system/lib/${ROSA_TRIPLE}/crtbeginS.o"
|
||||||
ln -s \
|
ln -s \
|
||||||
"clang_rt.crtend-` + linuxArch() + `.o" \
|
"clang_rt.crtend-` + t.linuxArch() + `.o" \
|
||||||
"/work/system/lib/${ROSA_TRIPLE}/crtendS.o"
|
"/work/system/lib/${ROSA_TRIPLE}/crtendS.o"
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
@@ -79,7 +85,7 @@ ln -s \
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[earlyCompilerRT] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newEarlyCompilerRT,
|
f: Toolchain.newEarlyCompilerRT,
|
||||||
|
|
||||||
Name: "early-compiler-rt",
|
Name: "early-compiler-rt",
|
||||||
@@ -88,30 +94,40 @@ func init() {
|
|||||||
Dependencies: P{
|
Dependencies: P{
|
||||||
Musl,
|
Musl,
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newEarlyRuntimes() (pkg.Artifact, string) {
|
func (t Toolchain) newEarlyRuntimes() (pkg.Artifact, string) {
|
||||||
version := t.Version(llvmSource)
|
source, version := t.Load(llvmSource)
|
||||||
return t.NewPackage("early-runtimes", version, t.Load(llvmSource), &PackageAttr{
|
return t.NewPackage("early-runtimes", version, source, &PackageAttr{
|
||||||
Flag: TExclusive,
|
Flag: TExclusive,
|
||||||
}, &CMakeHelper{
|
}, &CMakeHelper{
|
||||||
Append: []string{"runtimes"},
|
Append: []string{"runtimes"},
|
||||||
|
|
||||||
Cache: []KV{
|
Cache: []KV{
|
||||||
|
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||||
|
|
||||||
// libc++ not yet available
|
// libc++ not yet available
|
||||||
{"CMAKE_CXX_COMPILER_WORKS", "ON"},
|
{"CMAKE_CXX_COMPILER_WORKS", "ON"},
|
||||||
|
|
||||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||||
|
{"LLVM_ENABLE_RTTI", "ON"},
|
||||||
|
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||||
|
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||||
{"LLVM_ENABLE_RUNTIMES", "'libunwind;libcxx;libcxxabi'"},
|
{"LLVM_ENABLE_RUNTIMES", "'libunwind;libcxx;libcxxabi'"},
|
||||||
|
|
||||||
|
{"LIBUNWIND_ENABLE_ASSERTIONS", "OFF"},
|
||||||
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
|
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
|
||||||
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
|
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
|
||||||
{"LIBCXX_USE_COMPILER_RT", "ON"},
|
{"LIBCXX_USE_COMPILER_RT", "ON"},
|
||||||
|
{"LIBCXX_CXX_ABI", "libcxxabi"},
|
||||||
|
{"LIBCXX_ENABLE_STATIC_ABI_LIBRARY", "OFF"},
|
||||||
|
{"LIBCXX_HARDENING_MODE", "fast"},
|
||||||
{"LIBCXX_HAS_ATOMIC_LIB", "OFF"},
|
{"LIBCXX_HAS_ATOMIC_LIB", "OFF"},
|
||||||
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
|
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
|
||||||
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
|
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
|
||||||
|
{"LIBCXXABI_ENABLE_STATIC_UNWINDER", "OFF"},
|
||||||
{"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"},
|
{"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"},
|
||||||
|
|
||||||
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
||||||
@@ -129,7 +145,7 @@ func (t Toolchain) newEarlyRuntimes() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[earlyRuntimes] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newEarlyRuntimes,
|
f: Toolchain.newEarlyRuntimes,
|
||||||
|
|
||||||
Name: "early-runtimes",
|
Name: "early-runtimes",
|
||||||
@@ -138,17 +154,17 @@ func init() {
|
|||||||
Dependencies: P{
|
Dependencies: P{
|
||||||
earlyCompilerRT,
|
earlyCompilerRT,
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
||||||
var early PArtifact = muslHeaders
|
early := muslHeaders
|
||||||
if t.isStage0() {
|
if t.stage.isStage0() {
|
||||||
// The LLVM build system is buggy around LLVM_LINK_LLVM_DYLIB and leaks
|
// The LLVM build system uses the system installation when building with
|
||||||
// the system installation when invoking the newly built toolchain. This
|
// LLVM_LINK_LLVM_DYLIB, since it builds runtimes after the fact, using
|
||||||
// is worked around in stage0 by providing standalone builds of
|
// the just-built toolchain. This is unacceptable in stage0 due to the
|
||||||
// runtimes. Later stages rely on 3-stage determinism and allows the
|
// potential version difference. Later stages bootstrap off of runtimes
|
||||||
// system installation from its previous stage to leak through.
|
// of its previous stage via 3-stage determinism.
|
||||||
early = earlyRuntimes
|
early = earlyRuntimes
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +190,7 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
|||||||
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
||||||
{"LLVM_ENABLE_ZSTD", "FORCE_ON"},
|
{"LLVM_ENABLE_ZSTD", "FORCE_ON"},
|
||||||
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
||||||
|
{"LLVM_INCLUDE_BENCHMARKS", "OFF"},
|
||||||
{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
|
{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
|
||||||
{"CLANG_DEFAULT_UNWINDLIB", "libunwind"},
|
{"CLANG_DEFAULT_UNWINDLIB", "libunwind"},
|
||||||
{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
|
{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
|
||||||
@@ -200,7 +217,7 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
|||||||
}, ";") + "'"},
|
}, ";") + "'"},
|
||||||
}
|
}
|
||||||
|
|
||||||
if !t.isStage0() {
|
if !t.stage.isStage0() {
|
||||||
skipChecks := []string{
|
skipChecks := []string{
|
||||||
// expensive, pointless to run here
|
// expensive, pointless to run here
|
||||||
"benchmarks",
|
"benchmarks",
|
||||||
@@ -230,7 +247,7 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
|||||||
// unwind: fails on musl
|
// unwind: fails on musl
|
||||||
"eh_frame_fde_pc_range",
|
"eh_frame_fde_pc_range",
|
||||||
}
|
}
|
||||||
switch runtime.GOARCH {
|
switch t.arch {
|
||||||
case "arm64":
|
case "arm64":
|
||||||
skipChecks = append(skipChecks,
|
skipChecks = append(skipChecks,
|
||||||
// LLVM: intermittently crashes
|
// LLVM: intermittently crashes
|
||||||
@@ -240,7 +257,7 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if presetOpts&OptLLVMNoLTO == 0 {
|
if t.opts&OptLLVMNoLTO == 0 {
|
||||||
cache = append(cache, []KV{
|
cache = append(cache, []KV{
|
||||||
// very expensive
|
// very expensive
|
||||||
{"LLVM_ENABLE_LTO", "Thin"},
|
{"LLVM_ENABLE_LTO", "Thin"},
|
||||||
@@ -256,8 +273,10 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
|||||||
}...)
|
}...)
|
||||||
}
|
}
|
||||||
|
|
||||||
version := t.Version(llvmSource)
|
source, version := t.Load(llvmSource)
|
||||||
return t.NewPackage("llvm", version, t.Load(llvmSource), nil, &CMakeHelper{
|
return t.NewPackage("llvm", version, source, &PackageAttr{
|
||||||
|
Flag: TExclusive,
|
||||||
|
}, &CMakeHelper{
|
||||||
Append: []string{"llvm"},
|
Append: []string{"llvm"},
|
||||||
|
|
||||||
Cache: cache,
|
Cache: cache,
|
||||||
@@ -272,7 +291,7 @@ ln -s clang++ /work/system/bin/c++
|
|||||||
// installation into test environment, and the tests end up testing the
|
// installation into test environment, and the tests end up testing the
|
||||||
// system installation instead. Tests are disabled on stage0 and relies
|
// system installation instead. Tests are disabled on stage0 and relies
|
||||||
// on 3-stage determinism to test later stages.
|
// on 3-stage determinism to test later stages.
|
||||||
SkipTest: t.isStage0(),
|
SkipTest: t.stage.isStage0(),
|
||||||
|
|
||||||
Test: `
|
Test: `
|
||||||
chmod +w /bin && ln -s \
|
chmod +w /bin && ln -s \
|
||||||
@@ -301,11 +320,11 @@ ninja ` + jobsFlagE + ` check-all
|
|||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
const (
|
const (
|
||||||
version = "22.1.4"
|
version = "22.1.5"
|
||||||
checksum = "Bk3t-tV5sD5T0bqefFMcLeFuAwXnhFipywZmqst5hAZs97QQWGKB_5XyAFjj5tDB"
|
checksum = "32gOaLPHcUlo3hkdk5RbFumTE01XKeCAYZcpvn8IDHF95egXVfDFSl6eZL3ChMen"
|
||||||
)
|
)
|
||||||
|
|
||||||
artifactsM[llvmSource] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||||
return t.NewPatchedSource("llvm", version, newFromGitHub(
|
return t.NewPatchedSource("llvm", version, newFromGitHub(
|
||||||
"llvm/llvm-project",
|
"llvm/llvm-project",
|
||||||
@@ -318,9 +337,9 @@ func init() {
|
|||||||
Description: "LLVM monorepo with Rosa OS patches",
|
Description: "LLVM monorepo with Rosa OS patches",
|
||||||
|
|
||||||
ID: 1830,
|
ID: 1830,
|
||||||
}
|
})
|
||||||
|
|
||||||
artifactsM[LLVM] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLLVM,
|
f: Toolchain.newLLVM,
|
||||||
|
|
||||||
Name: "llvm",
|
Name: "llvm",
|
||||||
@@ -332,5 +351,5 @@ func init() {
|
|||||||
Zstd,
|
Zstd,
|
||||||
Musl,
|
Musl,
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,8 +90,23 @@ index 8ac8d4eb9181..e46b04a898ca 100644
|
|||||||
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
|
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
|
||||||
`},
|
`},
|
||||||
|
|
||||||
{"path-system-libraries", `diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
|
{"path-system-libraries", `diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
|
||||||
index d525b417b4ea..fdc411f2239c 100644
|
index cb6a9b242421..b8d31690d1af 100644
|
||||||
|
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
|
||||||
|
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
|
||||||
|
@@ -2314,6 +2314,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
|
||||||
|
Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (TargetTriple.getVendor() == llvm::Triple::Rosa) {
|
||||||
|
+ Prefixes.push_back(concat(SysRoot, "/system"));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// Fall back to /usr which is used by most non-Solaris systems.
|
||||||
|
Prefixes.push_back(concat(SysRoot, "/usr"));
|
||||||
|
}
|
||||||
|
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
|
||||||
|
index d525b417b4ea..2b93f401733e 100644
|
||||||
--- a/clang/lib/Driver/ToolChains/Linux.cpp
|
--- a/clang/lib/Driver/ToolChains/Linux.cpp
|
||||||
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
|
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
|
||||||
@@ -302,6 +302,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
@@ -302,6 +302,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||||
@@ -102,18 +117,7 @@ index d525b417b4ea..fdc411f2239c 100644
|
|||||||
|
|
||||||
if (IsCSKY && !SelectedMultilibs.empty())
|
if (IsCSKY && !SelectedMultilibs.empty())
|
||||||
SysRoot = SysRoot + SelectedMultilibs.back().osSuffix();
|
SysRoot = SysRoot + SelectedMultilibs.back().osSuffix();
|
||||||
@@ -337,12 +338,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
@@ -341,8 +342,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||||
const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
|
|
||||||
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
|
|
||||||
|
|
||||||
+ if (IsRosa) {
|
|
||||||
+ ExtraOpts.push_back("-rpath");
|
|
||||||
+ ExtraOpts.push_back("/system/lib");
|
|
||||||
+ ExtraOpts.push_back("-rpath");
|
|
||||||
+ ExtraOpts.push_back(concat("/system/lib", Triple.str()));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
// mips32: Debian multilib, we use /libo32, while in other case, /lib is
|
|
||||||
// used. We need add both libo32 and /lib.
|
// used. We need add both libo32 and /lib.
|
||||||
if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel) {
|
if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel) {
|
||||||
Generic_GCC::AddMultilibPaths(D, SysRoot, "libo32", MultiarchTriple, Paths);
|
Generic_GCC::AddMultilibPaths(D, SysRoot, "libo32", MultiarchTriple, Paths);
|
||||||
@@ -128,7 +132,7 @@ index d525b417b4ea..fdc411f2239c 100644
|
|||||||
}
|
}
|
||||||
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
|
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
|
||||||
|
|
||||||
@@ -360,18 +372,30 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
@@ -360,18 +365,30 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||||
Paths);
|
Paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +168,7 @@ index d525b417b4ea..fdc411f2239c 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
|
ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
|
||||||
@@ -572,6 +596,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
|
@@ -572,6 +589,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
|
||||||
return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
|
return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
|
||||||
}
|
}
|
||||||
if (Triple.isMusl()) {
|
if (Triple.isMusl()) {
|
||||||
@@ -174,18 +178,5 @@ index d525b417b4ea..fdc411f2239c 100644
|
|||||||
std::string ArchName;
|
std::string ArchName;
|
||||||
bool IsArm = false;
|
bool IsArm = false;
|
||||||
|
|
||||||
diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp
|
|
||||||
index f484d6f33ad8..dca55e72d67e 100644
|
|
||||||
--- a/clang/tools/clang-installapi/Options.cpp
|
|
||||||
+++ b/clang/tools/clang-installapi/Options.cpp
|
|
||||||
@@ -514,7 +514,7 @@ bool Options::processFrontendOptions(InputArgList &Args) {
|
|
||||||
FEOpts.FwkPaths = std::move(FrameworkPaths);
|
|
||||||
|
|
||||||
// Add default framework/library paths.
|
|
||||||
- PathSeq DefaultLibraryPaths = {"/usr/lib", "/usr/local/lib"};
|
|
||||||
+ PathSeq DefaultLibraryPaths = {"/usr/lib", "/system/lib", "/usr/local/lib"};
|
|
||||||
PathSeq DefaultFrameworkPaths = {"/Library/Frameworks",
|
|
||||||
"/System/Library/Frameworks"};
|
|
||||||
|
|
||||||
`},
|
`},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package rosa
|
||||||
|
|
||||||
|
import "hakurei.app/internal/pkg"
|
||||||
|
|
||||||
|
func (t Toolchain) newLMSensors() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "3-6-2"
|
||||||
|
checksum = "7JYNutrihe-FP6r3ftf96uFZJJWPfxnBHL0ALSMA-vovaXVRr-sAjlLitw7WWpCI"
|
||||||
|
)
|
||||||
|
return t.NewPackage("lm_sensors", version, newFromGitHub(
|
||||||
|
"lm-sensors/lm-sensors",
|
||||||
|
"V"+version,
|
||||||
|
checksum,
|
||||||
|
), &PackageAttr{
|
||||||
|
Writable: true,
|
||||||
|
Chmod: true,
|
||||||
|
EnterSource: true,
|
||||||
|
|
||||||
|
ScriptEarly: `
|
||||||
|
ln -s \
|
||||||
|
../../system/bin/perl \
|
||||||
|
/usr/bin/
|
||||||
|
`,
|
||||||
|
}, &MakeHelper{
|
||||||
|
InPlace: true,
|
||||||
|
SkipConfigure: true,
|
||||||
|
|
||||||
|
Make: []string{
|
||||||
|
"CC=cc",
|
||||||
|
"ETCDIR=/system/etc",
|
||||||
|
"PREFIX=/system",
|
||||||
|
},
|
||||||
|
|
||||||
|
Check: []string{
|
||||||
|
"CC=cc",
|
||||||
|
"check",
|
||||||
|
},
|
||||||
|
|
||||||
|
Install: "make DESTDIR=/work PREFIX=/system install",
|
||||||
|
},
|
||||||
|
Perl,
|
||||||
|
PerlTestCmd,
|
||||||
|
|
||||||
|
M4,
|
||||||
|
Bison,
|
||||||
|
Flex,
|
||||||
|
), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newLMSensors,
|
||||||
|
|
||||||
|
Name: "lm_sensors",
|
||||||
|
Description: "user-space support for hardware monitoring drivers",
|
||||||
|
Website: "https://hwmon.wiki.kernel.org/lm_sensors",
|
||||||
|
|
||||||
|
ID: 1831,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ cd "$(mktemp -d)"
|
|||||||
))), version
|
))), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Make] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newMake,
|
f: Toolchain.newMake,
|
||||||
|
|
||||||
Name: "make",
|
Name: "make",
|
||||||
@@ -35,7 +35,7 @@ func init() {
|
|||||||
Website: "https://www.gnu.org/software/make/",
|
Website: "https://www.gnu.org/software/make/",
|
||||||
|
|
||||||
ID: 1877,
|
ID: 1877,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeHelper is the [Make] build system helper.
|
// MakeHelper is the [Make] build system helper.
|
||||||
@@ -123,7 +123,7 @@ func (attr *MakeHelper) wantsDir() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// script generates the cure script.
|
// script generates the cure script.
|
||||||
func (attr *MakeHelper) script(name string) string {
|
func (attr *MakeHelper) script(s *S, name string) string {
|
||||||
if attr == nil {
|
if attr == nil {
|
||||||
attr = new(MakeHelper)
|
attr = new(MakeHelper)
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ make \
|
|||||||
}
|
}
|
||||||
scriptMake += "\n"
|
scriptMake += "\n"
|
||||||
|
|
||||||
if !attr.SkipCheck && presetOpts&OptSkipCheck == 0 {
|
if !attr.SkipCheck && s.opts&OptSkipCheck == 0 {
|
||||||
scriptMake += attr.ScriptCheckEarly + `make \
|
scriptMake += attr.ScriptCheckEarly + `make \
|
||||||
` + jobsFlagE + ` \
|
` + jobsFlagE + ` \
|
||||||
`
|
`
|
||||||
|
|||||||
+205
-6
@@ -1,6 +1,10 @@
|
|||||||
package rosa
|
package rosa
|
||||||
|
|
||||||
import "hakurei.app/internal/pkg"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"hakurei.app/internal/pkg"
|
||||||
|
)
|
||||||
|
|
||||||
func (t Toolchain) newLibglvnd() (pkg.Artifact, string) {
|
func (t Toolchain) newLibglvnd() (pkg.Artifact, string) {
|
||||||
const (
|
const (
|
||||||
@@ -12,20 +16,38 @@ func (t Toolchain) newLibglvnd() (pkg.Artifact, string) {
|
|||||||
"glvnd/libglvnd",
|
"glvnd/libglvnd",
|
||||||
"v"+version,
|
"v"+version,
|
||||||
checksum,
|
checksum,
|
||||||
), nil, (*MesonHelper)(nil),
|
), nil, &MesonHelper{
|
||||||
|
Setup: []KV{
|
||||||
|
{"Dx11", "enabled"},
|
||||||
|
{"Dglx", "enabled"},
|
||||||
|
},
|
||||||
|
ScriptCompiled: `
|
||||||
|
export DISPLAY=':0'
|
||||||
|
Xvfb &
|
||||||
|
XVFB_PID="$!"
|
||||||
|
trap 'kill $XVFB_PID && wait $XVFB_PID' EXIT
|
||||||
|
`,
|
||||||
|
},
|
||||||
Binutils, // symbols check fail with llvm nm
|
Binutils, // symbols check fail with llvm nm
|
||||||
|
Xserver, // test suite wants X server
|
||||||
|
|
||||||
|
LibXext,
|
||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libglvnd] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibglvnd,
|
f: Toolchain.newLibglvnd,
|
||||||
|
|
||||||
Name: "libglvnd",
|
Name: "libglvnd",
|
||||||
Description: "The GL Vendor-Neutral Dispatch library",
|
Description: "The GL Vendor-Neutral Dispatch library",
|
||||||
Website: "https://gitlab.freedesktop.org/glvnd/libglvnd",
|
Website: "https://gitlab.freedesktop.org/glvnd/libglvnd",
|
||||||
|
|
||||||
|
Dependencies: P{
|
||||||
|
LibXext,
|
||||||
|
},
|
||||||
|
|
||||||
ID: 12098,
|
ID: 12098,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newLibdrm() (pkg.Artifact, string) {
|
func (t Toolchain) newLibdrm() (pkg.Artifact, string) {
|
||||||
@@ -50,7 +72,7 @@ func (t Toolchain) newLibdrm() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libdrm] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibdrm,
|
f: Toolchain.newLibdrm,
|
||||||
|
|
||||||
Name: "libdrm",
|
Name: "libdrm",
|
||||||
@@ -62,5 +84,182 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 1596,
|
ID: 1596,
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Toolchain) newLibva() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "2.23.0"
|
||||||
|
checksum = "UmF5tPyWIG_w5kiR3KFpoYbF7UUcaak5tyc-RhOheNTwQlLkPlifreFYCM9FQxbq"
|
||||||
|
)
|
||||||
|
return t.NewPackage("libva", version, newFromGitHub(
|
||||||
|
"intel/libva",
|
||||||
|
version,
|
||||||
|
checksum,
|
||||||
|
), nil, &MesonHelper{
|
||||||
|
Setup: []KV{
|
||||||
|
{"Dwith_x11", "yes"},
|
||||||
|
{"Dwith_glx", "yes"},
|
||||||
|
{"Dwith_wayland", "yes"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Libdrm,
|
||||||
|
LibXfixes,
|
||||||
|
Libglvnd,
|
||||||
|
Wayland,
|
||||||
|
KernelHeaders,
|
||||||
|
), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newLibva,
|
||||||
|
|
||||||
|
Name: "libva",
|
||||||
|
Description: "an implementation for VA-API (Video Acceleration API)",
|
||||||
|
Website: "https://01.org/vaapi",
|
||||||
|
|
||||||
|
Dependencies: P{
|
||||||
|
Libdrm,
|
||||||
|
LibXfixes,
|
||||||
|
Libglvnd,
|
||||||
|
Wayland,
|
||||||
|
},
|
||||||
|
|
||||||
|
ID: 1752,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Toolchain) newMesa() (pkg.Artifact, string) {
|
||||||
|
const (
|
||||||
|
version = "26.1.0"
|
||||||
|
checksum = "zU0fjqevySBaoi_5SLW3e2UffmGeBdxOuHmAHTH68n2hV-sjYoqg30koLqFXuk5y"
|
||||||
|
)
|
||||||
|
return t.NewPackage("mesa", version, newFromGitLab(
|
||||||
|
"gitlab.freedesktop.org",
|
||||||
|
"mesa/mesa",
|
||||||
|
"mesa-"+version,
|
||||||
|
checksum,
|
||||||
|
), nil, &MesonHelper{
|
||||||
|
Setup: []KV{
|
||||||
|
{"Dplatforms", "x11,wayland"},
|
||||||
|
{"Dvideo-codecs", "all"},
|
||||||
|
|
||||||
|
{"Dglvnd", "enabled"},
|
||||||
|
{"Dgbm", "enabled"},
|
||||||
|
|
||||||
|
{"Dgallium-drivers", strings.Join([]string{
|
||||||
|
"asahi", // Apple AGX
|
||||||
|
"crocus", // Intel legacy
|
||||||
|
"etnaviv", // Vivante GPU designs (mostly NXP/Marvell SoCs)
|
||||||
|
"freedreno", // Qualcomm Adreno (all Qualcomm SoCs)
|
||||||
|
"i915", // Intel extra legacy
|
||||||
|
"iris", // new Intel (Broadwell+)
|
||||||
|
"lima", // ARM Mali 4xx
|
||||||
|
"llvmpipe", // software renderer
|
||||||
|
"nouveau", // Nvidia
|
||||||
|
"panfrost", // ARM Mali Midgard and up (T/G series)
|
||||||
|
"r300", // very old AMD
|
||||||
|
"r600", // less old AMD
|
||||||
|
"radeonsi", // new AMD (GCN+)
|
||||||
|
"softpipe", // older software renderer
|
||||||
|
"svga", // VMWare virtualized GPU
|
||||||
|
"tegra", // Nvidia Tegra SoCs
|
||||||
|
"v3d", // Broadcom VC5 (Raspberry Pi 4)
|
||||||
|
"vc4", // Broadcom VC4 (Raspberry Pi 0-3)
|
||||||
|
"virgl", // QEMU virtualized GPU (aka VirGL)
|
||||||
|
"zink", // generic OpenGL over Vulkan, experimental
|
||||||
|
|
||||||
|
// d3d12: WSL emulated GPU (aka Dozen)
|
||||||
|
// ethosu: accelerator
|
||||||
|
// rocket: accelerator
|
||||||
|
}, ",")},
|
||||||
|
|
||||||
|
{"Dvulkan-drivers", strings.Join([]string{
|
||||||
|
"amd", // AMD (aka RADV)
|
||||||
|
"broadcom", // Broadcom VC5 (Raspberry Pi 4, aka V3D)
|
||||||
|
"freedreno", // Qualcomm Adreno (all Qualcomm SoCs)
|
||||||
|
"intel", // new Intel (aka ANV)
|
||||||
|
"intel_hasvk", // Intel Haswell/Broadwell, "legacy" Vulkan driver (https://www.phoronix.com/news/Intel-HasVK-Drop-Dead-Code)
|
||||||
|
"panfrost", // ARM Mali Midgard and up (T/G series)
|
||||||
|
"swrast", // software renderer (aka Lavapipe)
|
||||||
|
"virtio", // QEMU virtualized GPU (aka VirGL)
|
||||||
|
"imagination", // PowerVR Rogue
|
||||||
|
"asahi", // Apple AGX
|
||||||
|
"gfxstream", // Android virtualized GPU
|
||||||
|
|
||||||
|
// nouveau: Nouveau (aka NVK), requires rust
|
||||||
|
// microsoft-experimental: WSL virtualized GPU (aka DZN/Dozen)
|
||||||
|
// kosmickrisp: macOS-specific
|
||||||
|
}, ",")},
|
||||||
|
{"Dvulkan-layers", strings.Join([]string{
|
||||||
|
"device-select",
|
||||||
|
"intel-nullhw",
|
||||||
|
"overlay",
|
||||||
|
"screenshot",
|
||||||
|
"anti-lag",
|
||||||
|
"vram-report-limit",
|
||||||
|
}, ",")},
|
||||||
|
|
||||||
|
{"Dfreedreno-kmds", "msm,virtio"},
|
||||||
|
{"Damdgpu-virtio", "true"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
M4,
|
||||||
|
PythonPackaging,
|
||||||
|
PythonMako,
|
||||||
|
PythonPyYAML,
|
||||||
|
PythonPycparser,
|
||||||
|
Glslang,
|
||||||
|
SPIRVLLVMTranslator,
|
||||||
|
|
||||||
|
Zlib,
|
||||||
|
Zstd,
|
||||||
|
Gzip,
|
||||||
|
Ncurses,
|
||||||
|
Libglvnd,
|
||||||
|
Libexpat,
|
||||||
|
Libva,
|
||||||
|
Libdrm,
|
||||||
|
Elfutils,
|
||||||
|
Bison,
|
||||||
|
Flex,
|
||||||
|
LMSensors,
|
||||||
|
Libconfig,
|
||||||
|
LibdisplayInfo,
|
||||||
|
Wayland,
|
||||||
|
WaylandProtocols,
|
||||||
|
Libxshmfence,
|
||||||
|
LibXxf86vm,
|
||||||
|
LibXrandr,
|
||||||
|
LibxcbUtilKeysyms,
|
||||||
|
Libpng,
|
||||||
|
Libarchive,
|
||||||
|
KernelHeaders,
|
||||||
|
), version
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
native.MustRegister(&Artifact{
|
||||||
|
f: Toolchain.newMesa,
|
||||||
|
|
||||||
|
Name: "mesa",
|
||||||
|
Description: "open source implementations of OpenGL, OpenGL ES, Vulkan, OpenCL, and more",
|
||||||
|
Website: "https://mesa3d.org",
|
||||||
|
|
||||||
|
Dependencies: P{
|
||||||
|
Libdrm,
|
||||||
|
Elfutils,
|
||||||
|
LMSensors,
|
||||||
|
LibdisplayInfo,
|
||||||
|
Wayland,
|
||||||
|
Libxshmfence,
|
||||||
|
LibXxf86vm,
|
||||||
|
LibXrandr,
|
||||||
|
LibxcbUtilKeysyms,
|
||||||
|
Libpng,
|
||||||
|
},
|
||||||
|
|
||||||
|
ID: 1970,
|
||||||
|
|
||||||
|
latest: (*Versions).getStable,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ python3 ./run_project_tests.py \
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Meson] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newMeson,
|
f: Toolchain.newMeson,
|
||||||
|
|
||||||
Name: "meson",
|
Name: "meson",
|
||||||
@@ -67,7 +67,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 6472,
|
ID: 6472,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// MesonHelper is the [Meson] build system helper.
|
// MesonHelper is the [Meson] build system helper.
|
||||||
@@ -106,7 +106,7 @@ func (*MesonHelper) createDir() bool { return false }
|
|||||||
func (*MesonHelper) wantsDir() string { return `"$(mktemp -d)"` }
|
func (*MesonHelper) wantsDir() string { return `"$(mktemp -d)"` }
|
||||||
|
|
||||||
// script generates the cure script.
|
// script generates the cure script.
|
||||||
func (attr *MesonHelper) script(name string) string {
|
func (attr *MesonHelper) script(s *S, name string) string {
|
||||||
if attr == nil {
|
if attr == nil {
|
||||||
attr = new(MesonHelper)
|
attr = new(MesonHelper)
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ func (attr *MesonHelper) script(name string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var scriptTest string
|
var scriptTest string
|
||||||
if !attr.SkipTest && presetOpts&OptSkipCheck == 0 {
|
if !attr.SkipTest && s.opts&OptSkipCheck == 0 {
|
||||||
scriptTest = `
|
scriptTest = `
|
||||||
meson test \
|
meson test \
|
||||||
--print-errorlogs`
|
--print-errorlogs`
|
||||||
@@ -128,7 +128,7 @@ cd "$(mktemp -d)"
|
|||||||
meson setup \
|
meson setup \
|
||||||
` + strings.Join(slices.Collect(func(yield func(string) bool) {
|
` + strings.Join(slices.Collect(func(yield func(string) bool) {
|
||||||
for _, v := range append([]KV{
|
for _, v := range append([]KV{
|
||||||
{"wrap-mode", "nodownload"},
|
{"wrap-mode", "nofallback"},
|
||||||
{"prefix", "/system"},
|
{"prefix", "/system"},
|
||||||
{"buildtype", "release"},
|
{"buildtype", "release"},
|
||||||
}, attr.Setup...) {
|
}, attr.Setup...) {
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ func (t Toolchain) newMksh() (pkg.Artifact, string) {
|
|||||||
version = "59c"
|
version = "59c"
|
||||||
checksum = "0Zj-k4nXEu3IuJY4lvwD2OrC2t27GdZj8SPy4DoaeuBRH1padWb7oREpYgwY8JNq"
|
checksum = "0Zj-k4nXEu3IuJY4lvwD2OrC2t27GdZj8SPy4DoaeuBRH1padWb7oREpYgwY8JNq"
|
||||||
)
|
)
|
||||||
return t.New("mksh-"+version, 0, t.AppendPresets(nil,
|
scriptTest := "./test.sh -C regress:no-ctty\n"
|
||||||
|
if t.opts&OptSkipCheck != 0 {
|
||||||
|
scriptTest = ""
|
||||||
|
}
|
||||||
|
return t.New("mksh-"+version, 0, t.Append(nil,
|
||||||
Perl,
|
Perl,
|
||||||
Coreutils,
|
Coreutils,
|
||||||
), nil, []string{
|
), nil, []string{
|
||||||
@@ -18,8 +22,7 @@ cd "$(mktemp -d)"
|
|||||||
sh /usr/src/mksh/Build.sh -r
|
sh /usr/src/mksh/Build.sh -r
|
||||||
CPPFLAGS="${CPPFLAGS} -DMKSH_BINSHPOSIX -DMKSH_BINSHREDUCED" \
|
CPPFLAGS="${CPPFLAGS} -DMKSH_BINSHPOSIX -DMKSH_BINSHREDUCED" \
|
||||||
sh /usr/src/mksh/Build.sh -r -L
|
sh /usr/src/mksh/Build.sh -r -L
|
||||||
./test.sh -C regress:no-ctty
|
`+scriptTest+`
|
||||||
|
|
||||||
mkdir -p /work/system/bin/
|
mkdir -p /work/system/bin/
|
||||||
cp -v mksh /work/system/bin/
|
cp -v mksh /work/system/bin/
|
||||||
cp -v lksh /work/system/bin/sh
|
cp -v lksh /work/system/bin/sh
|
||||||
@@ -33,7 +36,7 @@ ln -vs ../system/bin/sh /work/bin/
|
|||||||
))), version
|
))), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Mksh] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newMksh,
|
f: Toolchain.newMksh,
|
||||||
|
|
||||||
Name: "mksh",
|
Name: "mksh",
|
||||||
@@ -41,5 +44,5 @@ func init() {
|
|||||||
Website: "https://www.mirbsd.org/mksh",
|
Website: "https://www.mirbsd.org/mksh",
|
||||||
|
|
||||||
ID: 5590,
|
ID: 5590,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func (t Toolchain) newMuslFts() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[MuslFts] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newMuslFts,
|
f: Toolchain.newMuslFts,
|
||||||
|
|
||||||
Name: "musl-fts",
|
Name: "musl-fts",
|
||||||
@@ -32,5 +32,5 @@ func init() {
|
|||||||
Website: "https://github.com/void-linux/musl-fts",
|
Website: "https://github.com/void-linux/musl-fts",
|
||||||
|
|
||||||
ID: 26980,
|
ID: 26980,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func (t Toolchain) newMuslObstack() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[MuslObstack] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newMuslObstack,
|
f: Toolchain.newMuslObstack,
|
||||||
|
|
||||||
Name: "musl-obstack",
|
Name: "musl-obstack",
|
||||||
@@ -32,5 +32,5 @@ func init() {
|
|||||||
Website: "https://github.com/void-linux/musl-obstack",
|
Website: "https://github.com/void-linux/musl-obstack",
|
||||||
|
|
||||||
ID: 146206,
|
ID: 146206,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-7
@@ -14,7 +14,7 @@ func (t Toolchain) newMusl(headers bool) (pkg.Artifact, string) {
|
|||||||
SkipCheck: true,
|
SkipCheck: true,
|
||||||
Script: `
|
Script: `
|
||||||
mkdir -p /work/system/bin
|
mkdir -p /work/system/bin
|
||||||
COMPAT_LINKER_NAME="ld-musl-` + linuxArch() + `.so.1"
|
COMPAT_LINKER_NAME="ld-musl-` + t.linuxArch() + `.so.1"
|
||||||
ln -vs ../lib/libc.so /work/system/bin/linker
|
ln -vs ../lib/libc.so /work/system/bin/linker
|
||||||
ln -vs ../lib/libc.so /work/system/bin/ldd
|
ln -vs ../lib/libc.so /work/system/bin/ldd
|
||||||
ln -vs libc.so "/work/system/lib/${COMPAT_LINKER_NAME}"
|
ln -vs libc.so "/work/system/lib/${COMPAT_LINKER_NAME}"
|
||||||
@@ -34,9 +34,9 @@ rmdir -v /work/lib
|
|||||||
}
|
}
|
||||||
|
|
||||||
env := []string{
|
env := []string{
|
||||||
"LDFLAGS=" + earlyLDFLAGS(false),
|
"LDFLAGS=" + t.earlyLDFLAGS(false),
|
||||||
}
|
}
|
||||||
if t.isStage0() {
|
if t.stage.isStage0() {
|
||||||
env = append(env,
|
env = append(env,
|
||||||
"CC=clang",
|
"CC=clang",
|
||||||
"AR=ar",
|
"AR=ar",
|
||||||
@@ -53,12 +53,29 @@ rmdir -v /work/lib
|
|||||||
Chmod: true,
|
Chmod: true,
|
||||||
|
|
||||||
Env: env,
|
Env: env,
|
||||||
|
|
||||||
|
Patches: []KV{
|
||||||
|
{"ldso-rosa", `diff --git a/ldso/dynlink.c b/ldso/dynlink.c
|
||||||
|
index 715948f4..c2fece68 100644
|
||||||
|
--- a/ldso/dynlink.c
|
||||||
|
+++ b/ldso/dynlink.c
|
||||||
|
@@ -1157,7 +1157,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
|
||||||
|
sys_path = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (!sys_path) sys_path = "/lib:/usr/local/lib:/usr/lib";
|
||||||
|
+ if (!sys_path) sys_path = "/system/lib:/system/lib/" LDSO_ARCH "-rosa-linux-musl:/lib:/usr/local/lib:/usr/lib";
|
||||||
|
fd = path_open(name, sys_path, buf, sizeof buf);
|
||||||
|
}
|
||||||
|
pathname = buf;
|
||||||
|
`},
|
||||||
|
},
|
||||||
}, &helper,
|
}, &helper,
|
||||||
Coreutils,
|
Coreutils,
|
||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Musl] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||||
return t.newMusl(false)
|
return t.newMusl(false)
|
||||||
},
|
},
|
||||||
@@ -68,14 +85,14 @@ func init() {
|
|||||||
Website: "https://musl.libc.org/",
|
Website: "https://musl.libc.org/",
|
||||||
|
|
||||||
ID: 11688,
|
ID: 11688,
|
||||||
}
|
})
|
||||||
|
|
||||||
artifactsM[muslHeaders] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||||
return t.newMusl(true)
|
return t.newMusl(true)
|
||||||
},
|
},
|
||||||
|
|
||||||
Name: "musl-headers",
|
Name: "musl-headers",
|
||||||
Description: "system installation of musl headers",
|
Description: "system installation of musl headers",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func (t Toolchain) newNcurses() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Ncurses] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newNcurses,
|
f: Toolchain.newNcurses,
|
||||||
|
|
||||||
Name: "ncurses",
|
Name: "ncurses",
|
||||||
@@ -34,5 +34,5 @@ func init() {
|
|||||||
Website: "https://invisible-island.net/ncurses/",
|
Website: "https://invisible-island.net/ncurses/",
|
||||||
|
|
||||||
ID: 373226,
|
ID: 373226,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ index d223ac2..a7878d0 100644
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libmnl] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibmnl,
|
f: Toolchain.newLibmnl,
|
||||||
|
|
||||||
Name: "libmnl",
|
Name: "libmnl",
|
||||||
@@ -47,7 +47,7 @@ func init() {
|
|||||||
Website: "https://www.netfilter.org/projects/libmnl/",
|
Website: "https://www.netfilter.org/projects/libmnl/",
|
||||||
|
|
||||||
ID: 1663,
|
ID: 1663,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newLibnftnl() (pkg.Artifact, string) {
|
func (t Toolchain) newLibnftnl() (pkg.Artifact, string) {
|
||||||
@@ -77,7 +77,7 @@ func (t Toolchain) newLibnftnl() (pkg.Artifact, string) {
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[Libnftnl] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newLibnftnl,
|
f: Toolchain.newLibnftnl,
|
||||||
|
|
||||||
Name: "libnftnl",
|
Name: "libnftnl",
|
||||||
@@ -89,7 +89,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 1681,
|
ID: 1681,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Toolchain) newIPTables() (pkg.Artifact, string) {
|
func (t Toolchain) newIPTables() (pkg.Artifact, string) {
|
||||||
@@ -131,7 +131,7 @@ chmod +w /etc/ && ln -s ../usr/src/iptables/etc/ethertypes /etc/
|
|||||||
), version
|
), version
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
artifactsM[IPTables] = Metadata{
|
native.MustRegister(&Artifact{
|
||||||
f: Toolchain.newIPTables,
|
f: Toolchain.newIPTables,
|
||||||
|
|
||||||
Name: "iptables",
|
Name: "iptables",
|
||||||
@@ -143,5 +143,5 @@ func init() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ID: 1394,
|
ID: 1394,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user