From 68abb41a9b6fcbd6b61ee1066580b7719b988b42 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Tue, 15 Aug 2017 14:47:23 -0400 Subject: [PATCH] Add ability to change CID version. --- cid-fmt/main.go | 66 ++++++++++++++++++++++++++++++++++++-------- cid-fmt/main_test.go | 37 +++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/cid-fmt/main.go b/cid-fmt/main.go index b09d28a..cc870dd 100644 --- a/cid-fmt/main.go +++ b/cid-fmt/main.go @@ -13,7 +13,7 @@ import ( ) func usage() { - fmt.Fprintf(os.Stderr, "usage: %s [-b multibase-code] ...\n\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "usage: %s [-b multibase-code] [-v cid-version] ...\n\n", os.Args[0]) fmt.Fprintf(os.Stderr, " is either 'prefix' or a printf style format string:\n%s", fmtRef) os.Exit(1) } @@ -46,16 +46,38 @@ func main() { usage() } newBase := mb.Encoding(-1) + var verConv func(cid *c.Cid) (*c.Cid, error) args := os.Args[1:] - if args[0] == "-b" { - if len(args) < 2 { - usage() +outer: + for { + switch args[0] { + case "-b": + if len(args) < 2 { + usage() + } + if len(args[1]) != 1 { + fmt.Fprintf(os.Stderr, "Error: Invalid multibase code: %s\n", args[1]) + os.Exit(1) + } + newBase = mb.Encoding(args[1][0]) + args = args[2:] + case "-v": + if len(args) < 2 { + usage() + } + switch args[1] { + case "0": + verConv = toCidV0 + case "1": + verConv = toCidV1 + default: + fmt.Fprintf(os.Stderr, "Error: Invalid cid version: %s\n", args[1]) + os.Exit(1) + } + args = args[2:] + default: + break outer } - if len(args[1]) != 1 { - fmt.Fprintf(os.Stderr, "Error: Invalid multibase code: %s\n", args[1]) - } - newBase = mb.Encoding(args[1][0]) - args = args[2:] } if len(args) < 2 { usage() @@ -71,15 +93,24 @@ func main() { } for _, cidStr := range args[1:] { base, cid, err := decode(cidStr) - if newBase != -1 { - base = newBase - } if err != nil { fmt.Fprintf(os.Stderr, "Error: %s: %v\n", cidStr, err) fmt.Fprintf(os.Stdout, "!INVALID_CID!\n") // Don't abort on a bad cid continue } + if newBase != -1 { + base = newBase + } + if verConv != nil { + cid, err = verConv(cid) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %s: %v\n", cidStr, err) + fmt.Fprintf(os.Stdout, "!CONVERSION_ERROR!\n") + // Don't abort on a bad conversion + continue + } + } str, err := fmtCid(fmtStr, base, cid) if err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) @@ -221,3 +252,14 @@ func encode(base mb.Encoding, data []byte, strip bool) string { } return str } + +func toCidV0(cid *c.Cid) (*c.Cid, error) { + if cid.Type() != c.DagProtobuf { + return nil, fmt.Errorf("can't convert non-protobuf nodes to cidv0") + } + return c.NewCidV0(cid.Hash()), nil +} + +func toCidV1(cid *c.Cid) (*c.Cid, error) { + return c.NewCidV1(cid.Type(), cid.Hash()), nil +} diff --git a/cid-fmt/main_test.go b/cid-fmt/main_test.go index 2d69eb1..4d4713c 100644 --- a/cid-fmt/main_test.go +++ b/cid-fmt/main_test.go @@ -71,3 +71,40 @@ func testFmt(t *testing.T, cidStr string, newBase mb.Encoding, fmtStr string, re t.Error(fmt.Sprintf("expected: %s; but got: %s", result, str)) } } + +func TestCidConv(t *testing.T) { + cidv0 := "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" + cidv1 := "zdj7WbTaiJT1fgatdet9Ei9iDB5hdCxkbVyhyh8YTUnXMiwYi" + _, cid, err := decode(cidv0) + if err != nil { + t.Fatal(err) + } + cid, err = toCidV1(cid) + if err != nil { + t.Fatal(err) + } + if cid.String() != cidv1 { + t.Fatal("conversion failure") + } + cid, err = toCidV0(cid) + if err != nil { + t.Fatal(err) + } + cidStr := cid.String() + if cidStr != cidv0 { + t.Error(fmt.Sprintf("conversion failure, expected: %s; but got: %s", cidv0, cidStr)) + } +} + +func TestBadCidConv(t *testing.T) { + // this cid is a raw leaf and should not be able to convert to cidv0 + cidv1 := "zb2rhhzX7uSKrtQ2ZZXFAabKiKFYZrJqKY2KE1cJ8yre2GSWZ" + _, cid, err := decode(cidv1) + if err != nil { + t.Fatal(err) + } + cid, err = toCidV0(cid) + if err == nil { + t.Fatal("expected failure") + } +}