AT Protocol IPLD-CAR Repository toolkit (CLI)
at main 2.9 kB view raw
1package engine 2 3import ( 4 "bytes" 5 "context" 6 "errors" 7 "io" 8 "log" 9 "os" 10 "strings" 11 "time" 12 13 "github.com/atscan/atr/cli" 14 "github.com/atscan/atr/repo" 15 "github.com/klauspost/compress/zstd" 16 "github.com/schollz/progressbar/v3" 17) 18 19func Load(ctx *cli.Context, fn string) (repo.RepoSnapshot, error) { 20 var ss repo.RepoSnapshot 21 var err error 22 if strings.HasSuffix(fn, ".car.zst") { 23 ss, err = LoadCompressed(ctx, fn) 24 } else if strings.HasSuffix(fn, ".car") { 25 ss, err = LoadRaw(ctx, fn) 26 } 27 if err != nil { 28 log.Fatal("Cannot load: ", fn) 29 return ss, errors.New("Cannot load") 30 } 31 ss.File = fn 32 return ss, nil 33} 34 35func 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 } 40 dat, err := os.Open(fn) 41 if err != nil { 42 return repo.RepoSnapshot{}, err 43 } 44 defer dat.Close() 45 46 if err != nil { 47 return repo.RepoSnapshot{}, err 48 } 49 return LoadFromStream(ctx, dat, stat.Size()) 50} 51 52func LoadCompressed(ctx *cli.Context, fn string) (repo.RepoSnapshot, error) { 53 dat, err := os.Open(fn) 54 if err != nil { 55 return repo.RepoSnapshot{}, err 56 } 57 defer dat.Close() 58 59 if err != nil { 60 return repo.RepoSnapshot{}, err 61 } 62 decoder, _ := zstd.NewReader(dat) 63 return LoadFromStream(ctx, decoder, -1) 64} 65 66func 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 75} 76 77func LoadRepoFromStream(ctx *cli.Context, input io.Reader, sz int64) (repo.RepoSnapshot, error) { 78 rctx := context.TODO() 79 ss := repo.RepoSnapshot{} 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 107 buf := new(bytes.Buffer) 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 } 115 if err != nil { 116 log.Fatal(err) 117 } 118 ss.Size = int(size) 119 120 if bar != nil { 121 defer bar.Finish() 122 defer bar.Clear() 123 } 124 125 r, err := repo.ReadRepoFromCar(rctx, buf) 126 if err != nil { 127 return ss, err 128 } 129 ss.Repo = *r 130 return ss, nil 131}