-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Add global option to specify the multibase encoding (server side) #5789
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5512ad5
b22275f
8209ba6
57457af
727aea1
f31e6b6
19d8f62
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| package cmdenv | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "strings" | ||
|
|
||
| cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid" | ||
| cmds "gx/ipfs/QmWGm4AbZEbnmdgVTza52MSNpEmBdFVqzmAysRbjrRyGbH/go-ipfs-cmds" | ||
| cidenc "gx/ipfs/QmdPQx9fvN5ExVwMhRmh7YpCQJzJrFhd1AjVBwJmRMFJeX/go-cidutil/cidenc" | ||
| cmdkit "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit" | ||
| mbase "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase" | ||
| ) | ||
|
|
||
| var OptionCidBase = cmdkit.StringOption("cid-base", "Multibase encoding used for version 1 CIDs in output.") | ||
| var OptionUpgradeCidV0InOutput = cmdkit.BoolOption("upgrade-cidv0-in-output", "Upgrade version 0 to version 1 CIDs in output.") | ||
|
|
||
| // GetCidEncoder processes the `cid-base` and `output-cidv1` options and | ||
| // returns a encoder to use based on those parameters. | ||
| func GetCidEncoder(req *cmds.Request) (cidenc.Encoder, error) { | ||
| return getCidBase(req, true) | ||
| } | ||
|
|
||
| // GetLowLevelCidEncoder is like GetCidEncoder but meant to be used by | ||
| // lower level commands. It differs from GetCidEncoder in that CIDv0 | ||
| // are not, by default, auto-upgraded to CIDv1. | ||
| func GetLowLevelCidEncoder(req *cmds.Request) (cidenc.Encoder, error) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These functions should be named by what they do, not where they're used.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I hate naming, is it okay if we punt on this? |
||
| return getCidBase(req, false) | ||
| } | ||
|
|
||
| func getCidBase(req *cmds.Request, autoUpgrade bool) (cidenc.Encoder, error) { | ||
| base, _ := req.Options[OptionCidBase.Name()].(string) | ||
| upgrade, upgradeDefined := req.Options[OptionUpgradeCidV0InOutput.Name()].(bool) | ||
|
|
||
| e := cidenc.Default() | ||
|
|
||
| if base != "" { | ||
| var err error | ||
| e.Base, err = mbase.EncoderByName(base) | ||
| if err != nil { | ||
| return e, err | ||
| } | ||
| if autoUpgrade { | ||
| e.Upgrade = true | ||
| } | ||
| } | ||
|
|
||
| if upgradeDefined { | ||
| e.Upgrade = upgrade | ||
| } | ||
|
|
||
| return e, nil | ||
| } | ||
|
|
||
| // CidBaseDefined returns true if the `cid-base` option is specified | ||
| // on the command line | ||
| func CidBaseDefined(req *cmds.Request) bool { | ||
| base, _ := req.Options["cid-base"].(string) | ||
| return base != "" | ||
| } | ||
|
|
||
| // CidEncoderFromPath creates a new encoder that is influenced from | ||
| // the encoded Cid in a Path. For CidV0 the multibase from the base | ||
| // encoder is used and automatic upgrades are disabled. For CidV1 the | ||
| // multibase from the CID is used and upgrades are enabled. | ||
| // | ||
| // This logic is intentionally fuzzy and will match anything of the form | ||
| // `CidLike`, `CidLike/...`, or `/namespace/CidLike/...`. | ||
| // | ||
| // For example: | ||
| // | ||
| // * Qm... | ||
| // * Qm.../... | ||
| // * /ipfs/Qm... | ||
| // * /ipns/bafybeiahnxfi7fpmr5wtxs2imx4abnyn7fdxeiox7xxjem6zuiioqkh6zi/... | ||
| // * /bzz/bafybeiahnxfi7fpmr5wtxs2imx4abnyn7fdxeiox7xxjem6zuiioqkh6zi/... | ||
| func CidEncoderFromPath(p string) (cidenc.Encoder, error) { | ||
| components := strings.SplitN(p, "/", 4) | ||
|
|
||
| var maybeCid string | ||
| if components[0] != "" { | ||
| // No leading slash, first component is likely CID-like. | ||
| maybeCid = components[0] | ||
| } else if len(components) < 3 { | ||
| // Not enough components to include a CID. | ||
| return cidenc.Encoder{}, fmt.Errorf("no cid in path: %s", p) | ||
| } else { | ||
| maybeCid = components[2] | ||
| } | ||
| c, err := cid.Decode(maybeCid) | ||
| if err != nil { | ||
| // Ok, not a CID-like thing. Keep the current encoder. | ||
| return cidenc.Encoder{}, fmt.Errorf("no cid in path: %s", p) | ||
| } | ||
| if c.Version() == 0 { | ||
| // Version 0, use the base58 non-upgrading encoder. | ||
| return cidenc.Default(), nil | ||
| } | ||
|
|
||
| // Version 1+, extract multibase encoding. | ||
| encoding, _, err := mbase.Decode(maybeCid) | ||
| if err != nil { | ||
| // This should be impossible, we've already decoded the cid. | ||
| panic(fmt.Sprintf("BUG: failed to get multibase decoder for CID %s", maybeCid)) | ||
| } | ||
|
|
||
| return cidenc.Encoder{Base: mbase.MustNewEncoder(encoding), Upgrade: true}, nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| package cmdenv | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| cidenc "gx/ipfs/QmdPQx9fvN5ExVwMhRmh7YpCQJzJrFhd1AjVBwJmRMFJeX/go-cidutil/cidenc" | ||
| mbase "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase" | ||
| ) | ||
|
|
||
| func TestEncoderFromPath(t *testing.T) { | ||
| test := func(path string, expected cidenc.Encoder) { | ||
| actual, err := CidEncoderFromPath(path) | ||
| if err != nil { | ||
| t.Error(err) | ||
| } | ||
| if actual != expected { | ||
| t.Errorf("CidEncoderFromPath(%s) failed: expected %#v but got %#v", path, expected, actual) | ||
| } | ||
| } | ||
| p := "QmRqVG8VGdKZ7KARqR96MV7VNHgWvEQifk94br5HpURpfu" | ||
| enc := cidenc.Default() | ||
| test(p, enc) | ||
| test(p+"/a", enc) | ||
| test(p+"/a/b", enc) | ||
| test(p+"/a/b/", enc) | ||
| test(p+"/a/b/c", enc) | ||
| test("/ipfs/"+p, enc) | ||
| test("/ipfs/"+p+"/b", enc) | ||
|
|
||
| p = "zb2rhfkM4FjkMLaUnygwhuqkETzbYXnUDf1P9MSmdNjW1w1Lk" | ||
| enc = cidenc.Encoder{ | ||
| Base: mbase.MustNewEncoder(mbase.Base58BTC), | ||
| Upgrade: true, | ||
| } | ||
| test(p, enc) | ||
| test(p+"/a", enc) | ||
| test(p+"/a/b", enc) | ||
| test(p+"/a/b/", enc) | ||
| test(p+"/a/b/c", enc) | ||
| test("/ipfs/"+p, enc) | ||
| test("/ipfs/"+p+"/b", enc) | ||
| test("/ipld/"+p, enc) | ||
| test("/ipns/"+p, enc) // even IPNS should work. | ||
|
|
||
| p = "bafyreifrcnyjokuw4i4ggkzg534tjlc25lqgt3ttznflmyv5fftdgu52hm" | ||
| enc = cidenc.Encoder{ | ||
| Base: mbase.MustNewEncoder(mbase.Base32), | ||
| Upgrade: true, | ||
| } | ||
| test(p, enc) | ||
| test("/ipfs/"+p, enc) | ||
| test("/ipld/"+p, enc) | ||
|
|
||
| for _, badPath := range []string{ | ||
| "/ipld/", | ||
| "/ipld", | ||
| "/ipld//", | ||
| "ipld//", | ||
| "ipld", | ||
| "", | ||
| "ipns", | ||
| "/ipfs/asdf", | ||
| "/ipfs/...", | ||
| "...", | ||
| "abcdefg", | ||
| "boo", | ||
| } { | ||
| _, err := CidEncoderFromPath(badPath) | ||
| if err == nil { | ||
| t.Errorf("expected error extracting encoder from bad path: %s", badPath) | ||
| } | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.