Skip to content

Commit ff469b3

Browse files
committed
Refactor path manipulation around named types
1 parent 4308912 commit ff469b3

File tree

2 files changed

+62
-41
lines changed

2 files changed

+62
-41
lines changed

aptblob.go

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import (
3535
"zombiezen.com/go/aptblob/internal/deb"
3636
)
3737

38-
func cmdInit(ctx context.Context, bucket *blob.Bucket, dist string, keyID string) error {
38+
func cmdInit(ctx context.Context, bucket *blob.Bucket, dist distribution, keyID string) error {
3939
fmt.Fprintln(os.Stderr, "aptblob: reading Release from stdin...")
4040
newRelease, err := deb.ParseReleaseIndex(os.Stdin)
4141
if err != nil {
@@ -58,8 +58,8 @@ func cmdInit(ctx context.Context, bucket *blob.Bucket, dist string, keyID string
5858
return nil
5959
}
6060

61-
func downloadReleaseIndex(ctx context.Context, bucket *blob.Bucket, dist string) (deb.Paragraph, error) {
62-
key := releaseIndexPath(dist)
61+
func downloadReleaseIndex(ctx context.Context, bucket *blob.Bucket, dist distribution) (deb.Paragraph, error) {
62+
key := dist.indexPath()
6363
blob, err := bucket.NewReader(ctx, key, nil)
6464
if err != nil {
6565
if gcerrors.Code(err) == gcerrors.NotFound {
@@ -77,7 +77,7 @@ func downloadReleaseIndex(ctx context.Context, bucket *blob.Bucket, dist string)
7777

7878
const componentName = "main"
7979

80-
func cmdUpload(ctx context.Context, bucket *blob.Bucket, dist string, keyID string, debPath string) error {
80+
func cmdUpload(ctx context.Context, bucket *blob.Bucket, dist distribution, keyID string, debPath string) error {
8181
// Extract package metadata.
8282
debFile, err := os.Open(debPath)
8383
if err != nil {
@@ -96,11 +96,12 @@ func cmdUpload(ctx context.Context, bucket *blob.Bucket, dist string, keyID stri
9696
}
9797
}
9898
newPackage := p.Paragraph()
99+
promotePackageField(newPackage)
99100
arch := newPackage.Get("Architecture")
100101
if arch == "" {
101102
return fmt.Errorf("%s: no Architecture", debPath)
102103
}
103-
poolPath := "pool/" + filepath.Base(debPath)
104+
poolPath := poolPath(filepath.Base(debPath))
104105
packageHashes, err := upload(ctx, bucket, poolPath, "application/vnd.debian.binary-package", "immutable", debFile)
105106
if err != nil {
106107
return err
@@ -113,24 +114,25 @@ func cmdUpload(ctx context.Context, bucket *blob.Bucket, dist string, keyID stri
113114

114115
// List existing packages.
115116
var packages []deb.Paragraph
116-
if packagesReader, err := bucket.NewReader(ctx, binaryPackagesIndexPath(dist, componentName, arch), nil); err == nil {
117+
comp := component{dist: dist, name: componentName}
118+
if packagesReader, err := bucket.NewReader(ctx, comp.binaryIndexPath(arch), nil); err == nil {
117119
p := deb.NewParser(packagesReader)
118120
p.Fields = deb.ControlFields
119121
for p.Next() {
120122
packages = append(packages, p.Paragraph())
121123
}
122124
packagesReader.Close()
123125
if err := p.Err(); err != nil {
124-
return fmt.Errorf("%s: %w", binaryPackagesIndexPath(dist, componentName, arch), err)
126+
return fmt.Errorf("%s: %w", comp.binaryIndexPath(arch), err)
125127
}
126128
} else if gcerrors.Code(err) != gcerrors.NotFound {
127129
return err
128130
}
129131

130132
// Append package to index.
131133
packages = append(packages, newPackage)
132-
packageIndexHashes, packageIndexGzipHashes, err := uploadPackageIndex(
133-
ctx, bucket, dist, componentName, arch, packages)
134+
packageIndexHashes, packageIndexGzipHashes, err :=
135+
uploadPackageIndex(ctx, bucket, comp, arch, packages)
134136
if err != nil {
135137
return err
136138
}
@@ -140,14 +142,8 @@ func cmdUpload(ctx context.Context, bucket *blob.Bucket, dist string, keyID stri
140142
if err != nil {
141143
return err
142144
}
143-
packagesDistPath := strings.TrimPrefix(
144-
binaryPackagesIndexPath(dist, componentName, arch),
145-
distDirPath(dist)+"/",
146-
)
147-
packagesGzipDistPath := strings.TrimPrefix(
148-
binaryPackagesGzipIndexPath(dist, componentName, arch),
149-
distDirPath(dist)+"/",
150-
)
145+
packagesDistPath := strings.TrimPrefix(comp.binaryIndexPath(arch), dist.dir()+"/")
146+
packagesGzipDistPath := strings.TrimPrefix(comp.binaryIndexGzipPath(arch), dist.dir()+"/")
151147
err = updateSignature(&release, "MD5Sum",
152148
deb.IndexSignature{
153149
Filename: packagesDistPath,
@@ -161,7 +157,7 @@ func cmdUpload(ctx context.Context, bucket *blob.Bucket, dist string, keyID stri
161157
},
162158
)
163159
if err != nil {
164-
return fmt.Errorf("%s: %w", releaseIndexPath(dist), err)
160+
return fmt.Errorf("%s: %w", dist.indexPath(), err)
165161
}
166162
err = updateSignature(&release, "SHA1",
167163
deb.IndexSignature{
@@ -176,7 +172,7 @@ func cmdUpload(ctx context.Context, bucket *blob.Bucket, dist string, keyID stri
176172
},
177173
)
178174
if err != nil {
179-
return fmt.Errorf("%s: %w", releaseIndexPath(dist), err)
175+
return fmt.Errorf("%s: %w", dist.indexPath(), err)
180176
}
181177
err = updateSignature(&release, "SHA256",
182178
deb.IndexSignature{
@@ -191,7 +187,7 @@ func cmdUpload(ctx context.Context, bucket *blob.Bucket, dist string, keyID stri
191187
},
192188
)
193189
if err != nil {
194-
return fmt.Errorf("%s: %w", releaseIndexPath(dist), err)
190+
return fmt.Errorf("%s: %w", dist.indexPath(), err)
195191
}
196192
if err := uploadReleaseIndex(ctx, bucket, dist, release, keyID); err != nil {
197193
return err
@@ -238,6 +234,20 @@ func updateSignature(para *deb.Paragraph, key string, newSigs ...deb.IndexSignat
238234
return nil
239235
}
240236

237+
// promotePackageField ensures the Package field is the first in the paragraph.
238+
// It modifies the paragraph in-place.
239+
//
240+
// This is necessary for Packages and Sources paragraphs to be spec-compliant.
241+
func promotePackageField(para deb.Paragraph) {
242+
for i, f := range para {
243+
if f.Name == "Package" {
244+
copy(para[1:], para[:i])
245+
para[0] = f
246+
return
247+
}
248+
}
249+
}
250+
241251
func main() {
242252
rootCmd := &cobra.Command{
243253
Use: "aptblob",
@@ -265,7 +275,7 @@ func main() {
265275
if err != nil {
266276
return err
267277
}
268-
return cmdInit(cmd.Context(), bucket, args[1], *keyID)
278+
return cmdInit(cmd.Context(), bucket, distribution(args[1]), *keyID)
269279
},
270280
})
271281
rootCmd.AddCommand(&cobra.Command{
@@ -280,7 +290,7 @@ func main() {
280290
if err != nil {
281291
return err
282292
}
283-
return cmdUpload(cmd.Context(), bucket, args[1], *keyID, args[2])
293+
return cmdUpload(cmd.Context(), bucket, distribution(args[1]), *keyID, args[2])
284294
},
285295
})
286296
if err := rootCmd.Execute(); err != nil {

upload.go

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,34 +36,45 @@ func poolPath(name string) string {
3636
return "pool/" + name
3737
}
3838

39-
func distDirPath(dist string) string {
40-
return "dists/" + dist
39+
type distribution string
40+
41+
func (dist distribution) dir() string {
42+
return "dists/" + string(dist)
43+
}
44+
45+
func (dist distribution) indexPath() string {
46+
return dist.dir() + "/Release"
47+
}
48+
49+
func (dist distribution) signedIndexPath() string {
50+
return dist.dir() + "/InRelease"
4151
}
4252

43-
func releaseIndexPath(dist string) string {
44-
return distDirPath(dist) + "/Release"
53+
func (dist distribution) indexSignaturePath() string {
54+
return dist.dir() + "/Release.gpg"
4555
}
4656

47-
func signedReleaseIndexPath(dist string) string {
48-
return distDirPath(dist) + "/InRelease"
57+
type component struct {
58+
dist distribution
59+
name string
4960
}
5061

51-
func releaseSignatureIndexPath(dist string) string {
52-
return distDirPath(dist) + "/Release.gpg"
62+
func (comp component) dir() string {
63+
return comp.dist.dir() + "/" + comp.name
5364
}
5465

55-
func binaryPackagesIndexPath(dist, component, arch string) string {
56-
return distDirPath(dist) + "/" + component + "/binary-" + arch + "/Packages"
66+
func (comp component) binaryIndexPath(arch string) string {
67+
return comp.dir() + "/binary-" + arch + "/Packages"
5768
}
5869

59-
func binaryPackagesGzipIndexPath(dist, component, arch string) string {
60-
return distDirPath(dist) + "/" + component + "/binary-" + arch + "/Packages.gz"
70+
func (comp component) binaryIndexGzipPath(arch string) string {
71+
return comp.binaryIndexPath(arch) + ".gz"
6172
}
6273

63-
func uploadReleaseIndex(ctx context.Context, bucket *blob.Bucket, dist string, release deb.Paragraph, keyID string) error {
74+
func uploadReleaseIndex(ctx context.Context, bucket *blob.Bucket, dist distribution, release deb.Paragraph, keyID string) error {
6475
data := new(bytes.Buffer)
6576
deb.Save(data, []deb.Paragraph{release})
66-
err := bucket.WriteAll(ctx, releaseIndexPath(dist), data.Bytes(), &blob.WriterOptions{
77+
err := bucket.WriteAll(ctx, dist.indexPath(), data.Bytes(), &blob.WriterOptions{
6778
ContentType: "text/plain; charset=utf-8",
6879
})
6980
if err != nil {
@@ -82,7 +93,7 @@ func uploadReleaseIndex(ctx context.Context, bucket *blob.Bucket, dist string, r
8293
if err := clearSign.Run(); err != nil {
8394
return fmt.Errorf("generate InRelease: %w", err)
8495
}
85-
err = bucket.WriteAll(ctx, signedReleaseIndexPath(dist), clearSignOutput.Bytes(), &blob.WriterOptions{
96+
err = bucket.WriteAll(ctx, dist.signedIndexPath(), clearSignOutput.Bytes(), &blob.WriterOptions{
8697
ContentType: "text/plain; charset=utf-8",
8798
})
8899
if err != nil {
@@ -97,7 +108,7 @@ func uploadReleaseIndex(ctx context.Context, bucket *blob.Bucket, dist string, r
97108
if err := detachSign.Run(); err != nil {
98109
return fmt.Errorf("generate Release.gpg: %w", err)
99110
}
100-
err = bucket.WriteAll(ctx, releaseSignatureIndexPath(dist), detachSignOutput.Bytes(), &blob.WriterOptions{
111+
err = bucket.WriteAll(ctx, dist.indexSignaturePath(), detachSignOutput.Bytes(), &blob.WriterOptions{
101112
ContentType: "text/plain; charset=utf-8",
102113
})
103114
if err != nil {
@@ -113,12 +124,12 @@ type indexHashes struct {
113124
sha256 [sha256.Size]byte
114125
}
115126

116-
func uploadPackageIndex(ctx context.Context, bucket *blob.Bucket, dist, component, arch string, packages []deb.Paragraph) (uncompressed, compressed indexHashes, err error) {
127+
func uploadPackageIndex(ctx context.Context, bucket *blob.Bucket, comp component, arch string, packages []deb.Paragraph) (uncompressed, compressed indexHashes, err error) {
117128
buf := new(bytes.Buffer)
118129
if err := deb.Save(buf, packages); err != nil {
119130
return indexHashes{}, indexHashes{}, err
120131
}
121-
key := binaryPackagesIndexPath(dist, component, arch)
132+
key := comp.binaryIndexPath(arch)
122133
uncompressed, err = upload(ctx, bucket, key, "text/plain; charset=utf-8", "", bytes.NewReader(buf.Bytes()))
123134
if err != nil {
124135
return indexHashes{}, indexHashes{}, err
@@ -131,7 +142,7 @@ func uploadPackageIndex(ctx context.Context, bucket *blob.Bucket, dist, componen
131142
if err := zw.Close(); err != nil {
132143
return indexHashes{}, indexHashes{}, fmt.Errorf("compress %s: %w", key, err)
133144
}
134-
compressed, err = upload(ctx, bucket, binaryPackagesGzipIndexPath(dist, component, arch), "application/gzip", "", bytes.NewReader(gzipBuf.Bytes()))
145+
compressed, err = upload(ctx, bucket, comp.binaryIndexGzipPath(arch), "application/gzip", "", bytes.NewReader(gzipBuf.Bytes()))
135146
if err != nil {
136147
return indexHashes{}, indexHashes{}, err
137148
}

0 commit comments

Comments
 (0)