Skip to content

Commit e4396f9

Browse files
authored
feat(packer): add zstd compression support for extrafiles (#102)
1 parent 0f15665 commit e4396f9

3 files changed

Lines changed: 43 additions & 17 deletions

File tree

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/gokrazy/internal v0.0.0-20251208203110-3c1aa9087c82
1212
github.com/gokrazy/updater v0.0.0-20250705135802-db129c40879c
1313
github.com/google/renameio/v2 v2.0.0
14+
github.com/klauspost/compress v1.18.6
1415
github.com/mattn/go-isatty v0.0.20
1516
github.com/spf13/cobra v1.9.1
1617
github.com/spf13/pflag v1.0.6

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qA
1919
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
2020
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
2121
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
22+
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
23+
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
2224
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
2325
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
2426
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

internal/packer/packer.go

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package packer
44

55
import (
66
"archive/tar"
7+
"bufio"
78
"context"
89
"fmt"
910
"io"
@@ -18,6 +19,7 @@ import (
1819
"github.com/gokrazy/internal/deviceconfig"
1920
"github.com/gokrazy/tools/internal/log"
2021
"github.com/gokrazy/tools/packer"
22+
"github.com/klauspost/compress/zstd"
2123
)
2224

2325
type contextKey int
@@ -93,7 +95,22 @@ func (ae *archiveExtraction) extractArchive(path string) (time.Time, error) {
9395
return time.Time{}, err
9496
}
9597
defer f.Close()
96-
rd := tar.NewReader(f)
98+
99+
// Sniff zstd magic bytes (0x28 0xb5 0x2f 0xfd) to transparently handle both plain tar
100+
// and zstd-compressed tar archives.
101+
// Ref: https://datatracker.ietf.org/doc/html/rfc8878#section-3.1.1
102+
br := bufio.NewReader(f)
103+
var r io.Reader = br
104+
if magic, err := br.Peek(4); err == nil &&
105+
magic[0] == 0x28 && magic[1] == 0xb5 && magic[2] == 0x2f && magic[3] == 0xfd {
106+
zr, err := zstd.NewReader(br)
107+
if err != nil {
108+
return time.Time{}, fmt.Errorf("zstd %s: %v", path, err)
109+
}
110+
defer zr.Close()
111+
r = zr
112+
}
113+
rd := tar.NewReader(r)
97114

98115
var latestTime time.Time
99116
for {
@@ -147,17 +164,23 @@ func (ae *archiveExtraction) extractArchive(path string) (time.Time, error) {
147164
return latestTime, nil
148165
}
149166

167+
// extraFilesArchiveCandidates returns the list of archive paths to probe
168+
// for a given extrafiles directory, in priority order.
169+
func extraFilesArchiveCandidates(dir string) []string {
170+
targetArch := packer.TargetArch()
171+
return []string{
172+
dir + "_" + targetArch + ".tar.zst",
173+
dir + "_" + targetArch + ".tar",
174+
dir + ".tar.zst",
175+
dir + ".tar",
176+
}
177+
}
178+
150179
// findExtraFilesInDir probes for extrafiles .tar files (possibly with an
151180
// architecture suffix like _amd64), or whether dir itself exists.
152181
func findExtraFilesInDir(dir string) (string, error) {
153-
targetArch := packer.TargetArch()
154-
155182
var err error
156-
for _, p := range []string{
157-
dir + "_" + targetArch + ".tar",
158-
dir + ".tar",
159-
dir,
160-
} {
183+
for _, p := range append(extraFilesArchiveCandidates(dir), dir) {
161184
_, err = os.Stat(p)
162185
if err == nil {
163186
return p, nil
@@ -179,19 +202,19 @@ func addExtraFilesFromDir(pkg, dir string, fi *FileInfo) error {
179202
}
180203
ae.dirs["."] = fi // root
181204

182-
targetArch := packer.TargetArch()
183-
184-
effectivePath := dir + "_" + targetArch + ".tar"
185-
latestModTime, err := ae.extractArchive(effectivePath)
186-
if err != nil {
187-
return err
188-
}
189-
if len(fi.Dirents) == 0 {
190-
effectivePath = dir + ".tar"
205+
var (
206+
effectivePath string
207+
latestModTime time.Time
208+
err error
209+
)
210+
for _, effectivePath = range extraFilesArchiveCandidates(dir) {
191211
latestModTime, err = ae.extractArchive(effectivePath)
192212
if err != nil {
193213
return err
194214
}
215+
if len(fi.Dirents) > 0 {
216+
break
217+
}
195218
}
196219
if len(fi.Dirents) == 0 {
197220
effectivePath = dir

0 commit comments

Comments
 (0)