From 618c0a8079ef260f5dbaae94e65c7ee5d5484a62 Mon Sep 17 00:00:00 2001 From: savil <676452+savil@users.noreply.github.com> Date: Thu, 13 Oct 2022 16:00:43 -0500 Subject: [PATCH] [shell] warn when removing non-existent package (#230) ## Summary Previously, devbox would indicate that an uninstall happened even if a package wasn't part of the `devbox.json` packages. This isn't great, especially if a user made an inadvertent typo. This PR prints a warning for such a scenario. It also changes logic to print the confirmation messages outside `devbox shell`. ## How was it tested? ``` > cd testdata/rust/rust-stable > devbox shell (devbox)> devbox add go_1_18 nodejs # package doesn't exist (devbox)> devbox rm php Warning: the following packages were not found in your devbox.json: php Uninstalling nix packages. This may take a while...done. No packages removed. # subset of packages exist (devbox) > devbox rm php rummy nodejs Warning: the following packages were not found in your devbox.json: php, rummy Uninstalling nix packages. This may take a while...done. nodejs is now removed. Run `hash -r` to ensure your shell is updated. # package exists (devbox)> devbox rm go_1_18 Uninstalling nix packages. This may take a while...done. go_1_18 is now removed. Run `hash -r` to ensure your shell is updated. ``` --- devbox.go | 49 ++++++++++++++++++++++++++++++++++++------------- go.mod | 4 +--- go.sum | 9 +++------ 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/devbox.go b/devbox.go index 319d553e3de..2ff65485551 100644 --- a/devbox.go +++ b/devbox.go @@ -13,13 +13,14 @@ import ( "strconv" "strings" + "github.com/fatih/color" "github.com/pkg/errors" + "github.com/samber/lo" "go.jetpack.io/devbox/boxcli/usererr" "go.jetpack.io/devbox/cuecfg" "go.jetpack.io/devbox/debug" "go.jetpack.io/devbox/docker" "go.jetpack.io/devbox/nix" - "go.jetpack.io/devbox/pkgslice" "go.jetpack.io/devbox/planner" "go.jetpack.io/devbox/planner/plansdk" "golang.org/x/exp/slices" @@ -108,8 +109,21 @@ func (d *Devbox) Add(pkgs ...string) error { // Remove removes Nix packages from the config so that it no longer exists in // the devbox environment. func (d *Devbox) Remove(pkgs ...string) error { - // Remove packages from config. - d.cfg.Packages = pkgslice.Exclude(d.cfg.Packages, pkgs) + + // First, save which packages are being uninstalled. Do this before we modify d.cfg.Packages below. + uninstalledPackages := lo.Intersect(d.cfg.Packages, pkgs) + + var missingPkgs []string + d.cfg.Packages, missingPkgs = lo.Difference(d.cfg.Packages, pkgs) + + if len(missingPkgs) > 0 { + fmt.Fprintf( + d.writer, + "%s the following packages were not found in your devbox.json: %s\n", + color.HiYellowString("Warning:"), + strings.Join(missingPkgs, ", "), + ) + } if err := d.saveCfg(); err != nil { return err } @@ -117,7 +131,8 @@ func (d *Devbox) Remove(pkgs ...string) error { if err := d.ensurePackagesAreInstalled(uninstall); err != nil { return err } - return d.printPackageUpdateMessage(uninstall, pkgs) + + return d.printPackageUpdateMessage(uninstall, uninstalledPackages) } // Build creates a Docker image containing a shell with the devbox environment. @@ -367,21 +382,29 @@ func (d *Devbox) ensurePackagesAreInstalled(mode installMode) error { } func (d *Devbox) printPackageUpdateMessage(mode installMode, pkgs []string) error { - // (Only when in devbox shell) Prompt the user to run `hash -r` to ensure their - // shell can access the most recently installed binaries, or ensure their - // recently uninstalled binaries are not accidentally still available. - if len(pkgs) > 0 && IsDevboxShellEnabled() { - installedVerb := "installed" - if mode == uninstall { - installedVerb = "removed" - } + installedVerb := "installed" + if mode == uninstall { + installedVerb = "removed" + } + + if len(pkgs) > 0 { successMsg := fmt.Sprintf("%s is now %s.", pkgs[0], installedVerb) if len(pkgs) > 1 { successMsg = fmt.Sprintf("%s are now %s.", strings.Join(pkgs, ", "), installedVerb) } fmt.Fprint(d.writer, successMsg) - fmt.Fprintln(d.writer, " Run `hash -r` to ensure your shell is updated.") + + // (Only when in devbox shell) Prompt the user to run `hash -r` to ensure their + // shell can access the most recently installed binaries, or ensure their + // recently uninstalled binaries are not accidentally still available. + if !IsDevboxShellEnabled() { + fmt.Fprintln(d.writer) + } else { + fmt.Fprintln(d.writer, " Run `hash -r` to ensure your shell is updated.") + } + } else { + fmt.Fprintf(d.writer, "No packages %s.\n", installedVerb) } return nil } diff --git a/go.mod b/go.mod index 262391f8db1..1af948a4e9a 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/imdario/mergo v0.3.13 github.com/pelletier/go-toml/v2 v2.0.5 github.com/pkg/errors v0.9.1 + github.com/samber/lo v1.32.0 github.com/segmentio/analytics-go v3.1.0+incompatible github.com/spf13/cobra v1.5.0 github.com/spf13/pflag v1.0.5 @@ -30,11 +31,9 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/google/uuid v1.2.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.9 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/segmentio/backo-go v1.0.1 // indirect @@ -42,6 +41,5 @@ require ( golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 293bb14b173..6ec255012e8 100644 --- a/go.sum +++ b/go.sum @@ -9,7 +9,6 @@ github.com/cockroachdb/apd/v2 v2.0.1 h1:y1Rh3tEU89D+7Tgbw+lp52T6p/GJLpDmNvr10UWq github.com/cockroachdb/apd/v2 v2.0.1/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creekorful/mvnparser v1.5.0 h1:tcaof1yFnyzz2t4tWAM7mwYcRLgiHB1Ch5hJHtnBoDk= github.com/creekorful/mvnparser v1.5.0/go.mod h1:FeYOFPluW+0s5hTa8JSCjHjpo4lWGq190OHbMuvqbBE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -30,10 +29,7 @@ github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -43,7 +39,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de h1:D5x39vF5KCwKQaw+OC9ZPiLVHXz3UFw2+psEX+gYcto= github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de/go.mod h1:kJun4WP5gFuHZgRjZUWWuH1DTxCtxbHDOIJsudS8jzY= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -55,6 +50,8 @@ github.com/protocolbuffers/txtpbfmt v0.0.0-20201118171849-f6a6b3f636fc h1:gSVONB github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/samber/lo v1.32.0 h1:MjbngaDxbQ+ockKTEoF0IQtW2lX1VgqZ5IBhxi4fmTU= +github.com/samber/lo v1.32.0/go.mod h1:HLeWcJRRyLKp3+/XBJvOrerCQn9mhdKMHyd7IRlgeQ8= github.com/segmentio/analytics-go v3.1.0+incompatible h1:IyiOfUgQFVHvsykKKbdI7ZsH374uv3/DfZUo9+G0Z80= github.com/segmentio/analytics-go v3.1.0+incompatible/go.mod h1:C7CYBtQWk4vRk2RyLu0qOcbHJ18E3F1HV2C/8JvKN48= github.com/segmentio/backo-go v1.0.1 h1:68RQccglxZeyURy93ASB/2kc9QudzgIDexJ927N++y4= @@ -68,6 +65,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g= github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -91,7 +89,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=