Skip to content

Commit 7edfbb3

Browse files
Use in-memory control data everywhere (#1986)
Currently, apko sometimes uses an in-memory version of the control file and sometimes reads the data from the control file itself. This makes all of those instances use the cached data.
1 parent fbb7048 commit 7edfbb3

File tree

4 files changed

+48
-77
lines changed

4 files changed

+48
-77
lines changed

pkg/apk/apk/implementation.go

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,13 +1224,7 @@ func (a *APK) cachedPackage(ctx context.Context, pkg InstallablePackage, cacheDi
12241224
exp.SignatureHash = signatureHash[:]
12251225
}
12261226

1227-
f, err := os.Open(ctl)
1228-
if err != nil {
1229-
return nil, err
1230-
}
1231-
defer f.Close()
1232-
1233-
datahash, err := a.datahash(f)
1227+
datahash, err := a.datahash(exp.ControlFS)
12341228
if err != nil {
12351229
return nil, fmt.Errorf("datahash for %s: %w", pkg, err)
12361230
}
@@ -1497,29 +1491,26 @@ func (a *APK) installPackage(ctx context.Context, pkg *Package, expanded *expand
14971491
}
14981492

14991493
// update the scripts.tar
1500-
controlData, err := os.Open(expanded.ControlFile)
1494+
controlData, err := expanded.ControlData()
15011495
if err != nil {
15021496
return nil, fmt.Errorf("opening control file %q: %w", expanded.ControlFile, err)
15031497
}
1504-
defer controlData.Close()
15051498

1506-
if err := a.updateScriptsTar(pkg, controlData, sourceDateEpoch); err != nil {
1499+
controlTar := bytes.NewReader(controlData)
1500+
if err := a.updateScriptsTar(pkg, controlTar, sourceDateEpoch); err != nil {
15071501
return nil, fmt.Errorf("unable to update scripts.tar for pkg %s: %w", pkg.Name, err)
15081502
}
15091503

15101504
// update the triggers
1511-
if _, err := controlData.Seek(0, 0); err != nil {
1512-
return nil, fmt.Errorf("unable to seek to start of control data for pkg %s: %w", pkg.Name, err)
1513-
}
1514-
if err := a.updateTriggers(pkg, controlData); err != nil {
1505+
if err := a.updateTriggers(pkg, expanded.ControlFS); err != nil {
15151506
return nil, fmt.Errorf("unable to update triggers for pkg %s: %w", pkg.Name, err)
15161507
}
15171508

15181509
return installedFiles, nil
15191510
}
15201511

1521-
func (a *APK) datahash(controlTarGz io.Reader) (string, error) {
1522-
values, err := a.controlValue(controlTarGz, "datahash")
1512+
func (a *APK) datahash(controlFS fs.FS) (string, error) {
1513+
values, err := a.controlValue(controlFS, "datahash")
15231514
if err != nil {
15241515
return "", fmt.Errorf("reading datahash from control: %w", err)
15251516
}

pkg/apk/apk/installed.go

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,13 @@ import (
2222
"errors"
2323
"fmt"
2424
"io"
25+
"io/fs"
2526
"os"
2627
"path/filepath"
2728
"sort"
2829
"strconv"
2930
"strings"
3031
"time"
31-
32-
"github.com/klauspost/compress/gzip"
3332
)
3433

3534
type InstalledPackage struct {
@@ -121,13 +120,8 @@ func (a *APK) isInstalledPackage(pkg string) (bool, error) {
121120
}
122121

123122
// updateScriptsTar insert the scripts into the tarball
124-
func (a *APK) updateScriptsTar(pkg *Package, controlTarGz io.Reader, sourceDateEpoch *time.Time) error {
125-
gz, err := gzip.NewReader(controlTarGz)
126-
if err != nil {
127-
return fmt.Errorf("unable to gunzip control tar.gz file: %w", err)
128-
}
129-
defer gz.Close()
130-
tr := tar.NewReader(gz)
123+
func (a *APK) updateScriptsTar(pkg *Package, controlData io.Reader, sourceDateEpoch *time.Time) error {
124+
tr := tar.NewReader(controlData)
131125
fi, err := a.fs.Stat(scriptsFilePath)
132126
if err != nil {
133127
return fmt.Errorf("unable to stat scripts file: %w", err)
@@ -197,14 +191,8 @@ func (a *APK) readScriptsTar() (io.ReadCloser, error) {
197191
}
198192

199193
// TODO: We should probably parse control section on the first pass and reuse it.
200-
func (a *APK) controlValue(controlTarGz io.Reader, want string) ([]string, error) {
201-
gz, err := gzip.NewReader(controlTarGz)
202-
if err != nil {
203-
return nil, fmt.Errorf("unable to gunzip control tar file: %w", err)
204-
}
205-
defer gz.Close()
206-
207-
mapping, err := controlValue(gz, want)
194+
func (a *APK) controlValue(controlFs fs.FS, want string) ([]string, error) {
195+
mapping, err := controlValue(controlFs, want)
208196
if err != nil {
209197
return nil, err
210198
}
@@ -217,14 +205,14 @@ func (a *APK) controlValue(controlTarGz io.Reader, want string) ([]string, error
217205
}
218206

219207
// updateTriggers insert the triggers into the triggers file
220-
func (a *APK) updateTriggers(pkg *Package, controlTarGz io.Reader) error {
208+
func (a *APK) updateTriggers(pkg *Package, controlFs fs.FS) error {
221209
triggers, err := a.fs.OpenFile(triggersFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0)
222210
if err != nil {
223211
return fmt.Errorf("unable to open triggers file %s: %w", triggersFilePath, err)
224212
}
225213
defer triggers.Close()
226214

227-
values, err := a.controlValue(controlTarGz, "triggers")
215+
values, err := a.controlValue(controlFs, "triggers")
228216
if err != nil {
229217
return fmt.Errorf("updating triggers for %s: %w", pkg.Name, err)
230218
}

pkg/apk/apk/installed_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"github.com/stretchr/testify/assert"
3636
"github.com/stretchr/testify/require"
3737

38+
"chainguard.dev/apko/internal/tarfs"
3839
"chainguard.dev/apko/pkg/apk/expandapk"
3940
)
4041

@@ -361,8 +362,7 @@ func TestUpdateScriptsTar(t *testing.T) {
361362
".post-upgrade": []byte("echo 'post upgrade'"),
362363
}
363364
var buf bytes.Buffer
364-
gw := gzip.NewWriter(&buf)
365-
tw := tar.NewWriter(gw)
365+
tw := tar.NewWriter(&buf)
366366
for name, content := range scripts {
367367
_ = tw.WriteHeader(&tar.Header{
368368
Name: name,
@@ -379,7 +379,6 @@ func TestUpdateScriptsTar(t *testing.T) {
379379
})
380380
_, _ = tw.Write([]byte(pkginfo))
381381
tw.Close()
382-
gw.Close()
383382

384383
// pass the controltargz to updateScriptsTar
385384
r := bytes.NewReader(buf.Bytes())
@@ -450,8 +449,7 @@ func TestUpdateTriggers(t *testing.T) {
450449
".PKGINFO": []byte(pkginfo),
451450
}
452451
var buf bytes.Buffer
453-
gw := gzip.NewWriter(&buf)
454-
tw := tar.NewWriter(gw)
452+
tw := tar.NewWriter(&buf)
455453
for name, content := range scripts {
456454
_ = tw.WriteHeader(&tar.Header{
457455
Name: name,
@@ -461,11 +459,12 @@ func TestUpdateTriggers(t *testing.T) {
461459
_, _ = tw.Write(content)
462460
}
463461
tw.Close()
464-
gw.Close()
465462

466463
// pass the controltargz to updateScriptsTar
467464
r := bytes.NewReader(buf.Bytes())
468-
err = a.updateTriggers(pkg, r)
465+
fs, err := tarfs.New(r, int64(buf.Len()))
466+
require.NoError(t, err, "unable to create tarfs: %v", err)
467+
err = a.updateTriggers(pkg, fs)
469468
require.NoError(t, err, "unable to update triggers: %v", err)
470469

471470
// successfully wrote it; not check that it was written correctly

pkg/apk/apk/util.go

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
package apk
1616

1717
import (
18-
"archive/tar"
1918
"errors"
2019
"fmt"
2120
"io"
21+
"io/fs"
2222
"slices"
2323
"strings"
2424
)
@@ -38,48 +38,41 @@ func uniqify[T comparable](s []T) []T {
3838
return uniq
3939
}
4040

41-
func controlValue(controlTar io.Reader, want ...string) (map[string][]string, error) {
42-
tr := tar.NewReader(controlTar)
43-
for {
44-
header, err := tr.Next()
45-
if errors.Is(err, io.EOF) {
41+
func controlValue(controlFs fs.FS, want ...string) (map[string][]string, error) {
42+
f, err := controlFs.Open(".PKGINFO")
43+
if err != nil {
44+
if errors.Is(err, fs.ErrNotExist) {
4645
return nil, fmt.Errorf("control file not found")
4746
}
48-
if err != nil {
49-
return nil, err
50-
}
47+
return nil, fmt.Errorf("opening .PKGINFO: %w", err)
48+
}
49+
defer f.Close()
5150

52-
// ignore .PKGINFO as it is not a script
53-
if header.Name != ".PKGINFO" {
51+
b, err := io.ReadAll(f)
52+
if err != nil {
53+
return nil, fmt.Errorf("unable to read .PKGINFO from control tar.gz file: %w", err)
54+
}
55+
mapping := map[string][]string{}
56+
lines := strings.SplitSeq(string(b), "\n")
57+
for line := range lines {
58+
parts := strings.Split(line, "=")
59+
if len(parts) != 2 {
5460
continue
5561
}
56-
57-
b, err := io.ReadAll(tr)
58-
if err != nil {
59-
return nil, fmt.Errorf("unable to read .PKGINFO from control tar.gz file: %w", err)
62+
key := strings.TrimSpace(parts[0])
63+
if !slices.Contains(want, key) {
64+
continue
6065
}
61-
mapping := map[string][]string{}
62-
lines := strings.SplitSeq(string(b), "\n")
63-
for line := range lines {
64-
parts := strings.Split(line, "=")
65-
if len(parts) != 2 {
66-
continue
67-
}
68-
key := strings.TrimSpace(parts[0])
69-
if !slices.Contains(want, key) {
70-
continue
71-
}
7266

73-
values, ok := mapping[key]
74-
if !ok {
75-
values = []string{}
76-
}
67+
values, ok := mapping[key]
68+
if !ok {
69+
values = []string{}
70+
}
7771

78-
value := strings.TrimSpace(parts[1])
79-
values = append(values, value)
72+
value := strings.TrimSpace(parts[1])
73+
values = append(values, value)
8074

81-
mapping[key] = values
82-
}
83-
return mapping, nil
75+
mapping[key] = values
8476
}
77+
return mapping, nil
8578
}

0 commit comments

Comments
 (0)