From 2fb2720169e89f914955cfc4efeb35c1632e82e4 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 9 Oct 2024 10:58:51 +0200 Subject: [PATCH 1/8] basic clean command --- internal/boxcli/clean.go | 34 ++++++++++++++++++++++++++++++++++ internal/boxcli/root.go | 1 + internal/devbox/devbox.go | 5 +++++ internal/devconfig/clean.go | 19 +++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 internal/boxcli/clean.go create mode 100644 internal/devconfig/clean.go diff --git a/internal/boxcli/clean.go b/internal/boxcli/clean.go new file mode 100644 index 00000000000..1b8767e944f --- /dev/null +++ b/internal/boxcli/clean.go @@ -0,0 +1,34 @@ +// Copyright 2024 Jetify Inc. and contributors. All rights reserved. +// Use of this source code is governed by the license in the LICENSE file. + +package boxcli + +import ( + "github.com/spf13/cobra" + + "go.jetpack.io/devbox/internal/devbox" +) + +type cleanFlags struct{} + +func cleanCmd() *cobra.Command { + flags := &cleanFlags{} + command := &cobra.Command{ + Use: "clean", + Short: "Cleans up an existing devbox directory.", + Long: "Cleans up an existing devbox directory." + + "This will delete all devbox files and directories." + + "This includes .devbox, devbox.json, devbox.lock.", + Args: cobra.MaximumNArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + return runCleanCmd(cmd, args, flags) + }, + } + + return command +} + +func runCleanCmd(_ *cobra.Command, args []string, _ *cleanFlags) error { + path := pathArg(args) + return devbox.Clean(path) +} diff --git a/internal/boxcli/root.go b/internal/boxcli/root.go index e30ba6a363b..d09555d1fa4 100644 --- a/internal/boxcli/root.go +++ b/internal/boxcli/root.go @@ -66,6 +66,7 @@ func RootCmd() *cobra.Command { command.AddCommand(globalCmd()) command.AddCommand(infoCmd()) command.AddCommand(initCmd()) + command.AddCommand(cleanCmd()) command.AddCommand(installCmd()) command.AddCommand(integrateCmd()) command.AddCommand(listCmd()) diff --git a/internal/devbox/devbox.go b/internal/devbox/devbox.go index 557f6de7ebe..a91c4be2830 100644 --- a/internal/devbox/devbox.go +++ b/internal/devbox/devbox.go @@ -76,6 +76,11 @@ func InitConfig(dir string) error { return err } +func Clean(dir string) error { + err := devconfig.Clean(dir) + return err +} + func Open(opts *devopt.Opts) (*Devbox, error) { var cfg *devconfig.Config var err error diff --git a/internal/devconfig/clean.go b/internal/devconfig/clean.go new file mode 100644 index 00000000000..8872ef4dc20 --- /dev/null +++ b/internal/devconfig/clean.go @@ -0,0 +1,19 @@ +// Copyright 2024 Jetify Inc. and contributors. All rights reserved. +// Use of this source code is governed by the license in the LICENSE file. + +package devconfig + +import ( + "os" + + "go.jetpack.io/devbox/internal/devconfig/configfile" +) + +func Clean(dir string) error { + filesToDelete := []string{configfile.DefaultName, "devbox.lock", ".devbox"} + for _, f := range filesToDelete { + // TODO: what should we do here? print an error? + _ = os.Remove(f) + } + return nil +} From 64d8809b463506b6f72c5f629eac0bfabbf50d5f Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 9 Oct 2024 13:06:57 +0200 Subject: [PATCH 2/8] added clean functionality --- internal/boxcli/clean.go | 6 +++--- internal/devconfig/clean.go | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/internal/boxcli/clean.go b/internal/boxcli/clean.go index 1b8767e944f..0102ee895d9 100644 --- a/internal/boxcli/clean.go +++ b/internal/boxcli/clean.go @@ -16,9 +16,9 @@ func cleanCmd() *cobra.Command { command := &cobra.Command{ Use: "clean", Short: "Cleans up an existing devbox directory.", - Long: "Cleans up an existing devbox directory." + - "This will delete all devbox files and directories." + - "This includes .devbox, devbox.json, devbox.lock.", + Long: "Cleans up an existing devbox directory.\n" + + "This will delete all devbox files and directories.\n" + + "This includes .devbox, devbox.json, devbox.lock.\n", Args: cobra.MaximumNArgs(0), RunE: func(cmd *cobra.Command, args []string) error { return runCleanCmd(cmd, args, flags) diff --git a/internal/devconfig/clean.go b/internal/devconfig/clean.go index 8872ef4dc20..5d51af75678 100644 --- a/internal/devconfig/clean.go +++ b/internal/devconfig/clean.go @@ -10,10 +10,17 @@ import ( ) func Clean(dir string) error { - filesToDelete := []string{configfile.DefaultName, "devbox.lock", ".devbox"} + filesToDelete := []string{ + configfile.DefaultName, + "devbox.lock", + ".devbox", + } for _, f := range filesToDelete { // TODO: what should we do here? print an error? - _ = os.Remove(f) + _ = os.RemoveAll(dir + f) } + + // TODO: should the devbox shell be killed here? + return nil } From 657dc00ef01bddd44b1ba6f0e9f29723d7955b22 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 9 Oct 2024 22:16:23 +0200 Subject: [PATCH 3/8] boxcli: add test for clean --- internal/nix/source.go | 2 ++ testscripts/clean/clean.test.txt | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 testscripts/clean/clean.test.txt diff --git a/internal/nix/source.go b/internal/nix/source.go index 0c2f06cc64c..b211c674777 100644 --- a/internal/nix/source.go +++ b/internal/nix/source.go @@ -5,6 +5,7 @@ package nix import ( "bytes" + "fmt" "os" "os/exec" "path/filepath" @@ -35,6 +36,7 @@ func SourceNixEnv() error { // installed before we get here) srcFile := "" for _, f := range nixLinks() { + fmt.Println(f) if _, err := os.Stat(f); err == nil { srcFile = f break diff --git a/testscripts/clean/clean.test.txt b/testscripts/clean/clean.test.txt new file mode 100644 index 00000000000..04128b9092a --- /dev/null +++ b/testscripts/clean/clean.test.txt @@ -0,0 +1,18 @@ +# Create a new devbox, install a package and run clean + +! exists devbox.json +exec devbox init +exists devbox.json + +exec devbox add go + +exec devbox shell +exists devbox.json +exists devbox.lock +exists .devbox + +exec devbox clean +! exists devbox.json +! exists devbox.lock +! exists .devbox + From 31a569684253d1292bd9176cb2b341ca9ee0477b Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 9 Oct 2024 22:18:58 +0200 Subject: [PATCH 4/8] boxcli: removed debug message --- internal/nix/source.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/nix/source.go b/internal/nix/source.go index b211c674777..0c2f06cc64c 100644 --- a/internal/nix/source.go +++ b/internal/nix/source.go @@ -5,7 +5,6 @@ package nix import ( "bytes" - "fmt" "os" "os/exec" "path/filepath" @@ -36,7 +35,6 @@ func SourceNixEnv() error { // installed before we get here) srcFile := "" for _, f := range nixLinks() { - fmt.Println(f) if _, err := os.Stat(f); err == nil { srcFile = f break From b1fc9afc0770c4f30d326c12ea611d675895a90e Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 10 Oct 2024 21:06:55 +0200 Subject: [PATCH 5/8] boxcli: don't delete devbox.json on normal clean --- internal/devconfig/clean.go | 5 +---- testscripts/clean/clean.test.txt | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/internal/devconfig/clean.go b/internal/devconfig/clean.go index 5d51af75678..457aa42e131 100644 --- a/internal/devconfig/clean.go +++ b/internal/devconfig/clean.go @@ -5,18 +5,15 @@ package devconfig import ( "os" - - "go.jetpack.io/devbox/internal/devconfig/configfile" ) func Clean(dir string) error { filesToDelete := []string{ - configfile.DefaultName, "devbox.lock", ".devbox", } for _, f := range filesToDelete { - // TODO: what should we do here? print an error? + // TODO: what should we do here when an unexpected error occurs? print an error? _ = os.RemoveAll(dir + f) } diff --git a/testscripts/clean/clean.test.txt b/testscripts/clean/clean.test.txt index 04128b9092a..5f179a542a9 100644 --- a/testscripts/clean/clean.test.txt +++ b/testscripts/clean/clean.test.txt @@ -12,7 +12,6 @@ exists devbox.lock exists .devbox exec devbox clean -! exists devbox.json ! exists devbox.lock ! exists .devbox From f276e955568ed995506ea15c69889f3ecde06cf3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 10 Oct 2024 23:09:11 +0200 Subject: [PATCH 6/8] boxcli: add hard flag for clean --- internal/boxcli/clean.go | 33 ++++++++++++++++++++++++++------- internal/devbox/devbox.go | 5 ----- internal/devconfig/clean.go | 6 +----- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/internal/boxcli/clean.go b/internal/boxcli/clean.go index 0102ee895d9..b97162ed32a 100644 --- a/internal/boxcli/clean.go +++ b/internal/boxcli/clean.go @@ -6,29 +6,48 @@ package boxcli import ( "github.com/spf13/cobra" - "go.jetpack.io/devbox/internal/devbox" + "go.jetpack.io/devbox/internal/devconfig" ) -type cleanFlags struct{} +type cleanFlags struct { + hard bool +} + +const ( + devboxLockFile = "devbox.lock" + devboxConfigFile = "devbox.json" + devboxDotDir = ".devbox" +) func cleanCmd() *cobra.Command { flags := &cleanFlags{} command := &cobra.Command{ Use: "clean", Short: "Cleans up an existing devbox directory.", - Long: "Cleans up an existing devbox directory.\n" + - "This will delete all devbox files and directories.\n" + - "This includes .devbox, devbox.json, devbox.lock.\n", + Long: "Cleans up an existing devbox directory. " + + "This will delete .devbox and devbox.lock. ", Args: cobra.MaximumNArgs(0), RunE: func(cmd *cobra.Command, args []string) error { return runCleanCmd(cmd, args, flags) }, } + command.Flags().BoolVar(&flags.hard, "hard", false, "Also delete the devbox.json file") + return command } -func runCleanCmd(_ *cobra.Command, args []string, _ *cleanFlags) error { +func runCleanCmd(_ *cobra.Command, args []string, flags *cleanFlags) error { path := pathArg(args) - return devbox.Clean(path) + + filesToDelete := []string{ + devboxLockFile, + devboxDotDir, + } + + if flags.hard { + filesToDelete = append(filesToDelete, devboxConfigFile) + } + + return devconfig.Clean(path, filesToDelete) } diff --git a/internal/devbox/devbox.go b/internal/devbox/devbox.go index a91c4be2830..557f6de7ebe 100644 --- a/internal/devbox/devbox.go +++ b/internal/devbox/devbox.go @@ -76,11 +76,6 @@ func InitConfig(dir string) error { return err } -func Clean(dir string) error { - err := devconfig.Clean(dir) - return err -} - func Open(opts *devopt.Opts) (*Devbox, error) { var cfg *devconfig.Config var err error diff --git a/internal/devconfig/clean.go b/internal/devconfig/clean.go index 457aa42e131..e89e1520728 100644 --- a/internal/devconfig/clean.go +++ b/internal/devconfig/clean.go @@ -7,11 +7,7 @@ import ( "os" ) -func Clean(dir string) error { - filesToDelete := []string{ - "devbox.lock", - ".devbox", - } +func Clean(dir string, filesToDelete []string) error { for _, f := range filesToDelete { // TODO: what should we do here when an unexpected error occurs? print an error? _ = os.RemoveAll(dir + f) From 44561172e4e296613e504e99501e17661feda1a1 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 10 Oct 2024 23:13:24 +0200 Subject: [PATCH 7/8] boxcli: test for hard clean --- testscripts/clean/clean_hard.test.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 testscripts/clean/clean_hard.test.txt diff --git a/testscripts/clean/clean_hard.test.txt b/testscripts/clean/clean_hard.test.txt new file mode 100644 index 00000000000..a69873d22b3 --- /dev/null +++ b/testscripts/clean/clean_hard.test.txt @@ -0,0 +1,18 @@ +# Create a new devbox, install a package and run clean hard + +! exists devbox.json +exec devbox init +exists devbox.json + +exec devbox add go + +exec devbox shell +exists devbox.json +exists devbox.lock +exists .devbox + +exec devbox clean --hard +! exists devbox.json +! exists devbox.lock +! exists .devbox + From be61118493eff0ff65c773f028ae38ff5d7245f5 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 16 Oct 2024 21:03:02 +0200 Subject: [PATCH 8/8] boxcli: add suggestions from #2437 --- internal/boxcli/clean.go | 38 +++++++++++++++++++++++------------ internal/boxcli/multi/sync.go | 2 +- internal/devconfig/clean.go | 14 ++++++++++--- internal/lock/lockfile.go | 4 +++- internal/shellgen/generate.go | 4 +++- 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/internal/boxcli/clean.go b/internal/boxcli/clean.go index b97162ed32a..c8c7aeb6eca 100644 --- a/internal/boxcli/clean.go +++ b/internal/boxcli/clean.go @@ -4,50 +4,62 @@ package boxcli import ( + "github.com/AlecAivazis/survey/v2" "github.com/spf13/cobra" "go.jetpack.io/devbox/internal/devconfig" + "go.jetpack.io/devbox/internal/devconfig/configfile" + "go.jetpack.io/devbox/internal/lock" + "go.jetpack.io/devbox/internal/shellgen" ) type cleanFlags struct { + pathFlag hard bool } -const ( - devboxLockFile = "devbox.lock" - devboxConfigFile = "devbox.json" - devboxDotDir = ".devbox" -) - func cleanCmd() *cobra.Command { flags := &cleanFlags{} command := &cobra.Command{ Use: "clean", - Short: "Cleans up an existing devbox directory.", + Short: "Clean up devbox files from the current directory", Long: "Cleans up an existing devbox directory. " + "This will delete .devbox and devbox.lock. ", - Args: cobra.MaximumNArgs(0), RunE: func(cmd *cobra.Command, args []string) error { + if flags.hard { + prompt := &survey.Confirm{ + Message: "Are you sure you want to delete your devbox config?", + } + confirmed := false + if err := survey.AskOne(prompt, &confirmed); err != nil { + return err + } + if !confirmed { + return nil + } + } return runCleanCmd(cmd, args, flags) }, } command.Flags().BoolVar(&flags.hard, "hard", false, "Also delete the devbox.json file") + flags.register(command) + return command } -func runCleanCmd(_ *cobra.Command, args []string, flags *cleanFlags) error { +func runCleanCmd(cmd *cobra.Command, args []string, flags *cleanFlags) error { path := pathArg(args) filesToDelete := []string{ - devboxLockFile, - devboxDotDir, + lock.FileName, + shellgen.DevboxHiddenDirName, } if flags.hard { - filesToDelete = append(filesToDelete, devboxConfigFile) + filesToDelete = append(filesToDelete, configfile.DefaultName) } - return devconfig.Clean(path, filesToDelete) + return devconfig.Clean(path, filesToDelete, cmd.ErrOrStderr()) } diff --git a/internal/boxcli/multi/sync.go b/internal/boxcli/multi/sync.go index ac43ea8d2b7..f5f68ff3440 100644 --- a/internal/boxcli/multi/sync.go +++ b/internal/boxcli/multi/sync.go @@ -104,7 +104,7 @@ func collectLockfiles() ([]string, error) { return err } - if !dirEntry.IsDir() && filepath.Base(path) == "devbox.lock" { + if !dirEntry.IsDir() && filepath.Base(path) == lock.FileName { lockfiles = append(lockfiles, path) } diff --git a/internal/devconfig/clean.go b/internal/devconfig/clean.go index e89e1520728..0e90b195654 100644 --- a/internal/devconfig/clean.go +++ b/internal/devconfig/clean.go @@ -4,13 +4,21 @@ package devconfig import ( + "io" "os" + + "go.jetpack.io/devbox/internal/fileutil" + "go.jetpack.io/devbox/internal/ux" ) -func Clean(dir string, filesToDelete []string) error { +func Clean(dir string, filesToDelete []string, w io.Writer) error { for _, f := range filesToDelete { - // TODO: what should we do here when an unexpected error occurs? print an error? - _ = os.RemoveAll(dir + f) + if fileutil.Exists(f) { + ux.Finfof(w, "Deleting %s\n", f) + } + if err := os.RemoveAll(dir + f); err != nil { + return err + } } // TODO: should the devbox shell be killed here? diff --git a/internal/lock/lockfile.go b/internal/lock/lockfile.go index e4a47effa31..b7f90843a55 100644 --- a/internal/lock/lockfile.go +++ b/internal/lock/lockfile.go @@ -21,6 +21,8 @@ import ( "go.jetpack.io/devbox/internal/cuecfg" ) +const FileName = "devbox.lock" + const lockFileVersion = "1" // Lightly inspired by package-lock.json @@ -232,7 +234,7 @@ func (f *File) isDirty() (bool, error) { } func lockFilePath(projectDir string) string { - return filepath.Join(projectDir, "devbox.lock") + return filepath.Join(projectDir, FileName) } func ResolveRunXPackage(ctx context.Context, pkg string) (types.PkgRef, error) { diff --git a/internal/shellgen/generate.go b/internal/shellgen/generate.go index 57d8e37acc9..74df8988285 100644 --- a/internal/shellgen/generate.go +++ b/internal/shellgen/generate.go @@ -20,6 +20,8 @@ import ( "go.jetpack.io/devbox/internal/redact" ) +const DevboxHiddenDirName = ".devbox" + //go:embed tmpl/* var tmplFS embed.FS @@ -43,7 +45,7 @@ func GenerateForPrintEnv(ctx context.Context, devbox devboxer) error { } // Gitignore file is added to the .devbox directory - err = writeFromTemplate(filepath.Join(devbox.ProjectDir(), ".devbox"), plan, ".gitignore", ".gitignore") + err = writeFromTemplate(filepath.Join(devbox.ProjectDir(), DevboxHiddenDirName), plan, ".gitignore", ".gitignore") if err != nil { return errors.WithStack(err) }