package cli import ( "context" "io" "github.com/alecthomas/kingpin" "github.com/pkg/errors" "github.com/kopia/kopia/repo/logging" ) // RunSubcommand executes the subcommand asynchronously in current process // with flags in an isolated CLI environment and returns standard output and standard error. func (c *App) RunSubcommand(ctx context.Context, kpapp *kingpin.Application, argsAndFlags []string) (stdout, stderr io.Reader, wait func() error, kill func()) { stdoutReader, stdoutWriter := io.Pipe() stderrReader, stderrWriter := io.Pipe() c.stdoutWriter = stdoutWriter c.stderrWriter = stderrWriter c.rootctx = logging.WithLogger(ctx, logging.Writer(stderrWriter)) c.Attach(kpapp) // nolint:contextcheck var exitCode int resultErr := make(chan error, 1) c.osExit = func(ec int) { exitCode = ec } go func() { defer close(resultErr) defer stderrWriter.Close() //nolint:errcheck defer stdoutWriter.Close() //nolint:errcheck _, err := kpapp.Parse(argsAndFlags) if err != nil { resultErr <- err return } if exitCode != 0 { resultErr <- errors.Errorf("exit code %v", exitCode) return } }() return stdoutReader, stderrReader, func() error { return <-resultErr }, func() {} }