Skip to content
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

feat: add command output/error option #223

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 39 additions & 10 deletions cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@ type Closer interface {
}

func Run(ctx context.Context, root *cmds.Command,
cmdline []string, stdin, stdout, stderr *os.File,
cmdline []string, stdin *os.File,
buildEnv cmds.MakeEnvironment, makeExecutor cmds.MakeExecutor) error {

printErr := func(err error) {
fmt.Fprintf(stderr, "Error: %s\n", err)
req, errParse := Parse(ctx, cmdline[1:], stdin, root)

out, errFile, err := createDumpFiles(req)
if err != nil {
return err
}

req, errParse := Parse(ctx, cmdline[1:], stdin, root)
printErr := func(err error) {
fmt.Fprintf(errFile, "Error: %s\n", err)
}

// Handle the timeout up front.
var cancel func()
Expand Down Expand Up @@ -72,7 +77,7 @@ func Run(ctx context.Context, root *cmds.Command,

// BEFORE handling the parse error, if we have enough information
// AND the user requested help, print it out and exit
err := HandleHelp(cmdline[0], req, stdout)
err = HandleHelp(cmdline[0], req, out)
if err == nil {
return nil
} else if err != ErrNoHelpRequested {
Expand All @@ -87,8 +92,8 @@ func Run(ctx context.Context, root *cmds.Command,

// this was a user error, print help
if req != nil && req.Command != nil {
fmt.Fprintln(stderr) // i need some space
printHelp(false, stderr)
fmt.Fprintln(errFile) // i need some space
printHelp(false, errFile)
}

return errParse
Expand All @@ -98,7 +103,7 @@ func Run(ctx context.Context, root *cmds.Command,
// - commands with no Run func are invoked directly.
// - the main command is invoked.
if req == nil || req.Command == nil || req.Command.Run == nil {
printHelp(false, stdout)
printHelp(false, out)
return nil
}

Expand Down Expand Up @@ -127,7 +132,7 @@ func Run(ctx context.Context, root *cmds.Command,
req.Options[cmds.EncLong] = cmds.JSON
}

re, err := NewResponseEmitter(stdout, stderr, req)
re, err := NewResponseEmitter(out, errFile, req)
if err != nil {
printErr(err)
return err
Expand All @@ -144,7 +149,7 @@ func Run(ctx context.Context, root *cmds.Command,
err = *kiterr
}
if kiterr, ok := err.(cmds.Error); ok && kiterr.Code == cmds.ErrClient {
printMetaHelp(stderr)
printMetaHelp(errFile)
}

return err
Expand All @@ -155,3 +160,27 @@ func Run(ctx context.Context, root *cmds.Command,
}
return nil
}

func createDumpFiles(req *cmds.Request) (*os.File, *os.File, error) {
var err error
outFile := os.Stdout
if outPath, _ := req.Options[cmds.OutputFile].(string); outPath != "" {
// FIXME: Consider exporting the extract file logic (used in `ipfs get`)
// and using it here (https://github.com/ipfs/tar-utils/blob/16821db/extractor.go#L277).
outFile, err = os.Create(outPath)
if err != nil {
return nil, nil, err
}
// FIXME(BLOCKING): Where do we close the file? When the resp emitter closes?
}

errorFile := os.Stderr
if errPath, _ := req.Options[cmds.ErrorFile].(string); errPath != "" {
errorFile, err = os.Create(errPath)
if err != nil {
return nil, nil, err
}
}

return outFile, errorFile, nil
}
3 changes: 2 additions & 1 deletion cli/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ func TestRunWaits(t *testing.T) {
context.Background(),
root,
[]string{"test", "test"},
devnull, devnull, devnull,
// FIXME(BLOCKING): Redirect to devnull instead of stdout.
devnull,
func(ctx context.Context, req *cmds.Request) (cmds.Environment, error) {
return env{flag}, nil
},
Expand Down
2 changes: 2 additions & 0 deletions executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ func NewExecutor(root *Command) Executor {
}
}

// This is the *CLI* Executor (though is not in that package). The other one is
// the `client` HTTP Executor (defined in the HTTP package).
type executor struct {
root *Command
}
Expand Down
12 changes: 8 additions & 4 deletions opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ const (
OptLongHelp = "help"
DerefLong = "dereference-args"
StdinName = "stdin-name"
Hidden = "hidden"
HiddenShort = "H"
Ignore = "ignore"
IgnoreRules = "ignore-rules-path"
StdoutFile = "stdout"
StderrFile = "stderr"
Hidden = "hidden"
HiddenShort = "H"
Ignore = "ignore"
IgnoreRules = "ignore-rules-path"
)

// options that are used by this package
Expand All @@ -25,6 +27,8 @@ var OptionStreamChannels = BoolOption(ChanOpt, "Stream channel output")
var OptionTimeout = StringOption(TimeoutOpt, "Set a global timeout on the command")
var OptionDerefArgs = BoolOption(DerefLong, "Symlinks supplied in arguments are dereferenced")
var OptionStdinName = StringOption(StdinName, "Assign a name if the file source is stdin.")
var OptionOutputFile = StringOption(OutputFile, "Filename to save the output in (by default it's redirected to stdout).")
var OptionErrorFile = StringOption(OutputFile, "Filename to save the error in (by default it's redirected to stderr).")
var OptionHidden = BoolOption(Hidden, HiddenShort, "Include files that are hidden. Only takes effect on recursive add.")
var OptionIgnore = StringsOption(Ignore, "A rule (.gitignore-stype) defining which file(s) should be ignored (variadic, experimental)")
var OptionIgnoreRules = StringOption(IgnoreRules, "A path to a file with .gitignore-style ignore rules (experimental)")