Skip to content

Commit 1a2b388

Browse files
authored
Merge pull request #89 from infosiftr/context-checksum
Add `ArchGitChecksum` template command in `bashbrew cat`
2 parents 4e0ea8d + 795ff4b commit 1a2b388

File tree

12 files changed

+699
-99
lines changed

12 files changed

+699
-99
lines changed

cmd/bashbrew/git.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"path/filepath"
1212
"regexp"
1313
"strings"
14+
"time"
1415

1516
"github.com/urfave/cli"
1617

@@ -96,6 +97,35 @@ func getGitCommit(commit string) (string, error) {
9697
return h.String(), nil
9798
}
9899

100+
func (r Repo) archGitFS(arch string, entry *manifest.Manifest2822Entry) (fs.FS, error) {
101+
commit, err := r.fetchGitRepo(arch, entry)
102+
if err != nil {
103+
return nil, fmt.Errorf("failed fetching %q: %w", r.EntryIdentifier(entry), err)
104+
}
105+
106+
gitFS, err := gitCommitFS(commit)
107+
if err != nil {
108+
return nil, err
109+
}
110+
111+
return fs.Sub(gitFS, entry.ArchDirectory(arch))
112+
}
113+
114+
// returns the timestamp of the ArchGitCommit -- useful for SOURCE_DATE_EPOCH
115+
func (r Repo) ArchGitTime(arch string, entry *manifest.Manifest2822Entry) (time.Time, error) {
116+
f, err := r.archGitFS(arch, entry)
117+
if err != nil {
118+
return time.Time{}, err
119+
}
120+
121+
fi, err := fs.Stat(f, ".")
122+
if err != nil {
123+
return time.Time{}, err
124+
}
125+
126+
return fi.ModTime(), nil
127+
}
128+
99129
func gitCommitFS(commit string) (fs.FS, error) {
100130
if err := ensureGitInit(); err != nil {
101131
return nil, err

cmd/bashbrew/main.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package main
33
import (
44
"fmt"
55
"os"
6+
"path"
67
"path/filepath"
78
"strings"
89

910
"github.com/sirupsen/logrus" // this is used by containerd libraries, so we need to set the default log level for it
1011
"github.com/urfave/cli"
12+
xTerm "golang.org/x/term"
1113

1214
"github.com/docker-library/bashbrew/architecture"
1315
"github.com/docker-library/bashbrew/manifest"
@@ -421,6 +423,61 @@ func main() {
421423

422424
Category: "plumbing",
423425
},
426+
{
427+
Name: "context",
428+
Usage: "(eventually Dockerfile-filtered) git archive",
429+
Flags: []cli.Flag{
430+
cli.BoolFlag{
431+
Name: "sha256",
432+
Usage: `print sha256 instead of raw tar`,
433+
},
434+
// TODO "unfiltered" or something for not applying Dockerfile filtering (once that's implemented)
435+
},
436+
Before: subcommandBeforeFactory("context"),
437+
Action: func(c *cli.Context) error {
438+
repos, err := repos(false, c.Args()...)
439+
if err != nil {
440+
return err
441+
}
442+
if len(repos) != 1 {
443+
return fmt.Errorf("'context' expects to act on exactly one architecture of one entry of one repo (got %d repos)", len(repos))
444+
}
445+
446+
r, err := fetch(repos[0])
447+
if err != nil {
448+
return err
449+
}
450+
451+
// TODO technically something like "hello-world:latest" *could* be relaxed a little if it resolves via architecture to one and only one entry 🤔 (but that's a little hard to implement with the existing internal data structures -- see TODO at the top of "sort.go")
452+
453+
if r.TagEntry == nil {
454+
return fmt.Errorf("'context' expects to act on exactly one architecture of one entry of one repo (no specific entry of %q selected)", r.RepoName)
455+
}
456+
if len(r.TagEntries) != 1 {
457+
return fmt.Errorf("'context' expects to act on exactly one architecture of one entry of one repo (got %d entires)", len(r.TagEntries))
458+
}
459+
460+
if !r.TagEntry.HasArchitecture(arch) {
461+
return fmt.Errorf("%q does not include architecture %q", path.Join(namespace, r.RepoName)+":"+r.TagEntry.Tags[0], arch)
462+
}
463+
464+
if c.Bool("sha256") {
465+
sum, err := r.ArchGitChecksum(arch, r.TagEntry)
466+
if err != nil {
467+
return err
468+
}
469+
fmt.Println(sum)
470+
return nil
471+
} else {
472+
if xTerm.IsTerminal(int(os.Stdout.Fd())) {
473+
return fmt.Errorf("cowardly refusing to output a tar to a terminal")
474+
}
475+
return r.archContextTar(arch, r.TagEntry, os.Stdout)
476+
}
477+
},
478+
479+
Category: "plumbing",
480+
},
424481
{
425482
Name: "remote",
426483
Usage: "query registries for bashbrew-related data",

cmd/bashbrew/oci-builder.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func importOCIBlob(ctx context.Context, cs content.Store, fs iofs.FS, descriptor
8989

9090
// this is "docker build" but for "Builder: oci-import"
9191
func ociImportBuild(tags []string, commit, dir, file string) (*imagespec.Descriptor, error) {
92+
// TODO use r.archGitFS (we have no r or arch or entry here 😅)
9293
fs, err := gitCommitFS(commit)
9394
if err != nil {
9495
return nil, err

cmd/bashbrew/sort.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"pault.ag/go/topsort"
66
)
77

8+
// TODO unify archFilter and applyConstraints handling by pre-filtering the full list of Repo objects such that all that remains are things we should process (thus removing all "if" statements throughout the various loops); re-doing the Architectures and Entries lists to only include ones we should process, etc
9+
810
func sortRepos(repos []string, applyConstraints bool) ([]string, error) {
911
rs := []*Repo{}
1012
rsMap := map[*Repo]string{}
@@ -103,10 +105,10 @@ func sortRepoObjects(rs []*Repo, applyConstraints bool) ([]*Repo, error) {
103105
continue
104106
}
105107
/*
106-
// TODO need archFilter here :(
107-
if archFilter && !entry.HasArchitecture(arch) {
108-
continue
109-
}
108+
// TODO need archFilter here :(
109+
if archFilter && !entry.HasArchitecture(arch) {
110+
continue
111+
}
110112
*/
111113

112114
entryArches := []string{arch}

cmd/bashbrew/tar.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package main
2+
3+
import (
4+
"crypto/sha256"
5+
"fmt"
6+
"io"
7+
8+
"github.com/docker-library/bashbrew/manifest"
9+
"github.com/docker-library/bashbrew/pkg/tarscrub"
10+
)
11+
12+
func (r Repo) archContextTar(arch string, entry *manifest.Manifest2822Entry, w io.Writer) error {
13+
f, err := r.archGitFS(arch, entry)
14+
if err != nil {
15+
return err
16+
}
17+
18+
return tarscrub.WriteTar(f, w)
19+
}
20+
21+
func (r Repo) ArchGitChecksum(arch string, entry *manifest.Manifest2822Entry) (string, error) {
22+
h := sha256.New()
23+
err := r.archContextTar(arch, entry, h)
24+
if err != nil {
25+
return "", err
26+
}
27+
return fmt.Sprintf("%x", h.Sum(nil)), nil
28+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/sirupsen/logrus v1.9.0
1010
github.com/urfave/cli v1.22.10
1111
go.etcd.io/bbolt v1.3.7
12+
golang.org/x/term v0.5.0
1213
pault.ag/go/debian v0.12.0
1314
pault.ag/go/topsort v0.1.1
1415
)

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
940940
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
941941
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
942942
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
943+
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
943944
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
944945
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
945946
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

0 commit comments

Comments
 (0)