github.com/jbendotnet/noms@v0.0.0-20190904222105-c43e4293ea92/cmd/noms/noms_blob_get.go (about) 1 // Copyright 2016 Attic Labs, Inc. All rights reserved. 2 // Licensed under the Apache License, version 2.0: 3 // http://www.apache.org/licenses/LICENSE-2.0 4 5 package main 6 7 import ( 8 "fmt" 9 "io" 10 "os" 11 "time" 12 13 "github.com/attic-labs/noms/go/config" 14 "github.com/attic-labs/noms/go/d" 15 "github.com/attic-labs/noms/go/types" 16 "github.com/attic-labs/noms/go/util/profile" 17 "github.com/attic-labs/noms/go/util/progressreader" 18 "github.com/attic-labs/noms/go/util/status" 19 humanize "github.com/dustin/go-humanize" 20 ) 21 22 func nomsBlobGet(ds string, filePath string) int { 23 cfg := config.NewResolver() 24 var blob types.Blob 25 if db, val, err := cfg.GetPath(ds); err != nil { 26 d.CheckErrorNoUsage(err) 27 } else if val == nil { 28 d.CheckErrorNoUsage(fmt.Errorf("No value at %s", ds)) 29 } else if b, ok := val.(types.Blob); !ok { 30 d.CheckErrorNoUsage(fmt.Errorf("Value at %s is not a blob", ds)) 31 } else { 32 defer db.Close() 33 blob = b 34 } 35 36 defer profile.MaybeStartProfile().Stop() 37 38 if filePath == "" { 39 blob.Copy(os.Stdout) 40 return 0 41 } 42 43 // Note: overwrites any existing file. 44 file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0644) 45 d.CheckErrorNoUsage(err) 46 defer file.Close() 47 48 start := time.Now() 49 expected := humanize.Bytes(blob.Len()) 50 51 // Create a pipe so that we can connect a progress reader 52 preader, pwriter := io.Pipe() 53 54 go func() { 55 blob.Copy(pwriter) 56 pwriter.Close() 57 }() 58 59 blobReader := progressreader.New(preader, func(seen uint64) { 60 elapsed := time.Since(start).Seconds() 61 rate := uint64(float64(seen) / elapsed) 62 status.Printf("%s of %s written in %ds (%s/s)...", humanize.Bytes(seen), expected, int(elapsed), humanize.Bytes(rate)) 63 }) 64 65 io.Copy(file, blobReader) 66 status.Done() 67 return 0 68 }