From 1f3ba9fa57f871a4623298d2c2799b9f5bdaa720 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Thu, 13 Sep 2018 15:57:24 -0400
Subject: [PATCH 01/13] Add --cid-base & --upgrade-cidv0 global opt. and enable
 them on select cmds

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/add.go               | 16 ++++---
 core/commands/dns.go               |  2 +-
 core/commands/files.go             | 19 ++++++--
 core/commands/filestore.go         | 19 +++++++-
 core/commands/ls.go                | 14 ++++--
 core/commands/pin.go               | 38 +++++++++++-----
 core/commands/refs.go              | 30 +++++++++++--
 core/commands/resolve.go           |  8 +++-
 core/commands/root.go              | 72 +++++++++++++++++++++++++++++-
 core/commands/tar.go               | 10 ++++-
 core/coreapi/dht.go                |  2 +-
 core/coreunix/add.go               | 11 ++---
 core/coreunix/add_test.go          |  7 +--
 exchange/reprovide/providers.go    |  2 +-
 filestore/util.go                  |  7 +--
 package.json                       |  4 +-
 test/sharness/t0040-add-and-cat.sh | 31 ++++++++++++-
 test/sharness/t0045-ls.sh          | 10 ++++-
 test/sharness/t0085-pins.sh        |  7 ++-
 test/sharness/t0160-resolve.sh     | 32 ++++++++++++-
 thirdparty/cidv0v1/blockstore.go   | 22 ++-------
 21 files changed, 290 insertions(+), 73 deletions(-)

diff --git a/core/commands/add.go b/core/commands/add.go
index b7f3d6a8437..340da269303 100644
--- a/core/commands/add.go
+++ b/core/commands/add.go
@@ -17,12 +17,12 @@ import (
 
 	mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash"
 	pb "gx/ipfs/QmPtj12fdwuAqj9sBSTNUxBNu8kCGNp8b3o8yUzMm5GHpq/pb"
-	cidutil "gx/ipfs/QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt/go-cidutil"
 	offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline"
 	cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
 	files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files"
 	cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds"
 	mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs"
+	cidutil "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil"
 	bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore"
 )
 
@@ -367,6 +367,11 @@ You can now check what blocks have been created by:
 				log.Warning("cannot determine size of input file")
 			}
 
+			_, err := NewCidBaseHandler(req).UseGlobal().Proc()
+			if err != nil {
+				return err
+			}
+
 			progressBar := func(wait chan struct{}) {
 				defer close(wait)
 
@@ -402,8 +407,9 @@ You can now check what blocks have been created by:
 							break LOOP
 						}
 						output := out.(*coreunix.AddedObject)
-						if len(output.Hash) > 0 {
-							lastHash = output.Hash
+						hash := output.Hash.String()
+						if len(hash) > 0 {
+							lastHash = hash
 							if quieter {
 								continue
 							}
@@ -413,9 +419,9 @@ You can now check what blocks have been created by:
 								fmt.Fprintf(os.Stderr, "\033[2K\r")
 							}
 							if quiet {
-								fmt.Fprintf(os.Stdout, "%s\n", output.Hash)
+								fmt.Fprintf(os.Stdout, "%s\n", hash)
 							} else {
-								fmt.Fprintf(os.Stdout, "added %s %s\n", output.Hash, output.Name)
+								fmt.Fprintf(os.Stdout, "added %s %s\n", hash, output.Name)
 							}
 
 						} else {
diff --git a/core/commands/dns.go b/core/commands/dns.go
index 2353ee7ec65..2f2e7800e8d 100644
--- a/core/commands/dns.go
+++ b/core/commands/dns.go
@@ -54,7 +54,6 @@ The resolver can recursively resolve:
 		cmdkit.BoolOption("recursive", "r", "Resolve until the result is not a DNS link."),
 	},
 	Run: func(req cmds.Request, res cmds.Response) {
-
 		recursive, _, _ := req.Option("recursive").Bool()
 		name := req.Arguments()[0]
 		resolver := namesys.NewDNSResolver()
@@ -77,6 +76,7 @@ The resolver can recursively resolve:
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
+
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
 				return nil, err
diff --git a/core/commands/files.go b/core/commands/files.go
index 7ad62dabfea..e5df4b347de 100644
--- a/core/commands/files.go
+++ b/core/commands/files.go
@@ -32,6 +32,7 @@ import (
 	logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log"
 	mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs"
 	ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format"
+	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
 )
 
 var flog = logging.Logger("cmds/files")
@@ -77,7 +78,7 @@ var hashOption = cmdkit.StringOption("hash", "Hash function to use. Will set Cid
 var errFormat = errors.New("format was set by multiple options. Only one format option is allowed")
 
 type statOutput struct {
-	Hash           string
+	Hash           apicid.Hash
 	Size           uint64
 	CumulativeSize uint64
 	Blocks         int
@@ -162,13 +163,18 @@ var filesStatCmd = &cmds.Command{
 	},
 	Encoders: cmds.EncoderMap{
 		cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
+			_, err := NewCidBaseHandler(req).UseGlobal().Proc()
+			if err != nil {
+				return err
+			}
+
 			out, ok := v.(*statOutput)
 			if !ok {
 				return e.TypeErr(out, v)
 			}
 
 			s, _ := statGetFormatOptions(req)
-			s = strings.Replace(s, "<hash>", out.Hash, -1)
+			s = strings.Replace(s, "<hash>", out.Hash.String(), -1)
 			s = strings.Replace(s, "<size>", fmt.Sprintf("%d", out.Size), -1)
 			s = strings.Replace(s, "<cumulsize>", fmt.Sprintf("%d", out.CumulativeSize), -1)
 			s = strings.Replace(s, "<childs>", fmt.Sprintf("%d", out.Blocks), -1)
@@ -239,7 +245,7 @@ func statNode(nd ipld.Node) (*statOutput, error) {
 		}
 
 		return &statOutput{
-			Hash:           c.String(),
+			Hash:           apicid.FromCid(c),
 			Blocks:         len(nd.Links()),
 			Size:           d.FileSize(),
 			CumulativeSize: cumulsize,
@@ -247,7 +253,7 @@ func statNode(nd ipld.Node) (*statOutput, error) {
 		}, nil
 	case *dag.RawNode:
 		return &statOutput{
-			Hash:           c.String(),
+			Hash:           apicid.FromCid(c),
 			Blocks:         0,
 			Size:           cumulsize,
 			CumulativeSize: cumulsize,
@@ -486,6 +492,11 @@ Examples:
 	},
 	Marshalers: oldcmds.MarshalerMap{
 		oldcmds.Text: func(res oldcmds.Response) (io.Reader, error) {
+			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return nil, err
+			}
+
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
 				return nil, err
diff --git a/core/commands/filestore.go b/core/commands/filestore.go
index a45e01ef93f..87e4f7f0d91 100644
--- a/core/commands/filestore.go
+++ b/core/commands/filestore.go
@@ -74,6 +74,11 @@ The output is:
 	},
 	PostRun: cmds.PostRunMap{
 		cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error {
+			_, err := NewCidBaseHandler(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return err
+			}
+
 			var errors bool
 			for {
 				v, err := res.Next()
@@ -162,6 +167,11 @@ For ERROR entries the error will also be printed to stderr.
 	},
 	Marshalers: oldCmds.MarshalerMap{
 		oldCmds.Text: func(res oldCmds.Response) (io.Reader, error) {
+			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return nil, err
+			}
+
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
 				return nil, err
@@ -198,6 +208,13 @@ var dupsFileStore = &oldCmds.Command{
 			return
 		}
 
+		h, err := NewCidBaseHandlerLegacy(req).Proc()
+		if err != nil {
+			res.SetError(err, cmdkit.ErrNormal)
+			return
+		}
+		enc := h.Encoder()
+
 		out := make(chan interface{}, 128)
 		res.SetOutput((<-chan interface{})(out))
 
@@ -214,7 +231,7 @@ var dupsFileStore = &oldCmds.Command{
 				}
 				if have {
 					select {
-					case out <- &RefWrapper{Ref: cid.String()}:
+					case out <- &RefWrapper{Ref: enc.Encode(cid)}:
 					case <-req.Context().Done():
 						return
 					}
diff --git a/core/commands/ls.go b/core/commands/ls.go
index 491ab671a4d..4d4c403b4ff 100644
--- a/core/commands/ls.go
+++ b/core/commands/ls.go
@@ -21,12 +21,14 @@ import (
 	offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline"
 	"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
 	ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format"
+	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
 )
 
 type LsLink struct {
-	Name, Hash string
-	Size       uint64
-	Type       unixfspb.Data_DataType
+	Name string
+	Hash apicid.Hash
+	Size uint64
+	Type unixfspb.Data_DataType
 }
 
 type LsObject struct {
@@ -160,7 +162,7 @@ The JSON output contains type information.
 				}
 				output[i].Links[j] = LsLink{
 					Name: link.Name,
-					Hash: link.Cid.String(),
+					Hash: apicid.FromCid(link.Cid),
 					Size: link.Size,
 					Type: t,
 				}
@@ -171,6 +173,10 @@ The JSON output contains type information.
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
+			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return nil, err
+			}
 
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
diff --git a/core/commands/pin.go b/core/commands/pin.go
index bb6540fa5ec..5e46793f9f6 100644
--- a/core/commands/pin.go
+++ b/core/commands/pin.go
@@ -22,6 +22,7 @@ import (
 	bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice"
 	path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path"
 	resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver"
+	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
 )
 
 var PinCmd = &cmds.Command{
@@ -39,11 +40,11 @@ var PinCmd = &cmds.Command{
 }
 
 type PinOutput struct {
-	Pins []string
+	Pins []apicid.Hash
 }
 
 type AddPinOutput struct {
-	Pins     []string
+	Pins     []apicid.Hash
 	Progress int `json:",omitempty"`
 }
 
@@ -84,7 +85,7 @@ var addPinCmd = &cmds.Command{
 				res.SetError(err, cmdkit.ErrNormal)
 				return
 			}
-			res.SetOutput(&AddPinOutput{Pins: cidsToStrings(added)})
+			res.SetOutput(&AddPinOutput{Pins: toAPICids(added)})
 			return
 		}
 
@@ -117,7 +118,7 @@ var addPinCmd = &cmds.Command{
 				if pv := v.Value(); pv != 0 {
 					out <- &AddPinOutput{Progress: v.Value()}
 				}
-				out <- &AddPinOutput{Pins: cidsToStrings(val.pins)}
+				out <- &AddPinOutput{Pins: toAPICids(val.pins)}
 				return
 			case <-ticker.C:
 				out <- &AddPinOutput{Progress: v.Value()}
@@ -130,12 +131,16 @@ var addPinCmd = &cmds.Command{
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
+			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return nil, err
+			}
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
 				return nil, err
 			}
 
-			var added []string
+			var added []apicid.Hash
 
 			switch out := v.(type) {
 			case *AddPinOutput:
@@ -206,10 +211,15 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.)
 			return
 		}
 
-		res.SetOutput(&PinOutput{cidsToStrings(removed)})
+		res.SetOutput(&PinOutput{toAPICids(removed)})
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
+			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return nil, err
+			}
+
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
 				return nil, err
@@ -345,6 +355,10 @@ Example:
 	},
 }
 
+type UpdatePinOutput struct {
+	Pins []string // really paths
+}
+
 var updatePinCmd = &cmds.Command{
 	Helptext: cmdkit.HelpText{
 		Tagline: "Update a recursive pin",
@@ -362,7 +376,7 @@ new pin and removing the old one.
 	Options: []cmdkit.Option{
 		cmdkit.BoolOption("unpin", "Remove the old pin.").WithDefault(true),
 	},
-	Type: PinOutput{},
+	Type: UpdatePinOutput{},
 	Run: func(req cmds.Request, res cmds.Response) {
 		n, err := req.InvocContext().GetNode()
 		if err != nil {
@@ -417,7 +431,7 @@ new pin and removing the old one.
 			return
 		}
 
-		res.SetOutput(&PinOutput{Pins: []string{from.String(), to.String()}})
+		res.SetOutput(&UpdatePinOutput{Pins: []string{from.String(), to.String()}})
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
@@ -425,7 +439,7 @@ new pin and removing the old one.
 			if err != nil {
 				return nil, err
 			}
-			added, ok := v.(*PinOutput)
+			added, ok := v.(*UpdatePinOutput)
 			if !ok {
 				return nil, e.TypeErr(added, v)
 			}
@@ -680,10 +694,10 @@ func (r PinVerifyRes) Format(out io.Writer) {
 	}
 }
 
-func cidsToStrings(cs []cid.Cid) []string {
-	out := make([]string, 0, len(cs))
+func toAPICids(cs []cid.Cid) []apicid.Hash {
+	out := make([]apicid.Hash, 0, len(cs))
 	for _, c := range cs {
-		out = append(out, c.String())
+		out = append(out, apicid.FromCid(c))
 	}
 	return out
 }
diff --git a/core/commands/refs.go b/core/commands/refs.go
index c28af531719..b269c9626a7 100644
--- a/core/commands/refs.go
+++ b/core/commands/refs.go
@@ -10,6 +10,7 @@ import (
 	cmds "github.com/ipfs/go-ipfs/commands"
 	"github.com/ipfs/go-ipfs/core"
 	e "github.com/ipfs/go-ipfs/core/commands/e"
+	cidenc "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/cidenc"
 
 	cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid"
 	cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
@@ -117,6 +118,13 @@ NOTE: List all references recursively by using the flag '-r'.
 			format = "<src> -> <dst>"
 		}
 
+		h, err := NewCidBaseHandlerLegacy(req).Proc()
+		if err != nil {
+			res.SetError(err, cmdkit.ErrNormal)
+			return
+		}
+		enc := h.Encoder()
+
 		objs, err := objectsForPaths(ctx, n, req.Arguments())
 		if err != nil {
 			res.SetError(err, cmdkit.ErrNormal)
@@ -136,6 +144,7 @@ NOTE: List all references recursively by using the flag '-r'.
 				Unique:   unique,
 				PrintFmt: format,
 				MaxDepth: maxDepth,
+				Encoder:  enc,
 			}
 
 			for _, o := range objs {
@@ -169,6 +178,13 @@ Displays the hashes of all local objects.
 			return
 		}
 
+		h, err := NewCidBaseHandlerLegacy(req).Proc()
+		if err != nil {
+			res.SetError(err, cmdkit.ErrNormal)
+			return
+		}
+		enc := h.Encoder()
+
 		// todo: make async
 		allKeys, err := n.Blockstore.AllKeysChan(ctx)
 		if err != nil {
@@ -184,7 +200,7 @@ Displays the hashes of all local objects.
 
 			for k := range allKeys {
 				select {
-				case out <- &RefWrapper{Ref: k.String()}:
+				case out <- &RefWrapper{Ref: enc.Encode(k)}:
 				case <-req.Context().Done():
 					return
 				}
@@ -197,6 +213,11 @@ Displays the hashes of all local objects.
 
 var refsMarshallerMap = cmds.MarshalerMap{
 	cmds.Text: func(res cmds.Response) (io.Reader, error) {
+		_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+		if err != nil {
+			return nil, err
+		}
+
 		v, err := unwrapOutput(res.Output())
 		if err != nil {
 			return nil, err
@@ -245,6 +266,7 @@ type RefWriter struct {
 	Unique   bool
 	MaxDepth int
 	PrintFmt string
+	Encoder  cidenc.Interface
 
 	seen map[string]int
 }
@@ -379,11 +401,11 @@ func (rw *RefWriter) WriteEdge(from, to cid.Cid, linkname string) error {
 	switch {
 	case rw.PrintFmt != "":
 		s = rw.PrintFmt
-		s = strings.Replace(s, "<src>", from.String(), -1)
-		s = strings.Replace(s, "<dst>", to.String(), -1)
+		s = strings.Replace(s, "<src>", rw.Encoder.Encode(from), -1)
+		s = strings.Replace(s, "<dst>", rw.Encoder.Encode(to), -1)
 		s = strings.Replace(s, "<linkname>", linkname, -1)
 	default:
-		s += to.String()
+		s += rw.Encoder.Encode(to)
 	}
 
 	rw.out <- &RefWrapper{Ref: s}
diff --git a/core/commands/resolve.go b/core/commands/resolve.go
index 39963b6da95..7d3dbbd9059 100644
--- a/core/commands/resolve.go
+++ b/core/commands/resolve.go
@@ -89,6 +89,12 @@ Resolve the value of an IPFS DAG path:
 		name := req.Arguments[0]
 		recursive, _ := req.Options["recursive"].(bool)
 
+		h, err := NewCidBaseHandler(req).Proc()
+		if err != nil {
+			return err
+		}
+		enc := h.EncoderFromPath(name)
+
 		// the case when ipns is resolved step by step
 		if strings.HasPrefix(name, "/ipns/") && !recursive {
 			rc, rcok := req.Options["dht-record-count"].(uint)
@@ -131,7 +137,7 @@ Resolve the value of an IPFS DAG path:
 
 		c := rp.Cid()
 
-		return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: path.FromCid(c)})
+		return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: path.FromString("/ipfs/" + enc.Encode(c))})
 	},
 	Encoders: cmds.EncoderMap{
 		cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
diff --git a/core/commands/root.go b/core/commands/root.go
index 0268136f610..6deb8c67ee8 100644
--- a/core/commands/root.go
+++ b/core/commands/root.go
@@ -12,10 +12,12 @@ import (
 	name "github.com/ipfs/go-ipfs/core/commands/name"
 	ocmd "github.com/ipfs/go-ipfs/core/commands/object"
 	unixfs "github.com/ipfs/go-ipfs/core/commands/unixfs"
+	cidenc "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/cidenc"
 
 	"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
 	"gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds"
 	logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log"
+	mbase "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase"
 )
 
 var log = logging.Logger("core/commands")
@@ -23,7 +25,9 @@ var log = logging.Logger("core/commands")
 var ErrNotOnline = errors.New("this command must be run in online mode. Try running 'ipfs daemon' first")
 
 const (
-	ApiOption = "api"
+	ApiOption          = "api"
+	CidBaseOption      = "cid-base"
+	UpgradeCidV0Option = "upgrade-cidv0"
 )
 
 var Root = &cmds.Command{
@@ -95,6 +99,8 @@ The CLI will exit with one of the following values:
 		cmdkit.BoolOption("h", "Show a short version of the command help text."),
 		cmdkit.BoolOption("local", "L", "Run the command locally, instead of using the daemon."),
 		cmdkit.StringOption(ApiOption, "Use a specific API instance (defaults to /ip4/127.0.0.1/tcp/5001)"),
+		cmdkit.StringOption(CidBaseOption, "mbase", "Multi-base to use to encode version 1 CIDs in output."),
+		cmdkit.BoolOption(UpgradeCidV0Option, "Upgrade CID version 0 to version 1 in output."),
 
 		// global options, added to every command
 		cmds.OptionEncodingType,
@@ -222,3 +228,67 @@ func MessageTextMarshaler(res oldcmds.Response) (io.Reader, error) {
 
 	return strings.NewReader(out.Message), nil
 }
+
+type CidBaseHandler struct {
+	base           string
+	upgrade        bool
+	upgradeDefined bool
+	args           []string
+	enc            *cidenc.Encoder
+}
+
+func NewCidBaseHandler(req *cmds.Request) *CidBaseHandler {
+	h := &CidBaseHandler{}
+	h.base, _ = req.Options[CidBaseOption].(string)
+	h.upgrade, h.upgradeDefined = req.Options[UpgradeCidV0Option].(bool)
+	h.args = req.Arguments
+	return h
+}
+
+func NewCidBaseHandlerLegacy(req oldcmds.Request) *CidBaseHandler {
+	h := &CidBaseHandler{}
+	h.base, _, _ = req.Option(CidBaseOption).String()
+	h.upgrade, h.upgradeDefined, _ = req.Option(UpgradeCidV0Option).Bool()
+	h.args = req.Arguments()
+	return h
+}
+
+func (h *CidBaseHandler) UseGlobal() *CidBaseHandler {
+	h.enc = &cidenc.Default
+	return h
+}
+
+func (h *CidBaseHandler) Proc() (*CidBaseHandler, error) {
+	var e cidenc.Encoder = cidenc.Default
+	if h.base != "" {
+		var err error
+		e.Base, err = mbase.EncoderByName(h.base)
+		if err != nil {
+			return h, err
+		}
+	}
+
+	e.Upgrade = h.upgrade
+	if h.base != "" && !h.upgradeDefined {
+		e.Upgrade = true
+	}
+
+	if h.enc == nil {
+		h.enc = &cidenc.Encoder{}
+	}
+	*h.enc = e
+	return h, nil
+}
+
+func (h *CidBaseHandler) Encoder() cidenc.Encoder {
+	return *h.enc
+}
+
+func (h *CidBaseHandler) EncoderFromPath(p string) cidenc.Encoder {
+	if h.base == "" {
+		enc, _ := cidenc.FromPath(*h.enc, p)
+		return enc
+	} else {
+		return *h.enc
+	}
+}
diff --git a/core/commands/tar.go b/core/commands/tar.go
index a2fa3da20cc..7aefe2543ac 100644
--- a/core/commands/tar.go
+++ b/core/commands/tar.go
@@ -13,6 +13,7 @@ import (
 	path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path"
 
 	"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
+	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
 )
 
 var TarCmd = &cmds.Command{
@@ -62,12 +63,17 @@ represent it.
 		fi.FileName()
 		res.SetOutput(&coreunix.AddedObject{
 			Name: fi.FileName(),
-			Hash: c.String(),
+			Hash: apicid.FromCid(c),
 		})
 	},
 	Type: coreunix.AddedObject{},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
+			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return nil, err
+			}
+
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
 				return nil, err
@@ -77,7 +83,7 @@ represent it.
 			if !ok {
 				return nil, e.TypeErr(o, v)
 			}
-			return strings.NewReader(o.Hash + "\n"), nil
+			return strings.NewReader(o.Hash.String() + "\n"), nil
 		},
 	},
 }
diff --git a/core/coreapi/dht.go b/core/coreapi/dht.go
index 388b33b852d..0b950d09857 100644
--- a/core/coreapi/dht.go
+++ b/core/coreapi/dht.go
@@ -9,12 +9,12 @@ import (
 	caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
 
 	cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid"
-	cidutil "gx/ipfs/QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt/go-cidutil"
 	offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline"
 	routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing"
 	peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer"
 	dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag"
 	blockservice "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice"
+	cidutil "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil"
 	blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore"
 	pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore"
 )
diff --git a/core/coreunix/add.go b/core/coreunix/add.go
index ad8450f6a2b..96543c7152f 100644
--- a/core/coreunix/add.go
+++ b/core/coreunix/add.go
@@ -25,6 +25,7 @@ import (
 	logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log"
 	mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs"
 	ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format"
+	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
 	bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore"
 )
 
@@ -41,16 +42,16 @@ type Link struct {
 }
 
 type Object struct {
-	Hash  string
+	Hash  apicid.Hash
 	Links []Link
 	Size  string
 }
 
 type AddedObject struct {
 	Name  string
-	Hash  string `json:",omitempty"`
-	Bytes int64  `json:",omitempty"`
-	Size  string `json:",omitempty"`
+	Hash  apicid.Hash `json:",omitempty"`
+	Bytes int64       `json:",omitempty"`
+	Size  string      `json:",omitempty"`
 }
 
 // NewAdder Returns a new Adder used for a file add operation.
@@ -564,7 +565,7 @@ func getOutput(dagnode ipld.Node) (*Object, error) {
 	}
 
 	output := &Object{
-		Hash:  c.String(),
+		Hash:  apicid.FromCid(c),
 		Size:  strconv.FormatUint(s, 10),
 		Links: make([]Link, len(dagnode.Links())),
 	}
diff --git a/core/coreunix/add_test.go b/core/coreunix/add_test.go
index d2c9c7337d4..2e190f89818 100644
--- a/core/coreunix/add_test.go
+++ b/core/coreunix/add_test.go
@@ -23,6 +23,7 @@ import (
 	config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config"
 	dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag"
 	"gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice"
+	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
 	blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore"
 )
 
@@ -93,7 +94,7 @@ func TestAddGCLive(t *testing.T) {
 
 	}()
 
-	addedHashes := make(map[string]struct{})
+	addedHashes := make(map[apicid.Hash]struct{})
 	select {
 	case o := <-out:
 		addedHashes[o.(*AddedObject).Hash] = struct{}{}
@@ -132,7 +133,7 @@ func TestAddGCLive(t *testing.T) {
 		if r.Error != nil {
 			t.Fatal(err)
 		}
-		if _, ok := addedHashes[r.KeyRemoved.String()]; ok {
+		if _, ok := addedHashes[apicid.FromCid(r.KeyRemoved)]; ok {
 			t.Fatal("gc'ed a hash we just added")
 		}
 	}
@@ -140,7 +141,7 @@ func TestAddGCLive(t *testing.T) {
 	var last cid.Cid
 	for a := range out {
 		// wait for it to finish
-		c, err := cid.Decode(a.(*AddedObject).Hash)
+		c, err := a.(*AddedObject).Hash.Cid()
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/exchange/reprovide/providers.go b/exchange/reprovide/providers.go
index c579d0357ce..da9502402fe 100644
--- a/exchange/reprovide/providers.go
+++ b/exchange/reprovide/providers.go
@@ -6,9 +6,9 @@ import (
 	pin "github.com/ipfs/go-ipfs/pin"
 
 	cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid"
-	cidutil "gx/ipfs/QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt/go-cidutil"
 	merkledag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag"
 	ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format"
+	cidutil "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil"
 	blocks "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore"
 )
 
diff --git a/filestore/util.go b/filestore/util.go
index 6213b0f1044..cd9540d21f1 100644
--- a/filestore/util.go
+++ b/filestore/util.go
@@ -10,6 +10,7 @@ import (
 	dshelp "gx/ipfs/QmUDTSi6zJ6ACyQaKtxscCUxrg5DaXs9r4RQUPFQXGPHpo/go-ipfs-ds-help"
 	ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore"
 	dsq "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/query"
+	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
 	blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore"
 )
 
@@ -60,7 +61,7 @@ func (s Status) Format() string {
 type ListRes struct {
 	Status   Status
 	ErrorMsg string
-	Key      cid.Cid
+	Key      apicid.Cid
 	FilePath string
 	Offset   uint64
 	Size     uint64
@@ -269,14 +270,14 @@ func mkListRes(c cid.Cid, d *pb.DataObj, err error) *ListRes {
 		return &ListRes{
 			Status:   status,
 			ErrorMsg: errorMsg,
-			Key:      c,
+			Key:      apicid.Cid{Cid: c},
 		}
 	}
 
 	return &ListRes{
 		Status:   status,
 		ErrorMsg: errorMsg,
-		Key:      c,
+		Key:      apicid.Cid{Cid: c},
 		FilePath: d.FilePath,
 		Size:     d.Size_,
 		Offset:   d.Offset,
diff --git a/package.json b/package.json
index e5d03e70e4a..3b590388dcc 100644
--- a/package.json
+++ b/package.json
@@ -542,9 +542,9 @@
     },
     {
       "author": "kevina",
-      "hash": "QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt",
+      "hash": "QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic",
       "name": "go-cidutil",
-      "version": "0.1.1"
+      "version": "0.1.2"
     },
     {
       "author": "lgierth",
diff --git a/test/sharness/t0040-add-and-cat.sh b/test/sharness/t0040-add-and-cat.sh
index 0ee4477cdcd..480bcaecf6f 100755
--- a/test/sharness/t0040-add-and-cat.sh
+++ b/test/sharness/t0040-add-and-cat.sh
@@ -164,7 +164,6 @@ test_add_cat_file() {
     test_expect_code 1 ipfs add -Q --chunker rabin-12-512-1024 mountdir/hello.txt
   '
 
-
   test_expect_success "ipfs add on hidden file succeeds" '
     echo "Hello Worlds!" >mountdir/.hello.txt &&
     ipfs add mountdir/.hello.txt >actual
@@ -244,6 +243,36 @@ test_add_cat_file() {
     echo "added QmZQWnfcqJ6hNkkPvrY9Q5X39GP3jUnUbAV4AbmbbR3Cb1 test_current_dir" > expected
     test_cmp expected actual
   '
+    
+  # --cid-base=base32
+  
+  test_expect_success "ipfs add --cid-base=base32 succeeds" '
+    echo "Hello Worlds!" >mountdir/hello.txt &&
+    ipfs add --cid-base=base32 mountdir/hello.txt >actual
+  '
+
+  test_expect_success "ipfs add output looks good" '
+    HASH="bafybeidpq7lcjx4w5c6yr4vuthzvlav54hgxsremwk73to5ferdc2rxhai" &&
+    echo "added $HASH hello.txt" >expected &&
+    test_cmp expected actual
+  '
+
+  test_expect_success "ipfs add --cid-base=base32 --only-hash succeeds" '
+    ipfs add --cid-base=base32 --only-hash mountdir/hello.txt > oh_actual
+  '
+
+  test_expect_success "ipfs add --only-hash output looks good" '
+    test_cmp expected oh_actual
+  '
+
+  test_expect_success "ipfs cat succeeds" '
+    ipfs cat "$HASH" >actual
+  '
+
+  test_expect_success "ipfs cat output looks good" '
+    echo "Hello Worlds!" >expected &&
+    test_cmp expected actual
+  '
 }
 
 test_add_cat_5MB() {
diff --git a/test/sharness/t0045-ls.sh b/test/sharness/t0045-ls.sh
index 2cb46a7dde9..b9d4c0e814a 100755
--- a/test/sharness/t0045-ls.sh
+++ b/test/sharness/t0045-ls.sh
@@ -11,7 +11,6 @@ test_description="Test ls command"
 test_init_ipfs
 
 test_ls_cmd() {
-
   test_expect_success "'ipfs add -r testData' succeeds" '
     mkdir -p testData testData/d1 testData/d2 &&
     echo "test" >testData/f1 &&
@@ -88,6 +87,15 @@ QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 14   a
 EOF
     test_cmp expected_ls_headers actual_ls_headers
   '
+
+  test_expect_success "'ipfs ls --cid-base=base32 <three dir hashes>' succeeds" '
+    ipfs ls --cid-base=base32 $(cid-fmt -v 1 -b base32 %s QmfNy183bXiRVyrhyWtq3TwHn79yHEkiAGFr18P7YNzESj QmR3jhV4XpxxPjPT3Y8vNnWvWNvakdcT3H6vqpRBsX1MLy QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss) >actual_ls_base32
+  '
+
+  test_expect_success "'ipfs ls --cid-base=base32 <three dir hashes>' output looks good" '
+    cid-fmt -b base32 -v 1 --filter %s < expected_ls > expected_ls_base32
+    test_cmp expected_ls_base32 actual_ls_base32
+  '
 }
 
 test_ls_cmd_raw_leaves() {
diff --git a/test/sharness/t0085-pins.sh b/test/sharness/t0085-pins.sh
index 9fac885e887..c388386287c 100755
--- a/test/sharness/t0085-pins.sh
+++ b/test/sharness/t0085-pins.sh
@@ -36,6 +36,11 @@ test_pins() {
     cat hashes | ipfs pin add $EXTRA_ARGS
   '
 
+  #test_expect_success "'ipfs pin add $EXTRA_ARGS' output looks good" '
+  #  sed -e "s/^/pinned /; s/$/ recursively/" hashes > expected &&
+  #  test_cmp expected actual
+  #'
+
   test_expect_success "see if verify works" '
     ipfs pin verify
   '
@@ -51,7 +56,7 @@ test_pins() {
 
   test_expect_success "test pin update" '
     ipfs pin add "$HASH_A" &&
-    ipfs pin ls > before_update &&
+    ipfs pin ls | tee before_update &&
     test_should_contain "$HASH_A" before_update &&
     test_must_fail grep -q "$HASH_B" before_update &&
     ipfs pin update --unpin=true "$HASH_A" "$HASH_B" &&
diff --git a/test/sharness/t0160-resolve.sh b/test/sharness/t0160-resolve.sh
index dacd05d9f84..3261632c2dd 100755
--- a/test/sharness/t0160-resolve.sh
+++ b/test/sharness/t0160-resolve.sh
@@ -12,6 +12,9 @@ test_expect_success "resolve: prepare files" '
   a_hash=$(ipfs add -q -r a | tail -n1) &&
   b_hash=$(ipfs add -q -r a/b | tail -n1) &&
   c_hash=$(ipfs add -q -r a/b/c | tail -n1)
+  a_hash_b32=$(cid-fmt -v 1 -b b %s $a_hash)
+  b_hash_b32=$(cid-fmt -v 1 -b b %s $b_hash)
+  c_hash_b32=$(cid-fmt -v 1 -b b %s $c_hash)
 '
 
 test_resolve_setup_name() {
@@ -41,9 +44,10 @@ test_resolve_setup_name_fail() {
 test_resolve() {
   src=$1
   dst=$2
+  extra=$3
 
   test_expect_success "resolve succeeds: $src" '
-    ipfs resolve -r "$src" >actual
+    ipfs resolve $extra -r "$src" >actual
   '
 
   test_expect_success "resolved correctly: $src -> $dst" '
@@ -53,7 +57,6 @@ test_resolve() {
 }
 
 test_resolve_cmd() {
-
   test_resolve "/ipfs/$a_hash" "/ipfs/$a_hash"
   test_resolve "/ipfs/$a_hash/b" "/ipfs/$b_hash"
   test_resolve "/ipfs/$a_hash/b/c" "/ipfs/$c_hash"
@@ -72,6 +75,30 @@ test_resolve_cmd() {
   test_resolve "/ipns/$id_hash" "/ipfs/$c_hash"
 }
 
+test_resolve_cmd_b32() {
+  # no flags needed, base should be preserved
+
+  test_resolve "/ipfs/$a_hash_b32" "/ipfs/$a_hash_b32"
+  test_resolve "/ipfs/$a_hash_b32/b" "/ipfs/$b_hash_b32"
+  test_resolve "/ipfs/$a_hash_b32/b/c" "/ipfs/$c_hash_b32"
+  test_resolve "/ipfs/$b_hash_b32/c" "/ipfs/$c_hash_b32"
+
+  # flags needed passed in path does not contain cid to derive base
+ 
+  test_resolve_setup_name "/ipfs/$a_hash_b32"
+  test_resolve "/ipns/$id_hash" "/ipfs/$a_hash_b32" --cid-base=base32
+  test_resolve "/ipns/$id_hash/b" "/ipfs/$b_hash_b32" --cid-base=base32
+  test_resolve "/ipns/$id_hash/b/c" "/ipfs/$c_hash_b32" --cid-base=base32
+
+  test_resolve_setup_name "/ipfs/$b_hash_b32" --cid-base=base32
+  test_resolve "/ipns/$id_hash" "/ipfs/$b_hash_b32" --cid-base=base32
+  test_resolve "/ipns/$id_hash/c" "/ipfs/$c_hash_b32" --cid-base=base32
+
+  test_resolve_setup_name "/ipfs/$c_hash_b32"
+  test_resolve "/ipns/$id_hash" "/ipfs/$c_hash_b32" --cid-base=base32
+}
+
+
 #todo remove this once the online resolve is fixed
 test_resolve_fail() {
   src=$1
@@ -108,6 +135,7 @@ test_resolve_cmd_fail() {
 
 # should work offline
 test_resolve_cmd
+test_resolve_cmd_b32
 
 # should work online
 test_launch_ipfs_daemon
diff --git a/thirdparty/cidv0v1/blockstore.go b/thirdparty/cidv0v1/blockstore.go
index 2cb19a4f9a0..1fa13ef348e 100644
--- a/thirdparty/cidv0v1/blockstore.go
+++ b/thirdparty/cidv0v1/blockstore.go
@@ -2,8 +2,8 @@ package cidv0v1
 
 import (
 	cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid"
-	mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash"
 	blocks "gx/ipfs/QmRcHuYzAyswytBuMF78rj3LTChYszomRFXNg4685ZN1WM/go-block-format"
+	cidutil "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil"
 	bs "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore"
 )
 
@@ -20,7 +20,7 @@ func (b *blockstore) Has(c cid.Cid) (bool, error) {
 	if have || err != nil {
 		return have, err
 	}
-	c1 := tryOtherCidVersion(c)
+	c1 := cidutil.TryOtherCidVersion(c)
 	if !c1.Defined() {
 		return false, nil
 	}
@@ -35,7 +35,7 @@ func (b *blockstore) Get(c cid.Cid) (blocks.Block, error) {
 	if err != bs.ErrNotFound {
 		return nil, err
 	}
-	c1 := tryOtherCidVersion(c)
+	c1 := cidutil.TryOtherCidVersion(c)
 	if !c1.Defined() {
 		return nil, bs.ErrNotFound
 	}
@@ -65,23 +65,9 @@ func (b *blockstore) GetSize(c cid.Cid) (int, error) {
 	if err != bs.ErrNotFound {
 		return -1, err
 	}
-	c1 := tryOtherCidVersion(c)
+	c1 := cidutil.TryOtherCidVersion(c)
 	if !c1.Defined() {
 		return -1, bs.ErrNotFound
 	}
 	return b.Blockstore.GetSize(c1)
 }
-
-func tryOtherCidVersion(c cid.Cid) cid.Cid {
-	prefix := c.Prefix()
-	if prefix.Codec != cid.DagProtobuf || prefix.MhType != mh.SHA2_256 || prefix.MhLength != 32 {
-		return cid.Undef
-	}
-	var c1 cid.Cid
-	if prefix.Version == 0 {
-		c1 = cid.NewCidV1(cid.DagProtobuf, c.Hash())
-	} else {
-		c1 = cid.NewCidV0(c.Hash())
-	}
-	return c1
-}

From 2407670b77fe8e0cf31e617c4e8d431f3ce77b48 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Wed, 19 Sep 2018 00:53:26 -0400
Subject: [PATCH 02/13] Add support for preserving the CID string in `ipfs
 refs`.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/refs.go       |  2 +-
 core/commands/root.go       | 10 ++++++++++
 test/sharness/t0095-refs.sh | 40 +++++++++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/core/commands/refs.go b/core/commands/refs.go
index b269c9626a7..603b3263c9f 100644
--- a/core/commands/refs.go
+++ b/core/commands/refs.go
@@ -123,7 +123,7 @@ NOTE: List all references recursively by using the flag '-r'.
 			res.SetError(err, cmdkit.ErrNormal)
 			return
 		}
-		enc := h.Encoder()
+		enc := h.EncoderWithOverride()
 
 		objs, err := objectsForPaths(ctx, n, req.Arguments())
 		if err != nil {
diff --git a/core/commands/root.go b/core/commands/root.go
index 6deb8c67ee8..c678a2e10f7 100644
--- a/core/commands/root.go
+++ b/core/commands/root.go
@@ -292,3 +292,13 @@ func (h *CidBaseHandler) EncoderFromPath(p string) cidenc.Encoder {
 		return *h.enc
 	}
 }
+
+func (h *CidBaseHandler) EncoderWithOverride() cidenc.Interface {
+	if h.base == "" {
+		enc := cidenc.NewOverride(*h.enc)
+		enc.Add(h.args...)
+		return enc
+	} else {
+		return *h.enc
+	}
+}
diff --git a/test/sharness/t0095-refs.sh b/test/sharness/t0095-refs.sh
index 67dcdfaba85..dfa3c61bb95 100755
--- a/test/sharness/t0095-refs.sh
+++ b/test/sharness/t0095-refs.sh
@@ -173,4 +173,44 @@ EOF
   test_cmp refsr.txt expected.txt
 '
 
+test_expect_success "ipfs refs -r -l <mixed multibase>" '
+  cat <<EOF > expected.txt
+bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va -> QmdytmR4wULMd3SLo6ePF4s3WcRHWcpnJZ7bHhoj3QB13v
+bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va -> QmNkQvpiyAEtbeLviC7kqfifYoK1GXPcsSxTpP1yS3ykLa
+QmNkQvpiyAEtbeLviC7kqfifYoK1GXPcsSxTpP1yS3ykLa -> QmdytmR4wULMd3SLo6ePF4s3WcRHWcpnJZ7bHhoj3QB13v
+QmNkQvpiyAEtbeLviC7kqfifYoK1GXPcsSxTpP1yS3ykLa -> uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ
+uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ -> QmSFxnK675wQ9Kc1uqWKyJUaNxvSc2BP5DbXCD3x93oq61
+bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va -> QmXXazTjeNCKFnpW1D65vTKsTs8fbgkCWTv8Em4pdK2coH
+QmXXazTjeNCKFnpW1D65vTKsTs8fbgkCWTv8Em4pdK2coH -> QmNkQvpiyAEtbeLviC7kqfifYoK1GXPcsSxTpP1yS3ykLa
+QmNkQvpiyAEtbeLviC7kqfifYoK1GXPcsSxTpP1yS3ykLa -> QmdytmR4wULMd3SLo6ePF4s3WcRHWcpnJZ7bHhoj3QB13v
+QmNkQvpiyAEtbeLviC7kqfifYoK1GXPcsSxTpP1yS3ykLa -> uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ
+uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ -> QmSFxnK675wQ9Kc1uqWKyJUaNxvSc2BP5DbXCD3x93oq61
+bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va -> uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ
+uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ -> QmSFxnK675wQ9Kc1uqWKyJUaNxvSc2BP5DbXCD3x93oq61
+uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ -> QmSFxnK675wQ9Kc1uqWKyJUaNxvSc2BP5DbXCD3x93oq61
+EOF
+  ipfs refs -r -e bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ > refsr.txt
+  test_cmp refsr.txt expected.txt
+'
+
+test_expect_success "ipfs refs --output-cidv1 -r -l <mixed multibase> " '
+  cat <<EOF > expected.txt
+bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va -> zdj7Wm598r8nwoxVkkGXqc17Shc8pcjEAEvAsX7xWCPrqjuDr
+bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va -> zdj7WVqfJFnpdiVUMerSw5Ni3ZEB1WSz4okjmMzVBQeFVYeWW
+zdj7WVqfJFnpdiVUMerSw5Ni3ZEB1WSz4okjmMzVBQeFVYeWW -> zdj7Wm598r8nwoxVkkGXqc17Shc8pcjEAEvAsX7xWCPrqjuDr
+zdj7WVqfJFnpdiVUMerSw5Ni3ZEB1WSz4okjmMzVBQeFVYeWW -> uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ
+uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ -> zdj7WZMD9k9xZR122uweaTwqgK91B7tKZbWwY13s1ScxVNjFw
+bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va -> zdj7WecqMtoVqfv8W8Rjx3hnqAS65L7KEALNnKeuZTVSkbWyD
+zdj7WecqMtoVqfv8W8Rjx3hnqAS65L7KEALNnKeuZTVSkbWyD -> zdj7WVqfJFnpdiVUMerSw5Ni3ZEB1WSz4okjmMzVBQeFVYeWW
+zdj7WVqfJFnpdiVUMerSw5Ni3ZEB1WSz4okjmMzVBQeFVYeWW -> zdj7Wm598r8nwoxVkkGXqc17Shc8pcjEAEvAsX7xWCPrqjuDr
+zdj7WVqfJFnpdiVUMerSw5Ni3ZEB1WSz4okjmMzVBQeFVYeWW -> uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ
+uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ -> zdj7WZMD9k9xZR122uweaTwqgK91B7tKZbWwY13s1ScxVNjFw
+bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va -> uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ
+uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ -> zdj7WZMD9k9xZR122uweaTwqgK91B7tKZbWwY13s1ScxVNjFw
+uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ -> zdj7WZMD9k9xZR122uweaTwqgK91B7tKZbWwY13s1ScxVNjFw
+EOF
+  ipfs refs --output-cidv1 -r -e bafybeicvusi42o2fcso5ybswnsticebaetge4ispea3i4ayj4bgmy432va uAXASID8NjbmooGbiMTtNz1kVElOi4R4h3R2oKMEQu1lWaqBZ > refsr.txt
+  test_cmp refsr.txt expected.txt
+'
+
 test_done

From 7c974b2ca04f6f933767d6510fb8cb0b983eeb50 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Wed, 19 Sep 2018 02:10:33 -0400
Subject: [PATCH 03/13] Add --cid-base support for `files ls -l`.

Also add tests for both `files ls -l` and `files stat`.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/add.go             |  2 +-
 core/commands/files.go           |  4 ++--
 core/core.go                     |  2 +-
 core/corerepo/gc.go              |  2 +-
 core/coreunix/add.go             |  2 +-
 fuse/ipns/ipns_unix.go           |  2 +-
 package.json                     |  4 ++--
 test/sharness/t0250-files-api.sh | 19 +++++++++++++++++++
 8 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/core/commands/add.go b/core/commands/add.go
index 340da269303..a46a382cdea 100644
--- a/core/commands/add.go
+++ b/core/commands/add.go
@@ -21,7 +21,7 @@ import (
 	cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
 	files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files"
 	cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds"
-	mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs"
+	mfs "gx/ipfs/QmaxgEmTteUHnA1PQrKwHqHme1WQg3Fep9AmdbUGa4t6Wf/go-mfs"
 	cidutil "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil"
 	bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore"
 )
diff --git a/core/commands/files.go b/core/commands/files.go
index e5df4b347de..a4a80f06c03 100644
--- a/core/commands/files.go
+++ b/core/commands/files.go
@@ -30,7 +30,7 @@ import (
 	cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
 	cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds"
 	logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log"
-	mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs"
+	mfs "gx/ipfs/QmaxgEmTteUHnA1PQrKwHqHme1WQg3Fep9AmdbUGa4t6Wf/go-mfs"
 	ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format"
 	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
 )
@@ -482,7 +482,7 @@ Examples:
 					res.SetError(err, cmdkit.ErrNormal)
 					return
 				}
-				out.Entries[0].Hash = nd.Cid().String()
+				out.Entries[0].Hash = apicid.FromCid(nd.Cid())
 			}
 			res.SetOutput(out)
 			return
diff --git a/core/core.go b/core/core.go
index dc58a48338a..e17c0255f19 100644
--- a/core/core.go
+++ b/core/core.go
@@ -65,7 +65,7 @@ import (
 	dht "gx/ipfs/QmZVakpN44VAUxs9eXAuUGLFYTCGmSyqSy6hyEKfMv68ME/go-libp2p-kad-dht"
 	dhtopts "gx/ipfs/QmZVakpN44VAUxs9eXAuUGLFYTCGmSyqSy6hyEKfMv68ME/go-libp2p-kad-dht/opts"
 	pnet "gx/ipfs/QmZaQ3K9PRd5sYYoG1xbTGPtd3N7TYiKBRmcBUTsx8HVET/go-libp2p-pnet"
-	mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs"
+	mfs "gx/ipfs/QmaxgEmTteUHnA1PQrKwHqHme1WQg3Fep9AmdbUGa4t6Wf/go-mfs"
 	peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer"
 	merkledag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag"
 	bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice"
diff --git a/core/corerepo/gc.go b/core/corerepo/gc.go
index 032557a5f36..72e5476fd38 100644
--- a/core/corerepo/gc.go
+++ b/core/corerepo/gc.go
@@ -13,7 +13,7 @@ import (
 	humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
 	cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid"
 	logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log"
-	mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs"
+	mfs "gx/ipfs/QmaxgEmTteUHnA1PQrKwHqHme1WQg3Fep9AmdbUGa4t6Wf/go-mfs"
 )
 
 var log = logging.Logger("corerepo")
diff --git a/core/coreunix/add.go b/core/coreunix/add.go
index 96543c7152f..832335cb800 100644
--- a/core/coreunix/add.go
+++ b/core/coreunix/add.go
@@ -23,7 +23,7 @@ import (
 	files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files"
 	chunker "gx/ipfs/QmULKgr55cSWR8Kiwy3cVRcAiGVnR6EVSaB7hJcWS4138p/go-ipfs-chunker"
 	logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log"
-	mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs"
+	mfs "gx/ipfs/QmaxgEmTteUHnA1PQrKwHqHme1WQg3Fep9AmdbUGa4t6Wf/go-mfs"
 	ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format"
 	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
 	bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore"
diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go
index 61d94c593df..4f3ab3dfb92 100644
--- a/fuse/ipns/ipns_unix.go
+++ b/fuse/ipns/ipns_unix.go
@@ -22,7 +22,7 @@ import (
 	fuse "gx/ipfs/QmSJBsmLP1XMjv8hxYg2rUMdPDB7YUpyBo9idjrJ6Cmq6F/fuse"
 	fs "gx/ipfs/QmSJBsmLP1XMjv8hxYg2rUMdPDB7YUpyBo9idjrJ6Cmq6F/fuse/fs"
 	logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log"
-	mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs"
+	mfs "gx/ipfs/QmaxgEmTteUHnA1PQrKwHqHme1WQg3Fep9AmdbUGa4t6Wf/go-mfs"
 	peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer"
 )
 
diff --git a/package.json b/package.json
index 3b590388dcc..84e94d70333 100644
--- a/package.json
+++ b/package.json
@@ -536,9 +536,9 @@
     },
     {
       "author": "hsanjuan",
-      "hash": "QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2",
+      "hash": "QmaxgEmTteUHnA1PQrKwHqHme1WQg3Fep9AmdbUGa4t6Wf",
       "name": "go-mfs",
-      "version": "0.1.3"
+      "version": "0.1.4"
     },
     {
       "author": "kevina",
diff --git a/test/sharness/t0250-files-api.sh b/test/sharness/t0250-files-api.sh
index 7b97f31ded6..79d3e570b09 100755
--- a/test/sharness/t0250-files-api.sh
+++ b/test/sharness/t0250-files-api.sh
@@ -202,6 +202,12 @@ test_files_api() {
     test_cmp ls_l_expected ls_l_actual
   '
 
+  test_expect_success "file has correct hash and size listed with -l --cid-base=base32" '
+    echo "file1	`cid-fmt -v 1 -b base32 %s $FILE1`	4" > ls_l_expected &&
+    ipfs files ls --cid-base=base32 -l /cats/file1 > ls_l_actual &&
+    test_cmp ls_l_expected ls_l_actual
+  '
+
   test_expect_success "file shows up with the correct name" '
     echo "file1" > ls_l_expected &&
     ipfs files ls /cats/file1 > ls_l_actual &&
@@ -221,6 +227,19 @@ test_files_api() {
     test_cmp file1stat_expect file1stat_actual
   '
 
+  test_expect_success "can stat file with --cid-base=base32 $EXTRA" '
+    ipfs files stat --cid-base=base32 /cats/file1 > file1stat_orig
+  '
+
+  test_expect_success "stat output looks good with --cid-base=base32" '
+    grep -v CumulativeSize: file1stat_orig > file1stat_actual &&
+    echo `cid-fmt -v 1 -b base32 %s $FILE1` > file1stat_expect &&
+    echo "Size: 4" >> file1stat_expect &&
+    echo "ChildBlocks: 0" >> file1stat_expect &&
+    echo "Type: file" >> file1stat_expect &&
+    test_cmp file1stat_expect file1stat_actual
+  '
+
   test_expect_success "can read file $EXTRA" '
     ipfs files read /cats/file1 > file1out
   '

From 0b1ea38099e91dbcc9cf2013024efc6b58730b75 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Tue, 25 Sep 2018 13:56:15 -0400
Subject: [PATCH 04/13] Change --upgrade-cidv0 to --output-cidv1.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/root.go | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/core/commands/root.go b/core/commands/root.go
index c678a2e10f7..d41942df087 100644
--- a/core/commands/root.go
+++ b/core/commands/root.go
@@ -25,9 +25,9 @@ var log = logging.Logger("core/commands")
 var ErrNotOnline = errors.New("this command must be run in online mode. Try running 'ipfs daemon' first")
 
 const (
-	ApiOption          = "api"
-	CidBaseOption      = "cid-base"
-	UpgradeCidV0Option = "upgrade-cidv0"
+	ApiOption         = "api"
+	CidBaseOption     = "cid-base"
+	OutputCidV1Option = "output-cidv1"
 )
 
 var Root = &cmds.Command{
@@ -100,7 +100,7 @@ The CLI will exit with one of the following values:
 		cmdkit.BoolOption("local", "L", "Run the command locally, instead of using the daemon."),
 		cmdkit.StringOption(ApiOption, "Use a specific API instance (defaults to /ip4/127.0.0.1/tcp/5001)"),
 		cmdkit.StringOption(CidBaseOption, "mbase", "Multi-base to use to encode version 1 CIDs in output."),
-		cmdkit.BoolOption(UpgradeCidV0Option, "Upgrade CID version 0 to version 1 in output."),
+		cmdkit.BoolOption(OutputCidV1Option, "Upgrade CID version 0 to version 1 in output."),
 
 		// global options, added to every command
 		cmds.OptionEncodingType,
@@ -240,7 +240,7 @@ type CidBaseHandler struct {
 func NewCidBaseHandler(req *cmds.Request) *CidBaseHandler {
 	h := &CidBaseHandler{}
 	h.base, _ = req.Options[CidBaseOption].(string)
-	h.upgrade, h.upgradeDefined = req.Options[UpgradeCidV0Option].(bool)
+	h.upgrade, h.upgradeDefined = req.Options[OutputCidV1Option].(bool)
 	h.args = req.Arguments
 	return h
 }
@@ -248,7 +248,7 @@ func NewCidBaseHandler(req *cmds.Request) *CidBaseHandler {
 func NewCidBaseHandlerLegacy(req oldcmds.Request) *CidBaseHandler {
 	h := &CidBaseHandler{}
 	h.base, _, _ = req.Option(CidBaseOption).String()
-	h.upgrade, h.upgradeDefined, _ = req.Option(UpgradeCidV0Option).Bool()
+	h.upgrade, h.upgradeDefined, _ = req.Option(OutputCidV1Option).Bool()
 	h.args = req.Arguments()
 	return h
 }

From 9380c83df26c49d09bbe552a2cc2cfb1eabf137e Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Tue, 25 Sep 2018 14:30:17 -0400
Subject: [PATCH 05/13] Move `--cid-base` helpers to `cmdenc` package.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/add.go            |  2 +-
 core/commands/cmdenv/cidbase.go | 87 +++++++++++++++++++++++++++++++++
 core/commands/files.go          |  4 +-
 core/commands/filestore.go      |  6 +--
 core/commands/ls.go             |  3 +-
 core/commands/pin.go            |  5 +-
 core/commands/refs.go           |  7 +--
 core/commands/resolve.go        |  2 +-
 core/commands/root.go           | 86 ++------------------------------
 core/commands/tar.go            |  3 +-
 10 files changed, 110 insertions(+), 95 deletions(-)
 create mode 100644 core/commands/cmdenv/cidbase.go

diff --git a/core/commands/add.go b/core/commands/add.go
index a46a382cdea..bf0ad7e6192 100644
--- a/core/commands/add.go
+++ b/core/commands/add.go
@@ -367,7 +367,7 @@ You can now check what blocks have been created by:
 				log.Warning("cannot determine size of input file")
 			}
 
-			_, err := NewCidBaseHandler(req).UseGlobal().Proc()
+			_, err := cmdenv.NewCidBaseHandler(req).UseGlobal().Proc()
 			if err != nil {
 				return err
 			}
diff --git a/core/commands/cmdenv/cidbase.go b/core/commands/cmdenv/cidbase.go
new file mode 100644
index 00000000000..a0e318c8d76
--- /dev/null
+++ b/core/commands/cmdenv/cidbase.go
@@ -0,0 +1,87 @@
+package cmdenv
+
+import (
+	oldcmds "github.com/ipfs/go-ipfs/commands"
+
+	cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
+	cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds"
+	cidenc "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/cidenc"
+	mbase "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase"
+)
+
+var OptionCidBase = cmdkit.StringOption("cid-base", "mbase", "Multi-base to use to encode version 1 CIDs in output.")
+var OptionOutputCidV1 = cmdkit.BoolOption("output-cidv1", "Upgrade CID version 0 to version 1 in output.")
+
+type CidBaseHandler struct {
+	base           string
+	upgrade        bool
+	upgradeDefined bool
+	args           []string
+	enc            *cidenc.Encoder
+}
+
+func NewCidBaseHandler(req *cmds.Request) *CidBaseHandler {
+	h := &CidBaseHandler{}
+	h.base, _ = req.Options["cid-base"].(string)
+	h.upgrade, h.upgradeDefined = req.Options["output-cidv1"].(bool)
+	h.args = req.Arguments
+	return h
+}
+
+func NewCidBaseHandlerLegacy(req oldcmds.Request) *CidBaseHandler {
+	h := &CidBaseHandler{}
+	h.base, _, _ = req.Option("cid-base").String()
+	h.upgrade, h.upgradeDefined, _ = req.Option("output-cidv1").Bool()
+	h.args = req.Arguments()
+	return h
+}
+
+func (h *CidBaseHandler) UseGlobal() *CidBaseHandler {
+	h.enc = &cidenc.Default
+	return h
+}
+
+func (h *CidBaseHandler) Proc() (*CidBaseHandler, error) {
+	var e cidenc.Encoder = cidenc.Default
+	if h.base != "" {
+		var err error
+		e.Base, err = mbase.EncoderByName(h.base)
+		if err != nil {
+			return h, err
+		}
+	}
+
+	e.Upgrade = h.upgrade
+	if h.base != "" && !h.upgradeDefined {
+		e.Upgrade = true
+	}
+
+	if h.enc == nil {
+		h.enc = &cidenc.Encoder{}
+	}
+	*h.enc = e
+	return h, nil
+}
+
+func (h *CidBaseHandler) Encoder() cidenc.Encoder {
+	return *h.enc
+}
+
+func (h *CidBaseHandler) EncoderFromPath(p string) cidenc.Encoder {
+	if h.base == "" {
+		enc, _ := cidenc.FromPath(*h.enc, p)
+		return enc
+	} else {
+		return *h.enc
+	}
+}
+
+func (h *CidBaseHandler) EncoderWithOverride() cidenc.Interface {
+	if h.base == "" {
+		enc := cidenc.NewOverride(*h.enc)
+		enc.Add(h.args...)
+		return enc
+	} else {
+		return *h.enc
+	}
+}
diff --git a/core/commands/files.go b/core/commands/files.go
index a4a80f06c03..01e8aec0fa9 100644
--- a/core/commands/files.go
+++ b/core/commands/files.go
@@ -163,7 +163,7 @@ var filesStatCmd = &cmds.Command{
 	},
 	Encoders: cmds.EncoderMap{
 		cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
-			_, err := NewCidBaseHandler(req).UseGlobal().Proc()
+			_, err := cmdenv.NewCidBaseHandler(req).UseGlobal().Proc()
 			if err != nil {
 				return err
 			}
@@ -492,7 +492,7 @@ Examples:
 	},
 	Marshalers: oldcmds.MarshalerMap{
 		oldcmds.Text: func(res oldcmds.Response) (io.Reader, error) {
-			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
 			if err != nil {
 				return nil, err
 			}
diff --git a/core/commands/filestore.go b/core/commands/filestore.go
index 87e4f7f0d91..fa0e2a7c786 100644
--- a/core/commands/filestore.go
+++ b/core/commands/filestore.go
@@ -74,7 +74,7 @@ The output is:
 	},
 	PostRun: cmds.PostRunMap{
 		cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error {
-			_, err := NewCidBaseHandler(res.Request()).UseGlobal().Proc()
+			_, err := cmdenv.NewCidBaseHandler(res.Request()).UseGlobal().Proc()
 			if err != nil {
 				return err
 			}
@@ -167,7 +167,7 @@ For ERROR entries the error will also be printed to stderr.
 	},
 	Marshalers: oldCmds.MarshalerMap{
 		oldCmds.Text: func(res oldCmds.Response) (io.Reader, error) {
-			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
 			if err != nil {
 				return nil, err
 			}
@@ -208,7 +208,7 @@ var dupsFileStore = &oldCmds.Command{
 			return
 		}
 
-		h, err := NewCidBaseHandlerLegacy(req).Proc()
+		h, err := cmdenv.NewCidBaseHandlerLegacy(req).Proc()
 		if err != nil {
 			res.SetError(err, cmdkit.ErrNormal)
 			return
diff --git a/core/commands/ls.go b/core/commands/ls.go
index 4d4c403b4ff..d4adccb1d24 100644
--- a/core/commands/ls.go
+++ b/core/commands/ls.go
@@ -8,6 +8,7 @@ import (
 
 	cmds "github.com/ipfs/go-ipfs/commands"
 	core "github.com/ipfs/go-ipfs/core"
+	cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
 	e "github.com/ipfs/go-ipfs/core/commands/e"
 	unixfs "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs"
 	uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io"
@@ -173,7 +174,7 @@ The JSON output contains type information.
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
-			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
 			if err != nil {
 				return nil, err
 			}
diff --git a/core/commands/pin.go b/core/commands/pin.go
index 5e46793f9f6..09b566252db 100644
--- a/core/commands/pin.go
+++ b/core/commands/pin.go
@@ -9,6 +9,7 @@ import (
 
 	cmds "github.com/ipfs/go-ipfs/commands"
 	core "github.com/ipfs/go-ipfs/core"
+	cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
 	e "github.com/ipfs/go-ipfs/core/commands/e"
 	corerepo "github.com/ipfs/go-ipfs/core/corerepo"
 	pin "github.com/ipfs/go-ipfs/pin"
@@ -131,7 +132,7 @@ var addPinCmd = &cmds.Command{
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
-			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
 			if err != nil {
 				return nil, err
 			}
@@ -215,7 +216,7 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.)
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
-			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
 			if err != nil {
 				return nil, err
 			}
diff --git a/core/commands/refs.go b/core/commands/refs.go
index 603b3263c9f..8ca4beb2f0d 100644
--- a/core/commands/refs.go
+++ b/core/commands/refs.go
@@ -9,6 +9,7 @@ import (
 
 	cmds "github.com/ipfs/go-ipfs/commands"
 	"github.com/ipfs/go-ipfs/core"
+	cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
 	e "github.com/ipfs/go-ipfs/core/commands/e"
 	cidenc "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/cidenc"
 
@@ -118,7 +119,7 @@ NOTE: List all references recursively by using the flag '-r'.
 			format = "<src> -> <dst>"
 		}
 
-		h, err := NewCidBaseHandlerLegacy(req).Proc()
+		h, err := cmdenv.NewCidBaseHandlerLegacy(req).Proc()
 		if err != nil {
 			res.SetError(err, cmdkit.ErrNormal)
 			return
@@ -178,7 +179,7 @@ Displays the hashes of all local objects.
 			return
 		}
 
-		h, err := NewCidBaseHandlerLegacy(req).Proc()
+		h, err := cmdenv.NewCidBaseHandlerLegacy(req).Proc()
 		if err != nil {
 			res.SetError(err, cmdkit.ErrNormal)
 			return
@@ -213,7 +214,7 @@ Displays the hashes of all local objects.
 
 var refsMarshallerMap = cmds.MarshalerMap{
 	cmds.Text: func(res cmds.Response) (io.Reader, error) {
-		_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+		_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
 		if err != nil {
 			return nil, err
 		}
diff --git a/core/commands/resolve.go b/core/commands/resolve.go
index 7d3dbbd9059..45254cab481 100644
--- a/core/commands/resolve.go
+++ b/core/commands/resolve.go
@@ -89,7 +89,7 @@ Resolve the value of an IPFS DAG path:
 		name := req.Arguments[0]
 		recursive, _ := req.Options["recursive"].(bool)
 
-		h, err := NewCidBaseHandler(req).Proc()
+		h, err := cmdenv.NewCidBaseHandler(req).Proc()
 		if err != nil {
 			return err
 		}
diff --git a/core/commands/root.go b/core/commands/root.go
index d41942df087..5968185b2d5 100644
--- a/core/commands/root.go
+++ b/core/commands/root.go
@@ -7,17 +7,16 @@ import (
 
 	oldcmds "github.com/ipfs/go-ipfs/commands"
 	lgc "github.com/ipfs/go-ipfs/commands/legacy"
+	cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
 	dag "github.com/ipfs/go-ipfs/core/commands/dag"
 	e "github.com/ipfs/go-ipfs/core/commands/e"
 	name "github.com/ipfs/go-ipfs/core/commands/name"
 	ocmd "github.com/ipfs/go-ipfs/core/commands/object"
 	unixfs "github.com/ipfs/go-ipfs/core/commands/unixfs"
-	cidenc "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/cidenc"
 
 	"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
 	"gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds"
 	logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log"
-	mbase "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase"
 )
 
 var log = logging.Logger("core/commands")
@@ -25,9 +24,7 @@ var log = logging.Logger("core/commands")
 var ErrNotOnline = errors.New("this command must be run in online mode. Try running 'ipfs daemon' first")
 
 const (
-	ApiOption         = "api"
-	CidBaseOption     = "cid-base"
-	OutputCidV1Option = "output-cidv1"
+	ApiOption = "api"
 )
 
 var Root = &cmds.Command{
@@ -99,10 +96,11 @@ The CLI will exit with one of the following values:
 		cmdkit.BoolOption("h", "Show a short version of the command help text."),
 		cmdkit.BoolOption("local", "L", "Run the command locally, instead of using the daemon."),
 		cmdkit.StringOption(ApiOption, "Use a specific API instance (defaults to /ip4/127.0.0.1/tcp/5001)"),
-		cmdkit.StringOption(CidBaseOption, "mbase", "Multi-base to use to encode version 1 CIDs in output."),
-		cmdkit.BoolOption(OutputCidV1Option, "Upgrade CID version 0 to version 1 in output."),
 
 		// global options, added to every command
+		cmdenv.OptionCidBase,
+		cmdenv.OptionOutputCidV1,
+
 		cmds.OptionEncodingType,
 		cmds.OptionStreamChannels,
 		cmds.OptionTimeout,
@@ -228,77 +226,3 @@ func MessageTextMarshaler(res oldcmds.Response) (io.Reader, error) {
 
 	return strings.NewReader(out.Message), nil
 }
-
-type CidBaseHandler struct {
-	base           string
-	upgrade        bool
-	upgradeDefined bool
-	args           []string
-	enc            *cidenc.Encoder
-}
-
-func NewCidBaseHandler(req *cmds.Request) *CidBaseHandler {
-	h := &CidBaseHandler{}
-	h.base, _ = req.Options[CidBaseOption].(string)
-	h.upgrade, h.upgradeDefined = req.Options[OutputCidV1Option].(bool)
-	h.args = req.Arguments
-	return h
-}
-
-func NewCidBaseHandlerLegacy(req oldcmds.Request) *CidBaseHandler {
-	h := &CidBaseHandler{}
-	h.base, _, _ = req.Option(CidBaseOption).String()
-	h.upgrade, h.upgradeDefined, _ = req.Option(OutputCidV1Option).Bool()
-	h.args = req.Arguments()
-	return h
-}
-
-func (h *CidBaseHandler) UseGlobal() *CidBaseHandler {
-	h.enc = &cidenc.Default
-	return h
-}
-
-func (h *CidBaseHandler) Proc() (*CidBaseHandler, error) {
-	var e cidenc.Encoder = cidenc.Default
-	if h.base != "" {
-		var err error
-		e.Base, err = mbase.EncoderByName(h.base)
-		if err != nil {
-			return h, err
-		}
-	}
-
-	e.Upgrade = h.upgrade
-	if h.base != "" && !h.upgradeDefined {
-		e.Upgrade = true
-	}
-
-	if h.enc == nil {
-		h.enc = &cidenc.Encoder{}
-	}
-	*h.enc = e
-	return h, nil
-}
-
-func (h *CidBaseHandler) Encoder() cidenc.Encoder {
-	return *h.enc
-}
-
-func (h *CidBaseHandler) EncoderFromPath(p string) cidenc.Encoder {
-	if h.base == "" {
-		enc, _ := cidenc.FromPath(*h.enc, p)
-		return enc
-	} else {
-		return *h.enc
-	}
-}
-
-func (h *CidBaseHandler) EncoderWithOverride() cidenc.Interface {
-	if h.base == "" {
-		enc := cidenc.NewOverride(*h.enc)
-		enc.Add(h.args...)
-		return enc
-	} else {
-		return *h.enc
-	}
-}
diff --git a/core/commands/tar.go b/core/commands/tar.go
index 7aefe2543ac..981ea584c7e 100644
--- a/core/commands/tar.go
+++ b/core/commands/tar.go
@@ -6,6 +6,7 @@ import (
 
 	cmds "github.com/ipfs/go-ipfs/commands"
 	core "github.com/ipfs/go-ipfs/core"
+	cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
 	e "github.com/ipfs/go-ipfs/core/commands/e"
 	"github.com/ipfs/go-ipfs/core/coreunix"
 	tar "github.com/ipfs/go-ipfs/tar"
@@ -69,7 +70,7 @@ represent it.
 	Type: coreunix.AddedObject{},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
-			_, err := NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
 			if err != nil {
 				return nil, err
 			}

From dd7c66f27bf87b5d0f02cbbcd29a30d086a6ddf1 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Tue, 25 Sep 2018 14:55:39 -0400
Subject: [PATCH 06/13] Use apicid.Hash for `ipfs file ls`.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/unixfs/ls.go | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/core/commands/unixfs/ls.go b/core/commands/unixfs/ls.go
index 598823cfa9b..139f19d1858 100644
--- a/core/commands/unixfs/ls.go
+++ b/core/commands/unixfs/ls.go
@@ -9,6 +9,9 @@ import (
 
 	cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
 
+	cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
+	apicid "gx/ipfs/QmdPF1WZQHFNfLdwhaShiR3e4KvFviAM58TrxVxPMhukic/go-cidutil/apicid"
+
 	cmds "github.com/ipfs/go-ipfs/commands"
 	core "github.com/ipfs/go-ipfs/core"
 	e "github.com/ipfs/go-ipfs/core/commands/e"
@@ -26,7 +29,7 @@ type LsLink struct {
 }
 
 type LsObject struct {
-	Hash  string
+	Hash  apicid.Hash
 	Size  uint64
 	Type  string
 	Links []LsLink
@@ -128,7 +131,7 @@ possible, please use 'ipfs ls' instead.
 			t := unixFSNode.Type()
 
 			output.Objects[hash] = &LsObject{
-				Hash: c.String(),
+				Hash: apicid.FromCid(c),
 				Type: t.String(),
 				Size: unixFSNode.FileSize(),
 			}
@@ -186,6 +189,11 @@ possible, please use 'ipfs ls' instead.
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
+			_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return nil, err
+			}
+
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
 				return nil, err

From 0a4fb1f03518fb7106b3fc407860f0432b6ec348 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Tue, 25 Sep 2018 16:33:46 -0400
Subject: [PATCH 07/13] Add documenation.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/cmdenv/cidbase.go | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/core/commands/cmdenv/cidbase.go b/core/commands/cmdenv/cidbase.go
index a0e318c8d76..1546b62afa1 100644
--- a/core/commands/cmdenv/cidbase.go
+++ b/core/commands/cmdenv/cidbase.go
@@ -12,6 +12,14 @@ import (
 var OptionCidBase = cmdkit.StringOption("cid-base", "mbase", "Multi-base to use to encode version 1 CIDs in output.")
 var OptionOutputCidV1 = cmdkit.BoolOption("output-cidv1", "Upgrade CID version 0 to version 1 in output.")
 
+// CidBaseHandler is a helper class to process the `--cid-base` and
+// `--output-cidv1` options.  In the future it may also be used to
+// process relevant config settings.
+//
+// Several of its methods return the class itself in order to allow
+// easy chaining, a typical usage would be
+// `cmdenv.NewCidBaseHandler(req).UseGlobal().Proc()` or
+// `cmdenv.NewCidBaseHandlerLegacy(req).Proc()`.
 type CidBaseHandler struct {
 	base           string
 	upgrade        bool
@@ -20,6 +28,7 @@ type CidBaseHandler struct {
 	enc            *cidenc.Encoder
 }
 
+// NewCidBaseHandler created a a CidBaseHandler from a request
 func NewCidBaseHandler(req *cmds.Request) *CidBaseHandler {
 	h := &CidBaseHandler{}
 	h.base, _ = req.Options["cid-base"].(string)
@@ -28,6 +37,8 @@ func NewCidBaseHandler(req *cmds.Request) *CidBaseHandler {
 	return h
 }
 
+// NewCidBaseHandlerLegacy created a a CidBaseHandler from a request
+// using the old commands library
 func NewCidBaseHandlerLegacy(req oldcmds.Request) *CidBaseHandler {
 	h := &CidBaseHandler{}
 	h.base, _, _ = req.Option("cid-base").String()
@@ -36,11 +47,17 @@ func NewCidBaseHandlerLegacy(req oldcmds.Request) *CidBaseHandler {
 	return h
 }
 
+// UseGlobal enables the use of the global default.  This is somewhat
+// of a hack and should be used with care.  In particular it should
+// only be used on the client side and not the server side.
 func (h *CidBaseHandler) UseGlobal() *CidBaseHandler {
 	h.enc = &cidenc.Default
 	return h
 }
 
+// Proc processes the `--cid-base` and `--output-cidv1` options.  If
+// UseGlobal was enabled it will change the value of the global
+// default.
 func (h *CidBaseHandler) Proc() (*CidBaseHandler, error) {
 	var e cidenc.Encoder = cidenc.Default
 	if h.base != "" {
@@ -63,10 +80,19 @@ func (h *CidBaseHandler) Proc() (*CidBaseHandler, error) {
 	return h, nil
 }
 
+// Encoder returns a copy of the underlying Encoder
 func (h *CidBaseHandler) Encoder() cidenc.Encoder {
 	return *h.enc
 }
 
+// EncoderFromPath returns a a new Encoder that will format Cid like
+// the one in the path if the `--cid-base` option is not used.  (If
+// the `--cid-base` is used then a copy of the base encoder will be
+// returned.)  In particular: if the path contains a version 1 CID
+// then all CIDs will be outputting using the same multibase.  if the
+// path contains a version 0 CID then version 0 CIDs will be outputted
+// as is and version1 cids will use the multibase from the base
+// encoder
 func (h *CidBaseHandler) EncoderFromPath(p string) cidenc.Encoder {
 	if h.base == "" {
 		enc, _ := cidenc.FromPath(*h.enc, p)
@@ -76,6 +102,12 @@ func (h *CidBaseHandler) EncoderFromPath(p string) cidenc.Encoder {
 	}
 }
 
+// EncoderWithOverride returns a new encoder that will use the setting
+// from the base encoder unless it is a CID that was specified on the
+// command line and the `--cid-base` option was not used.  (If the
+// `--cid-base` is used then a copy of the base encoder will be
+// returned.) In that case the same CID string as specified on the
+// command line will be used.
 func (h *CidBaseHandler) EncoderWithOverride() cidenc.Interface {
 	if h.base == "" {
 		enc := cidenc.NewOverride(*h.enc)

From bf79948e1c03514ad984822d2e5fe70b212784a9 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Thu, 27 Sep 2018 15:11:25 -0400
Subject: [PATCH 08/13] Fix "ipfs pin verify --verbose" test.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 test/sharness/t0085-pins.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/sharness/t0085-pins.sh b/test/sharness/t0085-pins.sh
index c388386287c..12e86c453d8 100755
--- a/test/sharness/t0085-pins.sh
+++ b/test/sharness/t0085-pins.sh
@@ -47,7 +47,7 @@ test_pins() {
 
   test_expect_success "see if verify --verbose works" '
     ipfs pin verify --verbose > verify_out &&
-    test $(cat verify_out | wc -l) > 8
+    test $(cat verify_out | wc -l) -ge 7
   '
 
   test_expect_success "unpin those hashes" '

From 6c4033c2985c750bec33fa1ae92bbc25cf6028ab Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Thu, 27 Sep 2018 15:13:35 -0400
Subject: [PATCH 09/13] Fix `ipfs pin ls` to respect --cid-base add test cases.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/pin.go        | 21 ++++++++------
 test/sharness/t0085-pins.sh | 57 ++++++++++++++++++++++++++-----------
 2 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/core/commands/pin.go b/core/commands/pin.go
index 09b566252db..f7d87218231 100644
--- a/core/commands/pin.go
+++ b/core/commands/pin.go
@@ -312,7 +312,7 @@ Example:
 			return
 		}
 
-		var keys map[string]RefKeyObject
+		var keys map[apicid.Hash]RefKeyObject
 
 		if len(req.Arguments()) > 0 {
 			keys, err = pinLsKeys(req.Context(), req.Arguments(), typeStr, n)
@@ -329,6 +329,11 @@ Example:
 	Type: RefKeyList{},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
+			_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return nil, err
+			}
+
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
 				return nil, err
@@ -513,17 +518,17 @@ type RefKeyObject struct {
 }
 
 type RefKeyList struct {
-	Keys map[string]RefKeyObject
+	Keys map[apicid.Hash]RefKeyObject
 }
 
-func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsNode) (map[string]RefKeyObject, error) {
+func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsNode) (map[apicid.Hash]RefKeyObject, error) {
 
 	mode, ok := pin.StringToMode(typeStr)
 	if !ok {
 		return nil, fmt.Errorf("invalid pin mode '%s'", typeStr)
 	}
 
-	keys := make(map[string]RefKeyObject)
+	keys := make(map[apicid.Hash]RefKeyObject)
 
 	r := &resolver.Resolver{
 		DAG:         n.DAG,
@@ -555,7 +560,7 @@ func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsN
 		default:
 			pinType = "indirect through " + pinType
 		}
-		keys[c.String()] = RefKeyObject{
+		keys[apicid.FromCid(c)] = RefKeyObject{
 			Type: pinType,
 		}
 	}
@@ -563,13 +568,13 @@ func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsN
 	return keys, nil
 }
 
-func pinLsAll(ctx context.Context, typeStr string, n *core.IpfsNode) (map[string]RefKeyObject, error) {
+func pinLsAll(ctx context.Context, typeStr string, n *core.IpfsNode) (map[apicid.Hash]RefKeyObject, error) {
 
-	keys := make(map[string]RefKeyObject)
+	keys := make(map[apicid.Hash]RefKeyObject)
 
 	AddToResultKeys := func(keyList []cid.Cid, typeStr string) {
 		for _, c := range keyList {
-			keys[c.String()] = RefKeyObject{
+			keys[apicid.FromCid(c)] = RefKeyObject{
 				Type: typeStr,
 			}
 		}
diff --git a/test/sharness/t0085-pins.sh b/test/sharness/t0085-pins.sh
index 12e86c453d8..aa5d0f5a864 100755
--- a/test/sharness/t0085-pins.sh
+++ b/test/sharness/t0085-pins.sh
@@ -11,15 +11,19 @@ test_description="Test ipfs pinning operations"
 
 test_pins() {
   EXTRA_ARGS=$1
-
-  test_expect_success "create some hashes" '
-    HASH_A=$(echo "A" | ipfs add -q --pin=false) &&
-    HASH_B=$(echo "B" | ipfs add -q --pin=false) &&
-    HASH_C=$(echo "C" | ipfs add -q --pin=false) &&
-    HASH_D=$(echo "D" | ipfs add -q --pin=false) &&
-    HASH_E=$(echo "E" | ipfs add -q --pin=false) &&
-    HASH_F=$(echo "F" | ipfs add -q --pin=false) &&
-    HASH_G=$(echo "G" | ipfs add -q --pin=false)
+  BASE=$2
+  if [ -n "$BASE" ]; then
+    BASE_ARGS="--cid-base=$BASE"
+  fi
+
+  test_expect_success "create some hashes $BASE" '
+    HASH_A=$(echo "A" | ipfs add $BASE_ARGS -q --pin=false) &&
+    HASH_B=$(echo "B" | ipfs add $BASE_ARGS -q --pin=false) &&
+    HASH_C=$(echo "C" | ipfs add $BASE_ARGS -q --pin=false) &&
+    HASH_D=$(echo "D" | ipfs add $BASE_ARGS -q --pin=false) &&
+    HASH_E=$(echo "E" | ipfs add $BASE_ARGS -q --pin=false) &&
+    HASH_F=$(echo "F" | ipfs add $BASE_ARGS -q --pin=false) &&
+    HASH_G=$(echo "G" | ipfs add $BASE_ARGS -q --pin=false)
   '
 
   test_expect_success "put all those hashes in a file" '
@@ -32,14 +36,22 @@ test_pins() {
     echo $HASH_G >> hashes
   '
 
+  if [ -n "$BASE" ]; then
+    test_expect_success "make sure hashes are in $BASE" '
+      cat hashes | xargs cid-fmt %b | sort -u > actual
+      echo base32 > expected
+      test_cmp expected actual
+    '
+  fi
+
   test_expect_success "'ipfs pin add $EXTRA_ARGS' via stdin" '
-    cat hashes | ipfs pin add $EXTRA_ARGS
+    cat hashes | ipfs pin add $EXTRA_ARGS $BASE_ARGS | tee actual
   '
 
-  #test_expect_success "'ipfs pin add $EXTRA_ARGS' output looks good" '
-  #  sed -e "s/^/pinned /; s/$/ recursively/" hashes > expected &&
-  #  test_cmp expected actual
-  #'
+  test_expect_success "'ipfs pin add $EXTRA_ARGS' output looks good" '
+    sed -e "s/^/pinned /; s/$/ recursively/" hashes > expected &&
+    test_cmp expected actual
+  '
 
   test_expect_success "see if verify works" '
     ipfs pin verify
@@ -50,17 +62,28 @@ test_pins() {
     test $(cat verify_out | wc -l) -ge 7
   '
 
+  test_expect_success "ipfs pin ls $BASE_ARGS works" '
+    ipfs pin ls $BASE_ARGS > ls_out &&
+    test_should_contain "$HASH_A" ls_out &&
+    test_should_contain "$HASH_B" ls_out &&
+    test_should_contain "$HASH_C" ls_out &&
+    test_should_contain "$HASH_D" ls_out &&
+    test_should_contain "$HASH_E" ls_out &&
+    test_should_contain "$HASH_F" ls_out &&
+    test_should_contain "$HASH_G" ls_out
+  '
+
   test_expect_success "unpin those hashes" '
     cat hashes | ipfs pin rm
   '
 
   test_expect_success "test pin update" '
     ipfs pin add "$HASH_A" &&
-    ipfs pin ls | tee before_update &&
+    ipfs pin ls $BASE_ARGS | tee before_update &&
     test_should_contain "$HASH_A" before_update &&
     test_must_fail grep -q "$HASH_B" before_update &&
     ipfs pin update --unpin=true "$HASH_A" "$HASH_B" &&
-    ipfs pin ls > after_update &&
+    ipfs pin ls $BASE_ARGS > after_update &&
     test_must_fail grep -q "$HASH_A" after_update &&
     test_should_contain "$HASH_B" after_update &&
     ipfs pin rm "$HASH_B"
@@ -127,6 +150,7 @@ test_init_ipfs
 
 test_pins
 test_pins --progress
+test_pins '' base32
 
 test_pins_error_reporting
 test_pins_error_reporting --progress
@@ -140,6 +164,7 @@ test_launch_ipfs_daemon --offline
 
 test_pins
 test_pins --progress
+test_pins '' base32
 
 test_pins_error_reporting
 test_pins_error_reporting --progress

From b508f6dabbcad6e090757bc7ab7a5681f8faeae8 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Thu, 27 Sep 2018 15:23:04 -0400
Subject: [PATCH 10/13] Use CID's directly in map in `ipfs pin verify`.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/pin.go | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/core/commands/pin.go b/core/commands/pin.go
index f7d87218231..638c115c436 100644
--- a/core/commands/pin.go
+++ b/core/commands/pin.go
@@ -624,7 +624,7 @@ type pinVerifyOpts struct {
 }
 
 func pinVerify(ctx context.Context, n *core.IpfsNode, opts pinVerifyOpts) <-chan interface{} {
-	visited := make(map[string]PinStatus)
+	visited := make(map[cid.Cid]PinStatus)
 
 	bs := n.Blocks.Blockstore()
 	DAG := dag.NewDAGService(bserv.New(bs, offline.Exchange(bs)))
@@ -633,7 +633,7 @@ func pinVerify(ctx context.Context, n *core.IpfsNode, opts pinVerifyOpts) <-chan
 
 	var checkPin func(root cid.Cid) PinStatus
 	checkPin = func(root cid.Cid) PinStatus {
-		key := root.String()
+		key := root
 		if status, ok := visited[key]; ok {
 			return status
 		}
@@ -641,7 +641,7 @@ func pinVerify(ctx context.Context, n *core.IpfsNode, opts pinVerifyOpts) <-chan
 		if err := verifcid.ValidateCid(root); err != nil {
 			status := PinStatus{Ok: false}
 			if opts.explain {
-				status.BadNodes = []BadNode{BadNode{Cid: key, Err: err.Error()}}
+				status.BadNodes = []BadNode{BadNode{Cid: key.String(), Err: err.Error()}}
 			}
 			visited[key] = status
 			return status
@@ -651,7 +651,7 @@ func pinVerify(ctx context.Context, n *core.IpfsNode, opts pinVerifyOpts) <-chan
 		if err != nil {
 			status := PinStatus{Ok: false}
 			if opts.explain {
-				status.BadNodes = []BadNode{BadNode{Cid: key, Err: err.Error()}}
+				status.BadNodes = []BadNode{BadNode{Cid: key.String(), Err: err.Error()}}
 			}
 			visited[key] = status
 			return status

From 94bb70f89cdc0b37418caf2dff5b72dedfabf2e7 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Thu, 27 Sep 2018 15:31:59 -0400
Subject: [PATCH 11/13] Fix `ipfs pin verify` so it respects the `--cid-base`
 option.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/pin.go        | 15 ++++++++++-----
 test/sharness/t0085-pins.sh | 13 ++++++++++---
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/core/commands/pin.go b/core/commands/pin.go
index 638c115c436..c1ab54451ce 100644
--- a/core/commands/pin.go
+++ b/core/commands/pin.go
@@ -490,6 +490,11 @@ var verifyPinCmd = &cmds.Command{
 	Type: PinVerifyRes{},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
+			_, err := cmdenv.NewCidBaseHandlerLegacy(res.Request()).UseGlobal().Proc()
+			if err != nil {
+				return nil, err
+			}
+
 			quiet, _, _ := res.Request().Option("quiet").Bool()
 
 			out, err := unwrapOutput(res.Output())
@@ -602,7 +607,7 @@ func pinLsAll(ctx context.Context, typeStr string, n *core.IpfsNode) (map[apicid
 
 // PinVerifyRes is the result returned for each pin checked in "pin verify"
 type PinVerifyRes struct {
-	Cid string
+	Cid apicid.Hash
 	PinStatus
 }
 
@@ -614,7 +619,7 @@ type PinStatus struct {
 
 // BadNode is used in PinVerifyRes
 type BadNode struct {
-	Cid string
+	Cid apicid.Hash
 	Err string
 }
 
@@ -641,7 +646,7 @@ func pinVerify(ctx context.Context, n *core.IpfsNode, opts pinVerifyOpts) <-chan
 		if err := verifcid.ValidateCid(root); err != nil {
 			status := PinStatus{Ok: false}
 			if opts.explain {
-				status.BadNodes = []BadNode{BadNode{Cid: key.String(), Err: err.Error()}}
+				status.BadNodes = []BadNode{BadNode{Cid: apicid.FromCid(key), Err: err.Error()}}
 			}
 			visited[key] = status
 			return status
@@ -651,7 +656,7 @@ func pinVerify(ctx context.Context, n *core.IpfsNode, opts pinVerifyOpts) <-chan
 		if err != nil {
 			status := PinStatus{Ok: false}
 			if opts.explain {
-				status.BadNodes = []BadNode{BadNode{Cid: key.String(), Err: err.Error()}}
+				status.BadNodes = []BadNode{BadNode{Cid: apicid.FromCid(key), Err: err.Error()}}
 			}
 			visited[key] = status
 			return status
@@ -677,7 +682,7 @@ func pinVerify(ctx context.Context, n *core.IpfsNode, opts pinVerifyOpts) <-chan
 			pinStatus := checkPin(cid)
 			if !pinStatus.Ok || opts.includeOk {
 				select {
-				case out <- &PinVerifyRes{cid.String(), pinStatus}:
+				case out <- &PinVerifyRes{apicid.FromCid(cid), pinStatus}:
 				case <-ctx.Done():
 					return
 				}
diff --git a/test/sharness/t0085-pins.sh b/test/sharness/t0085-pins.sh
index aa5d0f5a864..e5dfb2718d0 100755
--- a/test/sharness/t0085-pins.sh
+++ b/test/sharness/t0085-pins.sh
@@ -57,9 +57,16 @@ test_pins() {
     ipfs pin verify
   '
 
-  test_expect_success "see if verify --verbose works" '
-    ipfs pin verify --verbose > verify_out &&
-    test $(cat verify_out | wc -l) -ge 7
+  test_expect_success "see if verify --verbose $BASE_ARGS works" '
+    ipfs pin verify --verbose $BASE_ARGS > verify_out &&
+    test $(cat verify_out | wc -l) -ge 7 &&
+    test_should_contain "$HASH_A ok" verify_out &&
+    test_should_contain "$HASH_B ok" verify_out &&
+    test_should_contain "$HASH_C ok" verify_out &&
+    test_should_contain "$HASH_D ok" verify_out &&
+    test_should_contain "$HASH_E ok" verify_out &&
+    test_should_contain "$HASH_F ok" verify_out &&
+    test_should_contain "$HASH_G ok" verify_out
   '
 
   test_expect_success "ipfs pin ls $BASE_ARGS works" '

From bcc58f03acecf52aee12d1b076029622992924e1 Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Thu, 4 Oct 2018 03:27:14 -0400
Subject: [PATCH 12/13] Documentation fixes.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/cmdenv/cidbase.go | 12 ++++++------
 core/commands/dns.go            |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/core/commands/cmdenv/cidbase.go b/core/commands/cmdenv/cidbase.go
index 1546b62afa1..abb58ed2a7c 100644
--- a/core/commands/cmdenv/cidbase.go
+++ b/core/commands/cmdenv/cidbase.go
@@ -9,7 +9,7 @@ import (
 	mbase "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase"
 )
 
-var OptionCidBase = cmdkit.StringOption("cid-base", "mbase", "Multi-base to use to encode version 1 CIDs in output.")
+var OptionCidBase = cmdkit.StringOption("cid-base", "mbase", "Multi-base encoding used for version 1 CIDs in output.")
 var OptionOutputCidV1 = cmdkit.BoolOption("output-cidv1", "Upgrade CID version 0 to version 1 in output.")
 
 // CidBaseHandler is a helper class to process the `--cid-base` and
@@ -28,7 +28,7 @@ type CidBaseHandler struct {
 	enc            *cidenc.Encoder
 }
 
-// NewCidBaseHandler created a a CidBaseHandler from a request
+// NewCidBaseHandler created a CidBaseHandler from a request
 func NewCidBaseHandler(req *cmds.Request) *CidBaseHandler {
 	h := &CidBaseHandler{}
 	h.base, _ = req.Options["cid-base"].(string)
@@ -37,7 +37,7 @@ func NewCidBaseHandler(req *cmds.Request) *CidBaseHandler {
 	return h
 }
 
-// NewCidBaseHandlerLegacy created a a CidBaseHandler from a request
+// NewCidBaseHandlerLegacy created a CidBaseHandler from a request
 // using the old commands library
 func NewCidBaseHandlerLegacy(req oldcmds.Request) *CidBaseHandler {
 	h := &CidBaseHandler{}
@@ -56,7 +56,7 @@ func (h *CidBaseHandler) UseGlobal() *CidBaseHandler {
 }
 
 // Proc processes the `--cid-base` and `--output-cidv1` options.  If
-// UseGlobal was enabled it will change the value of the global
+// UseGlobal was enabled, it will change the value of the global
 // default.
 func (h *CidBaseHandler) Proc() (*CidBaseHandler, error) {
 	var e cidenc.Encoder = cidenc.Default
@@ -85,13 +85,13 @@ func (h *CidBaseHandler) Encoder() cidenc.Encoder {
 	return *h.enc
 }
 
-// EncoderFromPath returns a a new Encoder that will format Cid like
+// EncoderFromPath returns a new Encoder that will format CIDs like
 // the one in the path if the `--cid-base` option is not used.  (If
 // the `--cid-base` is used then a copy of the base encoder will be
 // returned.)  In particular: if the path contains a version 1 CID
 // then all CIDs will be outputting using the same multibase.  if the
 // path contains a version 0 CID then version 0 CIDs will be outputted
-// as is and version1 cids will use the multibase from the base
+// as is and version 1 cids will use the multibase from the base
 // encoder
 func (h *CidBaseHandler) EncoderFromPath(p string) cidenc.Encoder {
 	if h.base == "" {
diff --git a/core/commands/dns.go b/core/commands/dns.go
index 2f2e7800e8d..2353ee7ec65 100644
--- a/core/commands/dns.go
+++ b/core/commands/dns.go
@@ -54,6 +54,7 @@ The resolver can recursively resolve:
 		cmdkit.BoolOption("recursive", "r", "Resolve until the result is not a DNS link."),
 	},
 	Run: func(req cmds.Request, res cmds.Response) {
+
 		recursive, _, _ := req.Option("recursive").Bool()
 		name := req.Arguments()[0]
 		resolver := namesys.NewDNSResolver()
@@ -76,7 +77,6 @@ The resolver can recursively resolve:
 	},
 	Marshalers: cmds.MarshalerMap{
 		cmds.Text: func(res cmds.Response) (io.Reader, error) {
-
 			v, err := unwrapOutput(res.Output())
 			if err != nil {
 				return nil, err

From 6a6af85ed02ad36c8b201b7ba81fa7e502603b7e Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Thu, 4 Oct 2018 03:45:47 -0400
Subject: [PATCH 13/13] Clean up logic in CidBaseHandler.Proc() method.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 core/commands/cmdenv/cidbase.go | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/core/commands/cmdenv/cidbase.go b/core/commands/cmdenv/cidbase.go
index abb58ed2a7c..cf8d683be03 100644
--- a/core/commands/cmdenv/cidbase.go
+++ b/core/commands/cmdenv/cidbase.go
@@ -59,18 +59,21 @@ func (h *CidBaseHandler) UseGlobal() *CidBaseHandler {
 // UseGlobal was enabled, it will change the value of the global
 // default.
 func (h *CidBaseHandler) Proc() (*CidBaseHandler, error) {
-	var e cidenc.Encoder = cidenc.Default
+	e := cidenc.Default
+
 	if h.base != "" {
 		var err error
 		e.Base, err = mbase.EncoderByName(h.base)
 		if err != nil {
 			return h, err
 		}
+		if !h.upgradeDefined {
+			e.Upgrade = true
+		}
 	}
 
-	e.Upgrade = h.upgrade
-	if h.base != "" && !h.upgradeDefined {
-		e.Upgrade = true
+	if h.upgradeDefined {
+		e.Upgrade = h.upgrade
 	}
 
 	if h.enc == nil {