2023-05-19 17:24:18 +03:00
|
|
|
// Package run holds the run.Run construct, which encapsulates CLI state
|
|
|
|
// for a command execution.
|
|
|
|
package run
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
|
2023-11-20 04:06:36 +03:00
|
|
|
"github.com/spf13/cobra"
|
2023-05-19 17:24:18 +03:00
|
|
|
|
|
|
|
"github.com/neilotoole/sq/cli/config"
|
2023-11-20 04:06:36 +03:00
|
|
|
"github.com/neilotoole/sq/cli/output"
|
|
|
|
"github.com/neilotoole/sq/libsq"
|
2023-05-19 17:24:18 +03:00
|
|
|
"github.com/neilotoole/sq/libsq/core/cleanup"
|
|
|
|
"github.com/neilotoole/sq/libsq/core/errz"
|
2024-01-15 04:45:34 +03:00
|
|
|
"github.com/neilotoole/sq/libsq/core/lg"
|
2023-11-20 04:06:36 +03:00
|
|
|
"github.com/neilotoole/sq/libsq/core/options"
|
2023-05-19 17:24:18 +03:00
|
|
|
"github.com/neilotoole/sq/libsq/driver"
|
|
|
|
"github.com/neilotoole/sq/libsq/source"
|
|
|
|
)
|
|
|
|
|
|
|
|
type runKey struct{}
|
|
|
|
|
|
|
|
// NewContext returns ctx with ru added as a value.
|
|
|
|
func NewContext(ctx context.Context, ru *Run) context.Context {
|
|
|
|
if ctx == nil {
|
|
|
|
ctx = context.Background()
|
|
|
|
}
|
|
|
|
|
|
|
|
return context.WithValue(ctx, runKey{}, ru)
|
|
|
|
}
|
|
|
|
|
|
|
|
// FromContext extracts the Run added to ctx via NewContext.
|
|
|
|
func FromContext(ctx context.Context) *Run {
|
|
|
|
return ctx.Value(runKey{}).(*Run)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run is a container for injectable resources passed
|
|
|
|
// to all cobra exec funcs. The Close method should be invoked when
|
|
|
|
// the Run is no longer needed.
|
|
|
|
type Run struct {
|
|
|
|
// Stdin typically is os.Stdin, but can be changed for testing.
|
|
|
|
Stdin *os.File
|
|
|
|
|
|
|
|
// Out is the output destination, typically os.Stdout.
|
|
|
|
Out io.Writer
|
|
|
|
|
|
|
|
// ErrOut is the error output destination, typically os.Stderr.
|
|
|
|
ErrOut io.Writer
|
|
|
|
|
|
|
|
// Cmd is the command instance provided by cobra for
|
|
|
|
// the currently executing command. This field will
|
|
|
|
// be set before the command's runFunc is invoked.
|
|
|
|
Cmd *cobra.Command
|
|
|
|
|
|
|
|
// Args is the arg slice supplied by cobra for
|
|
|
|
// the currently executing command. This field will
|
|
|
|
// be set before the command's runFunc is invoked.
|
|
|
|
Args []string
|
|
|
|
|
|
|
|
// Config is the run's config.
|
|
|
|
Config *config.Config
|
|
|
|
|
|
|
|
// ConfigStore manages config persistence.
|
|
|
|
ConfigStore config.Store
|
|
|
|
|
|
|
|
// OptionsRegistry is a registry of CLI options.Opt instances.
|
|
|
|
OptionsRegistry *options.Registry
|
|
|
|
|
|
|
|
// DriverRegistry is a registry of driver implementations.
|
|
|
|
DriverRegistry *driver.Registry
|
|
|
|
|
|
|
|
// Files manages file access.
|
|
|
|
Files *source.Files
|
|
|
|
|
2024-01-15 04:45:34 +03:00
|
|
|
// Grips mediates access to driver.Grip instances.
|
|
|
|
Grips *driver.Grips
|
2023-05-19 17:24:18 +03:00
|
|
|
|
|
|
|
// Writers holds the various writer types that
|
|
|
|
// the CLI uses to print output.
|
|
|
|
Writers *output.Writers
|
|
|
|
|
2024-01-15 04:45:34 +03:00
|
|
|
// Cleanup holds cleanup functions, except log closing, which
|
|
|
|
// is held by LogCloser.
|
2023-05-19 17:24:18 +03:00
|
|
|
Cleanup *cleanup.Cleanup
|
2024-01-15 04:45:34 +03:00
|
|
|
|
|
|
|
// LogCloser contains any log-closing action (such as closing
|
|
|
|
// a log file). It may be nil. Execution of this function
|
|
|
|
// should be more-or-less the final cleanup action performed by the CLI,
|
|
|
|
// and absolutely must happen after all other cleanup actions.
|
|
|
|
LogCloser func() error
|
2023-05-19 17:24:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Close should be invoked to dispose of any open resources
|
|
|
|
// held by ru. If an error occurs during Close and ru.Log
|
|
|
|
// is not nil, that error is logged at WARN level before
|
2024-01-15 04:45:34 +03:00
|
|
|
// being returned. Note that Run.LogCloser must be invoked separately.
|
2023-05-19 17:24:18 +03:00
|
|
|
func (ru *Run) Close() error {
|
|
|
|
if ru == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-01-15 04:45:34 +03:00
|
|
|
if ru.Cmd != nil {
|
|
|
|
lg.FromContext(ru.Cmd.Context()).Debug("Closing run")
|
|
|
|
}
|
|
|
|
|
|
|
|
return errz.Wrap(ru.Cleanup.Run(), "close run")
|
2023-05-19 17:24:18 +03:00
|
|
|
}
|
2023-05-22 18:08:14 +03:00
|
|
|
|
2023-06-18 04:28:11 +03:00
|
|
|
// NewQueryContext returns a *libsq.QueryContext constructed from ru.
|
|
|
|
func NewQueryContext(ru *Run, args map[string]string) *libsq.QueryContext {
|
2023-05-22 18:08:14 +03:00
|
|
|
return &libsq.QueryContext{
|
2024-01-15 04:45:34 +03:00
|
|
|
Collection: ru.Config.Collection,
|
|
|
|
Grips: ru.Grips,
|
|
|
|
Args: args,
|
2023-05-22 18:08:14 +03:00
|
|
|
}
|
|
|
|
}
|