From 87073cd88d56a4e4e6d93af3b748b41f1307ea18 Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Tue, 26 Sep 2023 17:31:56 -0700 Subject: [PATCH 1/6] [code-cleanup] Rename Writer to Stderr --- devbox.go | 4 +- internal/boxcli/add.go | 2 +- internal/boxcli/cloud.go | 4 +- internal/boxcli/generate.go | 4 +- internal/boxcli/global.go | 9 ++- internal/boxcli/info.go | 9 ++- internal/boxcli/install.go | 2 +- internal/boxcli/integrate.go | 2 +- internal/boxcli/midcobra/telemetry.go | 2 +- internal/boxcli/pull.go | 2 +- internal/boxcli/push.go | 2 +- internal/boxcli/rm.go | 2 +- internal/boxcli/run.go | 4 +- internal/boxcli/services.go | 10 ++-- internal/boxcli/shell.go | 2 +- internal/boxcli/shellenv.go | 2 +- internal/boxcli/update.go | 2 +- internal/impl/devbox.go | 86 +++++++++++++-------------- internal/impl/devbox_test.go | 4 +- internal/impl/devopt/devboxopts.go | 2 +- internal/impl/global.go | 8 --- internal/impl/packages.go | 27 +++++---- internal/impl/update.go | 16 ++--- internal/impl/util.go | 2 +- internal/plugin/info.go | 38 +++++++----- 25 files changed, 125 insertions(+), 122 deletions(-) diff --git a/devbox.go b/devbox.go index 8f77543d1b8..84e003ec193 100644 --- a/devbox.go +++ b/devbox.go @@ -28,13 +28,13 @@ type Devbox interface { GenerateDevcontainer(ctx context.Context, generateOpts devopt.GenerateOpts) error GenerateDockerfile(ctx context.Context, generateOpts devopt.GenerateOpts) error GenerateEnvrcFile(ctx context.Context, force bool, envFlags devopt.EnvFlags) error - Info(ctx context.Context, pkg string, markdown bool) error + Info(ctx context.Context, pkg string, markdown bool) (string, error) Install(ctx context.Context) error IsEnvEnabled() bool ListScripts() []string + PackageNames() []string PrintEnv(ctx context.Context, includeHooks bool) (string, error) PrintEnvVars(ctx context.Context) ([]string, error) - PrintGlobalList() error Pull(ctx context.Context, opts devopt.PullboxOpts) error Push(ctx context.Context, opts devopt.PullboxOpts) error // Remove removes Nix packages from the config so that it no longer exists in diff --git a/internal/boxcli/add.go b/internal/boxcli/add.go index 28531da1ddb..f0b4d1fd14c 100644 --- a/internal/boxcli/add.go +++ b/internal/boxcli/add.go @@ -66,7 +66,7 @@ func addCmd() *cobra.Command { func addCmdFunc(cmd *cobra.Command, args []string, flags addCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), AllowInsecureAdds: flags.allowInsecure, }) if err != nil { diff --git a/internal/boxcli/cloud.go b/internal/boxcli/cloud.go index 73ec642ae27..ea23566ff86 100644 --- a/internal/boxcli/cloud.go +++ b/internal/boxcli/cloud.go @@ -142,7 +142,7 @@ func runCloudShellCmd(cmd *cobra.Command, flags *cloudShellCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) @@ -158,7 +158,7 @@ func runCloudInit(cmd *cobra.Command, flags *cloudShellCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) diff --git a/internal/boxcli/generate.go b/internal/boxcli/generate.go index 3a780b73c3a..b9244a1dd79 100644 --- a/internal/boxcli/generate.go +++ b/internal/boxcli/generate.go @@ -139,7 +139,7 @@ func runGenerateCmd(cmd *cobra.Command, flags *generateCmdFlags) error { // Check the directory exists. box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) @@ -167,7 +167,7 @@ func runGenerateDirenvCmd(cmd *cobra.Command, flags *generateCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) diff --git a/internal/boxcli/global.go b/internal/boxcli/global.go index cd691074f50..20bc3b2de1d 100644 --- a/internal/boxcli/global.go +++ b/internal/boxcli/global.go @@ -68,12 +68,15 @@ func listGlobalCmdFunc(cmd *cobra.Command, args []string) error { box, err := devbox.Open(&devopt.Opts{ Dir: path, - Writer: cmd.OutOrStdout(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) } - return box.PrintGlobalList() + for _, p := range box.PackageNames() { + fmt.Fprintf(cmd.OutOrStdout(), "* %s\n", p) + } + return nil } var globalConfigPath string @@ -125,7 +128,7 @@ func ensureGlobalEnvEnabled(cmd *cobra.Command, args []string) error { box, err := devbox.Open(&devopt.Opts{ Dir: path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return err diff --git a/internal/boxcli/info.go b/internal/boxcli/info.go index 697b457e93e..fd3e1a61cb3 100644 --- a/internal/boxcli/info.go +++ b/internal/boxcli/info.go @@ -36,11 +36,16 @@ func infoCmd() *cobra.Command { func infoCmdFunc(cmd *cobra.Command, pkg string, flags infoCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.OutOrStdout(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) } - return box.Info(cmd.Context(), pkg, flags.markdown) + info, err := box.Info(cmd.Context(), pkg, flags.markdown) + if err != nil { + return errors.WithStack(err) + } + cmd.Print(info) + return nil } diff --git a/internal/boxcli/install.go b/internal/boxcli/install.go index 161f3d00521..fed39224e8d 100644 --- a/internal/boxcli/install.go +++ b/internal/boxcli/install.go @@ -34,7 +34,7 @@ func installCmdFunc(cmd *cobra.Command, flags runCmdFlags) error { // Check the directory exists. box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) diff --git a/internal/boxcli/integrate.go b/internal/boxcli/integrate.go index 0451b374a50..74aef69797d 100644 --- a/internal/boxcli/integrate.go +++ b/internal/boxcli/integrate.go @@ -75,7 +75,7 @@ func runIntegrateVSCodeCmd(cmd *cobra.Command) error { // todo: add error handling - consider sending error message to parent process box, err := devbox.Open(&devopt.Opts{ Dir: message.ConfigDir, - Writer: cmd.OutOrStdout(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return err diff --git a/internal/boxcli/midcobra/telemetry.go b/internal/boxcli/midcobra/telemetry.go index e1ea7043600..f5805303da3 100644 --- a/internal/boxcli/midcobra/telemetry.go +++ b/internal/boxcli/midcobra/telemetry.go @@ -94,7 +94,7 @@ func getPackagesAndCommitHash(c *cobra.Command) ([]string, string) { box, err := devbox.Open(&devopt.Opts{ Dir: path, - Writer: os.Stdout, + Stderr: os.Stderr, IgnoreWarnings: true, }) if err != nil { diff --git a/internal/boxcli/pull.go b/internal/boxcli/pull.go index 12fc565113f..cbcde521ecd 100644 --- a/internal/boxcli/pull.go +++ b/internal/boxcli/pull.go @@ -50,7 +50,7 @@ func pullCmd() *cobra.Command { func pullCmdFunc(cmd *cobra.Command, url string, flags *pullCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) diff --git a/internal/boxcli/push.go b/internal/boxcli/push.go index cdf9eeeb099..e1fc1269473 100644 --- a/internal/boxcli/push.go +++ b/internal/boxcli/push.go @@ -36,7 +36,7 @@ func pushCmd() *cobra.Command { func pushCmdFunc(cmd *cobra.Command, url string, flags pushCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) diff --git a/internal/boxcli/rm.go b/internal/boxcli/rm.go index b73c90ad54c..cc111140605 100644 --- a/internal/boxcli/rm.go +++ b/internal/boxcli/rm.go @@ -33,7 +33,7 @@ func removeCmd() *cobra.Command { func runRemoveCmd(cmd *cobra.Command, args []string, flags removeCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) diff --git a/internal/boxcli/run.go b/internal/boxcli/run.go index 04de0bd7cb6..e370864bf24 100644 --- a/internal/boxcli/run.go +++ b/internal/boxcli/run.go @@ -61,7 +61,7 @@ func runCmd() *cobra.Command { func listScripts(cmd *cobra.Command, flags runCmdFlags) []string { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), Pure: flags.pure, IgnoreWarnings: true, }) @@ -108,7 +108,7 @@ func runScriptCmd(cmd *cobra.Command, args []string, flags runCmdFlags) error { // Check the directory exists. box, err := devbox.Open(&devopt.Opts{ Dir: path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), Pure: flags.pure, Env: env, OmitBinWrappersFromPath: omitBinWrappersFromPath, diff --git a/internal/boxcli/services.go b/internal/boxcli/services.go index 1195335cc86..26d43fbeb3b 100644 --- a/internal/boxcli/services.go +++ b/internal/boxcli/services.go @@ -116,7 +116,7 @@ func servicesCmd(persistentPreRunE ...cobraFunc) *cobra.Command { func listServices(cmd *cobra.Command, flags servicesCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) @@ -133,7 +133,7 @@ func startServices(cmd *cobra.Command, services []string, flags servicesCmdFlags box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, Env: env, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) @@ -155,7 +155,7 @@ func stopServices( box, err := devbox.Open(&devopt.Opts{ Dir: servicesFlags.config.path, Env: env, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) @@ -178,7 +178,7 @@ func restartServices( box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, Env: env, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) @@ -201,7 +201,7 @@ func startProcessManager( Dir: servicesFlags.config.path, Env: env, CustomProcessComposeFile: flags.processComposeFile, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) diff --git a/internal/boxcli/shell.go b/internal/boxcli/shell.go index 6406d9bd41a..33af2342471 100644 --- a/internal/boxcli/shell.go +++ b/internal/boxcli/shell.go @@ -57,7 +57,7 @@ func runShellCmd(cmd *cobra.Command, flags shellCmdFlags) error { Dir: flags.config.path, Env: env, Pure: flags.pure, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) diff --git a/internal/boxcli/shellenv.go b/internal/boxcli/shellenv.go index 5baad06c35e..753f7e58551 100644 --- a/internal/boxcli/shellenv.go +++ b/internal/boxcli/shellenv.go @@ -60,7 +60,7 @@ func shellEnvFunc(cmd *cobra.Command, flags shellEnvCmdFlags) (string, error) { } box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), Pure: flags.pure, Env: env, }) diff --git a/internal/boxcli/update.go b/internal/boxcli/update.go index dba96dc5965..5f80cd5bd82 100644 --- a/internal/boxcli/update.go +++ b/internal/boxcli/update.go @@ -47,7 +47,7 @@ func updateCmd() *cobra.Command { func updateCmdFunc(cmd *cobra.Command, args []string, flags *updateCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Stderr: cmd.ErrOrStderr(), }) if err != nil { return errors.WithStack(err) diff --git a/internal/impl/devbox.go b/internal/impl/devbox.go index 4775fc0bf4b..f0cabcd7260 100644 --- a/internal/impl/devbox.go +++ b/internal/impl/devbox.go @@ -64,11 +64,8 @@ type Devbox struct { customProcessComposeFile string OmitBinWrappersFromPath bool - // Possible TODO: hardcode this to stderr. Allowing the caller to specify the - // writer is error prone. Since it is almost always stderr, we should default - // it and if the user wants stdout then they can return a string and print it. - // I can't think of a case where we want all the diagnostics to go to stdout. - writer io.Writer + // This is needed because of the --quiet flag. + Stderr io.Writer } var legacyPackagesWarningHasBeenShown = false @@ -92,7 +89,7 @@ func Open(opts *devopt.Opts) (*Devbox, error) { nix: &nix.Nix{}, projectDir: projectDir, pluginManager: plugin.NewManager(), - writer: opts.Writer, + Stderr: opts.Stderr, pure: opts.Pure, customProcessComposeFile: opts.CustomProcessComposeFile, allowInsecureAdds: opts.AllowInsecureAdds, @@ -171,7 +168,7 @@ func (d *Devbox) Shell(ctx context.Context) error { if err := d.ensurePackagesAreInstalled(ctx, ensure); err != nil { return err } - fmt.Fprintln(d.writer, "Starting a devbox shell...") + fmt.Fprintln(d.Stderr, "Starting a devbox shell...") profileDir, err := d.profilePath() if err != nil { @@ -338,7 +335,7 @@ func (d *Devbox) ShellEnvHashKey() string { return "__DEVBOX_SHELLENV_HASH_" + d.projectDirHash() } -func (d *Devbox) Info(ctx context.Context, pkg string, markdown bool) error { +func (d *Devbox) Info(ctx context.Context, pkg string, markdown bool) (string, error) { ctx, task := trace.NewTask(ctx, "devboxInfo") defer task.End() @@ -351,7 +348,7 @@ func (d *Devbox) Info(ctx context.Context, pkg string, markdown bool) error { packageVersion, err := searcher.Client().Resolve(name, version) if err != nil { if !errors.Is(err, searcher.ErrNotFound) { - return usererr.WithUserMessage(err, "Package %q not found\n", pkg) + return "", usererr.WithUserMessage(err, "Package %q not found\n", pkg) } packageVersion = nil @@ -359,28 +356,27 @@ func (d *Devbox) Info(ctx context.Context, pkg string, markdown bool) error { } if packageVersion == nil { - _, err := fmt.Fprintf(d.writer, "Package %q not found\n", pkg) - return errors.WithStack(err) + return "", usererr.WithUserMessage(err, "Package %q not found\n", pkg) } // we should only have one result - if _, err := fmt.Fprintf( - d.writer, + info := fmt.Sprintf( "%s%s %s\n%s\n", lo.Ternary(markdown, "## ", ""), packageVersion.Name, packageVersion.Version, packageVersion.Summary, - ); err != nil { - return errors.WithStack(err) - } - return plugin.PrintReadme( + ) + readme, err := plugin.Readme( ctx, devpkg.PackageFromString(pkg, d.lockfile), d.projectDir, - d.writer, markdown, ) + if err != nil { + return "", err + } + return info + readme, nil } // GenerateDevcontainer generates devcontainer.json and Dockerfile for vscode run-in-container @@ -481,7 +477,7 @@ func (d *Devbox) GenerateEnvrcFile(ctx context.Context, force bool, envFlags dev } // confirm .envrc doesn't exist and don't overwrite an existing .envrc if err := nix.EnsureNixInstalled( - d.writer, func() *bool { return lo.ToPtr(false) }, + d.Stderr, func() *bool { return lo.ToPtr(false) }, ); err != nil { return err } @@ -496,14 +492,14 @@ func (d *Devbox) GenerateEnvrcFile(ctx context.Context, force bool, envFlags dev if err != nil { return errors.WithStack(err) } - ux.Fsuccess(d.writer, "generated .envrc file\n") + ux.Fsuccess(d.Stderr, "generated .envrc file\n") if cmdutil.Exists("direnv") { cmd := exec.Command("direnv", "allow") err := cmd.Run() if err != nil { return errors.WithStack(err) } - ux.Fsuccess(d.writer, "ran `direnv allow`\n") + ux.Fsuccess(d.Stderr, "ran `direnv allow`\n") } return nil } @@ -542,8 +538,8 @@ func (d *Devbox) StartServices(ctx context.Context, serviceNames ...string) erro } if !services.ProcessManagerIsRunning(d.projectDir) { - fmt.Fprintln(d.writer, "Process-compose is not running. Starting it now...") - fmt.Fprintln(d.writer, "\nNOTE: We recommend using `devbox services up` to start process-compose and your services") + fmt.Fprintln(d.Stderr, "Process-compose is not running. Starting it now...") + fmt.Fprintln(d.Stderr, "\nNOTE: We recommend using `devbox services up` to start process-compose and your services") return d.StartProcessManager(ctx, serviceNames, true, "") } @@ -563,11 +559,11 @@ func (d *Devbox) StartServices(ctx context.Context, serviceNames ...string) erro } for _, s := range serviceNames { - err := services.StartServices(ctx, d.writer, s, d.projectDir) + err := services.StartServices(ctx, d.Stderr, s, d.projectDir) if err != nil { - fmt.Fprintf(d.writer, "Error starting service %s: %s", s, err) + fmt.Fprintf(d.Stderr, "Error starting service %s: %s", s, err) } else { - fmt.Fprintf(d.writer, "Service %s started successfully", s) + fmt.Fprintf(d.Stderr, "Service %s started successfully", s) } } return nil @@ -584,7 +580,7 @@ func (d *Devbox) StopServices(ctx context.Context, allProjects bool, serviceName } if allProjects { - return services.StopAllProcessManagers(ctx, d.writer) + return services.StopAllProcessManagers(ctx, d.Stderr) } if !services.ProcessManagerIsRunning(d.projectDir) { @@ -592,7 +588,7 @@ func (d *Devbox) StopServices(ctx context.Context, allProjects bool, serviceName } if len(serviceNames) == 0 { - return services.StopProcessManager(ctx, d.projectDir, d.writer) + return services.StopProcessManager(ctx, d.projectDir, d.Stderr) } svcSet, err := d.Services() @@ -604,9 +600,9 @@ func (d *Devbox) StopServices(ctx context.Context, allProjects bool, serviceName if _, ok := svcSet[s]; !ok { return usererr.New(fmt.Sprintf("Service %s not found in your project", s)) } - err := services.StopServices(ctx, s, d.projectDir, d.writer) + err := services.StopServices(ctx, s, d.projectDir, d.Stderr) if err != nil { - fmt.Fprintf(d.writer, "Error stopping service %s: %s", s, err) + fmt.Fprintf(d.Stderr, "Error stopping service %s: %s", s, err) } } return nil @@ -623,24 +619,24 @@ func (d *Devbox) ListServices(ctx context.Context) error { } if len(svcSet) == 0 { - fmt.Fprintln(d.writer, "No services found in your project") + fmt.Fprintln(d.Stderr, "No services found in your project") return nil } if !services.ProcessManagerIsRunning(d.projectDir) { - fmt.Fprintln(d.writer, "No services currently running. Run `devbox services up` to start them:") - fmt.Fprintln(d.writer, "") + fmt.Fprintln(d.Stderr, "No services currently running. Run `devbox services up` to start them:") + fmt.Fprintln(d.Stderr, "") for _, s := range svcSet { - fmt.Fprintf(d.writer, " %s\n", s.Name) + fmt.Fprintf(d.Stderr, " %s\n", s.Name) } return nil } - tw := tabwriter.NewWriter(d.writer, 3, 2, 8, ' ', tabwriter.TabIndent) - pcSvcs, err := services.ListServices(ctx, d.projectDir, d.writer) + tw := tabwriter.NewWriter(d.Stderr, 3, 2, 8, ' ', tabwriter.TabIndent) + pcSvcs, err := services.ListServices(ctx, d.projectDir, d.Stderr) if err != nil { - fmt.Fprintln(d.writer, "Error listing services: ", err) + fmt.Fprintln(d.Stderr, "Error listing services: ", err) } else { - fmt.Fprintln(d.writer, "Services running in process-compose:") + fmt.Fprintln(d.Stderr, "Services running in process-compose:") fmt.Fprintln(tw, "NAME\tSTATUS\tEXIT CODE") for _, s := range pcSvcs { fmt.Fprintf(tw, "%s\t%s\t%d\n", s.Name, s.Status, s.ExitCode) @@ -656,8 +652,8 @@ func (d *Devbox) RestartServices(ctx context.Context, serviceNames ...string) er } if !services.ProcessManagerIsRunning(d.projectDir) { - fmt.Fprintln(d.writer, "Process-compose is not running. Starting it now...") - fmt.Fprintln(d.writer, "\nTip: We recommend using `devbox services up` to start process-compose and your services") + fmt.Fprintln(d.Stderr, "Process-compose is not running. Starting it now...") + fmt.Fprintln(d.Stderr, "\nTip: We recommend using `devbox services up` to start process-compose and your services") return d.StartProcessManager(ctx, serviceNames, true, "") } @@ -672,7 +668,7 @@ func (d *Devbox) RestartServices(ctx context.Context, serviceNames ...string) er if _, ok := svcSet[s]; !ok { return usererr.New(fmt.Sprintf("Service %s not found in your project", s)) } - err := services.RestartServices(ctx, s, d.projectDir, d.writer) + err := services.RestartServices(ctx, s, d.projectDir, d.Stderr) if err != nil { fmt.Printf("Error restarting service %s: %s", s, err) } else { @@ -718,7 +714,7 @@ func (d *Devbox) StartProcessManager( processComposePath, err := utilityLookPath("process-compose") if err != nil { - fmt.Fprintln(d.writer, "Installing process-compose. This may take a minute but will only happen once.") + fmt.Fprintln(d.Stderr, "Installing process-compose. This may take a minute but will only happen once.") if err = d.addDevboxUtilityPackage(ctx, "github:F1bonacc1/process-compose/v0.43.1"); err != nil { return err } @@ -726,7 +722,7 @@ func (d *Devbox) StartProcessManager( // re-lookup the path to process-compose processComposePath, err = utilityLookPath("process-compose") if err != nil { - fmt.Fprintln(d.writer, "failed to find process-compose after installing it.") + fmt.Fprintln(d.Stderr, "failed to find process-compose after installing it.") return err } } @@ -735,7 +731,7 @@ func (d *Devbox) StartProcessManager( return services.StartProcessManager( ctx, - d.writer, + d.Stderr, requestedServices, svcs, d.projectDir, @@ -1046,7 +1042,7 @@ func (d *Devbox) checkOldEnvrc() error { } if !isNewEnvrc { ux.Fwarning( - d.writer, + d.Stderr, "Your .envrc file seems to be out of date. "+ "Run `devbox generate direnv --force` to update it.\n"+ "Or silence this warning by setting DEVBOX_NO_ENVRC_UPDATE=1 env variable.\n", diff --git a/internal/impl/devbox_test.go b/internal/impl/devbox_test.go index a4c3bc6120f..c0945d71637 100644 --- a/internal/impl/devbox_test.go +++ b/internal/impl/devbox_test.go @@ -44,7 +44,7 @@ func testShellPlan(t *testing.T, testPath string) { _, err := Open(&devopt.Opts{ Dir: baseDir, - Writer: os.Stdout, + Stderr: os.Stderr, Pure: false, }) assert.NoErrorf(err, "%s should be a valid devbox project", baseDir) @@ -128,7 +128,7 @@ func devboxForTesting(t *testing.T) *Devbox { require.NoError(t, err, "InitConfig should not fail") d, err := Open(&devopt.Opts{ Dir: path, - Writer: os.Stdout, + Stderr: os.Stderr, Pure: false, }) require.NoError(t, err, "Open should not fail") diff --git a/internal/impl/devopt/devboxopts.go b/internal/impl/devopt/devboxopts.go index 2edc71c2e01..2d7f45a30f2 100644 --- a/internal/impl/devopt/devboxopts.go +++ b/internal/impl/devopt/devboxopts.go @@ -12,7 +12,7 @@ type Opts struct { IgnoreWarnings bool CustomProcessComposeFile string OmitBinWrappersFromPath bool - Writer io.Writer + Stderr io.Writer } type GenerateOpts struct { diff --git a/internal/impl/global.go b/internal/impl/global.go index 919bdc20eed..ea73cb976e8 100644 --- a/internal/impl/global.go +++ b/internal/impl/global.go @@ -4,7 +4,6 @@ package impl import ( - "fmt" "io/fs" "os" "path/filepath" @@ -17,13 +16,6 @@ import ( // In the future we will support multiple global profiles const currentGlobalProfile = "default" -func (d *Devbox) PrintGlobalList() error { - for _, p := range d.PackageNames() { - fmt.Fprintf(d.writer, "* %s\n", p) - } - return nil -} - func GlobalDataPath() (string, error) { path := xdg.DataSubpath(filepath.Join("devbox/global", currentGlobalProfile)) if err := os.MkdirAll(path, 0755); err != nil { diff --git a/internal/impl/packages.go b/internal/impl/packages.go index bdd738c8db1..e4b5815ab93 100644 --- a/internal/impl/packages.go +++ b/internal/impl/packages.go @@ -123,13 +123,14 @@ func (d *Devbox) Add(ctx context.Context, platforms, excludePlatforms []string, } for _, input := range pkgs { - if err := plugin.PrintReadme( + if readme, err := plugin.Readme( ctx, input, d.projectDir, - d.writer, false /*markdown*/); err != nil { return err + } else if readme != "" { + fmt.Fprintf(d.Stderr, "%s\n", readme) } } @@ -160,7 +161,7 @@ func (d *Devbox) Remove(ctx context.Context, pkgs ...string) error { if len(missingPkgs) > 0 { ux.Fwarning( - d.writer, + d.Stderr, "the following packages were not found in your devbox.json: %s\n", strings.Join(missingPkgs, ", "), ) @@ -210,7 +211,7 @@ func (d *Devbox) ensurePackagesAreInstalled(ctx context.Context, mode installMod } if mode == ensure { - fmt.Fprintln(d.writer, "Ensuring packages are installed.") + fmt.Fprintln(d.Stderr, "Ensuring packages are installed.") } // Create plugin directories first because packages might need them @@ -299,7 +300,7 @@ func (d *Devbox) addPackagesToProfile(ctx context.Context, mode installMode) err // If packages are in profile but nixpkgs has been purged, the experience // will be poor when we try to run print-dev-env. So we ensure nixpkgs is // prefetched for all relevant packages (those not in binary cache). - if err := devpkg.EnsureNixpkgsPrefetched(ctx, d.writer, pkgs); err != nil { + if err := devpkg.EnsureNixpkgsPrefetched(ctx, d.Stderr, pkgs); err != nil { return err } @@ -310,7 +311,7 @@ func (d *Devbox) addPackagesToProfile(ctx context.Context, mode installMode) err pkgNames := lo.Map(pkgs, func(p *devpkg.Package, _ int) string { return p.Raw }) msg = fmt.Sprintf("Installing %d packages: %s.", len(pkgs), strings.Join(pkgNames, ", ")) } - fmt.Fprintf(d.writer, "\n%s\n\n", msg) + fmt.Fprintf(d.Stderr, "\n%s\n\n", msg) profileDir, err := d.profilePath() if err != nil { @@ -328,7 +329,7 @@ func (d *Devbox) addPackagesToProfile(ctx context.Context, mode installMode) err Lockfile: d.lockfile, Package: pkg.Raw, ProfilePath: profileDir, - Writer: d.writer, + Writer: d.Stderr, }); err != nil { return err } @@ -348,7 +349,7 @@ func (d *Devbox) removePackagesFromProfile(ctx context.Context, pkgs []string) e for _, pkg := range devpkg.PackageFromStrings(pkgs, d.lockfile) { index, err := nixprofile.ProfileListIndex(&nixprofile.ProfileListIndexArgs{ Lockfile: d.lockfile, - Writer: d.writer, + Writer: d.Stderr, Package: pkg, ProfileDir: profileDir, }) @@ -366,8 +367,8 @@ func (d *Devbox) removePackagesFromProfile(ctx context.Context, pkgs []string) e fmt.Sprintf("%d", index), ) cmd.Args = append(cmd.Args, nix.ExperimentalFlags()...) - cmd.Stdout = d.writer - cmd.Stderr = d.writer + cmd.Stdout = d.Stderr + cmd.Stderr = d.Stderr err = cmd.Run() if err != nil { return err @@ -407,7 +408,7 @@ func (d *Devbox) pendingPackagesForInstallation(ctx context.Context) ([]*devpkg. } pending := []*devpkg.Package{} - items, err := nixprofile.ProfileListItems(d.writer, profileDir) + items, err := nixprofile.ProfileListItems(d.Stderr, profileDir) if err != nil { return nil, err } @@ -419,7 +420,7 @@ func (d *Devbox) pendingPackagesForInstallation(ctx context.Context) ([]*devpkg. _, err := nixprofile.ProfileListIndex(&nixprofile.ProfileListIndexArgs{ Items: items, Lockfile: d.lockfile, - Writer: d.writer, + Writer: d.Stderr, Package: pkg, ProfileDir: profileDir, }) @@ -446,7 +447,7 @@ func (d *Devbox) extraPackagesInProfile(ctx context.Context) ([]*nixprofile.NixP return nil, err } - profileItems, err := nixprofile.ProfileListItems(d.writer, profileDir) + profileItems, err := nixprofile.ProfileListItems(d.Stderr, profileDir) if err != nil { return nil, err } diff --git a/internal/impl/update.go b/internal/impl/update.go index 584bb9dd780..61e06fad1aa 100644 --- a/internal/impl/update.go +++ b/internal/impl/update.go @@ -32,7 +32,7 @@ func (d *Devbox) Update(ctx context.Context, opts devopt.UpdateOpts) error { pendingPackagesToUpdate := []*devpkg.Package{} for _, pkg := range inputs { if pkg.IsLegacy() { - fmt.Fprintf(d.writer, "Updating %s -> %s\n", pkg.Raw, pkg.LegacyToVersioned()) + fmt.Fprintf(d.Stderr, "Updating %s -> %s\n", pkg.Raw, pkg.LegacyToVersioned()) // Get the package from the config to get the Platforms and ExcludedPlatforms later cfgPackage, ok := d.cfg.Packages.Get(pkg.Raw) @@ -113,17 +113,17 @@ func (d *Devbox) mergeResolvedPackageToLockfile( ) error { existing := lockfile.Packages[pkg.Raw] if existing == nil { - ux.Finfo(d.writer, "Resolved %s to %[1]s %[2]s\n", pkg, resolved.Resolved) + ux.Finfo(d.Stderr, "Resolved %s to %[1]s %[2]s\n", pkg, resolved.Resolved) lockfile.Packages[pkg.Raw] = resolved return nil } if existing.Version != resolved.Version { - ux.Finfo(d.writer, "Updating %s %s -> %s\n", pkg, existing.Version, resolved.Version) + ux.Finfo(d.Stderr, "Updating %s %s -> %s\n", pkg, existing.Version, resolved.Version) if err := d.removePackagesFromProfile(ctx, []string{pkg.Raw}); err != nil { // Warn but continue. TODO(landau): ensurePackagesAreInstalled should // sync the profile so we don't need to do this manually. - ux.Fwarning(d.writer, "Failed to remove %s from profile: %s\n", pkg, err) + ux.Fwarning(d.Stderr, "Failed to remove %s from profile: %s\n", pkg, err) } resolved.AllowInsecure = existing.AllowInsecure lockfile.Packages[pkg.Raw] = resolved @@ -159,12 +159,12 @@ func (d *Devbox) mergeResolvedPackageToLockfile( } } if updated { - ux.Finfo(d.writer, "Updated system information for %s\n", pkg) + ux.Finfo(d.Stderr, "Updated system information for %s\n", pkg) return nil } } - ux.Finfo(d.writer, "Already up-to-date %s %s\n", pkg, existing.Version) + ux.Finfo(d.Stderr, "Already up-to-date %s %s\n", pkg, existing.Version) return nil } @@ -177,7 +177,7 @@ func (d *Devbox) attemptToUpgradeFlake(pkg *devpkg.Package) error { } ux.Finfo( - d.writer, + d.Stderr, "Attempting to upgrade %s using `nix profile upgrade`\n", pkg.Raw, ) @@ -185,7 +185,7 @@ func (d *Devbox) attemptToUpgradeFlake(pkg *devpkg.Package) error { err = nixprofile.ProfileUpgrade(profilePath, pkg, d.lockfile) if err != nil { ux.Ferror( - d.writer, + d.Stderr, "Failed to upgrade %s using `nix profile upgrade`: %s\n", pkg.Raw, err, diff --git a/internal/impl/util.go b/internal/impl/util.go index 79d026289de..42c126d7996 100644 --- a/internal/impl/util.go +++ b/internal/impl/util.go @@ -29,7 +29,7 @@ func (d *Devbox) addDevboxUtilityPackage(ctx context.Context, pkg string) error Lockfile: d.lockfile, Package: pkg, ProfilePath: profilePath, - Writer: d.writer, + Writer: d.Stderr, }) } diff --git a/internal/plugin/info.go b/internal/plugin/info.go index a0243e5ed79..f0ba02a8eec 100644 --- a/internal/plugin/info.go +++ b/internal/plugin/info.go @@ -4,6 +4,7 @@ package plugin import ( + "bytes" "context" "fmt" "io" @@ -14,42 +15,47 @@ import ( "go.jetpack.io/devbox/internal/devpkg" ) -func PrintReadme(ctx context.Context, +func Readme(ctx context.Context, pkg *devpkg.Package, projectDir string, - w io.Writer, markdown bool, -) error { - defer trace.StartRegion(ctx, "PrintReadme").End() +) (string, error) { + defer trace.StartRegion(ctx, "Readme").End() cfg, err := getConfigIfAny(pkg, projectDir) if err != nil { - return err + return "", err } if cfg == nil { - return nil + return "", nil } - _, _ = fmt.Fprintln(w, "") + buf := bytes.NewBuffer(nil) + + _, _ = fmt.Fprintln(buf, "") + + if err = printReadme(cfg, buf, markdown); err != nil { + return "", err + } - if err = printReadme(cfg, w, markdown); err != nil { - return err + if err = printServices(cfg, buf, markdown); err != nil { + return "", err } - if err = printServices(cfg, w, markdown); err != nil { - return err + if err = printCreateFiles(cfg, buf, markdown); err != nil { + return "", err } - if err = printCreateFiles(cfg, w, markdown); err != nil { - return err + if err = printEnv(cfg, buf, markdown); err != nil { + return "", err } - if err = printEnv(cfg, w, markdown); err != nil { - return err + if err = printInfoInstructions(pkg.CanonicalName(), buf); err != nil { + return "", err } - return printInfoInstructions(pkg.CanonicalName(), w) + return buf.String(), nil } func printReadme(cfg *config, w io.Writer, markdown bool) error { From 64cbb860dbf18c22a6a563c718eb42bbe58702fe Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Tue, 26 Sep 2023 17:40:35 -0700 Subject: [PATCH 2/6] rename print functions --- devbox.go | 4 ++-- internal/boxcli/integrate.go | 2 +- internal/boxcli/shell.go | 2 +- internal/boxcli/shellenv.go | 2 +- internal/impl/devbox.go | 10 +++++----- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/devbox.go b/devbox.go index 84e003ec193..ae0a20090af 100644 --- a/devbox.go +++ b/devbox.go @@ -24,6 +24,7 @@ type Devbox interface { ProjectDir() string // Generate creates the directory of Nix files and the Dockerfile that define // the devbox environment. + EnvVars(ctx context.Context) ([]string, error) Generate(ctx context.Context) error GenerateDevcontainer(ctx context.Context, generateOpts devopt.GenerateOpts) error GenerateDockerfile(ctx context.Context, generateOpts devopt.GenerateOpts) error @@ -32,9 +33,8 @@ type Devbox interface { Install(ctx context.Context) error IsEnvEnabled() bool ListScripts() []string + NixEnv(ctx context.Context, includeHooks bool) (string, error) PackageNames() []string - PrintEnv(ctx context.Context, includeHooks bool) (string, error) - PrintEnvVars(ctx context.Context) ([]string, error) Pull(ctx context.Context, opts devopt.PullboxOpts) error Push(ctx context.Context, opts devopt.PullboxOpts) error // Remove removes Nix packages from the config so that it no longer exists in diff --git a/internal/boxcli/integrate.go b/internal/boxcli/integrate.go index 74aef69797d..4d54f70a695 100644 --- a/internal/boxcli/integrate.go +++ b/internal/boxcli/integrate.go @@ -81,7 +81,7 @@ func runIntegrateVSCodeCmd(cmd *cobra.Command) error { return err } // Get env variables of a devbox shell - envVars, err := box.PrintEnvVars(cmd.Context()) + envVars, err := box.EnvVars(cmd.Context()) if err != nil { return err } diff --git a/internal/boxcli/shell.go b/internal/boxcli/shell.go index 33af2342471..4cb5cff95f5 100644 --- a/internal/boxcli/shell.go +++ b/internal/boxcli/shell.go @@ -66,7 +66,7 @@ func runShellCmd(cmd *cobra.Command, flags shellCmdFlags) error { if flags.printEnv { // false for includeHooks is because init hooks is not compatible with .envrc files generated // by versions older than 0.4.6 - script, err := box.PrintEnv(cmd.Context(), false /*includeHooks*/) + script, err := box.NixEnv(cmd.Context(), false /*includeHooks*/) if err != nil { return err } diff --git a/internal/boxcli/shellenv.go b/internal/boxcli/shellenv.go index 753f7e58551..2c645c5b161 100644 --- a/internal/boxcli/shellenv.go +++ b/internal/boxcli/shellenv.go @@ -74,7 +74,7 @@ func shellEnvFunc(cmd *cobra.Command, flags shellEnvCmdFlags) (string, error) { } } - envStr, err := box.PrintEnv(cmd.Context(), flags.runInitHook) + envStr, err := box.NixEnv(cmd.Context(), flags.runInitHook) if err != nil { return "", err } diff --git a/internal/impl/devbox.go b/internal/impl/devbox.go index f0cabcd7260..32c8c8e4a20 100644 --- a/internal/impl/devbox.go +++ b/internal/impl/devbox.go @@ -265,7 +265,7 @@ func (d *Devbox) Install(ctx context.Context) error { ctx, task := trace.NewTask(ctx, "devboxInstall") defer task.End() - if _, err := d.PrintEnv(ctx, false /*includeHooks*/); err != nil { + if _, err := d.NixEnv(ctx, false /*includeHooks*/); err != nil { return err } return wrapnix.CreateWrappers(ctx, d) @@ -282,8 +282,8 @@ func (d *Devbox) ListScripts() []string { return keys } -func (d *Devbox) PrintEnv(ctx context.Context, includeHooks bool) (string, error) { - ctx, task := trace.NewTask(ctx, "devboxPrintEnv") +func (d *Devbox) NixEnv(ctx context.Context, includeHooks bool) (string, error) { + ctx, task := trace.NewTask(ctx, "devboxNixEnv") defer task.End() if err := d.ensurePackagesAreInstalled(ctx, ensure); err != nil { @@ -305,8 +305,8 @@ func (d *Devbox) PrintEnv(ctx context.Context, includeHooks bool) (string, error return envStr, nil } -func (d *Devbox) PrintEnvVars(ctx context.Context) ([]string, error) { - ctx, task := trace.NewTask(ctx, "devboxPrintEnvVars") +func (d *Devbox) EnvVars(ctx context.Context) ([]string, error) { + ctx, task := trace.NewTask(ctx, "devboxEnvVars") defer task.End() // this only returns env variables for the shell environment excluding hooks // and excluding "export " prefix in "export key=value" format From 5893444d0d529293642bb7a979e46e3449551579 Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Tue, 26 Sep 2023 17:47:09 -0700 Subject: [PATCH 3/6] Simplify interface --- devbox.go | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/devbox.go b/devbox.go index ae0a20090af..cbdc8c1fd27 100644 --- a/devbox.go +++ b/devbox.go @@ -16,41 +16,36 @@ import ( // Devbox provides an isolated development environment. type Devbox interface { - // Add adds Nix packages to the config so that they're available in the devbox - // environment. It validates that the Nix packages exist, and install them. - // Adding duplicate packages is a no-op. Add(ctx context.Context, platforms, excludePlatforms []string, pkgs ...string) error Config() *devconfig.Config - ProjectDir() string - // Generate creates the directory of Nix files and the Dockerfile that define - // the devbox environment. EnvVars(ctx context.Context) ([]string, error) - Generate(ctx context.Context) error - GenerateDevcontainer(ctx context.Context, generateOpts devopt.GenerateOpts) error - GenerateDockerfile(ctx context.Context, generateOpts devopt.GenerateOpts) error - GenerateEnvrcFile(ctx context.Context, force bool, envFlags devopt.EnvFlags) error Info(ctx context.Context, pkg string, markdown bool) (string, error) Install(ctx context.Context) error IsEnvEnabled() bool ListScripts() []string NixEnv(ctx context.Context, includeHooks bool) (string, error) PackageNames() []string + ProjectDir() string Pull(ctx context.Context, opts devopt.PullboxOpts) error Push(ctx context.Context, opts devopt.PullboxOpts) error - // Remove removes Nix packages from the config so that it no longer exists in - // the devbox environment. Remove(ctx context.Context, pkgs ...string) error - RestartServices(ctx context.Context, services ...string) error RunScript(ctx context.Context, scriptName string, scriptArgs []string) error - Services() (services.Services, error) - // Shell generates the devbox environment and launches nix-shell as a child process. Shell(ctx context.Context) error + Update(ctx context.Context, opts devopt.UpdateOpts) error + + // Interact with services + ListServices(ctx context.Context) error + RestartServices(ctx context.Context, services ...string) error + Services() (services.Services, error) StartProcessManager(ctx context.Context, requestedServices []string, background bool, processComposeFileOrDir string) error StartServices(ctx context.Context, services ...string) error StopServices(ctx context.Context, allProjects bool, services ...string) error - ListServices(ctx context.Context) error - Update(ctx context.Context, opts devopt.UpdateOpts) error + // Generate files + Generate(ctx context.Context) error + GenerateDevcontainer(ctx context.Context, generateOpts devopt.GenerateOpts) error + GenerateDockerfile(ctx context.Context, generateOpts devopt.GenerateOpts) error + GenerateEnvrcFile(ctx context.Context, force bool, envFlags devopt.EnvFlags) error } // Open opens a devbox by reading the config file in dir. From 97bcfd2b925a074101bf5d6e4fb00e5df8ccfb3d Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Tue, 26 Sep 2023 21:44:14 -0700 Subject: [PATCH 4/6] Fix --- internal/boxcli/root.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/boxcli/root.go b/internal/boxcli/root.go index 83520f579b7..cb679e3d599 100644 --- a/internal/boxcli/root.go +++ b/internal/boxcli/root.go @@ -37,6 +37,9 @@ func RootCmd() *cobra.Command { command := &cobra.Command{ Use: "devbox", Short: "Instant, easy, predictable development environments", + // Warning, PersistentPreRunE is not called if a subcommand also declares + // it. TODO: Figure out a better way to implement this so that subcommands + // can't accidentally override it. PersistentPreRun: func(cmd *cobra.Command, args []string) { if flags.quiet { cmd.SetErr(io.Discard) @@ -49,6 +52,8 @@ func RootCmd() *cobra.Command { SilenceErrors: true, SilenceUsage: true, } + command.SetOut(os.Stdout) + // Stable commands command.AddCommand(addCmd()) if featureflag.Auth.Enabled() { From 55ee060cc995da65dce5f348af3bd7caf67fa00e Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Wed, 27 Sep 2023 10:54:54 -0700 Subject: [PATCH 5/6] Requested changes --- internal/boxcli/info.go | 4 ++- internal/boxcli/root.go | 1 - internal/impl/devbox.go | 60 +++++++++++++++++----------------- internal/impl/packages.go | 24 +++++++------- internal/impl/update.go | 16 ++++----- internal/impl/util.go | 2 +- testscripts/info/info.test.txt | 4 +-- 7 files changed, 56 insertions(+), 55 deletions(-) diff --git a/internal/boxcli/info.go b/internal/boxcli/info.go index fd3e1a61cb3..9370bd8e9df 100644 --- a/internal/boxcli/info.go +++ b/internal/boxcli/info.go @@ -4,6 +4,8 @@ package boxcli import ( + "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" @@ -46,6 +48,6 @@ func infoCmdFunc(cmd *cobra.Command, pkg string, flags infoCmdFlags) error { if err != nil { return errors.WithStack(err) } - cmd.Print(info) + fmt.Fprint(cmd.OutOrStdout(), info) return nil } diff --git a/internal/boxcli/root.go b/internal/boxcli/root.go index cb679e3d599..560da3dbc95 100644 --- a/internal/boxcli/root.go +++ b/internal/boxcli/root.go @@ -52,7 +52,6 @@ func RootCmd() *cobra.Command { SilenceErrors: true, SilenceUsage: true, } - command.SetOut(os.Stdout) // Stable commands command.AddCommand(addCmd()) diff --git a/internal/impl/devbox.go b/internal/impl/devbox.go index 32c8c8e4a20..f435fac97ce 100644 --- a/internal/impl/devbox.go +++ b/internal/impl/devbox.go @@ -65,7 +65,7 @@ type Devbox struct { OmitBinWrappersFromPath bool // This is needed because of the --quiet flag. - Stderr io.Writer + stderr io.Writer } var legacyPackagesWarningHasBeenShown = false @@ -89,7 +89,7 @@ func Open(opts *devopt.Opts) (*Devbox, error) { nix: &nix.Nix{}, projectDir: projectDir, pluginManager: plugin.NewManager(), - Stderr: opts.Stderr, + stderr: opts.Stderr, pure: opts.Pure, customProcessComposeFile: opts.CustomProcessComposeFile, allowInsecureAdds: opts.AllowInsecureAdds, @@ -168,7 +168,7 @@ func (d *Devbox) Shell(ctx context.Context) error { if err := d.ensurePackagesAreInstalled(ctx, ensure); err != nil { return err } - fmt.Fprintln(d.Stderr, "Starting a devbox shell...") + fmt.Fprintln(d.stderr, "Starting a devbox shell...") profileDir, err := d.profilePath() if err != nil { @@ -477,7 +477,7 @@ func (d *Devbox) GenerateEnvrcFile(ctx context.Context, force bool, envFlags dev } // confirm .envrc doesn't exist and don't overwrite an existing .envrc if err := nix.EnsureNixInstalled( - d.Stderr, func() *bool { return lo.ToPtr(false) }, + d.stderr, func() *bool { return lo.ToPtr(false) }, ); err != nil { return err } @@ -492,14 +492,14 @@ func (d *Devbox) GenerateEnvrcFile(ctx context.Context, force bool, envFlags dev if err != nil { return errors.WithStack(err) } - ux.Fsuccess(d.Stderr, "generated .envrc file\n") + ux.Fsuccess(d.stderr, "generated .envrc file\n") if cmdutil.Exists("direnv") { cmd := exec.Command("direnv", "allow") err := cmd.Run() if err != nil { return errors.WithStack(err) } - ux.Fsuccess(d.Stderr, "ran `direnv allow`\n") + ux.Fsuccess(d.stderr, "ran `direnv allow`\n") } return nil } @@ -538,8 +538,8 @@ func (d *Devbox) StartServices(ctx context.Context, serviceNames ...string) erro } if !services.ProcessManagerIsRunning(d.projectDir) { - fmt.Fprintln(d.Stderr, "Process-compose is not running. Starting it now...") - fmt.Fprintln(d.Stderr, "\nNOTE: We recommend using `devbox services up` to start process-compose and your services") + fmt.Fprintln(d.stderr, "Process-compose is not running. Starting it now...") + fmt.Fprintln(d.stderr, "\nNOTE: We recommend using `devbox services up` to start process-compose and your services") return d.StartProcessManager(ctx, serviceNames, true, "") } @@ -559,11 +559,11 @@ func (d *Devbox) StartServices(ctx context.Context, serviceNames ...string) erro } for _, s := range serviceNames { - err := services.StartServices(ctx, d.Stderr, s, d.projectDir) + err := services.StartServices(ctx, d.stderr, s, d.projectDir) if err != nil { - fmt.Fprintf(d.Stderr, "Error starting service %s: %s", s, err) + fmt.Fprintf(d.stderr, "Error starting service %s: %s", s, err) } else { - fmt.Fprintf(d.Stderr, "Service %s started successfully", s) + fmt.Fprintf(d.stderr, "Service %s started successfully", s) } } return nil @@ -580,7 +580,7 @@ func (d *Devbox) StopServices(ctx context.Context, allProjects bool, serviceName } if allProjects { - return services.StopAllProcessManagers(ctx, d.Stderr) + return services.StopAllProcessManagers(ctx, d.stderr) } if !services.ProcessManagerIsRunning(d.projectDir) { @@ -588,7 +588,7 @@ func (d *Devbox) StopServices(ctx context.Context, allProjects bool, serviceName } if len(serviceNames) == 0 { - return services.StopProcessManager(ctx, d.projectDir, d.Stderr) + return services.StopProcessManager(ctx, d.projectDir, d.stderr) } svcSet, err := d.Services() @@ -600,9 +600,9 @@ func (d *Devbox) StopServices(ctx context.Context, allProjects bool, serviceName if _, ok := svcSet[s]; !ok { return usererr.New(fmt.Sprintf("Service %s not found in your project", s)) } - err := services.StopServices(ctx, s, d.projectDir, d.Stderr) + err := services.StopServices(ctx, s, d.projectDir, d.stderr) if err != nil { - fmt.Fprintf(d.Stderr, "Error stopping service %s: %s", s, err) + fmt.Fprintf(d.stderr, "Error stopping service %s: %s", s, err) } } return nil @@ -619,24 +619,24 @@ func (d *Devbox) ListServices(ctx context.Context) error { } if len(svcSet) == 0 { - fmt.Fprintln(d.Stderr, "No services found in your project") + fmt.Fprintln(d.stderr, "No services found in your project") return nil } if !services.ProcessManagerIsRunning(d.projectDir) { - fmt.Fprintln(d.Stderr, "No services currently running. Run `devbox services up` to start them:") - fmt.Fprintln(d.Stderr, "") + fmt.Fprintln(d.stderr, "No services currently running. Run `devbox services up` to start them:") + fmt.Fprintln(d.stderr, "") for _, s := range svcSet { - fmt.Fprintf(d.Stderr, " %s\n", s.Name) + fmt.Fprintf(d.stderr, " %s\n", s.Name) } return nil } - tw := tabwriter.NewWriter(d.Stderr, 3, 2, 8, ' ', tabwriter.TabIndent) - pcSvcs, err := services.ListServices(ctx, d.projectDir, d.Stderr) + tw := tabwriter.NewWriter(d.stderr, 3, 2, 8, ' ', tabwriter.TabIndent) + pcSvcs, err := services.ListServices(ctx, d.projectDir, d.stderr) if err != nil { - fmt.Fprintln(d.Stderr, "Error listing services: ", err) + fmt.Fprintln(d.stderr, "Error listing services: ", err) } else { - fmt.Fprintln(d.Stderr, "Services running in process-compose:") + fmt.Fprintln(d.stderr, "Services running in process-compose:") fmt.Fprintln(tw, "NAME\tSTATUS\tEXIT CODE") for _, s := range pcSvcs { fmt.Fprintf(tw, "%s\t%s\t%d\n", s.Name, s.Status, s.ExitCode) @@ -652,8 +652,8 @@ func (d *Devbox) RestartServices(ctx context.Context, serviceNames ...string) er } if !services.ProcessManagerIsRunning(d.projectDir) { - fmt.Fprintln(d.Stderr, "Process-compose is not running. Starting it now...") - fmt.Fprintln(d.Stderr, "\nTip: We recommend using `devbox services up` to start process-compose and your services") + fmt.Fprintln(d.stderr, "Process-compose is not running. Starting it now...") + fmt.Fprintln(d.stderr, "\nTip: We recommend using `devbox services up` to start process-compose and your services") return d.StartProcessManager(ctx, serviceNames, true, "") } @@ -668,7 +668,7 @@ func (d *Devbox) RestartServices(ctx context.Context, serviceNames ...string) er if _, ok := svcSet[s]; !ok { return usererr.New(fmt.Sprintf("Service %s not found in your project", s)) } - err := services.RestartServices(ctx, s, d.projectDir, d.Stderr) + err := services.RestartServices(ctx, s, d.projectDir, d.stderr) if err != nil { fmt.Printf("Error restarting service %s: %s", s, err) } else { @@ -714,7 +714,7 @@ func (d *Devbox) StartProcessManager( processComposePath, err := utilityLookPath("process-compose") if err != nil { - fmt.Fprintln(d.Stderr, "Installing process-compose. This may take a minute but will only happen once.") + fmt.Fprintln(d.stderr, "Installing process-compose. This may take a minute but will only happen once.") if err = d.addDevboxUtilityPackage(ctx, "github:F1bonacc1/process-compose/v0.43.1"); err != nil { return err } @@ -722,7 +722,7 @@ func (d *Devbox) StartProcessManager( // re-lookup the path to process-compose processComposePath, err = utilityLookPath("process-compose") if err != nil { - fmt.Fprintln(d.Stderr, "failed to find process-compose after installing it.") + fmt.Fprintln(d.stderr, "failed to find process-compose after installing it.") return err } } @@ -731,7 +731,7 @@ func (d *Devbox) StartProcessManager( return services.StartProcessManager( ctx, - d.Stderr, + d.stderr, requestedServices, svcs, d.projectDir, @@ -1042,7 +1042,7 @@ func (d *Devbox) checkOldEnvrc() error { } if !isNewEnvrc { ux.Fwarning( - d.Stderr, + d.stderr, "Your .envrc file seems to be out of date. "+ "Run `devbox generate direnv --force` to update it.\n"+ "Or silence this warning by setting DEVBOX_NO_ENVRC_UPDATE=1 env variable.\n", diff --git a/internal/impl/packages.go b/internal/impl/packages.go index e4b5815ab93..d606102c63a 100644 --- a/internal/impl/packages.go +++ b/internal/impl/packages.go @@ -130,7 +130,7 @@ func (d *Devbox) Add(ctx context.Context, platforms, excludePlatforms []string, false /*markdown*/); err != nil { return err } else if readme != "" { - fmt.Fprintf(d.Stderr, "%s\n", readme) + fmt.Fprintf(d.stderr, "%s\n", readme) } } @@ -161,7 +161,7 @@ func (d *Devbox) Remove(ctx context.Context, pkgs ...string) error { if len(missingPkgs) > 0 { ux.Fwarning( - d.Stderr, + d.stderr, "the following packages were not found in your devbox.json: %s\n", strings.Join(missingPkgs, ", "), ) @@ -211,7 +211,7 @@ func (d *Devbox) ensurePackagesAreInstalled(ctx context.Context, mode installMod } if mode == ensure { - fmt.Fprintln(d.Stderr, "Ensuring packages are installed.") + fmt.Fprintln(d.stderr, "Ensuring packages are installed.") } // Create plugin directories first because packages might need them @@ -300,7 +300,7 @@ func (d *Devbox) addPackagesToProfile(ctx context.Context, mode installMode) err // If packages are in profile but nixpkgs has been purged, the experience // will be poor when we try to run print-dev-env. So we ensure nixpkgs is // prefetched for all relevant packages (those not in binary cache). - if err := devpkg.EnsureNixpkgsPrefetched(ctx, d.Stderr, pkgs); err != nil { + if err := devpkg.EnsureNixpkgsPrefetched(ctx, d.stderr, pkgs); err != nil { return err } @@ -311,7 +311,7 @@ func (d *Devbox) addPackagesToProfile(ctx context.Context, mode installMode) err pkgNames := lo.Map(pkgs, func(p *devpkg.Package, _ int) string { return p.Raw }) msg = fmt.Sprintf("Installing %d packages: %s.", len(pkgs), strings.Join(pkgNames, ", ")) } - fmt.Fprintf(d.Stderr, "\n%s\n\n", msg) + fmt.Fprintf(d.stderr, "\n%s\n\n", msg) profileDir, err := d.profilePath() if err != nil { @@ -329,7 +329,7 @@ func (d *Devbox) addPackagesToProfile(ctx context.Context, mode installMode) err Lockfile: d.lockfile, Package: pkg.Raw, ProfilePath: profileDir, - Writer: d.Stderr, + Writer: d.stderr, }); err != nil { return err } @@ -349,7 +349,7 @@ func (d *Devbox) removePackagesFromProfile(ctx context.Context, pkgs []string) e for _, pkg := range devpkg.PackageFromStrings(pkgs, d.lockfile) { index, err := nixprofile.ProfileListIndex(&nixprofile.ProfileListIndexArgs{ Lockfile: d.lockfile, - Writer: d.Stderr, + Writer: d.stderr, Package: pkg, ProfileDir: profileDir, }) @@ -367,8 +367,8 @@ func (d *Devbox) removePackagesFromProfile(ctx context.Context, pkgs []string) e fmt.Sprintf("%d", index), ) cmd.Args = append(cmd.Args, nix.ExperimentalFlags()...) - cmd.Stdout = d.Stderr - cmd.Stderr = d.Stderr + cmd.Stdout = d.stderr + cmd.Stderr = d.stderr err = cmd.Run() if err != nil { return err @@ -408,7 +408,7 @@ func (d *Devbox) pendingPackagesForInstallation(ctx context.Context) ([]*devpkg. } pending := []*devpkg.Package{} - items, err := nixprofile.ProfileListItems(d.Stderr, profileDir) + items, err := nixprofile.ProfileListItems(d.stderr, profileDir) if err != nil { return nil, err } @@ -420,7 +420,7 @@ func (d *Devbox) pendingPackagesForInstallation(ctx context.Context) ([]*devpkg. _, err := nixprofile.ProfileListIndex(&nixprofile.ProfileListIndexArgs{ Items: items, Lockfile: d.lockfile, - Writer: d.Stderr, + Writer: d.stderr, Package: pkg, ProfileDir: profileDir, }) @@ -447,7 +447,7 @@ func (d *Devbox) extraPackagesInProfile(ctx context.Context) ([]*nixprofile.NixP return nil, err } - profileItems, err := nixprofile.ProfileListItems(d.Stderr, profileDir) + profileItems, err := nixprofile.ProfileListItems(d.stderr, profileDir) if err != nil { return nil, err } diff --git a/internal/impl/update.go b/internal/impl/update.go index 61e06fad1aa..aedd7981c7f 100644 --- a/internal/impl/update.go +++ b/internal/impl/update.go @@ -32,7 +32,7 @@ func (d *Devbox) Update(ctx context.Context, opts devopt.UpdateOpts) error { pendingPackagesToUpdate := []*devpkg.Package{} for _, pkg := range inputs { if pkg.IsLegacy() { - fmt.Fprintf(d.Stderr, "Updating %s -> %s\n", pkg.Raw, pkg.LegacyToVersioned()) + fmt.Fprintf(d.stderr, "Updating %s -> %s\n", pkg.Raw, pkg.LegacyToVersioned()) // Get the package from the config to get the Platforms and ExcludedPlatforms later cfgPackage, ok := d.cfg.Packages.Get(pkg.Raw) @@ -113,17 +113,17 @@ func (d *Devbox) mergeResolvedPackageToLockfile( ) error { existing := lockfile.Packages[pkg.Raw] if existing == nil { - ux.Finfo(d.Stderr, "Resolved %s to %[1]s %[2]s\n", pkg, resolved.Resolved) + ux.Finfo(d.stderr, "Resolved %s to %[1]s %[2]s\n", pkg, resolved.Resolved) lockfile.Packages[pkg.Raw] = resolved return nil } if existing.Version != resolved.Version { - ux.Finfo(d.Stderr, "Updating %s %s -> %s\n", pkg, existing.Version, resolved.Version) + ux.Finfo(d.stderr, "Updating %s %s -> %s\n", pkg, existing.Version, resolved.Version) if err := d.removePackagesFromProfile(ctx, []string{pkg.Raw}); err != nil { // Warn but continue. TODO(landau): ensurePackagesAreInstalled should // sync the profile so we don't need to do this manually. - ux.Fwarning(d.Stderr, "Failed to remove %s from profile: %s\n", pkg, err) + ux.Fwarning(d.stderr, "Failed to remove %s from profile: %s\n", pkg, err) } resolved.AllowInsecure = existing.AllowInsecure lockfile.Packages[pkg.Raw] = resolved @@ -159,12 +159,12 @@ func (d *Devbox) mergeResolvedPackageToLockfile( } } if updated { - ux.Finfo(d.Stderr, "Updated system information for %s\n", pkg) + ux.Finfo(d.stderr, "Updated system information for %s\n", pkg) return nil } } - ux.Finfo(d.Stderr, "Already up-to-date %s %s\n", pkg, existing.Version) + ux.Finfo(d.stderr, "Already up-to-date %s %s\n", pkg, existing.Version) return nil } @@ -177,7 +177,7 @@ func (d *Devbox) attemptToUpgradeFlake(pkg *devpkg.Package) error { } ux.Finfo( - d.Stderr, + d.stderr, "Attempting to upgrade %s using `nix profile upgrade`\n", pkg.Raw, ) @@ -185,7 +185,7 @@ func (d *Devbox) attemptToUpgradeFlake(pkg *devpkg.Package) error { err = nixprofile.ProfileUpgrade(profilePath, pkg, d.lockfile) if err != nil { ux.Ferror( - d.Stderr, + d.stderr, "Failed to upgrade %s using `nix profile upgrade`: %s\n", pkg.Raw, err, diff --git a/internal/impl/util.go b/internal/impl/util.go index 42c126d7996..063517ef2d9 100644 --- a/internal/impl/util.go +++ b/internal/impl/util.go @@ -29,7 +29,7 @@ func (d *Devbox) addDevboxUtilityPackage(ctx context.Context, pkg string) error Lockfile: d.lockfile, Package: pkg, ProfilePath: profilePath, - Writer: d.Stderr, + Writer: d.stderr, }) } diff --git a/testscripts/info/info.test.txt b/testscripts/info/info.test.txt index c977b48fccc..c518fcf051f 100644 --- a/testscripts/info/info.test.txt +++ b/testscripts/info/info.test.txt @@ -7,5 +7,5 @@ exec devbox info hello@latest stdout 'hello ' exec devbox init -exec devbox info notapackage -stdout 'Package "notapackage" not found' +!exec devbox info notapackage +stderr 'Package "notapackage" not found' From 32bb47ee42e038bea9859e75e476ba524430887f Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Wed, 27 Sep 2023 11:01:57 -0700 Subject: [PATCH 6/6] Fix test --- testscripts/info/info.test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testscripts/info/info.test.txt b/testscripts/info/info.test.txt index c518fcf051f..078e6096c96 100644 --- a/testscripts/info/info.test.txt +++ b/testscripts/info/info.test.txt @@ -7,5 +7,5 @@ exec devbox info hello@latest stdout 'hello ' exec devbox init -!exec devbox info notapackage +! exec devbox info notapackage stderr 'Package "notapackage" not found'