AT Protocol IPLD-CAR Repository toolkit (CLI)
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

inspect cmd

tree 9e8b801d 010e62a4

+198 -144
+183 -134
cmd/atr.go
··· 1 1 package main 2 2 3 3 import ( 4 + "bytes" 4 5 "context" 5 6 "errors" 6 7 "fmt" ··· 17 18 "github.com/alecthomas/chroma/lexers" 18 19 "github.com/alecthomas/chroma/styles" 19 20 repo "github.com/atscan/atr/repo" 21 + "github.com/dustin/go-humanize" 22 + "github.com/fatih/color" 20 23 "github.com/ipfs/go-cid" 21 24 "github.com/itchyny/gojq" 22 25 jsoniter "github.com/json-iterator/go" ··· 37 40 }, 38 41 }, 39 42 Commands: []*cli.Command{ 40 - { 41 - Name: "grep", 42 - Aliases: []string{"g"}, 43 - Action: func(ctx *cli.Context) error { 44 - return nil 45 - }, 46 - }, 47 - { 48 - Name: "show", 49 - ArgsUsage: "[<target>]", 50 - Flags: []cli.Flag{ 51 - &cli.StringFlag{ 52 - Name: "type", 53 - Aliases: []string{"t"}, 54 - Usage: "Filter by item type", 55 - Value: "", 56 - }, 57 - &cli.StringFlag{ 58 - Name: "query", 59 - Aliases: []string{"q"}, 60 - Usage: "Query results (jq syntax)", 61 - Value: "", 62 - }, 63 - &cli.BoolFlag{ 64 - Name: "raw", 65 - Usage: "Do not use pretty print (faster)", 66 - Value: false, 67 - }, 68 - }, 69 - Action: func(ctx *cli.Context) error { 70 - //q := ctx.Args().First() 71 - q := ctx.String("query") 72 - var query *gojq.Query 73 - if q != "" { 74 - tq, err := gojq.Parse(q) 75 - if err != nil { 76 - log.Fatalln("gojq parse error:", err) 77 - //return err 78 - } else { 79 - query = tq 80 - } 81 - } 82 - 83 - eo, err := exec.Command("defaults", "read", "-g", "AppleInterfaceStyle").Output() 84 - if err != nil { 85 - log.Fatal(err) 86 - } 87 - style := "paraiso-dark" 88 - if strings.Index(string(eo), "Dark") != 0 { 89 - style = "paraiso-light" 90 - } 91 - hg := highlight(style) 92 - 93 - walk := func(list []RepoItem, err error) { 94 - 95 - for _, e := range list { 96 - tf := ctx.String("type") 97 - if tf != "" { 98 - if m := regexp.MustCompile(tf).Match([]byte(e.Path)); !m { 99 - continue 100 - } 101 - } 102 - var out interface{} 103 - if q != "" { 104 - json, err := jsoniter.Marshal(e.Body) 105 - if err != nil { 106 - log.Fatal("jsoniter error:", err) 107 - continue 108 - } 109 - var pv interface{} 110 - err = jsoniter.Unmarshal(json, &pv) 111 - if err != nil { 112 - log.Fatal("jsoniter error:", err) 113 - continue 114 - } 115 - iter := query.Run(interface{}(pv)) 116 - for { 117 - v, ok := iter.Next() 118 - if !ok { 119 - break 120 - } 121 - if err, ok := v.(error); ok { 122 - log.Fatalln("gojq iter error:", err) 123 - continue 124 - } 125 - if v == nil { 126 - continue 127 - } 128 - out = v 129 - } 130 - } else { 131 - out = e.Body 132 - } 133 - stat, _ := os.Stdout.Stat() 134 - if ((stat.Mode() & os.ModeCharDevice) != 0) && ctx.Bool("raw") == false { 135 - prettyPrint(out, hg) 136 - } else { 137 - print(out) 138 - } 139 - } 140 - } 141 - 142 - stat, _ := os.Stdin.Stat() 143 - if (stat.Mode() & os.ModeCharDevice) == 0 { 144 - // data is being piped to stdin 145 - WalkStream(ctx, os.Stdin, walk) 146 - } else { 147 - //stdin is from a terminal 148 - WalkFiles(ctx, walk) 149 - } 150 - return nil 151 - }, 152 - }, 43 + ShowCommand, 44 + InspectCommand, 153 45 }, 154 46 } 155 47 ··· 164 56 Body interface{} 165 57 } 166 58 167 - func WalkFiles(ctx *cli.Context, cb func([]RepoItem, error)) error { 59 + type RepoSnapshot struct { 60 + Root cid.Cid 61 + File string 62 + Size int 63 + Items []RepoItem 64 + } 65 + 66 + var InspectCommand = &cli.Command{ 67 + Name: "inspect", 68 + Aliases: []string{"i"}, 69 + Usage: "Inspect repo(s)", 70 + Action: func(ctx *cli.Context) error { 71 + 72 + walk := func(ss RepoSnapshot, err error) { 73 + if ss.Root.String() == "b" { 74 + return 75 + } 76 + if ss.File == "" { 77 + ss.File = "(pipe)" 78 + } 79 + yellow := color.New(color.FgYellow).SprintFunc() 80 + cyan := color.New(color.FgCyan).SprintFunc() 81 + fmt.Printf("%v\n Head: %s\n Size: %s Commits: %v\n\n", yellow(ss.File), cyan(ss.Root.String()), cyan(humanize.Bytes(uint64(ss.Size))), cyan(humanize.Comma(int64(len(ss.Items))))) 82 + } 83 + 84 + stat, _ := os.Stdin.Stat() 85 + if (stat.Mode() & os.ModeCharDevice) == 0 { 86 + // data is being piped to stdin 87 + WalkStream(ctx, os.Stdin, walk) 88 + } else { 89 + //stdin is from a terminal 90 + WalkFiles(ctx, walk) 91 + } 92 + return nil 93 + }, 94 + } 95 + 96 + var ShowCommand = &cli.Command{ 97 + Name: "show", 98 + Aliases: []string{"s"}, 99 + ArgsUsage: "[<target>]", 100 + Usage: "Show repo(s) documents", 101 + Flags: []cli.Flag{ 102 + &cli.StringFlag{ 103 + Name: "type", 104 + Aliases: []string{"t"}, 105 + Usage: "Filter by item type", 106 + Value: "", 107 + }, 108 + &cli.StringFlag{ 109 + Name: "query", 110 + Aliases: []string{"q"}, 111 + Usage: "Query results (jq syntax)", 112 + Value: "", 113 + }, 114 + &cli.BoolFlag{ 115 + Name: "raw", 116 + Usage: "Do not use pretty print (faster)", 117 + Value: false, 118 + }, 119 + }, 120 + Action: func(ctx *cli.Context) error { 121 + //q := ctx.Args().First() 122 + q := ctx.String("query") 123 + var query *gojq.Query 124 + if q != "" { 125 + tq, err := gojq.Parse(q) 126 + if err != nil { 127 + log.Fatalln("gojq parse error:", err) 128 + //return err 129 + } else { 130 + query = tq 131 + } 132 + } 133 + 134 + eo, err := exec.Command("defaults", "read", "-g", "AppleInterfaceStyle").Output() 135 + if err != nil { 136 + log.Fatal(err) 137 + } 138 + style := "paraiso-dark" 139 + if strings.Index(string(eo), "Dark") != 0 { 140 + style = "paraiso-light" 141 + } 142 + hg := highlight(style) 143 + 144 + walk := func(ss RepoSnapshot, err error) { 145 + 146 + for _, e := range ss.Items { 147 + tf := ctx.String("type") 148 + if tf != "" { 149 + if m := regexp.MustCompile(tf).Match([]byte(e.Path)); !m { 150 + continue 151 + } 152 + } 153 + var out interface{} 154 + if q != "" { 155 + json, err := jsoniter.Marshal(e.Body) 156 + if err != nil { 157 + log.Fatal("jsoniter error:", err) 158 + continue 159 + } 160 + var pv interface{} 161 + err = jsoniter.Unmarshal(json, &pv) 162 + if err != nil { 163 + log.Fatal("jsoniter error:", err) 164 + continue 165 + } 166 + iter := query.Run(interface{}(pv)) 167 + for { 168 + v, ok := iter.Next() 169 + if !ok { 170 + break 171 + } 172 + if err, ok := v.(error); ok { 173 + log.Fatalln("gojq iter error:", err) 174 + continue 175 + } 176 + if v == nil { 177 + continue 178 + } 179 + out = v 180 + } 181 + } else { 182 + out = e.Body 183 + } 184 + stat, _ := os.Stdout.Stat() 185 + if ((stat.Mode() & os.ModeCharDevice) != 0) && ctx.Bool("raw") == false { 186 + prettyPrint(out, hg) 187 + } else { 188 + print(out) 189 + } 190 + } 191 + } 192 + 193 + stat, _ := os.Stdin.Stat() 194 + if (stat.Mode() & os.ModeCharDevice) == 0 { 195 + // data is being piped to stdin 196 + WalkStream(ctx, os.Stdin, walk) 197 + } else { 198 + //stdin is from a terminal 199 + WalkFiles(ctx, walk) 200 + } 201 + return nil 202 + }, 203 + } 204 + 205 + func WalkFiles(ctx *cli.Context, cb func(RepoSnapshot, error)) error { 168 206 dir := ctx.Args().First() 169 207 if dir == "" { 170 208 dir = "." ··· 174 212 fmt.Println(err) 175 213 return err 176 214 } 177 - //fmt.Println(info.IsDir()) 178 - 179 215 if !info.IsDir() { 180 216 cb(Load(dir)) 181 217 return nil ··· 194 230 return nil 195 231 } 196 232 197 - func WalkStream(ctx *cli.Context, input io.Reader, cb func([]RepoItem, error)) error { 198 - arr, err := LoadFromStream(input) 233 + func WalkStream(ctx *cli.Context, input io.Reader, cb func(RepoSnapshot, error)) error { 234 + ss, err := LoadFromStream(input) 199 235 if err != nil { 236 + log.Println("Cannot load from stream:", err) 200 237 return nil 201 238 } 202 - cb(arr, nil) 239 + cb(ss, nil) 203 240 return nil 204 241 } 205 242 206 - func Load(fn string) ([]RepoItem, error) { 207 - var list []RepoItem 243 + func Load(fn string) (RepoSnapshot, error) { 244 + var ss RepoSnapshot 208 245 var err error 209 246 if strings.HasSuffix(fn, ".car.zst") { 210 - list, err = LoadCompressed(fn) 247 + ss, err = LoadCompressed(fn) 211 248 } else if strings.HasSuffix(fn, ".car") { 212 - list, err = LoadRaw(fn) 249 + ss, err = LoadRaw(fn) 213 250 } 214 251 if err != nil { 215 252 log.Fatal("Cannot load: ", fn) 216 - return list, errors.New("Cannot load") 253 + return ss, errors.New("Cannot load") 217 254 } 218 - return list, nil 255 + ss.File = fn 256 + return ss, nil 219 257 } 220 258 221 - func LoadRaw(fn string) ([]RepoItem, error) { 259 + func LoadRaw(fn string) (RepoSnapshot, error) { 222 260 dat, err := os.Open(fn) 223 261 defer dat.Close() 224 262 225 263 if err != nil { 226 - return nil, err 264 + return RepoSnapshot{}, err 227 265 } 228 266 return LoadFromStream(dat) 229 267 } 230 268 231 - func LoadCompressed(fn string) ([]RepoItem, error) { 269 + func LoadCompressed(fn string) (RepoSnapshot, error) { 232 270 dat, err := os.Open(fn) 233 271 defer dat.Close() 234 272 235 273 if err != nil { 236 - return nil, err 274 + return RepoSnapshot{}, err 237 275 } 238 276 decoder, _ := zstd.NewReader(dat) 239 277 return LoadFromStream(decoder) 240 278 } 241 279 242 - func LoadFromStream(input io.Reader) ([]RepoItem, error) { 280 + func LoadFromStream(input io.Reader) (RepoSnapshot, error) { 243 281 rctx := context.TODO() 244 - r, err := repo.ReadRepoFromCar(rctx, input) 282 + ss := RepoSnapshot{} 283 + 284 + buf := new(bytes.Buffer) 285 + size, err := io.Copy(buf, input) 286 + if err != nil { 287 + log.Fatal(err) 288 + } 289 + ss.Size = int(size) 290 + 291 + r, err := repo.ReadRepoFromCar(rctx, buf) 245 292 if err != nil { 246 - return nil, err 293 + return ss, err 247 294 } 295 + ss.Root = r.Head() 248 296 var out []RepoItem 249 297 if err := r.ForEach(rctx, "", func(k string, v cid.Cid) error { 250 298 _, rec, err := r.GetRecord(rctx, k) ··· 252 300 log.Println("Cannot get record:", v.String()) 253 301 } 254 302 out = append(out, RepoItem{Cid: v, Path: k, Body: rec}) 303 + ss.Items = out 255 304 return nil 256 305 }); err != nil { 257 - return nil, err 306 + return ss, err 258 307 } 259 - return out, nil 308 + return ss, nil 260 309 } 261 310 262 311 func print(v interface{}) error {
+3
go.mod
··· 5 5 require ( 6 6 github.com/alecthomas/chroma v0.10.0 7 7 github.com/bluesky-social/indigo v0.0.0-20230714174244-57d75d8cfc65 8 + github.com/dustin/go-humanize v1.0.1 9 + github.com/fatih/color v1.15.0 8 10 github.com/fxamacker/cbor/v2 v2.4.0 9 11 github.com/ipfs/go-cid v0.4.1 10 12 github.com/ipfs/go-datastore v0.6.0 ··· 39 41 github.com/itchyny/timefmt-go v0.1.5 // indirect 40 42 github.com/jbenet/goprocess v0.1.4 // indirect 41 43 github.com/klauspost/cpuid/v2 v2.2.4 // indirect 44 + github.com/mattn/go-colorable v0.1.13 // indirect 42 45 github.com/mattn/go-isatty v0.0.19 // indirect 43 46 github.com/minio/sha256-simd v1.0.0 // indirect 44 47 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
+8
go.sum
··· 13 13 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 14 14 github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= 15 15 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= 16 + github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 17 + github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 18 + github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= 19 + github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= 16 20 github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= 17 21 github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= 18 22 github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= ··· 102 106 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 103 107 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 104 108 github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= 109 + github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 110 + github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 105 111 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 112 + github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 106 113 github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= 107 114 github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 108 115 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= ··· 228 235 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 229 236 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 230 237 golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 238 + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 231 239 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 232 240 golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= 233 241 golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+4 -10
repo/repo.go
··· 120 120 }, nil 121 121 } 122 122 123 + func (r *Repo) Head() cid.Cid { 124 + return r.repoCid 125 + } 126 + 123 127 func (r *Repo) getMst(ctx context.Context) (*mst.MerkleSearchTree, error) { 124 128 if r.mst != nil { 125 129 return r.mst, nil ··· 159 163 if err != nil { 160 164 return cid.Undef, nil, err 161 165 } 162 - 163 - //fmt.Println(hex.EncodeToString(blk.RawData())) 164 - 165 166 var v interface{} 166 167 cbor2.Unmarshal(blk.RawData(), &v) 167 - 168 - //fmt.Println(string(json)) 169 - 170 - /*rec, err := lexutil.CborDecodeValue(blk.RawData()) 171 - if err != nil { 172 - return cid.Undef, nil, err 173 - }*/ 174 168 175 169 return cc, v, nil 176 170 }