diff --git a/internal/boxcli/init.go b/internal/boxcli/init.go index 1efaebabb3f..a203217c375 100644 --- a/internal/boxcli/init.go +++ b/internal/boxcli/init.go @@ -4,6 +4,8 @@ package boxcli import ( + "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" @@ -31,7 +33,7 @@ func initCmd() *cobra.Command { } command.Flags().BoolVar(&flags.auto, "auto", false, "Automatically detect packages to add") - command.Flags().BoolVar(&flags.dryRun, "dry-run", false, "Dry run") + command.Flags().BoolVar(&flags.dryRun, "dry-run", false, "Dry run for auto mode. Prints the config that would be used") _ = command.Flags().MarkHidden("auto") _ = command.Flags().MarkHidden("dry-run") @@ -41,18 +43,17 @@ func initCmd() *cobra.Command { func runInitCmd(cmd *cobra.Command, args []string, flags *initFlags) error { path := pathArg(args) - if flags.auto && flags.dryRun { - return autodetect.DryRun(cmd.Context(), path, cmd.ErrOrStderr()) - } - - err := devbox.InitConfig(path) - if err != nil { - return errors.WithStack(err) - } - if flags.auto { - err = autodetect.PopulateConfig(cmd.Context(), path, cmd.ErrOrStderr()) + if flags.dryRun { + config, err := autodetect.DryRun(cmd.Context(), path) + if err != nil { + return errors.WithStack(err) + } + fmt.Fprintln(cmd.OutOrStdout(), string(config)) + return nil + } + return autodetect.InitConfig(cmd.Context(), path) } - return errors.WithStack(err) + return devbox.InitConfig(path) } diff --git a/internal/devbox/devbox.go b/internal/devbox/devbox.go index ec82a86b949..557f6de7ebe 100644 --- a/internal/devbox/devbox.go +++ b/internal/devbox/devbox.go @@ -72,7 +72,8 @@ type Devbox struct { var legacyPackagesWarningHasBeenShown = false func InitConfig(dir string) error { - return devconfig.Init(dir) + _, err := devconfig.Init(dir) + return err } func Open(opts *devopt.Opts) (*Devbox, error) { diff --git a/internal/devbox/devbox_test.go b/internal/devbox/devbox_test.go index 5d0346b86d4..579b5b7a496 100644 --- a/internal/devbox/devbox_test.go +++ b/internal/devbox/devbox_test.go @@ -122,7 +122,7 @@ func TestComputeDevboxPathWhenRemoving(t *testing.T) { func devboxForTesting(t *testing.T) *Devbox { path := t.TempDir() - err := devconfig.Init(path) + _, err := devconfig.Init(path) require.NoError(t, err, "InitConfig should not fail") d, err := Open(&devopt.Opts{ Dir: path, diff --git a/internal/devconfig/config_test.go b/internal/devconfig/config_test.go index d625de332bf..521aa09f033 100644 --- a/internal/devconfig/config_test.go +++ b/internal/devconfig/config_test.go @@ -16,7 +16,7 @@ import ( func TestOpen(t *testing.T) { t.Run("Dir", func(t *testing.T) { root, _, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } @@ -31,7 +31,7 @@ func TestOpen(t *testing.T) { }) t.Run("File", func(t *testing.T) { root, _, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } path := filepath.Join(root, "devbox.json") @@ -50,7 +50,7 @@ func TestOpen(t *testing.T) { func TestOpenError(t *testing.T) { t.Run("NotExist", func(t *testing.T) { root, _, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } @@ -79,7 +79,7 @@ func TestOpenError(t *testing.T) { }) t.Run("ParentNotFound", func(t *testing.T) { root, child, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } @@ -96,10 +96,10 @@ func TestOpenError(t *testing.T) { func TestFind(t *testing.T) { t.Run("StartInSameDir", func(t *testing.T) { root, child, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } - if err := Init(child); err != nil { + if _, err := Init(child); err != nil { t.Fatalf("Init(%q) error: %v", child, err) } @@ -114,7 +114,7 @@ func TestFind(t *testing.T) { }) t.Run("StartInChildDir", func(t *testing.T) { root, child, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } @@ -129,10 +129,10 @@ func TestFind(t *testing.T) { }) t.Run("StartInNestedChildDir", func(t *testing.T) { root, child, nested := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } - if err := Init(child); err != nil { + if _, err := Init(child); err != nil { t.Fatalf("Init(%q) error: %v", child, err) } @@ -147,7 +147,7 @@ func TestFind(t *testing.T) { }) t.Run("IgnoreDirsWithMatchingName", func(t *testing.T) { root, child, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } @@ -171,7 +171,7 @@ func TestFind(t *testing.T) { }) t.Run("ExactFile", func(t *testing.T) { root, _, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } @@ -189,7 +189,7 @@ func TestFind(t *testing.T) { func TestFindError(t *testing.T) { t.Run("NotExist", func(t *testing.T) { root, _, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } @@ -207,7 +207,7 @@ func TestFindError(t *testing.T) { }) t.Run("NotFound", func(t *testing.T) { root, child, _ := mkNestedDirs(t) - if err := Init(child); err != nil { + if _, err := Init(child); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } @@ -221,10 +221,10 @@ func TestFindError(t *testing.T) { }) t.Run("Permissions", func(t *testing.T) { root, child, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } - if err := Init(child); err != nil { + if _, err := Init(child); err != nil { t.Fatalf("Init(%q) error: %v", child, err) } path := filepath.Join(child, "devbox.json") @@ -260,7 +260,7 @@ func TestFindError(t *testing.T) { }) t.Run("ExactFilePermissions", func(t *testing.T) { root, _, _ := mkNestedDirs(t) - if err := Init(root); err != nil { + if _, err := Init(root); err != nil { t.Fatalf("Init(%q) error: %v", root, err) } path := filepath.Join(root, "devbox.json") diff --git a/internal/devconfig/init.go b/internal/devconfig/init.go index 8671cb03bd0..df7cc0cdfd1 100644 --- a/internal/devconfig/init.go +++ b/internal/devconfig/init.go @@ -11,17 +11,19 @@ import ( "go.jetpack.io/devbox/internal/devconfig/configfile" ) -func Init(dir string) error { +func Init(dir string) (*Config, error) { file, err := os.OpenFile( filepath.Join(dir, configfile.DefaultName), os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o644, ) if errors.Is(err, os.ErrExist) { - return nil + // TODO: Should we return an error here? + // If we do, it breaks a bunch of tests, but it's likely the correct behavior + return nil, nil } if err != nil { - return err + return nil, err } defer func() { if err != nil { @@ -29,10 +31,11 @@ func Init(dir string) error { } }() - _, err = file.Write(DefaultConfig().Root.Bytes()) + newConfig := DefaultConfig() + _, err = file.Write(newConfig.Root.Bytes()) + defer file.Close() if err != nil { - file.Close() - return err + return nil, err } - return file.Close() + return newConfig, nil } diff --git a/pkg/autodetect/autodetect.go b/pkg/autodetect/autodetect.go index 09cd51e064d..a4ac0c5710b 100644 --- a/pkg/autodetect/autodetect.go +++ b/pkg/autodetect/autodetect.go @@ -2,40 +2,35 @@ package autodetect import ( "context" - "fmt" - "io" - "go.jetpack.io/devbox/internal/devbox" - "go.jetpack.io/devbox/internal/devbox/devopt" + "go.jetpack.io/devbox/internal/devconfig" "go.jetpack.io/devbox/pkg/autodetect/detector" ) -func PopulateConfig(ctx context.Context, path string, stderr io.Writer) error { - pkgs, err := packages(ctx, path) +func InitConfig(ctx context.Context, path string) error { + config, err := devconfig.Init(path) if err != nil { return err } - devbox, err := devbox.Open(&devopt.Opts{ - Dir: path, - Stderr: stderr, - }) - if err != nil { - return err + + return populateConfig(ctx, path, config) +} + +func DryRun(ctx context.Context, path string) ([]byte, error) { + config := devconfig.DefaultConfig() + if err := populateConfig(ctx, path, config); err != nil { + return nil, err } - return devbox.Add(ctx, pkgs, devopt.AddOpts{}) + return config.Root.Bytes(), nil } -func DryRun(ctx context.Context, path string, stderr io.Writer) error { +func populateConfig(ctx context.Context, path string, config *devconfig.Config) error { pkgs, err := packages(ctx, path) if err != nil { return err - } else if len(pkgs) == 0 { - fmt.Fprintln(stderr, "No packages to add") - return nil } - fmt.Fprintln(stderr, "Packages to add:") for _, pkg := range pkgs { - fmt.Fprintln(stderr, pkg) + config.PackageMutator().Add(pkg) } return nil }