main.go 2.68 KB
Newer Older
1 2 3 4 5
package main

import (
	"fmt"
	"os"
Kevin Atkinson's avatar
Kevin Atkinson committed
6
	"strings"
7

8
	cidutil "github.com/ipfs/go-cidutil"
9

10
	c "github.com/ipfs/go-cid"
Kevin Atkinson's avatar
Kevin Atkinson committed
11
	mb "github.com/multiformats/go-multibase"
12 13
)

Kevin Atkinson's avatar
Kevin Atkinson committed
14
func usage() {
15
	fmt.Fprintf(os.Stderr, "usage: %s [-b multibase-code] [-v cid-version] <fmt-str> <cid> ...\n\n", os.Args[0])
16
	fmt.Fprintf(os.Stderr, "<fmt-str> is either 'prefix' or a printf style format string:\n%s", cidutil.FormatRef)
17
	os.Exit(2)
Kevin Atkinson's avatar
Kevin Atkinson committed
18 19
}

20 21
func main() {
	if len(os.Args) < 2 {
Kevin Atkinson's avatar
Kevin Atkinson committed
22 23 24
		usage()
	}
	newBase := mb.Encoding(-1)
25
	var verConv func(cid c.Cid) (c.Cid, error)
Kevin Atkinson's avatar
Kevin Atkinson committed
26
	args := os.Args[1:]
27 28 29 30 31 32 33
outer:
	for {
		switch args[0] {
		case "-b":
			if len(args) < 2 {
				usage()
			}
34 35 36
			encoder, err := mb.EncoderByName(args[1])
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
37
				os.Exit(2)
38
			}
39
			newBase = encoder.Encoding()
40 41 42 43 44 45 46 47 48 49 50 51
			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])
52
				os.Exit(2)
53 54 55 56
			}
			args = args[2:]
		default:
			break outer
Kevin Atkinson's avatar
Kevin Atkinson committed
57 58 59 60
		}
	}
	if len(args) < 2 {
		usage()
61
	}
Kevin Atkinson's avatar
Kevin Atkinson committed
62 63
	fmtStr := args[0]
	switch fmtStr {
64
	case "prefix":
Kevin Atkinson's avatar
Kevin Atkinson committed
65 66 67 68
		fmtStr = "%P"
	default:
		if strings.IndexByte(fmtStr, '%') == -1 {
			fmt.Fprintf(os.Stderr, "Error: Invalid format string: %s\n", fmtStr)
69
			os.Exit(2)
Kevin Atkinson's avatar
Kevin Atkinson committed
70 71 72
		}
	}
	for _, cidStr := range args[1:] {
73
		cid, err := c.Decode(cidStr)
74
		if err != nil {
Kevin Atkinson's avatar
Kevin Atkinson committed
75
			fmt.Fprintf(os.Stdout, "!INVALID_CID!\n")
76
			errorMsg("%s: %v", cidStr, err)
Kevin Atkinson's avatar
Kevin Atkinson committed
77 78 79
			// Don't abort on a bad cid
			continue
		}
80 81 82
		base := newBase
		if newBase == -1 {
			base, _ = c.ExtractEncoding(cidStr)
83 84 85 86
		}
		if verConv != nil {
			cid, err = verConv(cid)
			if err != nil {
87 88
				fmt.Fprintf(os.Stdout, "!ERROR!\n")
				errorMsg("%s: %v", cidStr, err)
89 90 91 92
				// Don't abort on a bad conversion
				continue
			}
		}
93
		str, err := cidutil.Format(fmtStr, base, cid)
Kevin Atkinson's avatar
Kevin Atkinson committed
94
		switch err.(type) {
95
		case cidutil.FormatStringError:
Kevin Atkinson's avatar
Kevin Atkinson committed
96
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
97
			os.Exit(2)
Kevin Atkinson's avatar
Kevin Atkinson committed
98 99 100 101 102 103 104
		default:
			fmt.Fprintf(os.Stdout, "!ERROR!\n")
			errorMsg("%s: %v", cidStr, err)
			// Don't abort on cid specific errors
			continue
		case nil:
			// no error
105
		}
Kevin Atkinson's avatar
Kevin Atkinson committed
106
		fmt.Fprintf(os.Stdout, "%s\n", str)
107
	}
108 109 110 111 112 113 114 115 116 117
	os.Exit(exitCode)
}

var exitCode = 0

func errorMsg(fmtStr string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, "Error: ")
	fmt.Fprintf(os.Stderr, fmtStr, a...)
	fmt.Fprintf(os.Stderr, "\n")
	exitCode = 1
118 119
}

120
func toCidV0(cid c.Cid) (c.Cid, error) {
121
	if cid.Type() != c.DagProtobuf {
122
		return c.Cid{}, fmt.Errorf("can't convert non-protobuf nodes to cidv0")
123 124 125 126
	}
	return c.NewCidV0(cid.Hash()), nil
}

127
func toCidV1(cid c.Cid) (c.Cid, error) {
128 129
	return c.NewCidV1(cid.Type(), cid.Hash()), nil
}