github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/core/commands/cat.go (about) 1 package commands 2 3 import ( 4 "fmt" 5 "io" 6 7 cmds "github.com/ipfs/go-ipfs/commands" 8 core "github.com/ipfs/go-ipfs/core" 9 path "github.com/ipfs/go-ipfs/path" 10 uio "github.com/ipfs/go-ipfs/unixfs/io" 11 12 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/cheggaaa/pb" 13 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" 14 ) 15 16 const progressBarMinSize = 1024 * 1024 * 8 // show progress bar for outputs > 8MiB 17 18 type clearlineReader struct { 19 io.Reader 20 out io.Writer 21 } 22 23 var CatCmd = &cmds.Command{ 24 Helptext: cmds.HelpText{ 25 Tagline: "Show IPFS object data", 26 ShortDescription: ` 27 Retrieves the object named by <ipfs-or-ipns-path> and outputs the data 28 it contains. 29 `, 30 }, 31 32 Arguments: []cmds.Argument{ 33 cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to be outputted").EnableStdin(), 34 }, 35 Run: func(req cmds.Request, res cmds.Response) { 36 node, err := req.InvocContext().GetNode() 37 if err != nil { 38 res.SetError(err, cmds.ErrNormal) 39 return 40 } 41 42 readers, length, err := cat(req.Context(), node, req.Arguments()) 43 if err != nil { 44 res.SetError(err, cmds.ErrNormal) 45 return 46 } 47 48 res.SetLength(length) 49 50 reader := io.MultiReader(readers...) 51 res.SetOutput(reader) 52 }, 53 PostRun: func(req cmds.Request, res cmds.Response) { 54 if res.Length() < progressBarMinSize { 55 return 56 } 57 58 bar := pb.New(int(res.Length())).SetUnits(pb.U_BYTES) 59 bar.Output = res.Stderr() 60 bar.Start() 61 62 reader := bar.NewProxyReader(res.Output().(io.Reader)) 63 res.SetOutput(&clearlineReader{reader, res.Stderr()}) 64 }, 65 } 66 67 func cat(ctx context.Context, node *core.IpfsNode, paths []string) ([]io.Reader, uint64, error) { 68 readers := make([]io.Reader, 0, len(paths)) 69 length := uint64(0) 70 for _, fpath := range paths { 71 dagnode, err := core.Resolve(ctx, node, path.Path(fpath)) 72 if err != nil { 73 return nil, 0, err 74 } 75 76 read, err := uio.NewDagReader(ctx, dagnode, node.DAG) 77 if err != nil { 78 return nil, 0, err 79 } 80 readers = append(readers, read) 81 length += uint64(read.Size()) 82 } 83 return readers, length, nil 84 } 85 86 func (r *clearlineReader) Read(p []byte) (n int, err error) { 87 n, err = r.Reader.Read(p) 88 if err == io.EOF { 89 fmt.Fprintf(r.out, "\033[2K\r") // clear progress bar line on EOF 90 } 91 return 92 }