diff --git a/core/commands/files/files.go b/core/commands/files/files.go index 731853d0960..c524a98664b 100644 --- a/core/commands/files/files.go +++ b/core/commands/files/files.go @@ -53,6 +53,8 @@ on the files in question, then data may be lost. This also applies to running }, } +var formatError = errors.New("Format was set by multiple options. Only one format option is allowed") + var FilesStatCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Display file status.", @@ -61,7 +63,24 @@ var FilesStatCmd = &cmds.Command{ Arguments: []cmds.Argument{ cmds.StringArg("path", true, false, "Path to node to stat."), }, + Options: []cmds.Option{ + cmds.StringOption("format", "Print statistics in given format. Allowed tokens: "+ + " . Conflicts with other format options.").Default( + ` +Size: +CumulativeSize: +ChildBlocks: +Type: `), + cmds.BoolOption("hash", "Print only hash. Implies '--format=. Conflicts with other format options.").Default(false), + cmds.BoolOption("size", "Print only size. Implies '--format=. Conflicts with other format options.").Default(false), + }, Run: func(req cmds.Request, res cmds.Response) { + + _, err := statGetFormatOptions(req) + if err != nil { + res.SetError(err, cmds.ErrClient) + } + node, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) @@ -90,19 +109,47 @@ var FilesStatCmd = &cmds.Command{ }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { + out := res.Output().(*Object) buf := new(bytes.Buffer) - fmt.Fprintln(buf, out.Hash) - fmt.Fprintf(buf, "Size: %d\n", out.Size) - fmt.Fprintf(buf, "CumulativeSize: %d\n", out.CumulativeSize) - fmt.Fprintf(buf, "ChildBlocks: %d\n", out.Blocks) - fmt.Fprintf(buf, "Type: %s\n", out.Type) + + s, _ := statGetFormatOptions(res.Request()) + s = strings.Replace(s, "", out.Hash, -1) + s = strings.Replace(s, "", fmt.Sprintf("%d", out.Size), -1) + s = strings.Replace(s, "", fmt.Sprintf("%d", out.CumulativeSize), -1) + s = strings.Replace(s, "", fmt.Sprintf("%d", out.Blocks), -1) + s = strings.Replace(s, "", out.Type, -1) + + fmt.Fprintln(buf, s) return buf, nil }, }, Type: Object{}, } +func moreThanOne(a, b, c bool) bool { + return a && b || b && c || a && c +} + +func statGetFormatOptions(req cmds.Request) (string, error) { + + hash, _, _ := req.Option("hash").Bool() + size, _, _ := req.Option("size").Bool() + format, found, _ := req.Option("format").String() + + if moreThanOne(hash, size, found) { + return "", formatError + } + + if hash { + return "", nil + } else if size { + return "", nil + } else { + return format, nil + } +} + func statNode(ds dag.DAGService, fsn mfs.FSNode) (*Object, error) { nd, err := fsn.GetNode() if err != nil { diff --git a/test/sharness/t0250-files-api.sh b/test/sharness/t0250-files-api.sh index 33a5f08d9a9..167ef3f9c4d 100755 --- a/test/sharness/t0250-files-api.sh +++ b/test/sharness/t0250-files-api.sh @@ -64,9 +64,39 @@ test_files_api() { test_expect_success "directory is empty" ' verify_dir_contents /cats ' + # we do verification of stat formatting now as we depend on it + + test_expect_success "stat works" ' + ipfs files stat / >stat + ' + + test_expect_success "hash is first line of stat" ' + ipfs ls $(head -1 stat) | grep "cats" + ' + + test_expect_success "stat --hash gives only hash" ' + ipfs files stat --hash / >actual && + head -n1 stat >expected && + test_cmp expected actual + ' + + test_expect_success "stat with multiple format options should fail" ' + test_must_fail ipfs files stat --hash --size / + ' + + test_expect_success "compare hash option with format" ' + ipfs files stat --hash / >expected && + ipfs files stat --format='"'"''"'"' / >actual && + test_cmp expected actual + ' + test_expect_success "compare size option with format" ' + ipfs files stat --size / >expected && + ipfs files stat --format='"'"''"'"' / >actual && + test_cmp expected actual + ' test_expect_success "check root hash" ' - ipfs files stat / | head -n1 > roothash + ipfs files stat --hash / > roothash ' test_expect_success "cannot mkdir /" ' @@ -74,7 +104,7 @@ test_files_api() { ' test_expect_success "check root hash was not changed" ' - ipfs files stat / | head -n1 > roothashafter && + ipfs files stat --hash / > roothashafter && test_cmp roothash roothashafter ' @@ -167,7 +197,7 @@ test_files_api() { ' test_expect_success "check root hash" ' - ipfs files stat / | head -n1 > roothash + ipfs files stat --hash / > roothash ' test_expect_success "cannot remove root" ' @@ -175,7 +205,7 @@ test_files_api() { ' test_expect_success "check root hash was not changed" ' - ipfs files stat / | head -n1 > roothashafter && + ipfs files stat --hash / > roothashafter && test_cmp roothash roothashafter ' @@ -273,12 +303,12 @@ test_files_api() { ' test_expect_success "cant write to negative offset" ' - ipfs files stat /cats/ipfs | head -n1 > filehash && + ipfs files stat --hash /cats/ipfs > filehash && test_expect_code 1 ipfs files write --offset -1 /cats/ipfs < output ' test_expect_success "verify file was not changed" ' - ipfs files stat /cats/ipfs | head -n1 > afterhash && + ipfs files stat --hash /cats/ipfs > afterhash && test_cmp filehash afterhash ' @@ -305,12 +335,12 @@ test_files_api() { ' test_expect_success "cannot write to directory" ' - ipfs files stat /cats | head -n1 > dirhash && + ipfs files stat --hash /cats > dirhash && test_expect_code 1 ipfs files write /cats < output ' test_expect_success "verify dir was not changed" ' - ipfs files stat /cats | head -n1 > afterdirhash && + ipfs files stat --hash /cats > afterdirhash && test_cmp dirhash afterdirhash ' @@ -333,7 +363,7 @@ test_files_api() { ' test_expect_success "changes bubbled up to root on inspection" ' - ipfs files stat / | head -n1 > root_hash + ipfs files stat --hash / > root_hash ' test_expect_success "root hash looks good" '