Documentation ¶
Overview ¶
Package commands implements the btfs command interface
Using github.com/TRON-US/go-btfs/commands to define the command line and HTTP APIs. This is the interface available to folks using BTFS from outside of the Go language.
Index ¶
- Constants
- Variables
- func CommandsCmd(root *cmds.Command) *cmds.Command
- func CreateCmdExtras(opts ...func(e *cmds.Extra)) *cmds.Extra
- func ExternalBinary(instructions string) *cmds.Command
- func GetDoesNotUseConfigAsInput(e *cmds.Extra) (val bool, found bool)
- func GetDoesNotUseRepo(e *cmds.Extra) (val bool, found bool)
- func GetPreemptsAutoUpdate(e *cmds.Extra) (val bool, found bool)
- func ParsePeerParam(text string) (ma.Multiaddr, peer.ID, error)
- func SetDoesNotUseConfigAsInput(val bool) func(e *cmds.Extra)
- func SetDoesNotUseRepo(val bool) func(e *cmds.Extra)
- func SetPreemptsAutoUpdate(val bool) func(e *cmds.Extra)
- type AddEvent
- type AddPinOutput
- type BadNode
- type BalanceResponse
- type BlockStat
- type BootstrapOutput
- type CidFormatRes
- type CodeAndName
- type Command
- type ConfigField
- type ConfigUpdateOutput
- type Dependency
- type DiscoveryResult
- type GcResult
- type IdOutput
- type KeyList
- type KeyOutput
- type KeyOutputList
- type KeyRenameOutput
- type Keys
- type LsLink
- type LsObject
- type LsOutput
- type MessageOutput
- type MetaResult
- type Option
- type P2PListenerInfoOutput
- type P2PLsOutput
- type P2PStreamInfoOutput
- type P2PStreamsOutput
- type PinLsList
- type PinLsObject
- type PinLsOutputWrapper
- type PinLsType
- type PinOutput
- type PinStatus
- type PinVerifyRes
- type PingResult
- type RefWrapper
- type RefWriter
- type RepoVersion
- type TransferResult
- type TxResult
- type VerifyProgress
- type VersionOutput
Constants ¶
const ( ConfigOption = "config" DebugOption = "debug" LocalOption = "local" // DEPRECATED: use OfflineOption OfflineOption = "offline" ApiOption = "api" )
const P2PProtoPrefix = "/x/"
P2PProtoPrefix is the default required prefix for protocol names
Variables ¶
var ActiveReqsCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List commands run on this BTFS node.", ShortDescription: ` Lists running and recently run commands. `, }, NoLocal: true, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { ctx := env.(*oldcmds.Context) return cmds.EmitOnce(res, ctx.ReqLog.Report()) }, Options: []cmds.Option{ cmds.BoolOption(verboseOptionName, "v", "Print extra information."), }, Subcommands: map[string]*cmds.Command{ "clear": clearInactiveCmd, "set-time": setRequestClearCmd, }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *[]*cmds.ReqLogEntry) error { verbose, _ := req.Options[verboseOptionName].(bool) tw := tabwriter.NewWriter(w, 4, 4, 2, ' ', 0) if verbose { fmt.Fprint(tw, "ID\t") } fmt.Fprint(tw, "Command\t") if verbose { fmt.Fprint(tw, "Arguments\tOptions\t") } fmt.Fprintln(tw, "Active\tStartTime\tRunTime") for _, req := range *out { if verbose { fmt.Fprintf(tw, "%d\t", req.ID) } fmt.Fprintf(tw, "%s\t", req.Command) if verbose { fmt.Fprintf(tw, "%v\t[", req.Args) var keys []string for k := range req.Options { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { fmt.Fprintf(tw, "%s=%v,", k, req.Options[k]) } fmt.Fprintf(tw, "]\t") } var live time.Duration if req.Active { live = time.Since(req.StartTime) } else { live = req.EndTime.Sub(req.StartTime) } t := req.StartTime.Format(time.Stamp) fmt.Fprintf(tw, "%t\t%s\t%s\n", req.Active, t, live) } tw.Flush() return nil }), }, Type: []*cmds.ReqLogEntry{}, }
var AddCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Add a file or directory to btfs.", ShortDescription: ` Adds contents of <path> to btfs. Use -r to add directories (recursively). `, LongDescription: ` Adds contents of <path> to btfs. Use -r to add directories. Note that directories are added recursively, to form the btfs MerkleDAG. If the daemon is not running, it will just add locally. If the daemon is started later, it will be advertised after a few seconds when the reprovider runs. The wrap option, '-w', wraps the file (or files, if using the recursive option) in a directory. This directory contains only the files which have been added, and means that the file retains its filename. For example: > btfs add example.jpg added QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH example.jpg > btfs add example.jpg -w added QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH example.jpg added QmaG4FuMqEBnQNn3C8XJ5bpW8kLs7zq2ZXgHptJHbKDDVx You can now refer to the added file in a gateway, like so: /btfs/QmaG4FuMqEBnQNn3C8XJ5bpW8kLs7zq2ZXgHptJHbKDDVx/example.jpg The chunker option, '-s', specifies the chunking strategy that dictates how to break files into blocks. Blocks with same content can be deduplicated. Different chunking strategies will produce different hashes for the same file. The default is a fixed block size of 256 * 1024 bytes, 'size-262144'. Alternatively, you can use the Rabin fingerprint chunker for content defined chunking by specifying rabin-[min]-[avg]-[max] (where min/avg/max refer to the desired chunk sizes in bytes), e.g. 'rabin-262144-524288-1048576'. Buzhash or Rabin fingerprint chunker for content defined chunking by specifying buzhash or rabin-[min]-[avg]-[max] (where min/avg/max refer to the desired chunk sizes in bytes), e.g. 'rabin-262144-524288-1048576'. For replicated files intended for host storage, reed-solomon should be used with default settings. It is also supported to customize data and parity shards using reed-solomon-[#data]-[#parity]-[size]. The following examples use very small byte sizes to demonstrate the properties of the different chunkers on a small file. You'll likely want to use a 1024 times larger chunk sizes for most files. > btfs add --chunker=size-2048 btfs-logo.svg added QmafrLBfzRLV4XSH1XcaMMeaXEUhDJjmtDfsYU95TrWG87 btfs-logo.svg > btfs add --chunker=rabin-512-1024-2048 btfs-logo.svg added Qmf1hDN65tR55Ubh2RN1FPxr69xq3giVBz1KApsresY8Gn btfs-logo.svg You can now check what blocks have been created by: > btfs object links QmafrLBfzRLV4XSH1XcaMMeaXEUhDJjmtDfsYU95TrWG87 QmY6yj1GsermExDXoosVE3aSPxdMNYr6aKuw3nA8LoWPRS 2059 Qmf7ZQeSxq2fJVJbCmgTrLLVN9tDR9Wy5k75DxQKuz5Gyt 1195 > btfs object links Qmf1hDN65tR55Ubh2RN1FPxr69xq3giVBz1KApsresY8Gn QmY6yj1GsermExDXoosVE3aSPxdMNYr6aKuw3nA8LoWPRS 2059 QmerURi9k4XzKCaaPbsK6BL5pMEjF7PGphjDvkkjDtsVf3 868 QmQB28iwSriSUSMqG2nXDTLtdPHgWb4rebBrU7Q1j4vxPv 338 Finally, a note on hash determinism. While not guaranteed, adding the same file/directory with the same flags will almost always result in the same output hash. However, almost all of the flags provided by this command (other than pin, only-hash, and progress/status related flags) will change the final hash. `, }, Arguments: []cmds.Argument{ cmds.FileArg("path", true, true, "The path to a file to be added to btfs.").EnableRecursive().EnableStdin(), }, Options: []cmds.Option{ cmds.OptionRecursivePath, cmds.OptionDerefArgs, cmds.OptionStdinName, cmds.OptionHidden, cmds.OptionIgnore, cmds.OptionIgnoreRules, cmds.BoolOption(quietOptionName, "q", "Write minimal output."), cmds.BoolOption(quieterOptionName, "Q", "Write only final hash."), cmds.BoolOption(silentOptionName, "Write no output."), cmds.BoolOption(progressOptionName, "p", "Stream progress data."), cmds.BoolOption(trickleOptionName, "t", "Use trickle-dag format for dag generation."), cmds.BoolOption(onlyHashOptionName, "n", "Only chunk and hash - do not write to disk."), cmds.BoolOption(wrapOptionName, "w", "Wrap files with a directory object."), cmds.StringOption(chunkerOptionName, "s", "Chunking algorithm, size-[bytes], rabin-[min]-[avg]-[max], buzhash or reed-solomon-[#data]-[#parity]-[size]").WithDefault("size-262144"), cmds.BoolOption(pinOptionName, "Pin this object when adding.").WithDefault(true), cmds.BoolOption(rawLeavesOptionName, "Use raw blocks for leaf nodes. (experimental)"), cmds.BoolOption(noCopyOptionName, "Add the file using filestore. Implies raw-leaves. (experimental)"), cmds.BoolOption(fstoreCacheOptionName, "Check the filestore for pre-existing blocks. (experimental)"), cmds.IntOption(cidVersionOptionName, "CID version. Defaults to 0 unless an option that depends on CIDv1 is passed. (experimental)"), cmds.StringOption(hashOptionName, "Hash function to use. Implies CIDv1 if not sha2-256. (experimental)").WithDefault("sha2-256"), cmds.BoolOption(inlineOptionName, "Inline small blocks into CIDs. (experimental)"), cmds.IntOption(inlineLimitOptionName, "Maximum block size to inline. (experimental)").WithDefault(32), cmds.StringOption(tokenMetaOptionName, "m", "Token metadata in JSON string"), cmds.BoolOption(encryptName, "Encrypt the file."), cmds.StringOption(pubkeyName, "The public key to encrypt the file."), cmds.StringOption(peerIdName, "The peer id to encrypt the file."), cmds.IntOption(pinDurationCountOptionName, "d", "Duration for which the object is pinned in days.").WithDefault(0), }, PreRun: func(req *cmds.Request, env cmds.Environment) error { quiet, _ := req.Options[quietOptionName].(bool) quieter, _ := req.Options[quieterOptionName].(bool) quiet = quiet || quieter silent, _ := req.Options[silentOptionName].(bool) if quiet || silent { return nil } _, found := req.Options[progressOptionName].(bool) if !found { req.Options[progressOptionName] = true } return nil }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } progress, _ := req.Options[progressOptionName].(bool) trickle, _ := req.Options[trickleOptionName].(bool) wrap, _ := req.Options[wrapOptionName].(bool) hash, _ := req.Options[onlyHashOptionName].(bool) silent, _ := req.Options[silentOptionName].(bool) chunker, _ := req.Options[chunkerOptionName].(string) dopin, _ := req.Options[pinOptionName].(bool) rawblks, rbset := req.Options[rawLeavesOptionName].(bool) nocopy, _ := req.Options[noCopyOptionName].(bool) fscache, _ := req.Options[fstoreCacheOptionName].(bool) cidVer, cidVerSet := req.Options[cidVersionOptionName].(int) hashFunStr, _ := req.Options[hashOptionName].(string) inline, _ := req.Options[inlineOptionName].(bool) inlineLimit, _ := req.Options[inlineLimitOptionName].(int) tokenMetadata, _ := req.Options[tokenMetaOptionName].(string) encrypt, _ := req.Options[encryptName].(bool) pubkey, _ := req.Options[pubkeyName].(string) peerId, _ := req.Options[peerIdName].(string) pinDuration, _ := req.Options[pinDurationCountOptionName].(int) hashFunCode, ok := mh.Names[strings.ToLower(hashFunStr)] if !ok { return fmt.Errorf("unrecognized hash function: %s", strings.ToLower(hashFunStr)) } enc, err := cmdenv.GetCidEncoder(req) if err != nil { return err } toadd := req.Files if wrap { toadd = files.NewSliceDirectory([]files.DirEntry{ files.FileEntry("", req.Files), }) } opts := []options.UnixfsAddOption{ options.Unixfs.Hash(hashFunCode), options.Unixfs.Inline(inline), options.Unixfs.InlineLimit(inlineLimit), options.Unixfs.Chunker(chunker), options.Unixfs.Pin(dopin), options.Unixfs.HashOnly(hash), options.Unixfs.FsCache(fscache), options.Unixfs.Nocopy(nocopy), options.Unixfs.Progress(progress), options.Unixfs.Silent(silent), options.Unixfs.TokenMetadata(tokenMetadata), options.Unixfs.PinDuration(int64(pinDuration)), } if cidVerSet { opts = append(opts, options.Unixfs.CidVersion(cidVer)) } if rbset { opts = append(opts, options.Unixfs.RawLeaves(rawblks)) } if trickle { opts = append(opts, options.Unixfs.Layout(options.TrickleLayout)) } if encrypt { opts = append(opts, options.Unixfs.Encrypt(encrypt)) opts = append(opts, options.Unixfs.Pubkey(pubkey)) opts = append(opts, options.Unixfs.PeerId(peerId)) } opts = append(opts, nil) var added int addit := toadd.Entries() for addit.Next() { _, dir := addit.Node().(files.Directory) errCh := make(chan error, 1) events := make(chan interface{}, adderOutChanSize) opts[len(opts)-1] = options.Unixfs.Events(events) go func() { var err error defer close(events) _, err = api.Unixfs().Add(req.Context, addit.Node(), opts...) errCh <- err }() for event := range events { output, ok := event.(*coreiface.AddEvent) if !ok { return errors.New("unknown event type") } h := "" if output.Path != nil { h = enc.Encode(output.Path.Cid()) } if !dir && addit.Name() != "" { output.Name = addit.Name() } else { output.Name = path.Join(addit.Name(), output.Name) } if err := res.Emit(&AddEvent{ Name: output.Name, Hash: h, Bytes: output.Bytes, Size: output.Size, }); err != nil { return err } } if err := <-errCh; err != nil { return err } added++ } if addit.Err() != nil { return addit.Err() } if added == 0 { return fmt.Errorf("expected a file argument") } return nil }, PostRun: cmds.PostRunMap{ cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error { sizeChan := make(chan int64, 1) outChan := make(chan interface{}) req := res.Request() go func() { op := res.Request().Options[encryptName] encrypt := op != nil && op.(bool) if encrypt { it := req.Files.Entries() var size int64 = 0 for it.Next() { s, err := it.Node().Size() if err != nil { log.Warnf("error getting files size: %s", err) return } blockCount := s/16 + 1 size += blockCount * 32 sizeChan <- size } } else { size, err := req.Files.Size() if err != nil { log.Warnf("error getting files size: %s", err) return } sizeChan <- size } }() progressBar := func(wait chan struct{}) { defer close(wait) quiet, _ := req.Options[quietOptionName].(bool) quieter, _ := req.Options[quieterOptionName].(bool) quiet = quiet || quieter progress, _ := req.Options[progressOptionName].(bool) var bar *pb.ProgressBar if progress { bar = pb.New64(0).SetUnits(pb.U_BYTES) bar.ManualUpdate = true bar.ShowTimeLeft = false bar.ShowPercent = false bar.Output = os.Stderr bar.Start() } lastFile := "" lastHash := "" var totalProgress, prevFiles, lastBytes int64 LOOP: for { select { case out, ok := <-outChan: if !ok { if quieter { fmt.Fprintln(os.Stdout, lastHash) } break LOOP } output := out.(*AddEvent) if len(output.Hash) > 0 { lastHash = output.Hash if quieter { continue } if progress { fmt.Fprintf(os.Stderr, "\033[2K\r") } if quiet { fmt.Fprintf(os.Stdout, "%s\n", output.Hash) } else { fmt.Fprintf(os.Stdout, "added %s %s\n", output.Hash, output.Name) } } else { if !progress { continue } if len(lastFile) == 0 { lastFile = output.Name } if output.Name != lastFile || output.Bytes < lastBytes { prevFiles += lastBytes lastFile = output.Name } lastBytes = output.Bytes delta := prevFiles + lastBytes - totalProgress totalProgress = bar.Add64(delta) } if progress { bar.Update() } case size := <-sizeChan: if progress { bar.Total = size bar.ShowPercent = true bar.ShowBar = true bar.ShowTimeLeft = true } case <-req.Context.Done(): return } } if progress && bar.Total == 0 && bar.Get() != 0 { bar.Total = bar.Get() bar.ShowPercent = true bar.ShowBar = true bar.ShowTimeLeft = true bar.Update() } } if e := res.Error(); e != nil { close(outChan) return e } wait := make(chan struct{}) go progressBar(wait) defer func() { <-wait }() defer close(outChan) for { v, err := res.Next() if err != nil { if err == io.EOF { return nil } return err } select { case outChan <- v: case <-req.Context.Done(): return req.Context.Err() } } }, }, Type: AddEvent{}, }
var BitswapCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with the bitswap agent.", ShortDescription: ``, }, Subcommands: map[string]*cmds.Command{ "stat": bitswapStatCmd, "wantlist": showWantlistCmd, "ledger": ledgerCmd, "reprovide": reprovideCmd, }, }
var BlockCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with raw BTFS blocks.", ShortDescription: ` 'btfs block' is a plumbing command used to manipulate raw BTFS blocks. Reads from stdin or writes to stdout, and <key> is a base58 encoded multihash. `, }, Subcommands: map[string]*cmds.Command{ "stat": blockStatCmd, "get": blockGetCmd, "put": blockPutCmd, "rm": blockRmCmd, }, }
var BootstrapCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Show or edit the list of bootstrap peers.", ShortDescription: ` Running 'btfs bootstrap' with no arguments will run 'btfs bootstrap list'. ` + bootstrapSecurityWarning, }, Run: bootstrapListCmd.Run, Encoders: bootstrapListCmd.Encoders, Type: bootstrapListCmd.Type, Subcommands: map[string]*cmds.Command{ "list": bootstrapListCmd, "add": bootstrapAddCmd, "rm": bootstrapRemoveCmd, }, }
var CatCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Show BTFS object data.", ShortDescription: "Displays the data contained by an BTFS or BTNS object(s) at the given path.", }, Arguments: []cmds.Argument{ cmds.StringArg("btfs-path", true, true, "The path to the BTFS object(s) to be outputted.").EnableStdin(), }, Options: []cmds.Option{ cmds.Int64Option(offsetOptionName, "o", "Byte offset to begin reading from."), cmds.Int64Option(lengthOptionName, "l", "Maximum number of bytes to read."), cmds.BoolOption(catMetaDisplayOptionName, "m", "Display token metadata"), cmds.BoolOption(decryptName, "d", "Decrypt the file."), cmds.StringOption(privateKeyName, "pk", "The private key to decrypt file."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } offset, _ := req.Options[offsetOptionName].(int64) if offset < 0 { return fmt.Errorf("cannot specify negative offset") } max, found := req.Options[lengthOptionName].(int64) if max < 0 { return fmt.Errorf("cannot specify negative length") } if !found { max = -1 } meta, _ := req.Options[catMetaDisplayOptionName].(bool) err = req.ParseBodyArgs() if err != nil { return err } readers, length, err := cat(req.Context, api, req.Arguments, int64(offset), int64(max), meta, req.Options) if err != nil { return err } res.SetLength(length) reader := io.MultiReader(readers...) return res.Emit(reader) }, PostRun: cmds.PostRunMap{ cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error { if res.Length() > 0 && res.Length() < progressBarMinSize { return cmds.Copy(re, res) } for { v, err := res.Next() if err != nil { if err == io.EOF { return nil } return err } switch val := v.(type) { case io.Reader: bar, reader := progressBarForReader(os.Stderr, val, int64(res.Length())) bar.Start() err = re.Emit(reader) if err != nil { return err } default: log.Warnf("cat postrun: received unexpected type %T", val) } } }, }, }
var CidCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Convert and discover properties of CIDs", }, Subcommands: map[string]*cmds.Command{ "format": cidFmtCmd, "base32": base32Cmd, "bases": basesCmd, "codecs": codecsCmd, "hashes": hashesCmd, }, Extra: CreateCmdExtras(SetDoesNotUseRepo(true)), }
var CommandsDaemonCmd = CommandsCmd(Root)
commandsDaemonCmd is the "btfs commands" command for daemon
var CommandsDaemonROCmd = CommandsCmd(RootRO)
var ConfigCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Get and set btfs config values.", ShortDescription: ` 'btfs config' controls configuration variables. It works like 'git config'. The configuration values are stored in a config file inside your btfs repository.`, LongDescription: ` 'btfs config' controls configuration variables. It works much like 'git config'. The configuration values are stored in a config file inside your BTFS repository. Examples: Get the value of the 'Datastore.Path' key: $ btfs config Datastore.Path Set the value of the 'Datastore.Path' key: $ btfs config Datastore.Path ~/.btfs/datastore `, }, Subcommands: map[string]*cmds.Command{ "show": configShowCmd, "edit": configEditCmd, "replace": configReplaceCmd, "profile": configProfileCmd, "optin": optInCmd, "optout": optOutCmd, }, Arguments: []cmds.Argument{ cmds.StringArg("key", true, false, "The key of the config entry (e.g. \"Addresses.API\")."), cmds.StringArg("value", false, false, "The value to set the config entry to."), }, Options: []cmds.Option{ cmds.BoolOption(configBoolOptionName, "Set a boolean value."), cmds.BoolOption(configJSONOptionName, "Parse stringified JSON."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { args := req.Arguments key := args[0] var output *ConfigField switch strings.ToLower(key) { case "identity", "identity.privkey", "identity.mnemonic", "identity.peerid": return fmt.Errorf("cannot show or change %s through API", key) default: } cfgRoot, err := cmdenv.GetConfigRoot(env) if err != nil { return err } r, err := fsrepo.Open(cfgRoot) if err != nil { return err } defer r.Close() if len(args) == 2 { value := args[1] if parseJSON, _ := req.Options[configJSONOptionName].(bool); parseJSON { var jsonVal interface{} if err := json.Unmarshal([]byte(value), &jsonVal); err != nil { err = fmt.Errorf("failed to unmarshal json. %s", err) return err } output, err = setConfig(r, key, jsonVal) } else if isbool, _ := req.Options[configBoolOptionName].(bool); isbool { output, err = setConfig(r, key, value == "true") } else { output, err = setConfig(r, key, value) } if err != nil { return err } if f, err := getConfig(r, "UI.Wallet.Initialized"); err == nil { if f.Value.(bool) == true { err := r.SetConfigKey("Identity.Mnemonic", "") if err != nil { return err } } } } else { output, err = getConfig(r, key) } if err != nil { return err } return cmds.EmitOnce(res, output) }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *ConfigField) error { if len(req.Arguments) == 2 { return nil } buf, err := config.HumanOutput(out.Value) if err != nil { return err } buf = append(buf, byte('\n')) _, err = w.Write(buf) return err }), }, Type: ConfigField{}, }
var DNSCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Resolve DNS links.", ShortDescription: ` Multihashes are hard to remember, but domain names are usually easy to remember. To create memorable aliases for multihashes, DNS TXT records can point to other DNS links, BTFS objects, BTNS keys, etc. This command resolves those links to the referenced object. `, LongDescription: ` Multihashes are hard to remember, but domain names are usually easy to remember. To create memorable aliases for multihashes, DNS TXT records can point to other DNS links, BTFS objects, BTNS keys, etc. This command resolves those links to the referenced object. Note: This command can only recursively resolve DNS links, it will fail to recursively resolve through BTNS keys etc. For general-purpose recursive resolution, use btfs name resolve -r. For example, with this DNS TXT record: > dig +short TXT _dnslink.ipfs.io dnslink=/btfs/QmRzTuh2Lpuz7Gr39stNr6mTFdqAghsZec1JoUnfySUzcy The resolver will give: > btfs dns ipfs.io /btfs/QmRzTuh2Lpuz7Gr39stNr6mTFdqAghsZec1JoUnfySUzcy The resolver can recursively resolve: > dig +short TXT recursive.ipfs.io dnslink=/ipns/ipfs.io > btfs dns -r recursive.ipfs.io /btfs/QmRzTuh2Lpuz7Gr39stNr6mTFdqAghsZec1JoUnfySUzcy `, }, Arguments: []cmds.Argument{ cmds.StringArg("domain-name", true, false, "The domain-name name to resolve.").EnableStdin(), }, Options: []cmds.Option{ cmds.BoolOption(dnsRecursiveOptionName, "r", "Resolve until the result is not a DNS link.").WithDefault(true), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { recursive, _ := req.Options[dnsRecursiveOptionName].(bool) name := req.Arguments[0] resolver := namesys.NewDNSResolver() var routing []nsopts.ResolveOpt if !recursive { routing = append(routing, nsopts.Depth(1)) } output, err := resolver.Resolve(req.Context, name, routing...) if err != nil && (recursive || err != namesys.ErrResolveRecursion) { return err } return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: output}) }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *ncmd.ResolvedPath) error { fmt.Fprintln(w, out.Path.String()) return nil }), }, Type: ncmd.ResolvedPath{}, }
var DefaultBufSize = 1048576
DefaultBufSize is the buffer size for gets. for now, 1MB, which is ~4 blocks. TODO: does this need to be configurable?
var DhtCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Issue commands directly through the DHT.", ShortDescription: ``, }, Subcommands: map[string]*cmds.Command{ "query": queryDhtCmd, "findprovs": findProvidersDhtCmd, "findpeer": findPeerDhtCmd, "get": getValueDhtCmd, "put": putValueDhtCmd, "provide": provideRefDhtCmd, }, }
var DiagCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Generate diagnostic reports.", }, Subcommands: map[string]*cmds.Command{ "sys": sysDiagCmd, "cmds": ActiveReqsCmd, }, }
var ErrDepthLimitExceeded = fmt.Errorf("depth limit exceeded")
ErrDepthLimitExceeded indicates that the max depth has been exceeded.
var ErrInvalidCompressionLevel = errors.New("compression level must be between 1 and 9")
var ErrNotDHT = errors.New("routing service is not a DHT")
var ErrNotOnline = errors.New("this command must be run in online mode. Try running 'btfs daemon' first")
var ErrPingSelf = errors.New("error: can't ping self")
ErrPingSelf is returned when the user attempts to ping themself.
var FileStoreCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with filestore objects.", }, Subcommands: map[string]*cmds.Command{ "ls": lsFileStore, "verify": verifyFileStore, "dups": dupsFileStore, }, }
var FilesCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with unixfs files.", ShortDescription: ` Files is an API for manipulating BTFS objects as if they were a unix filesystem. The files facility interacts with MFS (Mutable File System). MFS acts as a single, dynamic filesystem mount. MFS has a root CID that is transparently updated when a change happens (and can be checked with "ipfs files stat /"). All files and folders within MFS are respected and will not be cleaned up during garbage collections. MFS is independent from the list of pinned items ("ipfs pin ls"). Calls to "ipfs pin add" and "ipfs pin rm" will add and remove pins independently of MFS. If MFS content that was additionally pinned is removed by calling "ipfs files rm", it will still remain pinned. Content added with "ipfs add" (which by default also becomes pinned), is not added to MFS. Any content can be put into MFS with the command "ipfs files cp /ipfs/<cid> /some/path/". NOTE: Most of the subcommands of 'btfs files' accept the '--flush' flag. It defaults to true. Use caution when setting this flag to false. It will improve performance for large numbers of file operations, but it does so at the cost of consistency guarantees. If the daemon is unexpectedly killed before running 'btfs files flush' on the files in question, then data may be lost. This also applies to running 'btfs repo gc' concurrently with '--flush=false' operations. `, }, Options: []cmds.Option{ cmds.BoolOption(filesFlushOptionName, "f", "Flush target and ancestors after write.").WithDefault(true), }, Subcommands: map[string]*cmds.Command{ "read": filesReadCmd, "write": filesWriteCmd, "mv": filesMvCmd, "cp": filesCpCmd, "ls": filesLsCmd, "mkdir": filesMkdirCmd, "stat": filesStatCmd, "rm": filesRmCmd, "flush": filesFlushCmd, "chcid": filesChcidCmd, }, }
FilesCmd is the 'btfs files' command
var GetCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Download BTFS objects.", ShortDescription: ` Stores to disk the data contained an BTFS or BTNS object(s) at the given path. By default, the output will be stored at './<btfs-path>', but an alternate path can be specified with '--output=<path>' or '-o=<path>'. To output a TAR archive instead of unpacked files, use '--archive' or '-a'. To compress the output with GZIP compression, use '--compress' or '-C'. You may also specify the level of compression by specifying '-l=<1-9>'. To output just the metadata of this BTFS node, use '--meta' or '-m'. To repair missing shards of a Reed-Solomon encoded file, use '--repair-shards' or '-rs'. If '--meta' or '-m' is enabled, this option is ignored. `, }, Arguments: []cmds.Argument{ cmds.StringArg("btfs-path", true, false, "The path to the BTFS object(s) to be outputted.").EnableStdin(), }, Options: []cmds.Option{ cmds.StringOption(outputOptionName, "o", "The path where the output should be stored."), cmds.BoolOption(archiveOptionName, "a", "Output a TAR archive."), cmds.BoolOption(compressOptionName, "C", "Compress the output with GZIP compression."), cmds.IntOption(compressionLevelOptionName, "l", "The level of compression (1-9)."), cmds.BoolOption(getMetaDisplayOptionName, "m", "Display token metadata"), cmds.BoolOption(decryptName, "d", "Decrypt the file."), cmds.StringOption(privateKeyName, "pk", "The private key to decrypt file."), cmds.StringOption(repairShardsName, "rs", "Repair the list of shards. Multihashes separated by ','."), cmds.BoolOption(quietOptionName, "q", "Quiet mode: perform get operation without writing to anywhere. Same as using -o /dev/null."), }, PreRun: func(req *cmds.Request, env cmds.Environment) error { _, err := getCompressOptions(req) return err }, RunTimeout: 5 * time.Minute, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { cmplvl, err := getCompressOptions(req) if err != nil { return err } api, err := cmdenv.GetApi(env, req) if err != nil { return err } p := path.New(req.Arguments[0]) decrypt, _ := req.Options[decryptName].(bool) privateKey, _ := req.Options[privateKeyName].(string) meta, _ := req.Options[getMetaDisplayOptionName].(bool) var repairs []cid.Cid if rs, ok := req.Options[repairShardsName].(string); ok { rshards := strings.Split(rs, ",") for _, rshard := range rshards { rcid, err := cid.Parse(rshard) if err != nil { return err } repairs = append(repairs, rcid) } } opts := []options.UnixfsGetOption{ options.Unixfs.Decrypt(decrypt), options.Unixfs.PrivateKey(privateKey), options.Unixfs.Metadata(meta), options.Unixfs.Repairs(repairs), } file, err := api.Unixfs().Get(req.Context, p, opts...) if err != nil { return err } quiet, _ := req.Options[quietOptionName].(bool) if quiet { return cmds.EmitOnce(res, nil) } size, err := file.Size() if err != nil { return err } res.SetLength(uint64(size)) archive, _ := req.Options[archiveOptionName].(bool) reader, err := fileArchive(file, p.String(), archive, cmplvl) if err != nil { return err } return res.Emit(reader) }, PostRun: cmds.PostRunMap{ cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error { req := res.Request() v, err := res.Next() if err != nil { return err } if v == nil { return nil } outReader, ok := v.(io.Reader) if !ok { return e.New(e.TypeErr(outReader, v)) } outPath := getOutPath(req) cmplvl, err := getCompressOptions(req) if err != nil { return err } archive, _ := req.Options[archiveOptionName].(bool) gw := getWriter{ Out: os.Stdout, Err: os.Stderr, Archive: archive, Compression: cmplvl, Size: int64(res.Length()), } return gw.Write(outReader, outPath) }, }, }
var GuardCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with guard services from BTFS client.", ShortDescription: ` Connect with guard functions directly through this command. The subcommands here are mostly for debugging and testing purposes.`, }, Subcommands: map[string]*cmds.Command{ "test": guardTestCmd, }, }
var IDCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Show btfs node id info.", ShortDescription: ` Prints out information about the specified peer. If no peer is specified, prints out information for local peers. 'btfs id' supports the format option for output with the following keys: <id> : The peers id. <aver>: Agent version. <pver>: Protocol version. <pubkey>: Public key. <addrs>: Addresses (newline delimited). EXAMPLE: btfs id Qmece2RkXhsKe5CRooNisBTh4SK119KrXXGmoK6V3kb8aH -f="<addrs>\n" `, }, Arguments: []cmds.Argument{ cmds.StringArg("peerid", false, false, "Peer.ID of node to look up."), }, Options: []cmds.Option{ cmds.StringOption(formatOptionName, "f", "Optional output format."), cmds.StringOption(idFormatOptionName, "Encoding used for peer IDs: Can either be a multibase encoded CID or a base58btc encoded multihash. Takes {b58mh|base36|k|base32|b...}.").WithDefault("b58mh"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { keyEnc, err := ke.KeyEncoderFromString(req.Options[idFormatOptionName].(string)) if err != nil { return err } n, err := cmdenv.GetNode(env) if err != nil { return err } var id peer.ID if len(req.Arguments) > 0 { var err error id, err = peer.Decode(req.Arguments[0]) if err != nil { return fmt.Errorf("invalid peer id") } } else { id = n.Identity } if id == n.Identity { output, err := printSelf(keyEnc, n) if err != nil { return err } return cmds.EmitOnce(res, output) } if !n.IsOnline { return errors.New(offlineIdErrorMessage) } err = n.PeerHost.Connect(req.Context, peer.AddrInfo{ID: id}) switch err { case nil: case kb.ErrLookupFailure: return errors.New(offlineIdErrorMessage) default: return err } output, err := printPeer(keyEnc, n.Peerstore, id) if err != nil { return err } return cmds.EmitOnce(res, output) }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *IdOutput) error { format, found := req.Options[formatOptionName].(string) if found { output := format output = strings.Replace(output, "<id>", out.ID, -1) output = strings.Replace(output, "<aver>", out.AgentVersion, -1) output = strings.Replace(output, "<pver>", out.ProtocolVersion, -1) output = strings.Replace(output, "<pubkey>", out.PublicKey, -1) output = strings.Replace(output, "<addrs>", strings.Join(out.Addresses, "\n"), -1) output = strings.Replace(output, "<protocols>", strings.Join(out.Protocols, "\n"), -1) output = strings.Replace(output, "\\n", "\n", -1) output = strings.Replace(output, "\\t", "\t", -1) fmt.Fprint(w, output) } else { marshaled, err := json.MarshalIndent(out, "", "\t") if err != nil { return err } marshaled = append(marshaled, byte('\n')) fmt.Fprintln(w, string(marshaled)) } return nil }), }, Type: IdOutput{}, }
var KeyCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Create and list BTNS name keypairs", ShortDescription: ` 'btfs key gen' generates a new keypair for usage with BTNS and 'btfs name publish'. > btfs key gen --type=rsa --size=2048 mykey > btfs name publish --key=mykey QmSomeHash 'btfs key list' lists the available keys. > btfs key list self mykey `, }, Subcommands: map[string]*cmds.Command{ "gen": keyGenCmd, "list": keyListCmd, "rename": keyRenameCmd, "rm": keyRmCmd, }, }
var LogCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with the daemon log output.", ShortDescription: ` 'btfs log' contains utility commands to affect or read the logging output of a running daemon. There are also two environmental variables that direct the logging system (not just for the daemon logs, but all commands): IPFS_LOGGING - sets the level of verbosity of the logging. One of: debug, info, warn, error, dpanic, panic, fatal IPFS_LOGGING_FMT - sets formatting of the log output. One of: color, nocolor `, }, Subcommands: map[string]*cmds.Command{ "level": logLevelCmd, "ls": logLsCmd, "tail": logTailCmd, }, }
var LsCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List directory contents for Unix filesystem objects.", ShortDescription: ` Displays the contents of an BTFS or BTNS object(s) at the given path, with the following format: <link base58 hash> <link size in bytes> <link name> The JSON output contains type information. `, }, Arguments: []cmds.Argument{ cmds.StringArg("btfs-path", true, true, "The path to the BTFS object(s) to list links from.").EnableStdin(), }, Options: []cmds.Option{ cmds.BoolOption(lsHeadersOptionNameTime, "v", "Print table headers (Hash, Size, Name)."), cmds.BoolOption(lsResolveTypeOptionName, "Resolve linked objects to find out their types.").WithDefault(true), cmds.BoolOption(lsSizeOptionName, "Resolve linked objects to find out their file size.").WithDefault(true), cmds.BoolOption(lsStreamOptionName, "s", "Enable experimental streaming of directory entries as they are traversed."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } resolveType, _ := req.Options[lsResolveTypeOptionName].(bool) resolveSize, _ := req.Options[lsSizeOptionName].(bool) stream, _ := req.Options[lsStreamOptionName].(bool) err = req.ParseBodyArgs() if err != nil { return err } paths := req.Arguments enc, err := cmdenv.GetCidEncoder(req) if err != nil { return err } var processLink func(path string, link LsLink) error var dirDone func(i int) processDir := func() (func(path string, link LsLink) error, func(i int)) { return func(path string, link LsLink) error { output := []LsObject{{ Hash: path, Links: []LsLink{link}, }} return res.Emit(&LsOutput{output}) }, func(i int) {} } done := func() error { return nil } if !stream { output := make([]LsObject, len(req.Arguments)) processDir = func() (func(path string, link LsLink) error, func(i int)) { outputLinks := make([]LsLink, 0) return func(path string, link LsLink) error { outputLinks = append(outputLinks, link) return nil }, func(i int) { sort.Slice(outputLinks, func(i, j int) bool { return outputLinks[i].Name < outputLinks[j].Name }) output[i] = LsObject{ Hash: paths[i], Links: outputLinks, } } } done = func() error { return cmds.EmitOnce(res, &LsOutput{output}) } } for i, fpath := range paths { results, err := api.Unixfs().Ls(req.Context, path.New(fpath), options.Unixfs.ResolveChildren(resolveSize || resolveType)) if err != nil { return err } processLink, dirDone = processDir() for link := range results { if link.Err != nil { return link.Err } var ftype unixfs_pb.Data_DataType switch link.Type { case iface.TFile: ftype = unixfs.TFile case iface.TDirectory: ftype = unixfs.TDirectory case iface.TSymlink: ftype = unixfs.TSymlink } lsLink := LsLink{ Name: link.Name, Hash: enc.Encode(link.Cid), Size: link.Size, Type: ftype, Target: link.Target, } if err := processLink(paths[i], lsLink); err != nil { return err } } dirDone(i) } return done() }, PostRun: cmds.PostRunMap{ cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error { req := res.Request() lastObjectHash := "" for { v, err := res.Next() if err != nil { if err == io.EOF { return nil } return err } out := v.(*LsOutput) lastObjectHash = tabularOutput(req, os.Stdout, out, lastObjectHash, false) } }, }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *LsOutput) error { ignoreBreaks, _ := req.Options[lsStreamOptionName].(bool) tabularOutput(req, w, out, "", ignoreBreaks) return nil }), }, Type: LsOutput{}, }
var MetadataCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with metadata for BTFS files.", ShortDescription: ` 'btfs metadata' is a command to manipulate token metadata for BTFS files that are stored through BTT payment.`, }, Subcommands: map[string]*cmds.Command{ "add": metadataAddCmd, "rm": metadataRemoveCmd, }, }
MetadataCmd is the 'btfs metadata' command
var MountCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Mounts BTFS to the filesystem (read-only).", ShortDescription: ` Mount BTFS at a read-only mountpoint on the OS (default: /btfs and /btns). All BTFS objects will be accessible under that directory. Note that the root will not be listable, as it is virtual. Access known paths directly. You may have to create /btfs and /btns before using 'btfs mount': > sudo mkdir /btfs /btns > sudo chown $(whoami) /btfs /btns > btfs daemon & > btfs mount `, LongDescription: ` Mount BTFS at a read-only mountpoint on the OS. The default, /btfs and /btns, are set in the configuration file, but can be overridden by the options. All BTFS objects will be accessible under this directory. Note that the root will not be listable, as it is virtual. Access known paths directly. You may have to create /btfs and /btns before using 'btfs mount': > sudo mkdir /btfs /btns > sudo chown $(whoami) /btfs /btns > btfs daemon & > btfs mount Example: # setup > mkdir foo > echo "baz" > foo/bar > btfs add -r foo added QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR foo/bar added QmSh5e7S6fdcu75LAbXNZAFY2nGyZUJXyLCJDvn2zRkWyC foo > btfs ls QmSh5e7S6fdcu75LAbXNZAFY2nGyZUJXyLCJDvn2zRkWyC QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR 12 bar > btfs cat QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR baz # mount > btfs daemon & > btfs mount BTFS mounted at: /btfs BTNS mounted at: /btns > cd /btfs/QmSh5e7S6fdcu75LAbXNZAFY2nGyZUJXyLCJDvn2zRkWyC > ls bar > cat bar baz > cat /btfs/QmSh5e7S6fdcu75LAbXNZAFY2nGyZUJXyLCJDvn2zRkWyC/bar baz > cat /btfs/QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR baz `, }, Options: []cmds.Option{ cmds.StringOption(mountIPFSPathOptionName, "f", "The path where BTFS should be mounted."), cmds.StringOption(mountIPNSPathOptionName, "n", "The path where BTNS should be mounted."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { cfg, err := cmdenv.GetConfig(env) if err != nil { return err } nd, err := cmdenv.GetNode(env) if err != nil { return err } if !nd.IsOnline { return ErrNotOnline } fsdir, found := req.Options[mountIPFSPathOptionName].(string) if !found { fsdir = cfg.Mounts.IPFS } nsdir, found := req.Options[mountIPNSPathOptionName].(string) if !found { nsdir = cfg.Mounts.IPNS } err = nodeMount.Mount(nd, fsdir, nsdir) if err != nil { return err } var output config.Mounts output.IPFS = fsdir output.IPNS = nsdir return cmds.EmitOnce(res, &output) }, Type: config.Mounts{}, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, mounts *config.Mounts) error { fmt.Fprintf(w, "BTFS mounted at: %s\n", mounts.IPFS) fmt.Fprintf(w, "BTNS mounted at: %s\n", mounts.IPNS) return nil }), }, }
var P2PCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Libp2p stream mounting.", ShortDescription: ` Create and use tunnels to remote peers over libp2p Note: this command is experimental and subject to change as usecases and APIs are refined`, }, Subcommands: map[string]*cmds.Command{ "stream": p2pStreamCmd, "forward": p2pForwardCmd, "listen": p2pListenCmd, "close": p2pCloseCmd, "ls": p2pLsCmd, }, }
P2PCmd is the 'btfs p2p' command
var PinCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Pin (and unpin) objects to local storage.", }, Subcommands: map[string]*cmds.Command{ "add": addPinCmd, "rm": rmPinCmd, "ls": listPinCmd, "verify": verifyPinCmd, "update": updatePinCmd, }, }
var PingCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Send echo request packets to BTFS hosts.", ShortDescription: ` 'btfs ping' is a tool to test sending data to other nodes. It finds nodes via the routing system, sends pings, waits for pongs, and prints out round- trip latency information. `, }, Arguments: []cmds.Argument{ cmds.StringArg("peer ID", true, true, "ID of peer to be pinged.").EnableStdin(), }, Options: []cmds.Option{ cmds.IntOption(pingCountOptionName, "n", "Number of ping messages to send.").WithDefault(10), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { n, err := cmdenv.GetNode(env) if err != nil { return err } if !n.IsOnline { return ErrNotOnline } addr, pid, err := ParsePeerParam(req.Arguments[0]) if err != nil { return fmt.Errorf("failed to parse peer address '%s': %s", req.Arguments[0], err) } if pid == n.Identity { return ErrPingSelf } if addr != nil { n.Peerstore.AddAddr(pid, addr, pstore.TempAddrTTL) } numPings, _ := req.Options[pingCountOptionName].(int) if numPings <= 0 { return fmt.Errorf("ping count must be greater than 0, was %d", numPings) } if len(n.Peerstore.Addrs(pid)) == 0 { if err := res.Emit(&PingResult{ Text: fmt.Sprintf("Looking up peer %s", pid.Pretty()), Success: true, }); err != nil { return err } ctx, cancel := context.WithTimeout(req.Context, kPingTimeout) p, err := n.Routing.FindPeer(ctx, pid) cancel() if err != nil { return fmt.Errorf("peer lookup failed: %s", err) } n.Peerstore.AddAddrs(p.ID, p.Addrs, pstore.TempAddrTTL) } if err := res.Emit(&PingResult{ Text: fmt.Sprintf("PING %s.", pid.Pretty()), Success: true, }); err != nil { return err } ctx, cancel := context.WithTimeout(req.Context, kPingTimeout*time.Duration(numPings)) defer cancel() pings := ping.Ping(ctx, n.PeerHost, pid) var ( count int total time.Duration ) ticker := time.NewTicker(time.Second) defer ticker.Stop() for i := 0; i < numPings; i++ { r, ok := <-pings if !ok { break } if r.Error != nil { err = res.Emit(&PingResult{ Success: false, Text: fmt.Sprintf("Ping error: %s", r.Error), }) } else { count++ total += r.RTT err = res.Emit(&PingResult{ Success: true, Time: r.RTT, }) } if err != nil { return err } select { case <-ticker.C: case <-ctx.Done(): return ctx.Err() } } if count == 0 { return fmt.Errorf("ping failed") } averagems := total.Seconds() * 1000 / float64(count) return res.Emit(&PingResult{ Success: true, Text: fmt.Sprintf("Average latency: %.2fms", averagems), }) }, Type: PingResult{}, PostRun: cmds.PostRunMap{ cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error { var ( total time.Duration count int ) for { event, err := res.Next() switch err { case nil: case io.EOF: return nil case context.Canceled, context.DeadlineExceeded: if count == 0 { return err } averagems := total.Seconds() * 1000 / float64(count) return re.Emit(&PingResult{ Success: true, Text: fmt.Sprintf("Average latency: %.2fms", averagems), }) default: return err } pr := event.(*PingResult) if pr.Success && pr.Text == "" { total += pr.Time count++ } err = re.Emit(event) if err != nil { return err } } }, }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *PingResult) error { if len(out.Text) > 0 { fmt.Fprintln(w, out.Text) } else if out.Success { fmt.Fprintf(w, "Pong received: time=%.2f ms\n", out.Time.Seconds()*1000) } else { fmt.Fprintf(w, "Pong failed\n") } return nil }), }, }
var PubsubCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "An experimental publish-subscribe system on btfs.", ShortDescription: ` btfs pubsub allows you to publish messages to a given topic, and also to subscribe to new messages on a given topic. This is an experimental feature. It is not intended in its current state to be used in a production environment. To use, the daemon must be run with '--enable-pubsub-experiment'. `, }, Subcommands: map[string]*cmds.Command{ "pub": PubsubPubCmd, "sub": PubsubSubCmd, "ls": PubsubLsCmd, "peers": PubsubPeersCmd, }, }
var PubsubLsCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List subscribed topics by name.", ShortDescription: ` btfs pubsub ls lists out the names of topics you are currently subscribed to. This is an experimental feature. It is not intended in its current state to be used in a production environment. To use, the daemon must be run with '--enable-pubsub-experiment'. `, }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } l, err := api.PubSub().Ls(req.Context) if err != nil { return err } return cmds.EmitOnce(res, stringList{l}) }, Type: stringList{}, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(stringListEncoder), }, }
var PubsubPeersCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List peers we are currently pubsubbing with.", ShortDescription: ` btfs pubsub peers with no arguments lists out the pubsub peers you are currently connected to. If given a topic, it will list connected peers who are subscribed to the named topic. This is an experimental feature. It is not intended in its current state to be used in a production environment. To use, the daemon must be run with '--enable-pubsub-experiment'. `, }, Arguments: []cmds.Argument{ cmds.StringArg("topic", false, false, "topic to list connected peers of"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } var topic string if len(req.Arguments) == 1 { topic = req.Arguments[0] } peers, err := api.PubSub().Peers(req.Context, options.PubSub.Topic(topic)) if err != nil { return err } list := &stringList{make([]string, 0, len(peers))} for _, peer := range peers { list.Strings = append(list.Strings, peer.Pretty()) } sort.Strings(list.Strings) return cmds.EmitOnce(res, list) }, Type: stringList{}, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(stringListEncoder), }, }
var PubsubPubCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Publish a message to a given pubsub topic.", ShortDescription: ` btfs pubsub pub publishes a message to a specified topic. This is an experimental feature. It is not intended in its current state to be used in a production environment. To use, the daemon must be run with '--enable-pubsub-experiment'. `, }, Arguments: []cmds.Argument{ cmds.StringArg("topic", true, false, "Topic to publish to."), cmds.StringArg("data", true, true, "Payload of message to publish.").EnableStdin(), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } topic := req.Arguments[0] err = req.ParseBodyArgs() if err != nil { return err } for _, data := range req.Arguments[1:] { if err := api.PubSub().Publish(req.Context, topic, []byte(data)); err != nil { return err } } return nil }, }
var PubsubSubCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Subscribe to messages on a given topic.", ShortDescription: ` btfs pubsub sub subscribes to messages on a given topic. This is an experimental feature. It is not intended in its current state to be used in a production environment. To use, the daemon must be run with '--enable-pubsub-experiment'. `, LongDescription: ` btfs pubsub sub subscribes to messages on a given topic. This is an experimental feature. It is not intended in its current state to be used in a production environment. To use, the daemon must be run with '--enable-pubsub-experiment'. This command outputs data in the following encodings: * "json" (Specified by the "--encoding" or "--enc" flag) `, }, Arguments: []cmds.Argument{ cmds.StringArg("topic", true, false, "String name of topic to subscribe to."), }, Options: []cmds.Option{ cmds.BoolOption(pubsubDiscoverOptionName, "Deprecated option to instruct pubsub to discovery peers for the topic. Discovery is now built into pubsub."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } topic := req.Arguments[0] sub, err := api.PubSub().Subscribe(req.Context, topic) if err != nil { return err } defer sub.Close() if f, ok := res.(http.Flusher); ok { f.Flush() } for { msg, err := sub.Next(req.Context) if err == io.EOF || err == context.Canceled { return nil } else if err != nil { return err } if err := res.Emit(&pubsubMessage{ Data: msg.Data(), From: []byte(msg.From()), Seqno: msg.Seq(), TopicIDs: msg.Topics(), }); err != nil { return err } } }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, psm *pubsubMessage) error { _, err := w.Write(psm.Data) return err }), "ndpayload": cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, psm *pubsubMessage) error { psm.Data = append(psm.Data, '\n') _, err := w.Write(psm.Data) return err }), "lenpayload": cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, psm *pubsubMessage) error { buf := make([]byte, 8, len(psm.Data)+8) n := binary.PutUvarint(buf, uint64(len(psm.Data))) buf = append(buf[:n], psm.Data...) _, err := w.Write(buf) return err }), }, Type: pubsubMessage{}, }
var RefsCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List links (references) from an object.", ShortDescription: ` Lists the hashes of all the links an BTFS or BTNS object(s) contains, with the following format: <link base58 hash> NOTE: List all references recursively by using the flag '-r'. `, }, Subcommands: map[string]*cmds.Command{ "local": RefsLocalCmd, }, Arguments: []cmds.Argument{ cmds.StringArg("btfs-path", true, true, "Path to the object(s) to list refs from.").EnableStdin(), }, Options: []cmds.Option{ cmds.StringOption(refsFormatOptionName, "Emit edges with given format. Available tokens: <src> <dst> <linkname>.").WithDefault("<dst>"), cmds.BoolOption(refsEdgesOptionName, "e", "Emit edge format: `<from> -> <to>`."), cmds.BoolOption(refsUniqueOptionName, "u", "Omit duplicate refs from output."), cmds.BoolOption(refsRecursiveOptionName, "r", "Recursively list links of child nodes."), cmds.IntOption(refsMaxDepthOptionName, "Only for recursive refs, limits fetch and listing to the given depth").WithDefault(-1), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { err := req.ParseBodyArgs() if err != nil { return err } ctx := req.Context api, err := cmdenv.GetApi(env, req) if err != nil { return err } enc, err := cmdenv.GetCidEncoder(req) if err != nil { return err } unique, _ := req.Options[refsUniqueOptionName].(bool) recursive, _ := req.Options[refsRecursiveOptionName].(bool) maxDepth, _ := req.Options[refsMaxDepthOptionName].(int) edges, _ := req.Options[refsEdgesOptionName].(bool) format, _ := req.Options[refsFormatOptionName].(string) if !recursive { maxDepth = 1 } if edges { if format != "<dst>" { return errors.New("using format argument with edges is not allowed") } format = "<src> -> <dst>" } objs, err := objectsForPaths(ctx, api, req.Arguments) if err != nil { return err } rw := RefWriter{ res: res, DAG: merkledag.NewSession(ctx, api.Dag()), Ctx: ctx, Unique: unique, PrintFmt: format, MaxDepth: maxDepth, } for _, o := range objs { if _, err := rw.WriteRefs(o, enc); err != nil { if err := res.Emit(&RefWrapper{Err: err.Error()}); err != nil { return err } } } return nil }, Encoders: refsEncoderMap, Type: RefWrapper{}, }
RefsCmd is the `btfs refs` command
var RefsLocalCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List all local references.", ShortDescription: ` Displays the hashes of all local objects. `, }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { ctx := req.Context n, err := cmdenv.GetNode(env) if err != nil { return err } allKeys, err := n.Blockstore.AllKeysChan(ctx) if err != nil { return err } for k := range allKeys { err := res.Emit(&RefWrapper{Ref: k.String()}) if err != nil { return err } } return nil }, Encoders: refsEncoderMap, Type: RefWrapper{}, }
var RefsROCmd = &cmds.Command{}
RefsROCmd is `btfs refs` command
var RepoCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Manipulate the BTFS repo.", ShortDescription: ` 'btfs repo' is a plumbing command used to manipulate the repo. `, }, Subcommands: map[string]*cmds.Command{ "stat": repoStatCmd, "gc": repoGcCmd, "fsck": repoFsckCmd, "version": repoVersionCmd, "verify": repoVerifyCmd, }, }
var ResolveCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Resolve the value of names to BTFS.", ShortDescription: ` There are a number of mutable name protocols that can link among themselves and into BTNS. This command accepts any of these identifiers and resolves them to the referenced item. `, LongDescription: ` There are a number of mutable name protocols that can link among themselves and into BTNS. For example BTNS references can (currently) point at an BTFS object, and DNS links can point at other DNS links, BTNS entries, or BTFS objects. This command accepts any of these identifiers and resolves them to the referenced item. EXAMPLES Resolve the value of your identity: $ btfs resolve /btns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy /btfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj Resolve the value of another name: $ btfs resolve /btns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n /btns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy Resolve the value of another name recursively: $ btfs resolve -r /btns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n /btfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj Resolve the value of an BTFS DAG path: $ btfs resolve /btfs/QmeZy1fGbwgVSrqbfh9fKQrAWgeyRnj7h8fsHS1oy3k99x/beep/boop /btfs/QmYRMjyvAiHKN9UTi8Bzt1HUspmSRD8T8DwxfSMzLgBon1 `, }, Arguments: []cmds.Argument{ cmds.StringArg("name", true, false, "The name to resolve.").EnableStdin(), }, Options: []cmds.Option{ cmds.BoolOption(resolveRecursiveOptionName, "r", "Resolve until the result is an BTFS name.").WithDefault(true), cmds.IntOption(resolveDhtRecordCountOptionName, "dhtrc", "Number of records to request for DHT resolution."), cmds.StringOption(resolveDhtTimeoutOptionName, "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } name := req.Arguments[0] recursive, _ := req.Options[resolveRecursiveOptionName].(bool) if strings.HasPrefix(name, "/btns/") && !recursive { rc, rcok := req.Options[resolveDhtRecordCountOptionName].(uint) dhtt, dhttok := req.Options[resolveDhtTimeoutOptionName].(string) ropts := []options.NameResolveOption{ options.Name.ResolveOption(nsopts.Depth(1)), } if rcok { ropts = append(ropts, options.Name.ResolveOption(nsopts.DhtRecordCount(rc))) } if dhttok { d, err := time.ParseDuration(dhtt) if err != nil { return err } if d < 0 { return errors.New("DHT timeout value must be >= 0") } ropts = append(ropts, options.Name.ResolveOption(nsopts.DhtTimeout(d))) } p, err := api.Name().Resolve(req.Context, name, ropts...) if err != nil && err != ns.ErrResolveRecursion { return err } return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: ipfspath.Path(p.String())}) } var enc cidenc.Encoder switch { case !cmdenv.CidBaseDefined(req) && !strings.HasPrefix(name, "/ipns/"): enc, err = cmdenv.CidEncoderFromPath(name) if err == nil { break } fallthrough default: enc, err = cmdenv.GetCidEncoder(req) if err != nil { return err } } rp, err := api.ResolvePath(req.Context, path.New(name)) if err != nil { return err } encoded := "/" + rp.Namespace() + "/" + enc.Encode(rp.Cid()) if remainder := rp.Remainder(); remainder != "" { encoded += "/" + remainder } return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: ipfspath.Path(encoded)}) }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, rp *ncmd.ResolvedPath) error { fmt.Fprintln(w, rp.Path.String()) return nil }), }, Type: ncmd.ResolvedPath{}, }
var RmCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Remove files or directories from a local btfs node.", ShortDescription: `Removes all blocks under <hash> recursively from a local btfs node.`, }, Arguments: []cmds.Argument{ cmds.StringArg("hash", true, true, "The hash(es) of the file(s)/directory(s) to be removed from the local btfs node.").EnableStdin(), }, Options: []cmds.Option{ cmds.BoolOption(rmForceOptionName, "f", "Forcibly remove the object, even if there are constraints (such as host-stored file).").WithDefault(false), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { n, err := cmdenv.GetNode(env) if err != nil { return err } force, _ := req.Options[rmForceOptionName].(bool) results, err := rm.RmDag(req.Context, req.Arguments, n, req, env, force) if err != nil { return err } return cmds.EmitOnce(res, &stringList{Strings: results}) }, Type: stringList{}, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(stringListEncoder), }, }
var Root = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Global p2p merkle-dag filesystem.", Synopsis: "btfs [--config=<config> | -c] [--debug | -D] [--help] [-h] [--api=<api>] [--offline] [--cid-base=<base>] [--upgrade-cidv0-in-output] [--encoding=<encoding> | --enc] [--timeout=<timeout>] <command> ...", Subcommands: ` BASIC COMMANDS init Initialize btfs local configuration add <path> Add a file to BTFS cat <ref> Show BTFS object data get <ref> Download BTFS objects ls <ref> List links from an object refs <ref> List hashes of links from an object BTFS COMMANDS storage Manage client and host storage features rm Clean up locally stored files and objects DATA STRUCTURE COMMANDS block Interact with raw blocks in the datastore object Interact with raw dag nodes files Interact with objects as if they were a unix filesystem dag Interact with IPLD documents (experimental) metadata Interact with metadata for BTFS files ADVANCED COMMANDS daemon Start a long-running daemon process mount Mount an BTFS read-only mount point resolve Resolve any type of name name Publish and resolve BTNS names key Create and list BTNS name keypairs dns Resolve DNS links pin Pin objects to local storage repo Manipulate the BTFS repository stats Various operational stats p2p Libp2p stream mounting filestore Manage the filestore (experimental) NETWORK COMMANDS id Show info about BTFS peers bootstrap Add or remove bootstrap peers swarm Manage connections to the p2p network dht Query the DHT for values or peers ping Measure the latency of a connection diag Print diagnostics TOOL COMMANDS config Manage configuration version Show btfs version information commands List all available commands cid Convert and discover properties of CIDs log Manage and show logs of running daemon Use 'btfs <command> --help' to learn more about each command. btfs uses a repository in the local file system. By default, the repo is located at ~/.btfs. To change the repo location, set the $BTFS_PATH environment variable: export BTFS_PATH=/path/to/btfsrepo EXIT STATUS The CLI will exit with one of the following values: 0 Successful execution. 1 Failed executions. `, }, Options: []cmds.Option{ cmds.StringOption(ConfigOption, "c", "Path to the configuration file to use."), cmds.BoolOption(DebugOption, "D", "Operate in debug mode."), cmds.BoolOption(cmds.OptLongHelp, "Show the full command help text."), cmds.BoolOption(cmds.OptShortHelp, "Show a short version of the command help text."), cmds.BoolOption(LocalOption, "L", "Run the command locally, instead of using the daemon. DEPRECATED: use --offline."), cmds.BoolOption(OfflineOption, "Run the command offline."), cmds.StringOption(ApiOption, "Use a specific API instance (defaults to /ip4/127.0.0.1/tcp/5001)"), cmdenv.OptionCidBase, cmdenv.OptionUpgradeCidV0InOutput, cmds.OptionEncodingType, cmds.OptionStreamChannels, cmds.OptionTimeout, }, }
var RootRO = &cmds.Command{}
RootRO is the readonly version of Root
var RootRemote = &cmds.Command{}
RootRemote is the remote-facing version of Root
var StatsCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Query BTFS statistics.", ShortDescription: `'btfs stats' is a set of commands to help look at statistics for your BTFS node. `, LongDescription: `'btfs stats' is a set of commands to help look at statistics for your BTFS node.`, }, Subcommands: map[string]*cmds.Command{ "bw": statBwCmd, "repo": repoStatCmd, "bitswap": bitswapStatCmd, "dht": statDhtCmd, }, }
var SwarmCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with the swarm.", ShortDescription: ` 'btfs swarm' is a tool to manipulate the network swarm. The swarm is the component that opens, listens for, and maintains connections to other btfs peers in the internet. `, }, Subcommands: map[string]*cmds.Command{ "addrs": swarmAddrsCmd, "connect": swarmConnectCmd, "disconnect": swarmDisconnectCmd, "filters": swarmFiltersCmd, "peers": swarmPeersCmd, }, }
var TarCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Utility functions for tar files in btfs.", }, Subcommands: map[string]*cmds.Command{ "add": tarAddCmd, "cat": tarCatCmd, }, }
var TronCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "BTFS tron", ShortDescription: `'btfs tron' is a set of commands to forward requests to trongrid node.`, LongDescription: `'btfs tron' is a set of commands to forward requests to trongrid node.`, }, Subcommands: map[string]*cmds.Command{ "prepare": prepareCmd, "send": sendCmd, "status": statusCmd, "balance": balanceCmd, }, }
var VersionCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Show btfs version information.", ShortDescription: "Returns the current version of btfs and exits.", }, Subcommands: map[string]*cmds.Command{ "deps": depsVersionCommand, }, Options: []cmds.Option{ cmds.BoolOption(versionNumberOptionName, "n", "Only show the version number."), cmds.BoolOption(versionCommitOptionName, "Show the commit hash."), cmds.BoolOption(versionRepoOptionName, "Show repo version."), cmds.BoolOption(versionAllOptionName, "Show all version information"), }, Extra: CreateCmdExtras(SetDoesNotUseRepo(true), SetDoesNotUseConfigAsInput(true)), Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { return cmds.EmitOnce(res, &VersionOutput{ Version: version.CurrentVersionNumber, Commit: version.CurrentCommit, Repo: fmt.Sprint(fsrepo.RepoVersion), System: runtime.GOARCH + "/" + runtime.GOOS, Golang: runtime.Version(), }) }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, version *VersionOutput) error { all, _ := req.Options[versionAllOptionName].(bool) if all { ver := version.Version if version.Commit != "" { ver += "-" + version.Commit } out := fmt.Sprintf("go-btfs version: %s\n"+ "Repo version: %s\nSystem version: %s\nGolang version: %s\n", ver, version.Repo, version.System, version.Golang) fmt.Fprint(w, out) return nil } commit, _ := req.Options[versionCommitOptionName].(bool) commitTxt := "" if commit && version.Commit != "" { commitTxt = "-" + version.Commit } repo, _ := req.Options[versionRepoOptionName].(bool) if repo { fmt.Fprintln(w, version.Repo) return nil } number, _ := req.Options[versionNumberOptionName].(bool) if number { fmt.Fprintln(w, version.Version+commitTxt) return nil } fmt.Fprint(w, fmt.Sprintf("btfs version %s%s\n", version.Version, commitTxt)) return nil }), }, Type: VersionOutput{}, }
var VersionROCmd = &cmds.Command{}
VersionROCmd is `btfs version` command (without deps).
var WalletCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "BTFS wallet", ShortDescription: `'btfs wallet' is a set of commands to interact with block chain and ledger.`, LongDescription: `'btfs wallet' is a set of commands interact with block chain and ledger to deposit, withdraw and query balance of token used in BTFS.`, }, Subcommands: map[string]*cmds.Command{ "init": walletInitCmd, "deposit": walletDepositCmd, "withdraw": walletWithdrawCmd, "balance": walletBalanceCmd, "password": walletPasswordCmd, "keys": walletKeysCmd, "transactions": walletTransactionsCmd, "import": walletImportCmd, "transfer": walletTransferCmd, "discovery": walletDiscoveryCmd, "validate_password": walletCheckPasswordCmd, "generate_key": walletGenerateKeyCmd, }, }
Functions ¶
func CommandsCmd ¶
func CommandsCmd(root *cmds.Command) *cmds.Command
CommandsCmd takes in a root command, and returns a command that lists the subcommands in that root
func CreateCmdExtras ¶ added in v1.5.0
func ExternalBinary ¶
func GetDoesNotUseConfigAsInput ¶ added in v1.5.0
func GetDoesNotUseRepo ¶ added in v1.5.0
func GetPreemptsAutoUpdate ¶ added in v1.5.0
func SetDoesNotUseConfigAsInput ¶ added in v1.5.0
func SetDoesNotUseRepo ¶ added in v1.5.0
func SetPreemptsAutoUpdate ¶ added in v1.5.0
Types ¶
type AddPinOutput ¶
type BalanceResponse ¶ added in v1.5.0
type BootstrapOutput ¶
type BootstrapOutput struct {
Peers []string
}
type CidFormatRes ¶
type CodeAndName ¶
type ConfigField ¶
type ConfigField struct { Key string Value interface{} }
type ConfigUpdateOutput ¶
ConfigUpdateOutput is config profile apply command's output
type Dependency ¶
type DiscoveryResult ¶ added in v1.5.0
type DiscoveryResult struct {
Key string
}
type KeyOutputList ¶
type KeyOutputList struct {
Keys []KeyOutput
}
type KeyRenameOutput ¶
KeyRenameOutput define the output type of keyRenameCmd
type LsLink ¶
type LsLink struct {
Name, Hash string
Size uint64
Type unixfs_pb.Data_DataType
Target string
}
LsLink contains printable data for a single ipld link in ls output
type LsOutput ¶
type LsOutput struct {
Objects []LsObject
}
LsOutput is a set of printable data for directories, it can be complete or partial
type MessageOutput ¶
type MessageOutput struct {
Message string
}
type MetaResult ¶ added in v1.5.0
type MetaResult struct {
Hash string
}
type P2PListenerInfoOutput ¶
P2PListenerInfoOutput is output type of ls command
type P2PLsOutput ¶
type P2PLsOutput struct {
Listeners []P2PListenerInfoOutput
}
P2PLsOutput is output type of ls command
type P2PStreamInfoOutput ¶
type P2PStreamInfoOutput struct { HandlerID string Protocol string OriginAddress string TargetAddress string }
P2PStreamInfoOutput is output type of streams command
type P2PStreamsOutput ¶
type P2PStreamsOutput struct {
Streams []P2PStreamInfoOutput
}
P2PStreamsOutput is output type of streams command
type PinLsObject ¶ added in v1.5.0
PinLsObject contains the description of a pin
type PinLsOutputWrapper ¶ added in v1.5.0
type PinLsOutputWrapper struct { PinLsList PinLsObject }
PinLsOutputWrapper is the output type of the pin ls command. Pin ls needs to output two different type depending on if it's streamed or not. We use this to bypass the cmds lib refusing to have interface{}
type PinLsType ¶ added in v1.5.0
type PinLsType struct {
Type string
}
PinLsType contains the type of a pin
type PinVerifyRes ¶
PinVerifyRes is the result returned for each pin checked in "pin verify"
func (PinVerifyRes) Format ¶
func (r PinVerifyRes) Format(out io.Writer)
Format formats PinVerifyRes
type RefWrapper ¶
type RefWriter ¶
type RefWriter struct { DAG ipld.NodeGetter Ctx context.Context Unique bool MaxDepth int PrintFmt string // contains filtered or unexported fields }
type RepoVersion ¶
type RepoVersion struct {
Version string
}
type TransferResult ¶ added in v1.5.0
type VerifyProgress ¶
Source Files ¶
- active.go
- add.go
- bitswap.go
- block.go
- bootstrap.go
- cat.go
- cid.go
- commands.go
- config.go
- dht.go
- diag.go
- dns.go
- external.go
- extra.go
- files.go
- filestore.go
- get.go
- guard.go
- id.go
- keystore.go
- log.go
- ls.go
- metadata.go
- mount_unix.go
- p2p.go
- pin.go
- ping.go
- pubsub.go
- refs.go
- repo.go
- resolve.go
- restart.go
- rm.go
- root.go
- shutdown.go
- stat.go
- stat_dht.go
- swarm.go
- sysdiag.go
- tar.go
- tron.go
- urlstore.go
- version.go
- wallet.go