+2
-2
Makefile
+2
-2
Makefile
···
9
9
10
10
.PHONY: build
11
11
build: ## Build all executables
12
-
go build ./cmd/atr.go
12
+
go build -ldflags "-X main._version=`git tag --sort=-version:refname | head -n 1`" ./atr.go
13
13
b:
14
14
@make build
15
15
16
16
install: ## Install all executables
17
-
go install -ldflags "-X main._version=`git tag --sort=-version:refname | head -n 1`" ./cmd/atr.go
17
+
go install -ldflags "-X main._version=`git tag --sort=-version:refname | head -n 1`" ./atr.go
18
18
i:
19
19
@make install
20
20
+15
atr.go
+15
atr.go
+6
cli/context.go
+6
cli/context.go
+31
cli/highlight.go
+31
cli/highlight.go
···
1
+
package cli
2
+
3
+
import (
4
+
"io"
5
+
6
+
"github.com/alecthomas/chroma"
7
+
"github.com/alecthomas/chroma/formatters"
8
+
"github.com/alecthomas/chroma/lexers"
9
+
"github.com/alecthomas/chroma/styles"
10
+
)
11
+
12
+
func Highlight(style string) func(w io.Writer, source string) {
13
+
// Determine lexer.
14
+
l := lexers.Get("json")
15
+
l = chroma.Coalesce(l)
16
+
17
+
// Determine formatter.
18
+
f := formatters.Get("terminal")
19
+
if f == nil {
20
+
f = formatters.Fallback
21
+
}
22
+
// Determine style.
23
+
s := styles.Get(style)
24
+
if s == nil {
25
+
s = styles.Fallback
26
+
}
27
+
return func(w io.Writer, source string) {
28
+
it, _ := l.Tokenise(nil, source)
29
+
f.Format(w, s, it)
30
+
}
31
+
}
+36
cli/print.go
+36
cli/print.go
···
1
+
package cli
2
+
3
+
import (
4
+
"fmt"
5
+
"io"
6
+
"log"
7
+
"os"
8
+
9
+
jsoniter "github.com/json-iterator/go"
10
+
)
11
+
12
+
func Print(v interface{}) error {
13
+
json, err := jsoniter.Marshal(v)
14
+
if err != nil {
15
+
log.Fatal(err)
16
+
}
17
+
s := string(json)
18
+
if s == "null" {
19
+
return nil
20
+
}
21
+
fmt.Println(string(json))
22
+
return nil
23
+
}
24
+
25
+
func PrettyPrint(v interface{}, hg func(io.Writer, string)) error {
26
+
json, err := jsoniter.MarshalIndent(v, "", " ")
27
+
if err != nil {
28
+
log.Fatal(err)
29
+
}
30
+
s := string(json)
31
+
if s == "null" {
32
+
return nil
33
+
}
34
+
hg(os.Stdout, s+"\n")
35
+
return nil
36
+
}
+51
cmd/atr-inspect.go
+51
cmd/atr-inspect.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/dustin/go-humanize"
11
+
"github.com/fatih/color"
12
+
"github.com/spf13/cobra"
13
+
)
14
+
15
+
func init() {
16
+
rootCmd.AddCommand(InspectCmd)
17
+
}
18
+
19
+
var InspectCmd = &cobra.Command{
20
+
Use: "inspect",
21
+
Aliases: []string{"i"},
22
+
Short: "Inspect repo(s)",
23
+
Long: ``,
24
+
Run: func(cmd *cobra.Command, args []string) {
25
+
ctx := cli.Context{
26
+
WorkingDir: workingDir,
27
+
Args: args,
28
+
}
29
+
30
+
walk := func(ss repo.RepoSnapshot, err error) {
31
+
if ss.Root.String() == "b" {
32
+
return
33
+
}
34
+
if ss.File == "" {
35
+
ss.File = "(pipe)"
36
+
}
37
+
yellow := color.New(color.FgYellow).SprintFunc()
38
+
cyan := color.New(color.FgCyan).SprintFunc()
39
+
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)))))
40
+
}
41
+
42
+
stat, _ := os.Stdin.Stat()
43
+
if (stat.Mode() & os.ModeCharDevice) == 0 {
44
+
// data is being piped to stdin
45
+
engine.WalkStream(&ctx, os.Stdin, walk)
46
+
} else {
47
+
//stdin is from a terminal
48
+
engine.WalkFiles(&ctx, walk)
49
+
}
50
+
},
51
+
}
+144
cmd/atr-show.go
+144
cmd/atr-show.go
···
1
+
package cmd
2
+
3
+
import (
4
+
"log"
5
+
"os"
6
+
"os/exec"
7
+
"regexp"
8
+
"strings"
9
+
10
+
"github.com/atscan/atr/cli"
11
+
"github.com/atscan/atr/engine"
12
+
"github.com/atscan/atr/repo"
13
+
"github.com/itchyny/gojq"
14
+
"github.com/jmespath/go-jmespath"
15
+
jsoniter "github.com/json-iterator/go"
16
+
"github.com/spf13/cobra"
17
+
)
18
+
19
+
var (
20
+
Query string
21
+
QueryJmes string
22
+
Type string
23
+
Raw bool
24
+
)
25
+
26
+
func init() {
27
+
rootCmd.AddCommand(ShowCmd)
28
+
ShowCmd.Flags().StringVarP(&Type, "type", "t", "", "Filter by item type")
29
+
ShowCmd.Flags().StringVarP(&Query, "query", "q", "", "Query results (jq)")
30
+
ShowCmd.Flags().StringVarP(&QueryJmes, "query-jmes", "x", "", "Query results (jmespath)")
31
+
ShowCmd.Flags().BoolVar(&Raw, "raw", false, "Do not use colors (faster)")
32
+
}
33
+
34
+
var ShowCmd = &cobra.Command{
35
+
Use: "show",
36
+
Aliases: []string{"s"},
37
+
Short: "Show repo(s) documents",
38
+
Long: ``,
39
+
Run: func(cmd *cobra.Command, args []string) {
40
+
ctx := cli.Context{
41
+
WorkingDir: workingDir,
42
+
Args: args,
43
+
}
44
+
45
+
//q := ctx.Args().First()
46
+
q := Query
47
+
var query *gojq.Query
48
+
if q != "" {
49
+
tq, err := gojq.Parse(q)
50
+
if err != nil {
51
+
log.Fatalln("gojq parse error:", err)
52
+
//return err
53
+
} else {
54
+
query = tq
55
+
}
56
+
}
57
+
qq := QueryJmes
58
+
var queryJmes *jmespath.JMESPath
59
+
if qq != "" {
60
+
jc, err := jmespath.Compile(qq)
61
+
if err != nil {
62
+
return
63
+
}
64
+
queryJmes = jc
65
+
}
66
+
67
+
eo, err := exec.Command("defaults", "read", "-g", "AppleInterfaceStyle").Output()
68
+
if err != nil {
69
+
log.Fatal(err)
70
+
}
71
+
style := "paraiso-dark"
72
+
if strings.Index(string(eo), "Dark") != 0 {
73
+
style = "paraiso-light"
74
+
}
75
+
hg := cli.Highlight(style)
76
+
77
+
walk := func(ss repo.RepoSnapshot, err error) {
78
+
79
+
for _, e := range ss.Items {
80
+
tf := Type
81
+
if tf != "" {
82
+
if m := regexp.MustCompile(tf).Match([]byte(e.Path)); !m {
83
+
continue
84
+
}
85
+
}
86
+
var out interface{}
87
+
if q != "" || qq != "" {
88
+
json, err := jsoniter.Marshal(e.Body)
89
+
if err != nil {
90
+
log.Fatal("jsoniter error:", err)
91
+
continue
92
+
}
93
+
var pv interface{}
94
+
err = jsoniter.Unmarshal(json, &pv)
95
+
if err != nil {
96
+
log.Fatal("jsoniter error:", err)
97
+
continue
98
+
}
99
+
if q != "" {
100
+
iter := query.Run(interface{}(pv))
101
+
for {
102
+
v, ok := iter.Next()
103
+
if !ok {
104
+
break
105
+
}
106
+
if err, ok := v.(error); ok {
107
+
log.Fatalln("gojq iter error:", err)
108
+
continue
109
+
}
110
+
if v == nil {
111
+
continue
112
+
}
113
+
out = v
114
+
}
115
+
}
116
+
if qq != "" {
117
+
r, err := queryJmes.Search(pv)
118
+
if err != nil {
119
+
log.Fatalln("jmespath error:", err)
120
+
}
121
+
out = r
122
+
}
123
+
} else {
124
+
out = e.Body
125
+
}
126
+
stat, _ := os.Stdout.Stat()
127
+
if !Raw && (stat.Mode()&os.ModeCharDevice) != 0 {
128
+
cli.PrettyPrint(out, hg)
129
+
} else {
130
+
cli.Print(out)
131
+
}
132
+
}
133
+
}
134
+
135
+
stat, _ := os.Stdin.Stat()
136
+
if (stat.Mode() & os.ModeCharDevice) == 0 {
137
+
// data is being piped to stdin
138
+
engine.WalkStream(&ctx, os.Stdin, walk)
139
+
} else {
140
+
//stdin is from a terminal
141
+
engine.WalkFiles(&ctx, walk)
142
+
}
143
+
},
144
+
}
-390
cmd/atr.go
-390
cmd/atr.go
···
1
-
package main
2
-
3
-
import (
4
-
"bytes"
5
-
"context"
6
-
"errors"
7
-
"fmt"
8
-
"io"
9
-
"log"
10
-
"os"
11
-
"os/exec"
12
-
"path/filepath"
13
-
"regexp"
14
-
"strings"
15
-
"syscall"
16
-
17
-
"github.com/alecthomas/chroma"
18
-
"github.com/alecthomas/chroma/formatters"
19
-
"github.com/alecthomas/chroma/lexers"
20
-
"github.com/alecthomas/chroma/styles"
21
-
repo "github.com/atscan/atr/repo"
22
-
"github.com/dustin/go-humanize"
23
-
"github.com/fatih/color"
24
-
"github.com/ipfs/go-cid"
25
-
"github.com/itchyny/gojq"
26
-
"github.com/jmespath/go-jmespath"
27
-
jsoniter "github.com/json-iterator/go"
28
-
"github.com/klauspost/compress/zstd"
29
-
"github.com/urfave/cli/v2"
30
-
)
31
-
32
-
var _version string
33
-
34
-
func main() {
35
-
36
-
app := &cli.App{
37
-
Name: "atr",
38
-
Usage: "AT Protocol IPLD-CAR Repository toolkit",
39
-
Version: _version,
40
-
Flags: []cli.Flag{
41
-
&cli.StringFlag{
42
-
Name: "C",
43
-
Usage: "Working directory",
44
-
Value: ".",
45
-
},
46
-
},
47
-
Commands: []*cli.Command{
48
-
ShowCommand,
49
-
InspectCommand,
50
-
},
51
-
}
52
-
53
-
if err := app.Run(os.Args); err != nil {
54
-
log.Fatal(err)
55
-
}
56
-
}
57
-
58
-
type RepoItem struct {
59
-
Cid cid.Cid
60
-
Path string
61
-
Body interface{}
62
-
}
63
-
64
-
type RepoSnapshot struct {
65
-
Root cid.Cid
66
-
File string
67
-
Size int
68
-
Items []RepoItem
69
-
}
70
-
71
-
var InspectCommand = &cli.Command{
72
-
Name: "inspect",
73
-
Aliases: []string{"i"},
74
-
Usage: "Inspect repo(s)",
75
-
Action: func(ctx *cli.Context) error {
76
-
77
-
walk := func(ss RepoSnapshot, err error) {
78
-
if ss.Root.String() == "b" {
79
-
return
80
-
}
81
-
if ss.File == "" {
82
-
ss.File = "(pipe)"
83
-
}
84
-
yellow := color.New(color.FgYellow).SprintFunc()
85
-
cyan := color.New(color.FgCyan).SprintFunc()
86
-
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)))))
87
-
}
88
-
89
-
stat, _ := os.Stdin.Stat()
90
-
if (stat.Mode() & os.ModeCharDevice) == 0 {
91
-
// data is being piped to stdin
92
-
WalkStream(ctx, os.Stdin, walk)
93
-
} else {
94
-
//stdin is from a terminal
95
-
WalkFiles(ctx, walk)
96
-
}
97
-
return nil
98
-
},
99
-
}
100
-
101
-
var ShowCommand = &cli.Command{
102
-
Name: "show",
103
-
Aliases: []string{"s"},
104
-
ArgsUsage: "[<target>]",
105
-
Usage: "Show repo(s) documents",
106
-
Flags: []cli.Flag{
107
-
&cli.StringFlag{
108
-
Name: "type",
109
-
Aliases: []string{"t"},
110
-
Usage: "Filter by item type",
111
-
Value: "",
112
-
},
113
-
&cli.StringFlag{
114
-
Name: "query",
115
-
Aliases: []string{"q"},
116
-
Usage: "Query results (jq)",
117
-
Value: "",
118
-
},
119
-
&cli.StringFlag{
120
-
Name: "query-jmes",
121
-
Aliases: []string{"qq"},
122
-
Usage: "Query results (jmespath)",
123
-
Value: "",
124
-
},
125
-
&cli.BoolFlag{
126
-
Name: "raw",
127
-
Usage: "Do not use pretty print (faster)",
128
-
Value: false,
129
-
},
130
-
},
131
-
Action: func(ctx *cli.Context) error {
132
-
//q := ctx.Args().First()
133
-
q := ctx.String("query")
134
-
var query *gojq.Query
135
-
if q != "" {
136
-
tq, err := gojq.Parse(q)
137
-
if err != nil {
138
-
log.Fatalln("gojq parse error:", err)
139
-
//return err
140
-
} else {
141
-
query = tq
142
-
}
143
-
}
144
-
qq := ctx.String("query-jmes")
145
-
var queryJmes *jmespath.JMESPath
146
-
if qq != "" {
147
-
jc, err := jmespath.Compile(qq)
148
-
if err != nil {
149
-
return err
150
-
}
151
-
queryJmes = jc
152
-
}
153
-
154
-
eo, err := exec.Command("defaults", "read", "-g", "AppleInterfaceStyle").Output()
155
-
if err != nil {
156
-
log.Fatal(err)
157
-
}
158
-
style := "paraiso-dark"
159
-
if strings.Index(string(eo), "Dark") != 0 {
160
-
style = "paraiso-light"
161
-
}
162
-
hg := highlight(style)
163
-
164
-
walk := func(ss RepoSnapshot, err error) {
165
-
166
-
for _, e := range ss.Items {
167
-
tf := ctx.String("type")
168
-
if tf != "" {
169
-
if m := regexp.MustCompile(tf).Match([]byte(e.Path)); !m {
170
-
continue
171
-
}
172
-
}
173
-
var out interface{}
174
-
if q != "" || qq != "" {
175
-
json, err := jsoniter.Marshal(e.Body)
176
-
if err != nil {
177
-
log.Fatal("jsoniter error:", err)
178
-
continue
179
-
}
180
-
var pv interface{}
181
-
err = jsoniter.Unmarshal(json, &pv)
182
-
if err != nil {
183
-
log.Fatal("jsoniter error:", err)
184
-
continue
185
-
}
186
-
if q != "" {
187
-
iter := query.Run(interface{}(pv))
188
-
for {
189
-
v, ok := iter.Next()
190
-
if !ok {
191
-
break
192
-
}
193
-
if err, ok := v.(error); ok {
194
-
log.Fatalln("gojq iter error:", err)
195
-
continue
196
-
}
197
-
if v == nil {
198
-
continue
199
-
}
200
-
out = v
201
-
}
202
-
}
203
-
if qq != "" {
204
-
r, err := queryJmes.Search(pv)
205
-
if err != nil {
206
-
log.Fatalln("jmespath error:", err)
207
-
}
208
-
out = r
209
-
}
210
-
} else {
211
-
out = e.Body
212
-
}
213
-
stat, _ := os.Stdout.Stat()
214
-
if ((stat.Mode() & os.ModeCharDevice) != 0) && ctx.Bool("raw") == false {
215
-
prettyPrint(out, hg)
216
-
} else {
217
-
print(out)
218
-
}
219
-
}
220
-
}
221
-
222
-
stat, _ := os.Stdin.Stat()
223
-
if (stat.Mode() & os.ModeCharDevice) == 0 {
224
-
// data is being piped to stdin
225
-
WalkStream(ctx, os.Stdin, walk)
226
-
} else {
227
-
//stdin is from a terminal
228
-
WalkFiles(ctx, walk)
229
-
}
230
-
return nil
231
-
},
232
-
}
233
-
234
-
func WalkFiles(ctx *cli.Context, cb func(RepoSnapshot, error)) error {
235
-
wd := ctx.String("C")
236
-
if wd != "." {
237
-
syscall.Chdir(wd)
238
-
}
239
-
240
-
dir := ctx.Args().First()
241
-
if dir == "" {
242
-
dir = "."
243
-
}
244
-
info, err := os.Stat(dir)
245
-
if err != nil {
246
-
fmt.Println(err)
247
-
return err
248
-
}
249
-
if !info.IsDir() {
250
-
cb(Load(dir))
251
-
return nil
252
-
}
253
-
err = filepath.Walk(dir,
254
-
func(fn string, info os.FileInfo, err error) error {
255
-
if err != nil {
256
-
return err
257
-
}
258
-
cb(Load(fn))
259
-
return nil
260
-
})
261
-
if err != nil {
262
-
log.Println(err)
263
-
}
264
-
return nil
265
-
}
266
-
267
-
func WalkStream(ctx *cli.Context, input io.Reader, cb func(RepoSnapshot, error)) error {
268
-
ss, err := LoadFromStream(input)
269
-
if err != nil {
270
-
log.Println("Cannot load from stream:", err)
271
-
return nil
272
-
}
273
-
cb(ss, nil)
274
-
return nil
275
-
}
276
-
277
-
func Load(fn string) (RepoSnapshot, error) {
278
-
var ss RepoSnapshot
279
-
var err error
280
-
if strings.HasSuffix(fn, ".car.zst") {
281
-
ss, err = LoadCompressed(fn)
282
-
} else if strings.HasSuffix(fn, ".car") {
283
-
ss, err = LoadRaw(fn)
284
-
}
285
-
if err != nil {
286
-
log.Fatal("Cannot load: ", fn)
287
-
return ss, errors.New("Cannot load")
288
-
}
289
-
ss.File = fn
290
-
return ss, nil
291
-
}
292
-
293
-
func LoadRaw(fn string) (RepoSnapshot, error) {
294
-
dat, err := os.Open(fn)
295
-
defer dat.Close()
296
-
297
-
if err != nil {
298
-
return RepoSnapshot{}, err
299
-
}
300
-
return LoadFromStream(dat)
301
-
}
302
-
303
-
func LoadCompressed(fn string) (RepoSnapshot, error) {
304
-
dat, err := os.Open(fn)
305
-
defer dat.Close()
306
-
307
-
if err != nil {
308
-
return RepoSnapshot{}, err
309
-
}
310
-
decoder, _ := zstd.NewReader(dat)
311
-
return LoadFromStream(decoder)
312
-
}
313
-
314
-
func LoadFromStream(input io.Reader) (RepoSnapshot, error) {
315
-
rctx := context.TODO()
316
-
ss := RepoSnapshot{}
317
-
318
-
buf := new(bytes.Buffer)
319
-
size, err := io.Copy(buf, input)
320
-
if err != nil {
321
-
log.Fatal(err)
322
-
}
323
-
ss.Size = int(size)
324
-
325
-
r, err := repo.ReadRepoFromCar(rctx, buf)
326
-
if err != nil {
327
-
return ss, err
328
-
}
329
-
ss.Root = r.Head()
330
-
var out []RepoItem
331
-
if err := r.ForEach(rctx, "", func(k string, v cid.Cid) error {
332
-
_, rec, err := r.GetRecord(rctx, k)
333
-
if err != nil {
334
-
log.Println("Cannot get record:", v.String())
335
-
}
336
-
out = append(out, RepoItem{Cid: v, Path: k, Body: rec})
337
-
ss.Items = out
338
-
return nil
339
-
}); err != nil {
340
-
return ss, err
341
-
}
342
-
return ss, nil
343
-
}
344
-
345
-
func print(v interface{}) error {
346
-
json, err := jsoniter.Marshal(v)
347
-
if err != nil {
348
-
log.Fatal(err)
349
-
}
350
-
s := string(json)
351
-
if s == "null" {
352
-
return nil
353
-
}
354
-
fmt.Println(string(json))
355
-
return nil
356
-
}
357
-
358
-
func prettyPrint(v interface{}, hg func(io.Writer, string)) error {
359
-
json, err := jsoniter.MarshalIndent(v, "", " ")
360
-
if err != nil {
361
-
log.Fatal(err)
362
-
}
363
-
s := string(json)
364
-
if s == "null" {
365
-
return nil
366
-
}
367
-
hg(os.Stdout, s+"\n")
368
-
return nil
369
-
}
370
-
371
-
func highlight(style string) func(w io.Writer, source string) {
372
-
// Determine lexer.
373
-
l := lexers.Get("json")
374
-
l = chroma.Coalesce(l)
375
-
376
-
// Determine formatter.
377
-
f := formatters.Get("terminal")
378
-
if f == nil {
379
-
f = formatters.Fallback
380
-
}
381
-
// Determine style.
382
-
s := styles.Get(style)
383
-
if s == nil {
384
-
s = styles.Fallback
385
-
}
386
-
return func(w io.Writer, source string) {
387
-
it, _ := l.Tokenise(nil, source)
388
-
f.Format(w, s, it)
389
-
}
390
-
}
+64
cmd/root.go
+64
cmd/root.go
···
1
+
package cmd
2
+
3
+
import (
4
+
"fmt"
5
+
6
+
"github.com/atscan/atr/util/version"
7
+
"github.com/spf13/cobra"
8
+
)
9
+
10
+
var (
11
+
// Used for flags.
12
+
//cfgFile string
13
+
workingDir string
14
+
15
+
rootCmd = &cobra.Command{
16
+
Use: "atr",
17
+
Short: "AT Protocol IPLD-CAR Repository toolkit",
18
+
//Long: `.`,
19
+
}
20
+
)
21
+
22
+
// Execute executes the root command.
23
+
func Execute() error {
24
+
return rootCmd.Execute()
25
+
}
26
+
27
+
func init() {
28
+
//cobra.OnInitialize(initConfig)
29
+
30
+
rootCmd.PersistentFlags().StringVarP(&workingDir, "working-dir", "C", ".", "")
31
+
32
+
//rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
33
+
rootCmd.AddCommand(versionCmd)
34
+
//rootCmd.AddCommand(ShowCmd)
35
+
}
36
+
37
+
/*func initConfig() {
38
+
if cfgFile != "" {
39
+
// Use config file from the flag.
40
+
//viper.SetConfigFile(cfgFile)
41
+
} else {
42
+
// Find home directory.
43
+
//home, err := os.UserHomeDir()
44
+
//cobra.CheckErr(err)
45
+
46
+
viper.AddConfigPath(home)
47
+
viper.SetConfigType("yaml")
48
+
viper.SetConfigName(".atr")
49
+
}
50
+
51
+
//viper.AutomaticEnv()
52
+
53
+
if err := viper.ReadInConfig(); err == nil {
54
+
fmt.Println("Using config file:", viper.ConfigFileUsed())
55
+
}
56
+
}*/
57
+
58
+
var versionCmd = &cobra.Command{
59
+
Use: "version",
60
+
Short: "Print the version number",
61
+
Run: func(cmd *cobra.Command, args []string) {
62
+
fmt.Println(version.Version(""))
63
+
},
64
+
}
+1
engine/file.go
+1
engine/file.go
···
1
+
package engine
+83
engine/io.go
+83
engine/io.go
···
1
+
package engine
2
+
3
+
import (
4
+
"bytes"
5
+
"context"
6
+
"errors"
7
+
"io"
8
+
"log"
9
+
"os"
10
+
"strings"
11
+
12
+
"github.com/atscan/atr/repo"
13
+
"github.com/ipfs/go-cid"
14
+
"github.com/klauspost/compress/zstd"
15
+
)
16
+
17
+
func Load(fn string) (repo.RepoSnapshot, error) {
18
+
var ss repo.RepoSnapshot
19
+
var err error
20
+
if strings.HasSuffix(fn, ".car.zst") {
21
+
ss, err = LoadCompressed(fn)
22
+
} else if strings.HasSuffix(fn, ".car") {
23
+
ss, err = LoadRaw(fn)
24
+
}
25
+
if err != nil {
26
+
log.Fatal("Cannot load: ", fn)
27
+
return ss, errors.New("Cannot load")
28
+
}
29
+
ss.File = fn
30
+
return ss, nil
31
+
}
32
+
33
+
func LoadRaw(fn string) (repo.RepoSnapshot, error) {
34
+
dat, err := os.Open(fn)
35
+
defer dat.Close()
36
+
37
+
if err != nil {
38
+
return repo.RepoSnapshot{}, err
39
+
}
40
+
return LoadFromStream(dat)
41
+
}
42
+
43
+
func LoadCompressed(fn string) (repo.RepoSnapshot, error) {
44
+
dat, err := os.Open(fn)
45
+
defer dat.Close()
46
+
47
+
if err != nil {
48
+
return repo.RepoSnapshot{}, err
49
+
}
50
+
decoder, _ := zstd.NewReader(dat)
51
+
return LoadFromStream(decoder)
52
+
}
53
+
54
+
func LoadFromStream(input io.Reader) (repo.RepoSnapshot, error) {
55
+
rctx := context.TODO()
56
+
ss := repo.RepoSnapshot{}
57
+
58
+
buf := new(bytes.Buffer)
59
+
size, err := io.Copy(buf, input)
60
+
if err != nil {
61
+
log.Fatal(err)
62
+
}
63
+
ss.Size = int(size)
64
+
65
+
r, err := repo.ReadRepoFromCar(rctx, buf)
66
+
if err != nil {
67
+
return ss, err
68
+
}
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
+
}
82
+
return ss, nil
83
+
}
+59
engine/walk.go
+59
engine/walk.go
···
1
+
package engine
2
+
3
+
import (
4
+
"fmt"
5
+
"io"
6
+
"log"
7
+
"os"
8
+
"path/filepath"
9
+
"syscall"
10
+
11
+
"github.com/atscan/atr/cli"
12
+
"github.com/atscan/atr/repo"
13
+
)
14
+
15
+
func WalkFiles(ctx *cli.Context, cb func(repo.RepoSnapshot, error)) error {
16
+
wd := ctx.WorkingDir
17
+
if wd != "." {
18
+
syscall.Chdir(wd)
19
+
}
20
+
21
+
dir := "."
22
+
if len(ctx.Args) > 0 {
23
+
dir = ctx.Args[0]
24
+
}
25
+
if dir == "" {
26
+
dir = "."
27
+
}
28
+
info, err := os.Stat(dir)
29
+
if err != nil {
30
+
fmt.Println(err)
31
+
return err
32
+
}
33
+
if !info.IsDir() {
34
+
cb(Load(dir))
35
+
return nil
36
+
}
37
+
err = filepath.Walk(dir,
38
+
func(fn string, info os.FileInfo, err error) error {
39
+
if err != nil {
40
+
return err
41
+
}
42
+
cb(Load(fn))
43
+
return nil
44
+
})
45
+
if err != nil {
46
+
log.Println(err)
47
+
}
48
+
return nil
49
+
}
50
+
51
+
func WalkStream(ctx *cli.Context, input io.Reader, cb func(repo.RepoSnapshot, error)) error {
52
+
ss, err := LoadFromStream(input)
53
+
if err != nil {
54
+
log.Println("Cannot load from stream:", err)
55
+
return nil
56
+
}
57
+
cb(ss, nil)
58
+
return nil
59
+
}
+5
-7
go.mod
+5
-7
go.mod
···
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/urfave/cli/v2 v2.25.7
20
+
github.com/spf13/cobra v1.7.0
21
21
github.com/whyrusleeping/cbor-gen v0.0.0-20230331140348-1f892b517e70
22
22
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2
23
23
)
24
24
25
25
require (
26
-
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
27
26
github.com/dlclark/regexp2 v1.4.0 // indirect
28
27
github.com/gogo/protobuf v1.3.2 // indirect
29
28
github.com/google/uuid v1.3.0 // indirect
30
29
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
30
+
github.com/hashicorp/go-hclog v1.2.0 // indirect
31
31
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
32
32
github.com/hashicorp/golang-lru v0.5.4 // indirect
33
33
github.com/inconshreveable/mousetrap v1.1.0 // indirect
···
46
46
github.com/mattn/go-colorable v0.1.13 // indirect
47
47
github.com/mattn/go-isatty v0.0.19 // indirect
48
48
github.com/minio/sha256-simd v1.0.0 // indirect
49
-
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
49
+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
50
50
github.com/modern-go/reflect2 v1.0.2 // indirect
51
51
github.com/mr-tron/base58 v1.2.0 // indirect
52
52
github.com/multiformats/go-base32 v0.1.0 // indirect
···
57
57
github.com/multiformats/go-varint v0.0.7 // indirect
58
58
github.com/opentracing/opentracing-go v1.2.0 // indirect
59
59
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
60
+
github.com/pkg/errors v0.9.1 // indirect
60
61
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect
61
-
github.com/russross/blackfriday/v2 v2.1.0 // indirect
62
62
github.com/spaolacci/murmur3 v1.1.0 // indirect
63
-
github.com/spf13/cobra v1.7.0 // indirect
64
63
github.com/spf13/pflag v1.0.5 // indirect
65
64
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect
66
65
github.com/x448/float16 v0.8.4 // indirect
67
-
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
68
66
go.uber.org/atomic v1.10.0 // indirect
69
67
go.uber.org/multierr v1.11.0 // indirect
70
68
go.uber.org/zap v1.24.0 // indirect
71
-
golang.org/x/crypto v0.7.0 // indirect
69
+
golang.org/x/crypto v0.9.0 // indirect
72
70
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
73
71
golang.org/x/sys v0.10.0 // indirect
74
72
lukechampine.com/blake3 v1.1.7 // indirect
+14
-11
go.sum
+14
-11
go.sum
···
6
6
github.com/bluesky-social/indigo v0.0.0-20230714174244-57d75d8cfc65 h1:0z5rF7oA9eqqoAFoiHTfioBK8U4hzMmyGMoajEqJVFE=
7
7
github.com/bluesky-social/indigo v0.0.0-20230714174244-57d75d8cfc65/go.mod h1:oDI5NiD0XzShv5VITWyUJNP3pSh4prTDEzhKbkdKORA=
8
8
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
9
-
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
10
9
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
11
10
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
···
15
14
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
16
15
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
17
16
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
17
+
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
18
18
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
19
19
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
20
20
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
···
34
34
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
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
-
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
38
37
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
38
+
github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
39
+
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
39
40
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
40
41
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
41
42
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
···
112
113
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
113
114
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
114
115
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
116
+
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
115
117
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
116
118
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
119
+
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
120
+
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
117
121
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
118
122
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
119
123
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
···
122
126
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
123
127
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
124
128
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
125
-
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
126
129
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
130
+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
131
+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
127
132
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
128
133
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
129
134
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
···
152
157
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
153
158
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk=
154
159
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw=
155
-
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
156
160
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
161
+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
162
+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
157
163
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
158
164
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
159
165
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0=
···
161
167
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
162
168
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
163
169
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
164
-
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
165
170
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
166
171
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
167
172
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
···
181
186
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
182
187
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
183
188
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
184
-
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
185
-
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
186
189
github.com/warpfork/go-testmark v0.11.0 h1:J6LnV8KpceDvo7spaNU4+DauH2n1x+6RaO2rJrmpQ9U=
187
190
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
188
191
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
···
193
196
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=
194
197
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
195
198
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
196
-
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
197
-
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
198
199
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
199
200
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
200
201
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
···
218
219
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
219
220
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
220
221
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
221
-
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
222
-
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
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=
223
224
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
224
225
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
225
226
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
···
238
239
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
239
240
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
240
241
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
242
+
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
241
243
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
244
+
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
242
245
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
243
246
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
244
247
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=