Skip to content

Commit

Permalink
commands/pin: fix gofmt and block
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Overbool <overbool.xu@gmail.com>
  • Loading branch information
overbool committed Oct 27, 2018
1 parent 62b68b2 commit a3a91c2
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 21 deletions.
96 changes: 96 additions & 0 deletions cmd/ipfs/QmQknf5Kj3k6RWRood7t5AEw5DhBT3SN5U3vhMdtVZAqHf
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import (
"fmt"

commands "github.com/ipfs/go-ipfs/core/commands"

cmds "gx/ipfs/QmSXUokcP4TJpFfqozT69AVAYRtzXVMUjzQVkYX41R9Svs/go-ipfs-cmds"
)

// This is the CLI root, used for executing commands accessible to CLI clients.
// Some subcommands (like 'ipfs daemon' or 'ipfs init') are only accessible here,
// and can't be called through the HTTP API.
var Root = &cmds.Command{
Options: commands.Root.Options,
Helptext: commands.Root.Helptext,
}

// commandsClientCmd is the "ipfs commands" command for local cli
var commandsClientCmd = commands.CommandsCmd(Root)

// Commands in localCommands should always be run locally (even if daemon is running).
// They can override subcommands in commands.Root by defining a subcommand with the same name.
var localCommands = map[string]*cmds.Command{
"daemon": daemonCmd,
"init": initCmd,
"commands": commandsClientCmd,
}

func init() {
// setting here instead of in literal to prevent initialization loop
// (some commands make references to Root)
Root.Subcommands = localCommands

for k, v := range commands.Root.Subcommands {
if _, found := Root.Subcommands[k]; !found {
Root.Subcommands[k] = v
}
}
}

// NB: when necessary, properties are described using negatives in order to
// provide desirable defaults
type cmdDetails struct {
cannotRunOnClient bool
cannotRunOnDaemon bool
doesNotUseRepo bool

// doesNotUseConfigAsInput describes commands that do not use the config as
// input. These commands either initialize the config or perform operations
// that don't require access to the config.
//
// pre-command hooks that require configs must not be run before these
// commands.
doesNotUseConfigAsInput bool

// preemptsAutoUpdate describes commands that must be executed without the
// auto-update pre-command hook
preemptsAutoUpdate bool
}

func (d *cmdDetails) String() string {
return fmt.Sprintf("on client? %t, on daemon? %t, uses repo? %t",
d.canRunOnClient(), d.canRunOnDaemon(), d.usesRepo())
}

func (d *cmdDetails) Loggable() map[string]interface{} {
return map[string]interface{}{
"canRunOnClient": d.canRunOnClient(),
"canRunOnDaemon": d.canRunOnDaemon(),
"preemptsAutoUpdate": d.preemptsAutoUpdate,
"usesConfigAsInput": d.usesConfigAsInput(),
"usesRepo": d.usesRepo(),
}
}

func (d *cmdDetails) usesConfigAsInput() bool { return !d.doesNotUseConfigAsInput }
func (d *cmdDetails) canRunOnClient() bool { return !d.cannotRunOnClient }
func (d *cmdDetails) canRunOnDaemon() bool { return !d.cannotRunOnDaemon }
func (d *cmdDetails) usesRepo() bool { return !d.doesNotUseRepo }

// "What is this madness!?" you ask. Our commands have the unfortunate problem of
// not being able to run on all the same contexts. This map describes these
// properties so that other code can make decisions about whether to invoke a
// command or return an error to the user.
var cmdDetailsMap = map[string]cmdDetails{
"init": {doesNotUseConfigAsInput: true, cannotRunOnDaemon: true, doesNotUseRepo: true},
"daemon": {doesNotUseConfigAsInput: true, cannotRunOnDaemon: true},
"commands": {doesNotUseRepo: true},
"version": {doesNotUseConfigAsInput: true, doesNotUseRepo: true}, // must be permitted to run before init
"log": {cannotRunOnClient: true},
"diag/cmds": {cannotRunOnClient: true},
"repo/fsck": {cannotRunOnDaemon: true},
"config/edit": {cannotRunOnDaemon: true, doesNotUseRepo: true},
"cid": {doesNotUseRepo: true},
}
54 changes: 33 additions & 21 deletions core/commands/pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ var addPinCmd = &cmds.Command{
}

out := make(chan interface{})
res.Emit(out)

v := new(dag.ProgressTracker)
ctx := v.DeriveContext(req.Context)
Expand All @@ -105,30 +104,43 @@ var addPinCmd = &cmds.Command{
ch <- pinResult{pins: added, err: err}
}()

ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
defer close(out)
for {
select {
case val := <-ch:
if val.err != nil {
return val.err
}
errC := make(chan error)
go func() {
var err error
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
defer func() { errC <- err }()
defer close(out)

if pv := v.Value(); pv != 0 {
for {
select {
case val := <-ch:
if val.err != nil {
err = val.err
return
}

if pv := v.Value(); pv != 0 {
out <- &AddPinOutput{Progress: v.Value()}
}
out <- &AddPinOutput{Pins: cidsToStrings(val.pins)}
return
case <-ticker.C:
out <- &AddPinOutput{Progress: v.Value()}
case <-ctx.Done():
log.Error(ctx.Err())
err = ctx.Err()
return
}
out <- &AddPinOutput{Pins: cidsToStrings(val.pins)}
return nil
case <-ticker.C:
out <- &AddPinOutput{Progress: v.Value()}
case <-ctx.Done():
log.Error(ctx.Err())
return ctx.Err()
}
}()

err = res.Emit(out)
if err != nil {
return err
}

return nil
return <-errC
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *AddPinOutput) error {
Expand Down Expand Up @@ -294,9 +306,9 @@ Example:

if err != nil {
return err
} else {
return res.Emit(&RefKeyList{Keys: keys})
}

return res.Emit(&RefKeyList{Keys: keys})
},
Type: RefKeyList{},
Encoders: cmds.EncoderMap{
Expand Down

0 comments on commit a3a91c2

Please sign in to comment.