diff --git a/cmd/car/README.md b/cmd/car/README.md index 995850fd..e9cdb421 100644 --- a/cmd/car/README.md +++ b/cmd/car/README.md @@ -18,7 +18,7 @@ COMMANDS: create, c Create a car file debug debug a car file detach-index Detach an index to a detached file - extract, x Extract the contents of a car when the car encodes UnixFS data + extract, x Extract the contents of a car when the car encodes UnixFS or Git data filter, f Filter the CIDs in a car get-block, gb Get a block out of a car get-dag, gd Get a dag out of a car diff --git a/cmd/car/car.go b/cmd/car/car.go index 29dd9c10..d15a0482 100644 --- a/cmd/car/car.go +++ b/cmd/car/car.go @@ -102,7 +102,7 @@ func main1() int { { Name: "extract", Aliases: []string{"x"}, - Usage: "Extract the contents of a car when the car encodes UnixFS data", + Usage: "Extract the contents of a car when the car encodes UnixFS or Git data", Action: ExtractCar, ArgsUsage: "[output directory|-]", Flags: []cli.Flag{ diff --git a/cmd/car/extract.go b/cmd/car/extract.go index 91c0c033..d5482e2e 100644 --- a/cmd/car/extract.go +++ b/cmd/car/extract.go @@ -10,6 +10,7 @@ import ( "sync" "github.com/ipfs/go-cid" + _ "github.com/ipfs/go-ipld-git" "github.com/ipld/go-car/cmd/car/lib" "github.com/ipld/go-car/v2" carstorage "github.com/ipld/go-car/v2/storage" diff --git a/cmd/car/get.go b/cmd/car/get.go index df71f4d6..2d20114c 100644 --- a/cmd/car/get.go +++ b/cmd/car/get.go @@ -8,6 +8,7 @@ import ( "io" "os" + _ "github.com/ipfs/go-ipld-git" dagpb "github.com/ipld/go-codec-dagpb" "github.com/ipld/go-ipld-prime" _ "github.com/ipld/go-ipld-prime/codec/cbor" diff --git a/cmd/car/lib/extract.go b/cmd/car/lib/extract.go index 51ac9594..031177ef 100644 --- a/cmd/car/lib/extract.go +++ b/cmd/car/lib/extract.go @@ -1,6 +1,7 @@ package lib import ( + "bytes" "context" "errors" "fmt" @@ -54,6 +55,22 @@ func ExtractToDir(c context.Context, ls *ipld.LinkSystem, root cid.Cid, outputDi return 0, nil } + if root.Prefix().Codec == cid.GitRaw { + var outputResolvedDir string + var err error + if outputDir != "-" { + outputResolvedDir, err = filepath.EvalSymlinks(outputDir) + if err != nil { + return 0, err + } + } + var blobName string + if outputDir != "-" { + blobName = filepath.Join(outputResolvedDir, "unknown") + } + return extractGitAnyNode(c, ls, cidlink.Link{Cid: root}, outputResolvedDir, "/", blobName, path, verbose, logger) + } + pbn, err := ls.Load(ipld.LinkContext{}, cidlink.Link{Cid: root}, dagpb.Type.PBNode) if err != nil { return 0, err @@ -299,3 +316,184 @@ func extractFile(c context.Context, ls *ipld.LinkSystem, n ipld.Node, outputName _, err = io.Copy(f, nlr) return err } + +// extractGitDir extracts a git-raw tree node to a directory, following the +// same path-filtering and output conventions as extractDir. +func extractGitDir(c context.Context, ls *ipld.LinkSystem, n ipld.Node, outputRoot, outputPath string, matchPath []string, verbose bool, logger io.Writer) (int, error) { + if n.Kind() != ipld.Kind_Map { + return 0, ErrNotDir + } + + if outputRoot != "" { + dirPath, err := resolvePath(outputRoot, outputPath) + if err != nil { + return 0, err + } + if err := os.MkdirAll(dirPath, 0755); err != nil { + return 0, err + } + } + + if outputPath == "-" && len(matchPath) == 0 { + return 0, fmt.Errorf("cannot extract a directory to stdout, use a path to extract a specific file") + } + + subPath := matchPath + if len(matchPath) > 0 { + subPath = matchPath[1:] + } + + extractEntry := func(name string, entry ipld.Node) (int, error) { + nextPath := path.Join(outputPath, name) + var nextRes string + if outputRoot != "" { + var err error + nextRes, err = resolvePath(outputRoot, nextPath) + if err != nil { + return 0, err + } + if verbose { + fmt.Fprintf(logger, "%s\n", nextRes) + } + } + + hashNode, err := entry.LookupByString("hash") + if err != nil { + return 0, err + } + link, err := hashNode.AsLink() + if err != nil { + return 0, err + } + cnt, err := extractGitAnyNode(c, ls, link, outputRoot, nextPath, nextRes, subPath, verbose, logger) + if err != nil { + if nf, ok := err.(interface{ NotFound() bool }); ok && nf.NotFound() { + fmt.Fprintf(logger, "data for entry not found: %s (skipping...)\n", nextPath) + return 0, nil + } + return 0, err + } + return cnt, nil + } + + if len(matchPath) > 0 { + val, err := n.LookupByString(matchPath[0]) + if err != nil { + return 0, err + } + return extractEntry(matchPath[0], val) + } + + var count int + mi := n.MapIterator() + for !mi.Done() { + key, val, err := mi.Next() + if err != nil { + return 0, err + } + ks, err := key.AsString() + if err != nil { + return 0, err + } + ecount, err := extractEntry(ks, val) + if err != nil { + return 0, err + } + count += ecount + } + return count, nil +} + +// gitRawType reads the first bytes of a git-raw block to return its type +// string: "blob", "tree", "commit", or "tag". +func gitRawType(ls *ipld.LinkSystem, lnk ipld.Link) (string, error) { + r, err := ls.StorageReadOpener(ipld.LinkContext{}, lnk) + if err != nil { + return "", err + } + buf := make([]byte, 7) // long enough for "commit " (7 bytes) + n, err := r.Read(buf) + if n == 0 { + return "", fmt.Errorf("reading git object header: %w", err) + } + raw := buf[:n] + for _, t := range []string{"blob", "tree", "commit", "tag"} { + prefix := t + " " + if len(raw) >= len(prefix) && string(raw[:len(prefix)]) == prefix { + return t, nil + } + } + return "", fmt.Errorf("unrecognized git object header: %q", raw) +} + +// extractGitAnyNode dispatches a git-raw link to the right handler by reading +// the object-type from its raw block header ("blob", "tree", "commit", "tag"). +// blobPath is the output file path for a bare blob (empty = stdout); dirPath +// is the current relative path within outputRoot when entering a tree. +func extractGitAnyNode(c context.Context, ls *ipld.LinkSystem, lnk ipld.Link, outputRoot, dirPath, blobPath string, matchPath []string, verbose bool, logger io.Writer) (int, error) { + typ, err := gitRawType(ls, lnk) + if err != nil { + return 0, err + } + nd, err := ls.Load(ipld.LinkContext{}, lnk, basicnode.Prototype.Any) + if err != nil { + return 0, err + } + switch typ { + case "blob": + return 1, extractGitBlob(nd, blobPath) + case "commit": + treeNd, err := nd.LookupByString("tree") + if err != nil { + return 0, err + } + treeLnk, err := treeNd.AsLink() + if err != nil { + return 0, err + } + return extractGitAnyNode(c, ls, treeLnk, outputRoot, dirPath, blobPath, matchPath, verbose, logger) + case "tag": + objNd, err := nd.LookupByString("object") + if err != nil { + return 0, err + } + objLnk, err := objNd.AsLink() + if err != nil { + return 0, err + } + return extractGitAnyNode(c, ls, objLnk, outputRoot, dirPath, blobPath, matchPath, verbose, logger) + case "tree": + return extractGitDir(c, ls, nd, outputRoot, dirPath, matchPath, verbose, logger) + default: + return 0, fmt.Errorf("unrecognized git object type: %s", typ) + } +} + +// extractGitBlob writes the content of a git blob node to outputName (or +// stdout when outputName is ""). Git blob bytes include the object header +// "blob \0", which is stripped before writing. +func extractGitBlob(n ipld.Node, outputName string) error { + b, err := n.AsBytes() + if err != nil { + return err + } + // Strip git object header: "blob \0" + nullIdx := bytes.IndexByte(b, 0) + if nullIdx < 0 { + return fmt.Errorf("invalid git blob: missing null byte in header") + } + content := b[nullIdx+1:] + + var f *os.File + if outputName == "" { + f = os.Stdout + } else { + f, err = os.Create(outputName) + if err != nil { + return err + } + defer f.Close() + } + _, err = f.Write(content) + return err +} diff --git a/cmd/car/testdata/inputs/sample-git-commit.car b/cmd/car/testdata/inputs/sample-git-commit.car new file mode 100644 index 00000000..5038716f Binary files /dev/null and b/cmd/car/testdata/inputs/sample-git-commit.car differ diff --git a/cmd/car/testdata/inputs/sample-git-raw.car b/cmd/car/testdata/inputs/sample-git-raw.car new file mode 100644 index 00000000..d7d3fbeb Binary files /dev/null and b/cmd/car/testdata/inputs/sample-git-raw.car differ diff --git a/cmd/car/testdata/inputs/sample-git-tag-blob.car b/cmd/car/testdata/inputs/sample-git-tag-blob.car new file mode 100644 index 00000000..28ea61ca Binary files /dev/null and b/cmd/car/testdata/inputs/sample-git-tag-blob.car differ diff --git a/cmd/car/testdata/inputs/sample-git-tag.car b/cmd/car/testdata/inputs/sample-git-tag.car new file mode 100644 index 00000000..dbe6ab25 Binary files /dev/null and b/cmd/car/testdata/inputs/sample-git-tag.car differ diff --git a/cmd/car/testdata/script/extract.txt b/cmd/car/testdata/script/extract.txt index aa2713be..6b012a0a 100644 --- a/cmd/car/testdata/script/extract.txt +++ b/cmd/car/testdata/script/extract.txt @@ -93,6 +93,52 @@ stderr -count=1 '^data for entry not found: /zimdump_version \(skipping\.\.\.\)$ stderr -count=1 '^data for entry not found: /favicon.ico \(skipping\.\.\.\)$' stderr -count=1 '^data for entry not found: /index.html \(skipping\.\.\.\)$' +# git-raw CAR extract +mkdir actual-git-raw +car extract -f ${INPUTS}/sample-git-raw.car actual-git-raw +stderr '^extracted 1 file\(s\)$' +cmp actual-git-raw/baz expected-git-raw/baz + +# git-raw CAR rooted at a commit: extracts the commit's tree +mkdir actual-git-commit +car extract -f ${INPUTS}/sample-git-commit.car actual-git-commit +stderr '^extracted 5 file\(s\)$' +cmp actual-git-commit/file expected-git-commit/file +cmp actual-git-commit/dir/f1 expected-git-commit/dir/f1 +cmp actual-git-commit/dir/f4 expected-git-commit/dir/f4 +cmp actual-git-commit/dir/subdir/f2 expected-git-commit/dir/subdir/f2 +cmp actual-git-commit/dir2/f3 expected-git-commit/dir2/f3 + +# git-raw CAR rooted at a tag pointing to a commit: follows tag then extracts tree +mkdir actual-git-tag +car extract -f ${INPUTS}/sample-git-tag.car actual-git-tag +stderr '^extracted 5 file\(s\)$' +cmp actual-git-tag/file expected-git-commit/file +cmp actual-git-tag/dir/f1 expected-git-commit/dir/f1 +cmp actual-git-tag/dir/f4 expected-git-commit/dir/f4 +cmp actual-git-tag/dir/subdir/f2 expected-git-commit/dir/subdir/f2 +cmp actual-git-tag/dir2/f3 expected-git-commit/dir2/f3 + +# git-raw CAR rooted at a tag pointing to a blob: extracts the blob as 'unknown' +mkdir actual-git-tag-blob +car extract -f ${INPUTS}/sample-git-tag-blob.car actual-git-tag-blob +stderr '^extracted 1 file\(s\)$' +cmp actual-git-tag-blob/unknown expected-git-tag-blob/unknown + +-- expected-git-raw/baz -- +hello +-- expected-git-commit/file -- +Hello world +-- expected-git-commit/dir/f1 -- +qwerty +-- expected-git-commit/dir/f4 -- +;qjkxb +-- expected-git-commit/dir/subdir/f2 -- +123456 +-- expected-git-commit/dir2/f3 -- +',.pyf +-- expected-git-tag-blob/unknown -- +fgcrl -- expected/a/1/A.txt -- a1A -- expected/a/2/B.txt -- diff --git a/cmd/car/testdata/script/get-dag-git-raw.txt b/cmd/car/testdata/script/get-dag-git-raw.txt new file mode 100644 index 00000000..68c946f2 --- /dev/null +++ b/cmd/car/testdata/script/get-dag-git-raw.txt @@ -0,0 +1,8 @@ +env TREE_CID='baf4bcfe6bkemw5kpijnvfjzm575jntlvrqnfhky' +env BLOB_CID='baf4bcfgoae3ckaylvdn2sbxxk2lh7hu4uokemsq' +car get-dag ${INPUTS}/sample-git-raw.car ${TREE_CID} out.car +! stderr . +car list out.car +! stderr . +stdout ${TREE_CID} +stdout ${BLOB_CID} diff --git a/cmd/go.mod b/cmd/go.mod index a7eec70c..5967cfb4 100644 --- a/cmd/go.mod +++ b/cmd/go.mod @@ -7,6 +7,7 @@ require ( github.com/ipfs/go-block-format v0.2.3 github.com/ipfs/go-cid v0.6.0 github.com/ipfs/go-ipld-format v0.6.3 + github.com/ipfs/go-ipld-git v0.1.1 github.com/ipfs/go-unixfsnode v1.10.3 github.com/ipld/go-car v0.6.3 github.com/ipld/go-car/v2 v2.16.0 diff --git a/cmd/go.sum b/cmd/go.sum index 5682c29c..1d29265c 100644 --- a/cmd/go.sum +++ b/cmd/go.sum @@ -86,6 +86,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9gd6MPfXbKVU= github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -210,8 +211,11 @@ github.com/ipfs/boxo v0.36.0 h1:DarrMBM46xCs6GU6Vz+AL8VUyXykqHAqZYx8mR0Oics= github.com/ipfs/boxo v0.36.0/go.mod h1:92hnRXfP5ScKEIqlq9Ns7LR1dFXEVADKWVGH0fjk83k= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= +github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk= github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA= +github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= +github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/ipfs/go-cid v0.6.0 h1:DlOReBV1xhHBhhfy/gBNNTSyfOM6rLiIx9J7A4DGf30= github.com/ipfs/go-cid v0.6.0/go.mod h1:NC4kS1LZjzfhK40UGmpXv5/qD2kcMzACYJNntCUiDhQ= github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q= @@ -228,10 +232,13 @@ github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1I github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-pq v0.0.4 h1:U7jjENWJd1jhcrR8X/xHTaph14PTAK9O+yaLJbjqgOw= github.com/ipfs/go-ipfs-pq v0.0.4/go.mod h1:9UdLOIIb99IFrgT0Fc53pvbvlJBhpUb4GJuAQf3+O2A= +github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E= github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A= github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8= github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk= +github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y= +github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI= github.com/ipfs/go-ipld-legacy v0.2.2 h1:DThbqCPVLpWBcGtU23KDLiY2YRZZnTkXQyfz8aOfBkQ= github.com/ipfs/go-ipld-legacy v0.2.2/go.mod h1:hhkj+b3kG9b2BcUNw8IFYAsfeNo8E3U7eYlWeAOPyDU= github.com/ipfs/go-log/v2 v2.9.1 h1:3JXwHWU31dsCpvQ+7asz6/QsFJHqFr4gLgQ0FWteujk= @@ -250,6 +257,7 @@ github.com/ipld/go-car/v2 v2.16.0 h1:LWe0vmN/QcQmUU4tr34W5Nv5mNraW+G6jfN2s+ndBco github.com/ipld/go-car/v2 v2.16.0/go.mod h1:RqFGWN9ifcXVmCrTAVnfnxiWZk1+jIx67SYhenlmL34= github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0= github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM= +github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= github.com/ipld/go-ipld-prime v0.22.0 h1:YJhDhjEOvOYaqshd3b4atIWUoRg/rKrgmwCyUHwlbuY= github.com/ipld/go-ipld-prime v0.22.0/go.mod h1:ol7vKxOOVgEh0iAPuiDalM+0gScXVMA5ZZa4DVrTnEA= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 h1:cqNk8PEwHnK0vqWln+U/YZhQc9h2NB3KjUjDPZo5Q2s= @@ -263,12 +271,14 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -299,6 +309,9 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -312,10 +325,15 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw= @@ -324,14 +342,22 @@ github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= github.com/multiformats/go-multicodec v0.10.0 h1:UpP223cig/Cx8J76jWt91njpK3GTAO1w02sdcjZDSuc= github.com/multiformats/go-multicodec v0.10.0/go.mod h1:wg88pM+s2kZJEQfRCKBNU+g32F5aWBEjyFHXvZLTcLI= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= github.com/multiformats/go-multistream v0.6.1 h1:4aoX5v6T+yWmc2raBHsTvzmFhOI8WVOer28DeBBEYdQ= github.com/multiformats/go-multistream v0.6.1/go.mod h1:ksQf6kqHAb6zIsyw7Zm+gAuVo57Qbq84E27YlYqavqw= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.1.0 h1:i2wqFp4sdl3IcIxfAonHQV9qU5OsZ4Ts9IOoETFs5dI= github.com/multiformats/go-varint v0.1.0/go.mod h1:5KVAVXegtfmNQQm/lCY+ATvDzvJJhSkUlGQV9wgObdI= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -346,6 +372,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= 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/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.89.1-0.20231129105047-37766d95467a h1:cgqrm0F3zwf9IPzca7xN4w+Zy6MC9ZkPvAC8QEWa/iQ= github.com/polydawn/refmt v0.89.1-0.20231129105047-37766d95467a/go.mod h1:ocZfO/tLSHqfScRDNTJbAJR1by4D1lewauX9OwTaPuY= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -403,6 +430,7 @@ github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4= github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y= +github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= @@ -452,9 +480,11 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= @@ -606,6 +636,7 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -619,6 +650,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=