Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement an ipfs cat --length flag #4553

Merged
merged 3 commits into from
Jan 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions core/commands/cat.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var CatCmd = &cmds.Command{
},
Options: []cmdkit.Option{
cmdkit.IntOption("offset", "o", "Byte offset to begin reading from."),
cmdkit.IntOption("length", "l", "Maximum number of bytes to read."),
},
Run: func(req cmds.Request, res cmds.ResponseEmitter) {
node, err := req.InvocContext().GetNode()
Expand All @@ -50,7 +51,20 @@ var CatCmd = &cmds.Command{
return
}

readers, length, err := cat(req.Context(), node, req.Arguments(), int64(offset))
max, found, err := req.Option("length").Int()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

USE int64. THIS COULD OVERFLOW

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a int64 option in go-ipfs-cmdkit, we could use a uint instead? We could also add a new option if not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was really just giving @Stebalien crap, he was sitting behind me while i reviewed this and pointed out that this should be an int64

if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}
if max < 0 {
res.SetError(fmt.Errorf("Cannot specify negative length."), cmdkit.ErrNormal)
return
}
if !found {
max = -1
}

readers, length, err := cat(req.Context(), node, req.Arguments(), int64(offset), int64(max))
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
Expand Down Expand Up @@ -116,9 +130,12 @@ var CatCmd = &cmds.Command{
},
}

func cat(ctx context.Context, node *core.IpfsNode, paths []string, offset int64) ([]io.Reader, uint64, error) {
func cat(ctx context.Context, node *core.IpfsNode, paths []string, offset int64, max int64) ([]io.Reader, uint64, error) {
readers := make([]io.Reader, 0, len(paths))
length := uint64(0)
if max == 0 {
return nil, 0, nil
}
for _, fpath := range paths {
read, err := coreunix.Cat(ctx, node, fpath)
if err != nil {
Expand All @@ -134,8 +151,18 @@ func cat(ctx context.Context, node *core.IpfsNode, paths []string, offset int64)
}
offset = 0

size := uint64(read.Size() - uint64(count))
length += size
if max > 0 && length >= uint64(max) {
var r io.Reader = read
if overshoot := int64(length - uint64(max)); overshoot != 0 {
r = io.LimitReader(read, int64(size)-overshoot)
length = uint64(max)
}
readers = append(readers, r)
break
}
readers = append(readers, read)
length += uint64(read.Size() - uint64(count))
}
return readers, length, nil
}
49 changes: 49 additions & 0 deletions test/sharness/t0040-add-and-cat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,55 @@ test_add_cat_file() {
test_expect_code 1 ipfs cat --offset -102 "$HASH" > actual
'

test_expect_success "ipfs cat with length succeeds" '
ipfs cat --length 8 "$HASH" >actual
'

test_expect_success "ipfs cat with length output looks good" '
printf "Hello Wo" >expected &&
test_cmp expected actual
'

test_expect_success "ipfs cat multiple hashes with offset and length succeeds" '
ipfs cat --offset 5 --length 15 "$HASH" "$HASH" "$HASH" >actual
'

test_expect_success "ipfs cat multiple hashes with offset and length looks good" '
printf " Worlds!\nHello " >expected &&
test_cmp expected actual
'

test_expect_success "ipfs cat with exact length succeeds" '
ipfs cat --length $(ipfs cat "$HASH" | wc -c) "$HASH" >actual
'

test_expect_success "ipfs cat with exact length looks good" '
echo "Hello Worlds!" >expected &&
test_cmp expected actual
'

test_expect_success "ipfs cat with 0 length succeeds" '
ipfs cat --length 0 "$HASH" >actual
'

test_expect_success "ipfs cat with 0 length looks good" '
: >expected &&
test_cmp expected actual
'

test_expect_success "ipfs cat with oversized length succeeds" '
ipfs cat --length 100 "$HASH" >actual
'

test_expect_success "ipfs cat with oversized length looks good" '
echo "Hello Worlds!" >expected &&
test_cmp expected actual
'

test_expect_success "ipfs cat with negitive length should fail" '
test_expect_code 1 ipfs cat --length -102 "$HASH" > actual
'

test_expect_success "ipfs cat /ipfs/file succeeds" '
ipfs cat /ipfs/$HASH >actual
'
Expand Down