From db69dcf0be0c1be4e3187027fa4199538013e76d Mon Sep 17 00:00:00 2001 From: Ophestra Date: Thu, 4 Jun 2026 18:37:07 +0900 Subject: [PATCH] internal/pkg: remove tar built-in decompressor This is replaced by decompressArtifact and is no longer necessary. Signed-off-by: Ophestra --- internal/pkg/compress.go | 2 +- internal/pkg/ir_test.go | 34 +++++++--------- internal/pkg/tar.go | 79 +++++++------------------------------ internal/pkg/tar_test.go | 80 +++++++++----------------------------- internal/rosa/builtins.go | 15 ++++--- internal/rosa/etc.go | 2 +- internal/rosa/go.go | 4 +- internal/rosa/llvm_test.go | 2 +- internal/rosa/state.go | 24 ++++++++---- 9 files changed, 78 insertions(+), 164 deletions(-) diff --git a/internal/pkg/compress.go b/internal/pkg/compress.go index 310fe065..a683c816 100644 --- a/internal/pkg/compress.go +++ b/internal/pkg/compress.go @@ -36,7 +36,7 @@ type decompressArtifactNamed struct { var _ fmt.Stringer = new(decompressArtifactNamed) // NewDecompress returns a [FileArtifact] decompressing the supplied [Artifact]. -func NewDecompress(a Artifact, compress uint32) Artifact { +func NewDecompress(a Artifact, compress uint32) FileArtifact { da := decompressArtifact{a, compress} if s, ok := a.(fmt.Stringer); ok { if name := s.String(); name != "" { diff --git a/internal/pkg/ir_test.go b/internal/pkg/ir_test.go index d49d2c56..0cb4a6ef 100644 --- a/internal/pkg/ir_test.go +++ b/internal/pkg/ir_test.go @@ -27,16 +27,14 @@ func TestIRRoundtrip(t *testing.T) { pkg.Checksum(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))), )}, - {"http get tar", pkg.NewHTTPGetTar( + {"http get tar", pkg.NewTar(pkg.NewDecompress(pkg.NewHTTPGet( nil, "file:///testdata", pkg.Checksum(bytes.Repeat([]byte{0xff}, len(pkg.Checksum{}))), - pkg.TarBzip2, - )}, - {"http get tar unaligned", pkg.NewHTTPGetTar( + ), pkg.Bzip2))}, + {"http get tar unaligned", pkg.NewTar(pkg.NewHTTPGet( nil, "https://hakurei.app", pkg.Checksum(bytes.Repeat([]byte{0xfe}, len(pkg.Checksum{}))), - pkg.TarUncompressed, - )}, + ))}, {"exec offline", pkg.NewExec( "exec-offline", "", nil, 0, false, false, @@ -47,15 +45,13 @@ func TestIRRoundtrip(t *testing.T) { pkg.MustPath("/file", false, pkg.NewFile("file", []byte( "stub file", - ))), pkg.MustPath("/.hakurei", false, pkg.NewHTTPGetTar( + ))), pkg.MustPath("/.hakurei", false, pkg.NewTar(pkg.NewHTTPGet( nil, "file:///hakurei.tar", pkg.Checksum(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))), - pkg.TarUncompressed, - )), pkg.MustPath("/opt", false, pkg.NewHTTPGetTar( + ))), pkg.MustPath("/opt", false, pkg.NewTar(pkg.NewDecompress(pkg.NewHTTPGet( nil, "file:///testtool.tar.gz", pkg.Checksum(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))), - pkg.TarGzip, - )), + ), pkg.Gzip))), )}, {"exec net", pkg.NewExec( @@ -69,15 +65,13 @@ func TestIRRoundtrip(t *testing.T) { pkg.MustPath("/file", false, pkg.NewFile("file", []byte( "stub file", - ))), pkg.MustPath("/.hakurei", false, pkg.NewHTTPGetTar( + ))), pkg.MustPath("/.hakurei", false, pkg.NewTar(pkg.NewHTTPGet( nil, "file:///hakurei.tar", pkg.Checksum(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))), - pkg.TarUncompressed, - )), pkg.MustPath("/opt", false, pkg.NewHTTPGetTar( + ))), pkg.MustPath("/opt", false, pkg.NewTar(pkg.NewDecompress(pkg.NewHTTPGet( nil, "file:///testtool.tar.gz", pkg.Checksum(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))), - pkg.TarGzip, - )), + ), pkg.Gzip))), )}, {"exec measured", pkg.NewExec( @@ -91,15 +85,13 @@ func TestIRRoundtrip(t *testing.T) { pkg.MustPath("/file", false, pkg.NewFile("file", []byte( "stub file", - ))), pkg.MustPath("/.hakurei", false, pkg.NewHTTPGetTar( + ))), pkg.MustPath("/.hakurei", false, pkg.NewTar(pkg.NewHTTPGet( nil, "file:///hakurei.tar", pkg.Checksum(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))), - pkg.TarUncompressed, - )), pkg.MustPath("/opt", false, pkg.NewHTTPGetTar( + ))), pkg.MustPath("/opt", false, pkg.NewTar(pkg.NewDecompress(pkg.NewHTTPGet( nil, "file:///testtool.tar.gz", pkg.Checksum(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))), - pkg.TarGzip, - )), + ), pkg.Gzip))), )}, {"file anonymous", pkg.NewFile("", []byte{0})}, diff --git a/internal/pkg/tar.go b/internal/pkg/tar.go index 1c558d52..0b40e103 100644 --- a/internal/pkg/tar.go +++ b/internal/pkg/tar.go @@ -2,32 +2,18 @@ package pkg import ( "archive/tar" - "compress/bzip2" - "compress/gzip" "errors" "fmt" "io" "io/fs" - "net/http" "os" "path/filepath" ) -const ( - // TarUncompressed denotes an uncompressed tarball. - TarUncompressed = iota - // TarGzip denotes a tarball compressed via [gzip]. - TarGzip - // TarBzip2 denotes a tarball compressed via [bzip2]. - TarBzip2 -) - // A tarArtifact is an [Artifact] unpacking a tarball backed by a [FileArtifact]. type tarArtifact struct { // Caller-supplied backing tarball. f Artifact - // Compression on top of the tarball. - compression uint32 } // tarArtifactNamed embeds tarArtifact for a [fmt.Stringer] tarball. @@ -42,10 +28,10 @@ var _ fmt.Stringer = new(tarArtifactNamed) // String returns the name of the underlying [Artifact] suffixed with unpack. func (a *tarArtifactNamed) String() string { return a.name + "-unpack" } -// NewTar returns a new [Artifact] backed by the supplied [Artifact] and -// compression method. The source [Artifact] must be a [FileArtifact]. -func NewTar(a Artifact, compression uint32) Artifact { - ta := tarArtifact{a, compression} +// NewTar returns a new [Artifact] unpacking the tar stream produced by the +// backing [Artifact]. The source [Artifact] must be a [FileArtifact]. +func NewTar(a Artifact) Artifact { + ta := tarArtifact{a} if s, ok := a.(fmt.Stringer); ok { if name := s.String(); name != "" { return &tarArtifactNamed{ta, name} @@ -54,25 +40,15 @@ func NewTar(a Artifact, compression uint32) Artifact { return &ta } -// NewHTTPGetTar is abbreviation for NewHTTPGet passed to NewTar. -func NewHTTPGetTar( - hc *http.Client, - url string, - checksum Checksum, - compression uint32, -) Artifact { - return NewTar(NewHTTPGet(hc, url, checksum), compression) -} - // Kind returns the hardcoded [Kind] constant. func (a *tarArtifact) Kind() Kind { return KindTar } -// Params writes compression encoded in little endian. -func (a *tarArtifact) Params(ctx *IContext) { ctx.WriteUint32(a.compression) } +// Params is a noop. +func (a *tarArtifact) Params(*IContext) {} func init() { register(KindTar, func(r *IRReader) Artifact { - a := NewTar(r.Next(), r.ReadUint32()) + a := NewTar(r.Next()) if _, ok := r.Finalise(); ok { panic(ErrUnexpectedChecksum) } @@ -98,42 +74,17 @@ func (e DisallowedTypeflagError) Error() string { // Cure cures the [Artifact], producing a directory located at work. func (a *tarArtifact) Cure(t *TContext) (err error) { - var tr io.ReadCloser - if tr, err = t.Open(a.f); err != nil { + var r io.ReadCloser + if r, err = t.Open(a.f); err != nil { return } - defer func(f io.ReadCloser) { - if err == nil { - err = tr.Close() - } - - closeErr := f.Close() + defer func() { + closeErr := r.Close() if err == nil { err = closeErr } - }(tr) - br := t.cache.getReader(tr) - defer t.cache.putReader(br) - tr = io.NopCloser(br) - - switch a.compression { - case TarUncompressed: - break - - case TarGzip: - if tr, err = gzip.NewReader(tr); err != nil { - return - } - break - - case TarBzip2: - tr = io.NopCloser(bzip2.NewReader(tr)) - break - - default: - return os.ErrInvalid - } + }() type dirTargetPerm struct { path string @@ -156,8 +107,8 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { }() var header *tar.Header - r := tar.NewReader(tr) - for header, err = r.Next(); err == nil; header, err = r.Next() { + tr := tar.NewReader(r) + for header, err = tr.Next(); err == nil; header, err = tr.Next() { typeflag := header.Typeflag if typeflag == 0 { if len(header.Name) > 0 && header.Name[len(header.Name)-1] == '/' { @@ -183,7 +134,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { ); err != nil { return } - if _, err = io.Copy(f, r); err != nil { + if _, err = io.Copy(f, tr); err != nil { _ = f.Close() return } else if err = f.Close(); err != nil { diff --git a/internal/pkg/tar_test.go b/internal/pkg/tar_test.go index c7f8fca5..29ddcdad 100644 --- a/internal/pkg/tar_test.go +++ b/internal/pkg/tar_test.go @@ -80,8 +80,8 @@ func TestTar(t *testing.T) { "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)}, + "identifier/T68YqeEW5moiwVe4J0wPvjERgyMUd4k_cKKxTcQx6AXqZaQAuuryu-Iv-qxDV6-T": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)}, + "identifier/WbWIIUGl6bqDBsjU-UB69JqOWLjG5waiUJBUBGeeRp3V7FBbwaBe3sG1qm7DlPSk": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)}, "substitute": {Mode: fs.ModeDir | 0700}, @@ -104,8 +104,8 @@ func TestTar(t *testing.T) { "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)}, + "identifier/WbWIIUGl6bqDBsjU-UB69JqOWLjG5waiUJBUBGeeRp3V7FBbwaBe3sG1qm7DlPSk": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)}, + "identifier/e3BECw_x_vDyTvj2P48MJVgwpgALeXQ90Ye2Y8gr6SwIPtMup6SR2LVcCTDRGpVi": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)}, "substitute": {Mode: fs.ModeDir | 0700}, @@ -156,49 +156,6 @@ func checkTarHTTP( "testdata": {Data: []byte(testdata), Mode: 0400}, })) - wantIdent := func() pkg.ID { - h := sha512.New384() - - // kind uint64 - h.Write([]byte{byte(pkg.KindTar), 0, 0, 0, 0, 0, 0, 0}) - // deps_sz uint64 - h.Write([]byte{1, 0, 0, 0, 0, 0, 0, 0}) - - // kind uint64 - h.Write([]byte{byte(pkg.KindHTTPGet), 0, 0, 0, 0, 0, 0, 0}) - // ident ID - h0 := sha512.New384() - // kind uint64 - h0.Write([]byte{byte(pkg.KindHTTPGet), 0, 0, 0, 0, 0, 0, 0}) - // deps_sz uint64 - h0.Write([]byte{0, 0, 0, 0, 0, 0, 0, 0}) - // url string - h0.Write([]byte{byte(pkg.IRKindString), 0, 0, 0}) - h0.Write([]byte{0x10, 0, 0, 0}) - h0.Write([]byte("file:///testdata")) - // end(KnownChecksum) - h0.Write([]byte{byte(pkg.IRKindEnd), 0, 0, 0}) - h0.Write([]byte{byte(pkg.IREndKnownChecksum), 0, 0, 0}) - // checksum Checksum - h0.Write(testdataChecksum[:]) - h.Write(h0.Sum(nil)) - // compression uint32 - h.Write([]byte{byte(pkg.IRKindUint32), 0, 0, 0}) - h.Write([]byte{pkg.TarGzip, 0, 0, 0}) - // end - h.Write([]byte{byte(pkg.IRKindEnd), 0, 0, 0}) - h.Write([]byte{0, 0, 0, 0}) - - return pkg.ID(h.Sum(nil)) - }() - - a := pkg.NewHTTPGetTar( - &client, - "file:///testdata", - testdataChecksum, - pkg.TarGzip, - ) - tarDir := stubArtifact{ kind: pkg.KindExec, params: []byte("directory containing a single regular file"), @@ -251,27 +208,28 @@ func checkTarHTTP( defer newDestroyArtifactFunc(&tarDirType)(t, base, c) cureMany(t, c, []cureStep{ - {"file", a, base.Append( - "identifier", - pkg.Encode(wantIdent), - ), want, nil}, + {"file", pkg.NewTar(pkg.NewDecompress(pkg.NewHTTPGet( + &client, + "file:///testdata", + testdataChecksum, + ), pkg.Gzip)), ignorePathname, want, nil}, - {"directory", pkg.NewTar( + {"directory", pkg.NewTar(pkg.NewDecompress( &tarDir, - pkg.TarGzip, - ), ignorePathname, want, nil}, + pkg.Gzip, + )), ignorePathname, want, nil}, - {"multiple entries", pkg.NewTar( + {"multiple entries", pkg.NewTar(pkg.NewDecompress( &tarDirMulti, - pkg.TarGzip, - ), nil, nil, errors.New( + pkg.Gzip, + )), nil, nil, errors.New( "input directory does not contain a single regular file", )}, - {"bad type", pkg.NewTar( + {"bad type", pkg.NewTar(pkg.NewDecompress( &tarDirType, - pkg.TarGzip, - ), nil, nil, errors.New( + pkg.Gzip, + )), nil, nil, errors.New( "input directory does not contain a single regular file", )}, @@ -281,6 +239,6 @@ func checkTarHTTP( cure: func(t *pkg.TContext) error { return stub.UniqueError(0xcafe) }, - }, pkg.TarGzip), nil, nil, stub.UniqueError(0xcafe)}, + }), nil, nil, stub.UniqueError(0xcafe)}, }) } diff --git a/internal/rosa/builtins.go b/internal/rosa/builtins.go index b0ec65b1..55ac0cf1 100644 --- a/internal/rosa/builtins.go +++ b/internal/rosa/builtins.go @@ -21,8 +21,13 @@ const ( ) // newTar wraps [pkg.NewHTTPGetTar] with a simpler function signature. -func newTar(url, checksum string, compression uint32) pkg.Artifact { - return pkg.NewHTTPGetTar(nil, url, mustDecode(checksum), compression) +func newTar(url, checksum string, compress uint32) pkg.Artifact { + return pkg.NewTar( + pkg.NewDecompress( + pkg.NewHTTPGet(nil, url, mustDecode(checksum)), + compress, + ), + ) } // newFromCPAN is a helper for downloading release from CPAN. @@ -32,7 +37,7 @@ func newFromCPAN(author, name, version, checksum string) pkg.Artifact { author[:1]+"/"+author[:2]+"/"+author+"/"+ name+"-"+version+".tar.gz", checksum, - pkg.TarGzip, + pkg.Gzip, ) } @@ -43,7 +48,7 @@ func newFromGitLab(domain, suffix, ref, checksum string) pkg.Artifact { ref+"/"+path.Base(suffix)+"-"+ strings.ReplaceAll(ref, "/", "-")+".tar.bz2", checksum, - pkg.TarBzip2, + pkg.Bzip2, ) } @@ -53,7 +58,7 @@ func newFromGitHub(suffix, tag, checksum string) pkg.Artifact { "https://github.com/"+suffix+ "/archive/refs/tags/"+tag+".tar.gz", checksum, - pkg.TarGzip, + pkg.Gzip, ) } diff --git a/internal/rosa/etc.go b/internal/rosa/etc.go index 7b5542db..4ffebdba 100644 --- a/internal/rosa/etc.go +++ b/internal/rosa/etc.go @@ -140,7 +140,7 @@ func newIANAEtc() pkg.Artifact { version, "iana-etc-"+version+".tar.gz", checksum, - pkg.TarGzip, + pkg.Gzip, ) } diff --git a/internal/rosa/go.go b/internal/rosa/go.go index fbee360b..26b99929 100644 --- a/internal/rosa/go.go +++ b/internal/rosa/go.go @@ -16,7 +16,7 @@ func (t Toolchain) newGo( return t.NewPackage("go", version, newTar( "https://go.dev/dl/go"+version+".src.tar.gz", checksum, - pkg.TarGzip, + pkg.Gzip, ), &PackageAttr{ EnterSource: true, Env: slices.Concat([]string{ @@ -79,7 +79,7 @@ func init() { bootstrapEarly = []pkg.Artifact{t.NewPackage("go", "1.4-bootstrap", newTar( "https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz", "8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23", - pkg.TarGzip, + pkg.Gzip, ), &PackageAttr{ EnterSource: true, Env: []string{ diff --git a/internal/rosa/llvm_test.go b/internal/rosa/llvm_test.go index de63cb6b..48adcf20 100644 --- a/internal/rosa/llvm_test.go +++ b/internal/rosa/llvm_test.go @@ -8,7 +8,7 @@ import ( ) func TestLLVMInputs(t *testing.T) { - const wantInputCount = 688 + const wantInputCount = 857 _, llvm := rosa.Native().Std().MustLoad(rosa.H("llvm")) var n int diff --git a/internal/rosa/state.go b/internal/rosa/state.go index d55610fe..feb06f82 100644 --- a/internal/rosa/state.go +++ b/internal/rosa/state.go @@ -433,10 +433,11 @@ func (s *S) getFrame() azalea.Frame { identDefault := k("default") identArch := unique.Make(azalea.Ident(s.arch)) + const compressOffset = 1 << 8 enumCompress := map[unique.Handle[azalea.Ident]]any{ - k("uncompressed"): uint32(pkg.TarUncompressed), - k("gzip"): uint32(pkg.TarGzip), - k("bzip2"): uint32(pkg.TarBzip2), + k("uncompressed"): 0, + k("gzip"): pkg.Gzip + compressOffset, + k("bzip2"): pkg.Bzip2 + compressOffset, } s.frame.Val = map[unique.Handle[azalea.Ident]]any{ @@ -609,15 +610,19 @@ func (s *S) getFrame() azalea.Frame { args azalea.FArgs, ) (v any, set bool, err error) { var url, checksum string - var compress uint32 + var _compress int if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ k("url"): &url, k("checksum"): &checksum, - k("compress"): &compress, + k("compress"): &_compress, }); err != nil { return } - v = pkg.NewHTTPGetTar(nil, url, mustDecode(checksum), compress) + f := pkg.NewHTTPGet(nil, url, mustDecode(checksum)) + if _compress != 0 { + f = pkg.NewDecompress(f, uint32(_compress-compressOffset)) + } + v = pkg.NewTar(f) set = true return }, V: enumCompress}, @@ -744,7 +749,10 @@ func (s *S) getFrame() azalea.Frame { v = newFromGitHubRelease(suffix, tag, name, checksum, compress) set = true return - }, V: enumCompress}, + }, V: map[unique.Handle[azalea.Ident]]any{ + k("gzip"): uint32(pkg.Gzip), + k("bzip2"): uint32(pkg.Bzip2), + }}, // high-level helpers @@ -1275,7 +1283,7 @@ func (s *S) SetSource(fsys fs.FS) error { Description: "hakurei source tree (current)", Version: "1.0.0-CURRENT", Exclude: true, - }, pkg.NewTar(a, pkg.TarGzip) + }, pkg.NewTar(pkg.NewDecompress(a, pkg.Gzip)) }), ) s.DropCaches(s.Arch(), s.Flags())