Skip to content

Commit

Permalink
Add file listing for bundle unpacking
Browse files Browse the repository at this point in the history
Add flag to enable to print a file listing when the unpacking of a
source bundle is complete.

Signed-off-by: Matthias Diester <[email protected]>
  • Loading branch information
HeavyWombat committed Oct 28, 2024
1 parent 84aa01c commit fd07cc9
Show file tree
Hide file tree
Showing 24 changed files with 2,845 additions and 7 deletions.
80 changes: 80 additions & 0 deletions cmd/bundle/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ package main
import (
"context"
"fmt"
"io/fs"
"log"
"os"
"path/filepath"
"strconv"
"syscall"

"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/olekukonko/tablewriter"
"github.com/spf13/pflag"

"github.com/shipwright-io/build/pkg/bundle"
Expand All @@ -28,6 +32,7 @@ type settings struct {
secretPath string
resultFileImageDigest string
resultFileSourceTimestamp string
showListing bool
}

var flagValues settings
Expand All @@ -44,6 +49,7 @@ func init() {

pflag.StringVar(&flagValues.secretPath, "secret-path", "", "A directory that contains access credentials (optional)")
pflag.BoolVar(&flagValues.prune, "prune", false, "Delete bundle image from registry after it was pulled")
pflag.BoolVar(&flagValues.showListing, "show-listing", false, "Print file listing of files unpacked from the bundle")
}

func main() {
Expand All @@ -57,6 +63,10 @@ func Do(ctx context.Context) error {
flagValues = settings{}
pflag.Parse()

if val, ok := os.LookupEnv("BUNDLE_SHOW_LISTING"); ok {
flagValues.showListing, _ = strconv.ParseBool(val)
}

if flagValues.help {
pflag.Usage()
return nil
Expand Down Expand Up @@ -96,6 +106,43 @@ func Do(ctx context.Context) error {
}

log.Printf("Image content was extracted to %s\n", flagValues.target)
if flagValues.showListing {
t := tablewriter.NewWriter(os.Stdout)
t.SetBorder(false)
t.SetColumnSeparator("")
t.SetAutoWrapText(false)

// ignore any errors when walking through the file system, the listing is only for informational purposes
_ = filepath.Walk(flagValues.target, func(path string, info fs.FileInfo, err error) error {
if err != nil {
log.Printf("ignoring error for path %s: %v\n", path, err)
return nil
}

// Omit the target path itself
if path == flagValues.target {
return nil
}

// use relative paths to keep output compact
if l, err := filepath.Rel(flagValues.target, path); err == nil {
path = l
}

// if possible, try to obtain nlink count and user/group details
var nlink, user, group string = "?", "?", "?"
if stat, ok := info.Sys().(*syscall.Stat_t); ok {
user = strconv.FormatUint(uint64(stat.Uid), 10)
group = strconv.FormatUint(uint64(stat.Gid), 10)
nlink = strconv.FormatUint(uint64(stat.Nlink), 10)
}

t.Append([]string{filemode(info), nlink, user, group, strconv.FormatInt(info.Size(), 10), path})
return nil
})

t.Render()
}

digest, err := img.Digest()
if err != nil {
Expand Down Expand Up @@ -136,3 +183,36 @@ func Do(ctx context.Context) error {

return nil
}

// filemode is a minimal effort function to translate os.FileMode to the
// commonly known human representation, i.e. rw-r--r--. However, it does
// not implement all features such as sticky bits.
func filemode(info fs.FileInfo) string {
var translate = func(i os.FileMode) string {
var result = []rune{'-', '-', '-'}
if i&0x1 != 0 {
result[2] = 'x'
}

if i&0x2 != 0 {
result[1] = 'w'
}

if i&0x4 != 0 {
result[0] = 'r'
}

return string(result)
}

var dirBit = func(i os.FileMode) string {
if i&fs.ModeDir != 0 {
return "d"
}

return "-"
}

var mode = info.Mode()
return dirBit(mode) + translate((mode>>6)&0x7) + translate((mode>>3)&0x7) + translate(mode&0x7)
}
16 changes: 13 additions & 3 deletions cmd/bundle/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package main_test
import (
"context"
"fmt"
"io"
"log"
"net/http/httptest"
"net/url"
Expand All @@ -34,8 +33,7 @@ var _ = Describe("Bundle Loader", func() {
const exampleImage = "ghcr.io/shipwright-io/sample-go/source-bundle:latest"

run := func(args ...string) error {
// discard log output
log.SetOutput(io.Discard)
log.SetOutput(GinkgoWriter)

// discard stderr output
var tmp = os.Stderr
Expand Down Expand Up @@ -316,4 +314,16 @@ var _ = Describe("Bundle Loader", func() {
})
})
})

Context("Using show listing flag", func() {
It("should run without issues", func() {
withTempDir(func(target string) {
Expect(run(
"--image", exampleImage,
"--target", target,
"--show-listing",
)).To(Succeed())
})
})
})
})
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/google/go-containerregistry v0.20.2
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
github.com/olekukonko/tablewriter v0.0.5
github.com/onsi/ginkgo/v2 v2.20.2
github.com/onsi/gomega v1.34.2
github.com/prometheus/client_golang v1.20.5
Expand Down Expand Up @@ -43,7 +44,7 @@ require (
github.com/cloudflare/circl v1.3.7 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
Expand Down Expand Up @@ -80,13 +81,15 @@ require (
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
Expand Down
10 changes: 8 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ=
github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
Expand Down Expand Up @@ -287,6 +288,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
Expand All @@ -301,6 +304,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
Expand All @@ -315,8 +320,9 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
Expand Down
16 changes: 16 additions & 0 deletions vendor/github.com/mattn/go-runewidth/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions vendor/github.com/mattn/go-runewidth/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions vendor/github.com/mattn/go-runewidth/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions vendor/github.com/mattn/go-runewidth/go.test.sh

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit fd07cc9

Please sign in to comment.