AT Protocol IPLD-CAR Repository toolkit (CLI)

Compare changes

Choose any two refs to compare.

-2
.github/workflows/release.yaml
··· 28 28 github_token: ${{ secrets.PAT }} 29 29 goos: ${{ matrix.goos }} 30 30 goarch: ${{ matrix.goarch }} 31 - project_path: "./cmd" 32 31 ldflags: "-X main._version=${{ env.RELEASE_VERSION }}" 33 - binary_name: atr 34 32 sha256sum: true 35 33 md5sum: false
+40 -3
README.md
··· 22 22 atr show -t post 23 23 24 24 # use jq query language 25 - atr show -q .displayName 25 + atr show -q .body.displayName 26 + 27 + # use jmespath query language 28 + atr show -q body.displayName 26 29 27 30 # Search with grep: 28 31 atr show -t post | grep love 29 32 30 33 # Repositories can also be read via pipe: 31 - curl -sL "https://xrpc.link/r/atproto.com" | atr show 34 + curl -sL "https://enoki.us-east.host.bsky.network/xrpc/com.atproto.sync.getRepo?did=did:plc:ewvi7nxzyoun6zhxrhs64oiz" | atr show 35 + curl -sL "xrpc.link/r/atproto.com" | atr show 32 36 33 37 # FYI xrpc.link is shortcut domain which redirecting to 34 38 # relevant /xrpc/... endpoints 35 39 ``` 36 40 41 + Example output: 42 + ```bash 43 + ~> curl -sL "https://enoki.us-east.host.bsky.network/xrpc/com.atproto.sync.getRepo?did=did:plc:ewvi7nxzyoun6zhxrhs64oiz" | atr i 44 + 45 + (pipe): 46 + DID: did:plc:ewvi7nxzyoun6zhxrhs64oiz Repo Version: 3 47 + Head: bafyreiapeyhetsiuz6jcybcmgxw7k45imuu22shmbhybccq4vef57fc4mi 48 + Sig: d03ed428c77a9e4964560f575426f81ed694861c93372b866d77b3b1f814a39b4d27033fa86593e194dfe07278a96aa1a9b76f1b2f7ff8d4313130b557177fb1 49 + Size: 566 kB Blocks: 1,837 Commits: 1 Objects: 1,434 50 + Profile: 51 + Display Name: AT Protocol Developers 52 + Description: Social networking technology created by Bluesky. 53 + 54 + Developer-focused account. Follow @bsky.app for general announcements! 55 + 56 + Bluesky API docs: docs.bsky.app 57 + AT Protocol specs: atproto.com 58 + Collections: 59 + app.bsky.actor.profile: 1 60 + app.bsky.feed.generator: 2 61 + app.bsky.feed.like: 686 62 + app.bsky.feed.post: 150 63 + app.bsky.feed.repost: 541 64 + app.bsky.feed.threadgate: 1 65 + app.bsky.graph.follow: 21 66 + app.bsky.graph.list: 1 67 + app.bsky.graph.listitem: 29 68 + app.bsky.graph.starterpack: 1 69 + chat.bsky.actor.declaration: 1 70 + Last 5 commits: 71 + bafyreiapeyhetsiuz6jcybcmgxw7k45imuu22shmbhybccq4vef57fc4mi 72 + ``` 73 + 37 74 ## License 38 75 39 - MIT 76 + MIT
+2
atr.go
··· 2 2 3 3 import ( 4 4 "github.com/atscan/atr/cmd" 5 + "github.com/atscan/atr/util/version" 5 6 ) 6 7 7 8 var _version string 8 9 9 10 func main() { 11 + version.Version(_version) 10 12 cmd.Execute() 11 13 } 12 14
+6 -2
cli/context.go
··· 1 1 package cli 2 2 3 + import "github.com/schollz/progressbar/v3" 4 + 3 5 type Context struct { 4 - Args []string 5 - WorkingDir string 6 + Args []string 7 + WorkingDir string 8 + Raw bool 9 + ProgressBar *progressbar.ProgressBar 6 10 }
+13 -2
cli/print.go
··· 6 6 "log" 7 7 "os" 8 8 9 + "github.com/atscan/atr/repo" 9 10 jsoniter "github.com/json-iterator/go" 10 11 ) 11 12 12 - func Print(v interface{}) error { 13 + type ObjectOutput struct { 14 + Did string `json:"did"` 15 + Rkey string `json:"rkey"` 16 + Cid string `json:"cid"` 17 + Body interface{} `json:"body"` 18 + Match interface{} `json:"-"` 19 + } 20 + 21 + func Print(v interface{}, ri repo.RepoItem, rs repo.RepoSnapshot) error { 22 + 13 23 json, err := jsoniter.Marshal(v) 14 24 if err != nil { 15 25 log.Fatal(err) ··· 22 32 return nil 23 33 } 24 34 25 - func PrettyPrint(v interface{}, hg func(io.Writer, string)) error { 35 + func PrettyPrint(v interface{}, ri repo.RepoItem, rs repo.RepoSnapshot, hg func(io.Writer, string)) error { 36 + 26 37 json, err := jsoniter.MarshalIndent(v, "", " ") 27 38 if err != nil { 28 39 log.Fatal(err)
+60 -4
cmd/atr-inspect.go
··· 1 1 package cmd 2 2 3 3 import ( 4 + "context" 5 + "encoding/hex" 4 6 "fmt" 5 7 "os" 8 + "sort" 9 + "strings" 6 10 7 11 "github.com/atscan/atr/cli" 8 12 "github.com/atscan/atr/engine" ··· 13 17 ) 14 18 15 19 func init() { 16 - rootCmd.AddCommand(InspectCmd) 20 + rootCmd.AddCommand(LsCmd) 17 21 } 18 22 19 - var InspectCmd = &cobra.Command{ 23 + var LsCmd = &cobra.Command{ 20 24 Use: "inspect", 21 25 Aliases: []string{"i"}, 22 26 Short: "Inspect repo(s)", ··· 26 30 WorkingDir: workingDir, 27 31 Args: args, 28 32 } 29 - 33 + fmt.Println("") 30 34 walk := func(ss repo.RepoSnapshot, err error) { 31 35 if ss.Root.String() == "b" { 32 36 return ··· 36 40 } 37 41 yellow := color.New(color.FgYellow).SprintFunc() 38 42 cyan := color.New(color.FgCyan).SprintFunc() 39 - fmt.Printf("%v:\n Head: %s\n Size: %s Items: %v\n\n", yellow(ss.File), cyan(ss.Root.String()), cyan(humanize.Bytes(uint64(ss.Size))), cyan(humanize.Comma(int64(len(ss.Items))))) 43 + boldCyan := color.New(color.FgCyan, color.Bold).SprintFunc() 44 + green := color.New(color.FgGreen).SprintFunc() 45 + 46 + fmt.Printf("%v:\n", yellow(ss.File)) 47 + fmt.Printf(" DID: %s Repo Version: %v\n", boldCyan(ss.Repo.SignedCommit().Did), cyan(ss.Repo.SignedCommit().Version)) 48 + fmt.Printf(" Head: %s\n", cyan(ss.Root.String())) 49 + fmt.Printf(" Sig: %s\n", cyan(hex.EncodeToString(ss.Repo.SignedCommit().Sig))) 50 + 51 + stats, _ := ss.GetCollectionStats("") 52 + keys := make([]string, 0, len(stats)) 53 + total := 0 54 + for k := range stats { 55 + keys = append(keys, k) 56 + total += stats[k] 57 + } 58 + sort.Strings(keys) 59 + cp, _ := ss.Repo.GetCommitsPath(-1) 60 + _, v, _ := ss.Repo.GetRecord(context.TODO(), "app.bsky.actor.profile/self") 61 + 62 + dn := v["displayName"] 63 + if dn != nil { 64 + dn = boldCyan(dn) 65 + } else { 66 + dn = "(empty)" 67 + } 68 + desc := v["description"] 69 + if desc != nil { 70 + desc = cyan(strings.Replace(desc.(string), "\n", "\n ", -1)) 71 + } else { 72 + desc = "(empty)" 73 + } 74 + 75 + fmt.Printf(" Size: %s Blocks: %v Commits: %v Objects: %v\n", cyan(humanize.Bytes(uint64(ss.Size))), cyan(humanize.Comma(int64(ss.Repo.Blocks))), cyan(humanize.Comma(int64(len(cp)))), cyan(humanize.Comma(int64(total)))) 76 + fmt.Printf(" Profile:\n") 77 + fmt.Printf(" Display Name: %v\n", dn) 78 + fmt.Printf(" Description: %v\n", desc) 79 + 80 + fmt.Printf(" Collections:\n") 81 + for _, k := range keys { 82 + fmt.Printf(" %s: %v\n", green(k), cyan(humanize.Comma(int64(stats[k])))) 83 + } 84 + fmt.Printf(" Last 5 commits:\n") 85 + for i, cid := range cp { 86 + fmt.Printf(" %v\n", cyan(cid.String())) 87 + if i >= 5 { 88 + break 89 + } 90 + } 91 + if len(cp) > 5 { 92 + fmt.Printf(" %s\n", cyan("...")) 93 + } 94 + 95 + fmt.Println("") 40 96 } 41 97 42 98 stat, _ := os.Stdin.Stat()
+71
cmd/atr-log.go
··· 1 + package cmd 2 + 3 + import ( 4 + "fmt" 5 + "os" 6 + 7 + "github.com/atscan/atr/cli" 8 + "github.com/atscan/atr/engine" 9 + "github.com/atscan/atr/repo" 10 + "github.com/fatih/color" 11 + "github.com/spf13/cobra" 12 + ) 13 + 14 + var ( 15 + LogRaw bool 16 + ) 17 + 18 + func init() { 19 + rootCmd.AddCommand(LogCmd) 20 + LogCmd.Flags().BoolVar(&LogRaw, "raw", false, "Do not use colors (faster)") 21 + } 22 + 23 + var LogCmd = &cobra.Command{ 24 + Use: "log [target] [--raw]", 25 + Aliases: []string{"l"}, 26 + Short: "Show commit history (path)", 27 + Long: ``, 28 + Run: func(cmd *cobra.Command, args []string) { 29 + ctx := cli.Context{ 30 + WorkingDir: workingDir, 31 + Args: args, 32 + Raw: Raw, 33 + } 34 + walk := func(ss repo.RepoSnapshot, err error) { 35 + if ss.Root.String() == "b" { 36 + return 37 + } 38 + cp, _ := ss.Repo.GetCommitsPath(-1) 39 + //cp = util.ReverseCidSlice(cp) 40 + 41 + if LogRaw { 42 + for _, cid := range cp { 43 + fmt.Printf("%v\n", cid.String()) 44 + } 45 + } else { 46 + yellow := color.New(color.FgYellow).SprintFunc() 47 + cyan := color.New(color.FgCyan).SprintFunc() 48 + 49 + fmt.Printf("[%v]\n", yellow(ss.File)) 50 + for i, cid := range cp { 51 + /*stats, _ := ss.GetCollectionStats(cid.String()) 52 + 53 + sum := 0 54 + for _, v := range stats { 55 + sum += v 56 + }*/ 57 + fmt.Printf("%v [#%v]\n", cyan(cid.String()), len(cp)-i) 58 + } 59 + } 60 + } 61 + 62 + stat, _ := os.Stdin.Stat() 63 + if (stat.Mode() & os.ModeCharDevice) == 0 { 64 + // data is being piped to stdin 65 + engine.WalkStream(&ctx, os.Stdin, walk) 66 + } else { 67 + //stdin is from a terminal 68 + engine.WalkFiles(&ctx, walk) 69 + } 70 + }, 71 + }
+37 -13
cmd/atr-show.go
··· 5 5 "os" 6 6 "os/exec" 7 7 "regexp" 8 + "runtime" 8 9 "strings" 9 10 10 11 "github.com/atscan/atr/cli" ··· 21 22 QueryJmes string 22 23 Type string 23 24 Raw bool 25 + Root string 26 + GoBack int 24 27 ) 25 28 26 29 func init() { 27 30 rootCmd.AddCommand(ShowCmd) 31 + ShowCmd.Flags().StringVarP(&Root, "root", "r", "", "Use specific root") 32 + ShowCmd.Flags().IntVarP(&GoBack, "back", "b", 0, "Go back (n) commits") 28 33 ShowCmd.Flags().StringVarP(&Type, "type", "t", "", "Filter by item type") 29 34 ShowCmd.Flags().StringVarP(&Query, "query", "q", "", "Query results (jq)") 30 35 ShowCmd.Flags().StringVarP(&QueryJmes, "query-jmes", "x", "", "Query results (jmespath)") ··· 40 45 ctx := cli.Context{ 41 46 WorkingDir: workingDir, 42 47 Args: args, 48 + Raw: Raw, 43 49 } 44 50 45 51 //q := ctx.Args().First() ··· 64 70 queryJmes = jc 65 71 } 66 72 67 - eo, err := exec.Command("defaults", "read", "-g", "AppleInterfaceStyle").Output() 68 - if err != nil { 69 - log.Fatal(err) 70 - } 71 73 style := "paraiso-dark" 72 - if strings.Index(string(eo), "Dark") != 0 { 73 - style = "paraiso-light" 74 + if runtime.GOOS == "darwin" { 75 + eo, err := exec.Command("defaults", "read", "-g", "AppleInterfaceStyle").Output() 76 + if err != nil { 77 + log.Fatal(err) 78 + } 79 + if strings.Index(string(eo), "Dark") != 0 { 80 + style = "paraiso-light" 81 + } 74 82 } 75 83 hg := cli.Highlight(style) 76 84 77 85 walk := func(ss repo.RepoSnapshot, err error) { 78 86 87 + rr := Root 88 + if GoBack > 0 { 89 + gb, _ := ss.Repo.GetCommitsPath(GoBack) 90 + rr = gb[len(gb)-1].String() 91 + 92 + } 93 + ss.LoadItems(rr) 94 + 79 95 for _, e := range ss.Items { 80 96 tf := Type 81 97 if tf != "" { ··· 83 99 continue 84 100 } 85 101 } 86 - var out interface{} 102 + 103 + out := cli.ObjectOutput{Did: ss.Repo.SignedCommit().Did, Cid: e.Cid.String(), Rkey: e.Path, Body: e.Body} 104 + 87 105 if q != "" || qq != "" { 88 - json, err := jsoniter.Marshal(e.Body) 106 + json, err := jsoniter.Marshal(out) 89 107 if err != nil { 90 108 log.Fatal("jsoniter error:", err) 91 109 continue ··· 110 128 if v == nil { 111 129 continue 112 130 } 113 - out = v 131 + out.Match = v 114 132 } 115 133 } 116 134 if qq != "" { ··· 118 136 if err != nil { 119 137 log.Fatalln("jmespath error:", err) 120 138 } 121 - out = r 139 + out.Match = r 122 140 } 141 + } 142 + 143 + var ro interface{} 144 + if out.Match != nil { 145 + ro = out.Match 123 146 } else { 124 - out = e.Body 147 + ro = out 125 148 } 149 + 126 150 stat, _ := os.Stdout.Stat() 127 151 if !Raw && (stat.Mode()&os.ModeCharDevice) != 0 { 128 - cli.PrettyPrint(out, hg) 152 + cli.PrettyPrint(ro, e, ss, hg) 129 153 } else { 130 - cli.Print(out) 154 + cli.Print(ro, e, ss) 131 155 } 132 156 } 133 157 }
+71 -23
engine/io.go
··· 8 8 "log" 9 9 "os" 10 10 "strings" 11 + "time" 11 12 13 + "github.com/atscan/atr/cli" 12 14 "github.com/atscan/atr/repo" 13 - "github.com/ipfs/go-cid" 14 15 "github.com/klauspost/compress/zstd" 16 + "github.com/schollz/progressbar/v3" 15 17 ) 16 18 17 - func Load(fn string) (repo.RepoSnapshot, error) { 19 + func Load(ctx *cli.Context, fn string) (repo.RepoSnapshot, error) { 18 20 var ss repo.RepoSnapshot 19 21 var err error 20 22 if strings.HasSuffix(fn, ".car.zst") { 21 - ss, err = LoadCompressed(fn) 23 + ss, err = LoadCompressed(ctx, fn) 22 24 } else if strings.HasSuffix(fn, ".car") { 23 - ss, err = LoadRaw(fn) 25 + ss, err = LoadRaw(ctx, fn) 24 26 } 25 27 if err != nil { 26 28 log.Fatal("Cannot load: ", fn) ··· 30 32 return ss, nil 31 33 } 32 34 33 - func LoadRaw(fn string) (repo.RepoSnapshot, error) { 35 + func LoadRaw(ctx *cli.Context, fn string) (repo.RepoSnapshot, error) { 36 + stat, err := os.Stat(fn) 37 + if err != nil { 38 + return repo.RepoSnapshot{}, err 39 + } 34 40 dat, err := os.Open(fn) 41 + if err != nil { 42 + return repo.RepoSnapshot{}, err 43 + } 35 44 defer dat.Close() 36 45 37 46 if err != nil { 38 47 return repo.RepoSnapshot{}, err 39 48 } 40 - return LoadFromStream(dat) 49 + return LoadFromStream(ctx, dat, stat.Size()) 41 50 } 42 51 43 - func LoadCompressed(fn string) (repo.RepoSnapshot, error) { 52 + func LoadCompressed(ctx *cli.Context, fn string) (repo.RepoSnapshot, error) { 44 53 dat, err := os.Open(fn) 54 + if err != nil { 55 + return repo.RepoSnapshot{}, err 56 + } 45 57 defer dat.Close() 46 58 47 59 if err != nil { 48 60 return repo.RepoSnapshot{}, err 49 61 } 50 62 decoder, _ := zstd.NewReader(dat) 51 - return LoadFromStream(decoder) 63 + return LoadFromStream(ctx, decoder, -1) 64 + } 65 + 66 + func LoadFromStream(ctx *cli.Context, input io.Reader, sz int64) (repo.RepoSnapshot, error) { 67 + ss, err := LoadRepoFromStream(ctx, input, sz) 68 + if err != nil { 69 + return ss, err 70 + } 71 + 72 + ss.Root = ss.Repo.Head() 73 + 74 + return ss, nil 52 75 } 53 76 54 - func LoadFromStream(input io.Reader) (repo.RepoSnapshot, error) { 77 + func LoadRepoFromStream(ctx *cli.Context, input io.Reader, sz int64) (repo.RepoSnapshot, error) { 55 78 rctx := context.TODO() 56 79 ss := repo.RepoSnapshot{} 57 80 81 + var bar *progressbar.ProgressBar 82 + if sz > 150_000_000 && !ctx.Raw { 83 + bar = progressbar.NewOptions(int(sz), 84 + progressbar.OptionSetDescription("loading"), 85 + progressbar.OptionSetWriter(os.Stderr), 86 + progressbar.OptionShowBytes(true), 87 + //progressbar.OptionSetWidth(10), 88 + progressbar.OptionThrottle(35*time.Millisecond), 89 + progressbar.OptionShowCount(), 90 + //progressbar.OptionOnCompletion(func() { 91 + //}), 92 + //progressbar.OptionSpinnerType(14), 93 + //progressbar.OptionFullWidth(), 94 + //progressbar.OptionUseANSICodes(true), 95 + progressbar.OptionSetRenderBlankState(false), 96 + /*progressbar.OptionSetTheme(progressbar.Theme{ 97 + Saucer: "=", 98 + SaucerHead: ">", 99 + SaucerPadding: " ", 100 + BarStart: "[", 101 + BarEnd: "]", 102 + }),*/ 103 + ) 104 + ctx.ProgressBar = bar 105 + } 106 + 58 107 buf := new(bytes.Buffer) 59 - size, err := io.Copy(buf, input) 108 + var err error 109 + var size int64 110 + if bar != nil { 111 + size, err = io.Copy(io.MultiWriter(buf, bar), input) 112 + } else { 113 + size, err = io.Copy(buf, input) 114 + } 60 115 if err != nil { 61 116 log.Fatal(err) 62 117 } 63 118 ss.Size = int(size) 64 119 120 + if bar != nil { 121 + defer bar.Finish() 122 + defer bar.Clear() 123 + } 124 + 65 125 r, err := repo.ReadRepoFromCar(rctx, buf) 66 126 if err != nil { 67 127 return ss, err 68 128 } 69 - ss.Root = r.Head() 70 - var out []repo.RepoItem 71 - if err := r.ForEach(rctx, "", func(k string, v cid.Cid) error { 72 - _, rec, err := r.GetRecord(rctx, k) 73 - if err != nil { 74 - log.Println("Cannot get record:", v.String()) 75 - } 76 - out = append(out, repo.RepoItem{Cid: v, Path: k, Body: rec}) 77 - ss.Items = out 78 - return nil 79 - }); err != nil { 80 - return ss, err 81 - } 129 + ss.Repo = *r 82 130 return ss, nil 83 131 }
+3 -3
engine/walk.go
··· 31 31 return err 32 32 } 33 33 if !info.IsDir() { 34 - cb(Load(dir)) 34 + cb(Load(ctx, dir)) 35 35 return nil 36 36 } 37 37 err = filepath.Walk(dir, ··· 39 39 if err != nil { 40 40 return err 41 41 } 42 - cb(Load(fn)) 42 + cb(Load(ctx, fn)) 43 43 return nil 44 44 }) 45 45 if err != nil { ··· 49 49 } 50 50 51 51 func WalkStream(ctx *cli.Context, input io.Reader, cb func(repo.RepoSnapshot, error)) error { 52 - ss, err := LoadFromStream(input) 52 + ss, err := LoadFromStream(ctx, input, -1) 53 53 if err != nil { 54 54 log.Println("Cannot load from stream:", err) 55 55 return nil
+19 -14
go.mod
··· 4 4 5 5 require ( 6 6 github.com/alecthomas/chroma v0.10.0 7 - github.com/bluesky-social/indigo v0.0.0-20230714174244-57d75d8cfc65 7 + github.com/bluesky-social/indigo v0.0.0-20230718161430-1e5d9abdee8f 8 8 github.com/dustin/go-humanize v1.0.1 9 9 github.com/fatih/color v1.15.0 10 10 github.com/fxamacker/cbor/v2 v2.4.0 11 + github.com/ipfs/boxo v0.10.2 11 12 github.com/ipfs/go-cid v0.4.1 12 13 github.com/ipfs/go-datastore v0.6.0 13 - github.com/ipfs/go-ipfs-blockstore v1.3.0 14 14 github.com/ipfs/go-ipld-cbor v0.0.7-0.20230126201833-a73d038d90bc 15 15 github.com/ipld/go-car/v2 v2.10.1 16 16 github.com/itchyny/gojq v0.12.13 17 17 github.com/jmespath/go-jmespath v0.4.0 18 18 github.com/json-iterator/go v1.1.12 19 19 github.com/klauspost/compress v1.16.7 20 + github.com/schollz/progressbar/v3 v3.13.1 20 21 github.com/spf13/cobra v1.7.0 21 - github.com/whyrusleeping/cbor-gen v0.0.0-20230331140348-1f892b517e70 22 + github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0 22 23 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 23 24 ) 24 25 25 26 require ( 26 - github.com/dlclark/regexp2 v1.4.0 // indirect 27 + github.com/dlclark/regexp2 v1.10.0 // indirect 27 28 github.com/gogo/protobuf v1.3.2 // indirect 28 29 github.com/google/uuid v1.3.0 // indirect 29 30 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 30 31 github.com/hashicorp/go-hclog v1.2.0 // indirect 31 - github.com/hashicorp/go-retryablehttp v0.7.2 // indirect 32 + github.com/hashicorp/go-retryablehttp v0.7.4 // indirect 32 33 github.com/hashicorp/golang-lru v0.5.4 // indirect 33 34 github.com/inconshreveable/mousetrap v1.1.0 // indirect 34 35 github.com/ipfs/bbloom v0.0.4 // indirect 35 36 github.com/ipfs/go-block-format v0.1.2 // indirect 36 - github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect 37 - github.com/ipfs/go-ipfs-util v0.0.2 // indirect 37 + github.com/ipfs/go-ipfs-blockstore v1.3.1 // indirect 38 + github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect 39 + github.com/ipfs/go-ipfs-util v0.0.3 // indirect 38 40 github.com/ipfs/go-ipld-format v0.5.0 // indirect 39 41 github.com/ipfs/go-log v1.0.5 // indirect 40 42 github.com/ipfs/go-log/v2 v2.5.1 // indirect ··· 42 44 github.com/ipld/go-ipld-prime v0.20.0 // indirect 43 45 github.com/itchyny/timefmt-go v0.1.5 // indirect 44 46 github.com/jbenet/goprocess v0.1.4 // indirect 45 - github.com/klauspost/cpuid/v2 v2.2.4 // indirect 47 + github.com/klauspost/cpuid/v2 v2.2.5 // indirect 46 48 github.com/mattn/go-colorable v0.1.13 // indirect 47 49 github.com/mattn/go-isatty v0.0.19 // indirect 48 - github.com/minio/sha256-simd v1.0.0 // indirect 50 + github.com/mattn/go-runewidth v0.0.14 // indirect 51 + github.com/minio/sha256-simd v1.0.1 // indirect 52 + github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect 49 53 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 50 54 github.com/modern-go/reflect2 v1.0.2 // indirect 51 55 github.com/mr-tron/base58 v1.2.0 // indirect ··· 57 61 github.com/multiformats/go-varint v0.0.7 // indirect 58 62 github.com/opentracing/opentracing-go v1.2.0 // indirect 59 63 github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect 60 - github.com/pkg/errors v0.9.1 // indirect 61 64 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect 65 + github.com/rivo/uniseg v0.4.4 // indirect 62 66 github.com/spaolacci/murmur3 v1.1.0 // indirect 63 67 github.com/spf13/pflag v1.0.5 // indirect 64 68 github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect 65 69 github.com/x448/float16 v0.8.4 // indirect 66 - go.uber.org/atomic v1.10.0 // indirect 70 + go.uber.org/atomic v1.11.0 // indirect 67 71 go.uber.org/multierr v1.11.0 // indirect 68 72 go.uber.org/zap v1.24.0 // indirect 69 - golang.org/x/crypto v0.9.0 // indirect 70 - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect 73 + golang.org/x/crypto v0.11.0 // indirect 74 + golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect 71 75 golang.org/x/sys v0.10.0 // indirect 72 - lukechampine.com/blake3 v1.1.7 // indirect 76 + golang.org/x/term v0.10.0 // indirect 77 + lukechampine.com/blake3 v1.2.1 // indirect 73 78 )
+45 -39
go.sum
··· 1 1 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 2 2 github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= 3 3 github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= 4 - github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= 5 4 github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 6 - github.com/bluesky-social/indigo v0.0.0-20230714174244-57d75d8cfc65 h1:0z5rF7oA9eqqoAFoiHTfioBK8U4hzMmyGMoajEqJVFE= 7 - github.com/bluesky-social/indigo v0.0.0-20230714174244-57d75d8cfc65/go.mod h1:oDI5NiD0XzShv5VITWyUJNP3pSh4prTDEzhKbkdKORA= 5 + github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= 6 + github.com/bluesky-social/indigo v0.0.0-20230718161430-1e5d9abdee8f h1:UyXR9qPzchWhuGLam3UizuAmweGRmlLnq0fgKaT4Q2Y= 7 + github.com/bluesky-social/indigo v0.0.0-20230718161430-1e5d9abdee8f/go.mod h1:zhrvkTF/VhT/QxOvNVbc3B1w5pKugta0g08+H4YcMlU= 8 8 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 9 9 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 10 10 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 11 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 12 12 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 13 - github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= 14 13 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= 14 + github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= 15 + github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= 15 16 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 16 17 github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 17 18 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= ··· 27 28 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 28 29 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 29 30 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 30 - github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 31 31 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 32 32 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 33 - github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 34 33 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 34 + github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= 35 35 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 36 36 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 37 37 github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= 38 38 github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= 39 39 github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 40 - github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= 41 - github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= 40 + github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= 41 + github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= 42 42 github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= 43 43 github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 44 44 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 45 45 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 46 46 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= 47 47 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= 48 + github.com/ipfs/boxo v0.10.2 h1:kspw9HmMyKzLQxpKk417sF69i6iuf50AXtRjFqCYyL4= 49 + github.com/ipfs/boxo v0.10.2/go.mod h1:1qgKq45mPRCxf4ZPoJV2lnXxyxucigILMJOrQrVivv8= 48 50 github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= 49 51 github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo= 50 52 github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE= 51 - github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= 52 53 github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= 53 54 github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= 54 55 github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= 55 - github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= 56 56 github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk= 57 57 github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= 58 58 github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= 59 - github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= 60 - github.com/ipfs/go-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12XwJyvYvMM= 61 - github.com/ipfs/go-ipfs-blockstore v1.3.0/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE= 59 + github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ= 60 + github.com/ipfs/go-ipfs-blockstore v1.3.1/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE= 62 61 github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= 63 - github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= 64 - github.com/ipfs/go-ipfs-ds-help v1.1.0 h1:yLE2w9RAsl31LtfMt91tRZcrx+e61O5mDxFRR994w4Q= 65 - github.com/ipfs/go-ipfs-ds-help v1.1.0/go.mod h1:YR5+6EaebOhfcqVCyqemItCLthrpVNot+rsOU/5IatU= 66 - github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= 67 - github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= 62 + github.com/ipfs/go-ipfs-ds-help v1.1.1 h1:B5UJOH52IbcfS56+Ul+sv8jnIV10lbjLF5eOO0C66Nw= 63 + github.com/ipfs/go-ipfs-ds-help v1.1.1/go.mod h1:75vrVCkSdSFidJscs8n4W+77AtTpCIAdDGAwjitJMIo= 64 + github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0= 65 + github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs= 68 66 github.com/ipfs/go-ipld-cbor v0.0.7-0.20230126201833-a73d038d90bc h1:eUEo764smNy0EVRuMTSmirmuh552Mf2aBjfpDcLnDa8= 69 67 github.com/ipfs/go-ipld-cbor v0.0.7-0.20230126201833-a73d038d90bc/go.mod h1:X7SgEIwC4COC5OWfcepZBWafO5kA1Rmt9ZsLLbhihQk= 70 68 github.com/ipfs/go-ipld-format v0.5.0 h1:WyEle9K96MSrvr47zZHKKcDxJ/vlpET6PSiQsAFO+Ds= ··· 98 96 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 99 97 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 100 98 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 99 + github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= 101 100 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 102 101 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 103 102 github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= 104 103 github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 105 - github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 106 - github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 107 - github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= 108 - github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 104 + github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= 105 + github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= 109 106 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 110 - github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 111 107 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 112 108 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 113 109 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= ··· 120 116 github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= 121 117 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 122 118 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 119 + github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 123 120 github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= 124 121 github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 122 + github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= 123 + github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 125 124 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= 126 125 github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 127 - github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= 128 - github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= 126 + github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= 127 + github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= 128 + github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= 129 + github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= 129 130 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 130 131 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 131 132 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= ··· 141 142 github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= 142 143 github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= 143 144 github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= 144 - github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= 145 145 github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= 146 146 github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= 147 147 github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= ··· 159 159 github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= 160 160 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 161 161 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 162 - github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 163 162 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 164 163 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 165 164 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0= 166 165 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= 166 + github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 167 + github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= 168 + github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 167 169 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 168 170 github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= 169 171 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 170 172 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 173 + github.com/schollz/progressbar/v3 v3.13.1 h1:o8rySDYiQ59Mwzy2FELeHY5ZARXZTVJC7iHD6PEFUiE= 174 + github.com/schollz/progressbar/v3 v3.13.1/go.mod h1:xvrbki8kfT1fzWzBT/UZd9L6GA+jdL7HAgq2RFnO6fQ= 171 175 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 172 176 github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= 173 177 github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= ··· 191 195 github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= 192 196 github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= 193 197 github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= 194 - github.com/whyrusleeping/cbor-gen v0.0.0-20230331140348-1f892b517e70 h1:iNBzUKTsJc9RqStEVX2VYgVHATTU39IuB7g0e8OPWXU= 195 - github.com/whyrusleeping/cbor-gen v0.0.0-20230331140348-1f892b517e70/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 198 + github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0 h1:XYEgH2nJgsrcrj32p+SAbx6T3s/6QknOXezXtz7kzbg= 199 + github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 196 200 github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= 197 201 github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= 198 202 github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= ··· 201 205 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 202 206 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 203 207 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 204 - go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= 205 - go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 208 + go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= 209 + go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 206 210 go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 207 211 go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= 208 212 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= ··· 219 223 golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 220 224 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 221 225 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 222 - golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= 223 - golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= 224 - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= 225 - golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= 226 + golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= 227 + golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= 228 + golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= 229 + golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= 226 230 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 227 231 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 228 232 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= ··· 247 251 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 248 252 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 249 253 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 250 - golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 251 254 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 255 + golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 252 256 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 253 257 golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= 254 258 golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 255 259 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 260 + golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= 261 + golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= 262 + golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= 256 263 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 257 264 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 258 265 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= ··· 275 282 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 276 283 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 277 284 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 278 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 279 285 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 280 286 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 281 287 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= ··· 285 291 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 286 292 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 287 293 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 288 - lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= 289 - lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= 294 + lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= 295 + lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
-16
repo/ext.go
··· 1 - package repo 2 - 3 - import cid "github.com/ipfs/go-cid" 4 - 5 - type RepoItem struct { 6 - Cid cid.Cid 7 - Path string 8 - Body interface{} 9 - } 10 - 11 - type RepoSnapshot struct { 12 - Root cid.Cid 13 - File string 14 - Size int 15 - Items []RepoItem 16 - }
+63 -14
repo/repo.go
··· 9 9 10 10 "github.com/bluesky-social/indigo/mst" 11 11 "github.com/bluesky-social/indigo/util" 12 + blockstore "github.com/ipfs/boxo/blockstore" 12 13 "github.com/ipfs/go-cid" 13 14 "github.com/ipfs/go-datastore" 14 - blockstore "github.com/ipfs/go-ipfs-blockstore" 15 15 cbor "github.com/ipfs/go-ipld-cbor" 16 16 "github.com/ipld/go-car/v2" 17 17 ) 18 18 19 19 // current version of repo currently implemented 20 - const ATP_REPO_VERSION int64 = 2 20 + const ATP_REPO_VERSION int64 = 3 21 21 22 22 type SignedCommit struct { 23 23 Did string `cborgen:"did"` ··· 35 35 } 36 36 37 37 type Repo struct { 38 + Blocks int 39 + 38 40 sc SignedCommit 39 41 cst cbor.IpldStore 40 42 bs blockstore.Blockstore ··· 67 69 return buf.Bytes(), nil 68 70 }*/ 69 71 70 - func IngestRepo(ctx context.Context, bs blockstore.Blockstore, r io.Reader) (cid.Cid, error) { 72 + func IngestRepo(ctx context.Context, bs blockstore.Blockstore, r io.Reader) (cid.Cid, int, error) { 71 73 br, err := car.NewBlockReader(r) 72 74 if err != nil { 73 - return cid.Undef, err 75 + return cid.Undef, 0, err 74 76 } 75 77 78 + size := 0 76 79 for { 77 80 blk, err := br.Next() 78 81 if err != nil { 79 82 if err == io.EOF { 80 83 break 81 84 } 82 - return cid.Undef, err 85 + return cid.Undef, size, err 83 86 } 84 87 85 88 if err := bs.Put(ctx, blk); err != nil { 86 - return cid.Undef, err 89 + return cid.Undef, size, err 87 90 } 91 + size++ 88 92 } 89 93 90 - return br.Roots[0], nil 94 + return br.Roots[0], size, nil 91 95 } 92 96 93 97 func ReadRepoFromCar(ctx context.Context, r io.Reader) (*Repo, error) { 94 98 bs := blockstore.NewBlockstore(datastore.NewMapDatastore()) 95 - root, err := IngestRepo(ctx, bs, r) 99 + root, size, err := IngestRepo(ctx, bs, r) 96 100 if err != nil { 97 101 return nil, err 98 102 } 99 103 100 - return OpenRepo(ctx, bs, root, false) 104 + return OpenRepo(ctx, bs, root, size) 101 105 } 102 106 103 - func OpenRepo(ctx context.Context, bs blockstore.Blockstore, root cid.Cid, fullRepo bool) (*Repo, error) { 107 + func OpenRepo(ctx context.Context, bs blockstore.Blockstore, root cid.Cid, size int) (*Repo, error) { 104 108 cst := util.CborStore(bs) 105 109 106 110 var sc SignedCommit ··· 108 112 return nil, fmt.Errorf("loading root from blockstore: %w", err) 109 113 } 110 114 111 - if sc.Version != ATP_REPO_VERSION { 115 + if sc.Version > ATP_REPO_VERSION { 112 116 return nil, fmt.Errorf("unsupported repo version: %d", sc.Version) 113 117 } 114 118 ··· 117 121 bs: bs, 118 122 cst: cst, 119 123 repoCid: root, 124 + Blocks: size, 120 125 }, nil 121 126 } 122 127 128 + func (r *Repo) GetCommitsPath(len int) ([]cid.Cid, error) { 129 + path := []cid.Cid{} 130 + path = append(path, r.repoCid) 131 + if r.sc.Prev != nil { 132 + getParentCommits(r, *r.sc.Prev, &path, len-1) 133 + } 134 + return path, nil 135 + } 136 + 137 + func getParentCommits(r *Repo, c cid.Cid, p *[]cid.Cid, len int) ([]cid.Cid, error) { 138 + var sc SignedCommit 139 + ctx := context.TODO() 140 + if err := r.cst.Get(ctx, c, &sc); err != nil { 141 + return nil, fmt.Errorf("loading root from blockstore: %w", err) 142 + } 143 + *p = append(*p, c) 144 + if len == 0 { 145 + return nil, nil 146 + } else { 147 + len-- 148 + } 149 + if sc.Prev != nil { 150 + return getParentCommits(r, *sc.Prev, p, len) 151 + } 152 + return nil, nil 153 + } 154 + 123 155 func (r *Repo) Head() cid.Cid { 124 156 return r.repoCid 125 157 } 126 158 159 + func (r *Repo) SignedCommit() SignedCommit { 160 + return r.sc 161 + } 162 + 163 + func (r *Repo) MerkleSearchTree() *mst.MerkleSearchTree { 164 + return r.mst 165 + } 166 + 167 + func (r *Repo) BlockStore() blockstore.Blockstore { 168 + return r.bs 169 + } 170 + 127 171 func (r *Repo) getMst(ctx context.Context) (*mst.MerkleSearchTree, error) { 128 172 if r.mst != nil { 129 173 return r.mst, nil ··· 134 178 return t, nil 135 179 } 136 180 181 + func (r *Repo) MST() *mst.MerkleSearchTree { 182 + mst, _ := r.getMst(context.TODO()) 183 + return mst 184 + } 185 + 137 186 var ErrDoneIterating = fmt.Errorf("done iterating") 138 187 139 188 func (r *Repo) ForEach(ctx context.Context, prefix string, cb func(k string, v cid.Cid) error) error { 140 - t := mst.LoadMST(r.cst, r.sc.Data) 189 + t, _ := r.getMst(ctx) 141 190 142 191 if err := t.WalkLeavesFrom(ctx, prefix, cb); err != nil { 143 192 if err != ErrDoneIterating { ··· 148 197 return nil 149 198 } 150 199 151 - func (r *Repo) GetRecord(ctx context.Context, rpath string) (cid.Cid, interface{}, error) { 200 + func (r *Repo) GetRecord(ctx context.Context, rpath string) (cid.Cid, map[string]interface{}, error) { 152 201 mst, err := r.getMst(ctx) 153 202 if err != nil { 154 203 return cid.Undef, nil, fmt.Errorf("getting repo mst: %w", err) ··· 163 212 if err != nil { 164 213 return cid.Undef, nil, err 165 214 } 166 - var v interface{} 215 + var v map[string]interface{} 167 216 cbor2.Unmarshal(blk.RawData(), &v) 168 217 169 218 return cc, v, nil
+84
repo/snapshot.go
··· 1 + package repo 2 + 3 + import ( 4 + "context" 5 + "log" 6 + "strings" 7 + 8 + cid "github.com/ipfs/go-cid" 9 + ) 10 + 11 + type RepoItem struct { 12 + Cid cid.Cid 13 + Path string 14 + Body interface{} 15 + } 16 + 17 + type RepoSnapshot struct { 18 + Root cid.Cid 19 + File string 20 + Size int 21 + Items []RepoItem 22 + Repo Repo 23 + } 24 + 25 + func (ss *RepoSnapshot) GetCollectionStats(root string) (map[string]int, error) { 26 + rctx := context.TODO() 27 + 28 + rr := ss.Repo 29 + if root != "" && root != "b" { 30 + cid, err := cid.Parse(root) 31 + if err != nil { 32 + log.Fatalf("cannot parse CID: %s", root) 33 + } 34 + cr, err := OpenRepo(rctx, rr.BlockStore(), cid, 0) 35 + if err != nil { 36 + log.Fatal("cannot open repo") 37 + } 38 + rr = *cr 39 + } 40 + stats := make(map[string]int) 41 + if err := rr.ForEach(rctx, "", func(k string, v cid.Cid) error { 42 + col := strings.Split(k, "/")[0] 43 + _, ok := stats[col] 44 + if !ok { 45 + stats[col] = 0 46 + } 47 + stats[col]++ 48 + return nil 49 + }); err != nil { 50 + return nil, err 51 + } 52 + return stats, nil 53 + } 54 + 55 + func (ss *RepoSnapshot) LoadItems(root string) error { 56 + rctx := context.TODO() 57 + 58 + rr := ss.Repo 59 + if root != "" && root != "b" { 60 + cid, err := cid.Parse(root) 61 + if err != nil { 62 + log.Fatalf("cannot parse CID: %s", root) 63 + } 64 + cr, err := OpenRepo(rctx, rr.BlockStore(), cid, 0) 65 + if err != nil { 66 + log.Fatal("cannot open repo") 67 + } 68 + rr = *cr 69 + } 70 + 71 + var out []RepoItem 72 + if err := rr.ForEach(rctx, "", func(k string, v cid.Cid) error { 73 + _, rec, err := rr.GetRecord(rctx, k) 74 + if err != nil { 75 + log.Println("Cannot get record:", v.String()) 76 + } 77 + out = append(out, RepoItem{Cid: v, Path: k, Body: rec}) 78 + ss.Items = out 79 + return nil 80 + }); err != nil { 81 + return err 82 + } 83 + return nil 84 + }
+10
util/util.go
··· 1 + package util 2 + 3 + import "github.com/ipfs/go-cid" 4 + 5 + func ReverseCidSlice(arr []cid.Cid) []cid.Cid { 6 + for i, j := 0, len(arr)-1; i < j; i, j = i+1, j-1 { 7 + arr[i], arr[j] = arr[j], arr[i] 8 + } 9 + return arr 10 + }