Skip to content

[versioned] If user adds new version, remove previous versions of canonical #1105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 25 additions & 17 deletions internal/impl/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,39 @@ import (
"go.jetpack.io/devbox/internal/wrapnix"
)

// packages.go has functions for adding, removing and getting info about nix packages
// packages.go has functions for adding, removing and getting info about nix
// packages

// Add adds the `pkgs` to the config (i.e. devbox.json) and nix profile for this devbox project
// Add adds the `pkgs` to the config (i.e. devbox.json) and nix profile for this
// devbox project
func (d *Devbox) Add(ctx context.Context, pkgsNames ...string) error {
ctx, task := trace.NewTask(ctx, "devboxAdd")
defer task.End()

pkgs := nix.InputsFromStrings(lo.Uniq(pkgsNames), d.lockfile)

versionedPackages := []*nix.Input{}
// Add to Packages of the config only if it's not already there. We do this
// before addin @latest to ensure we don't accidentally add a package that
// is already in the config.
for _, pkg := range pkgs {
// Only add packages that are not already in config. If same canonical exists,
// replace it.
pkgs := []*nix.Input{}
for _, pkg := range nix.InputsFromStrings(lo.Uniq(pkgsNames), d.lockfile) {
versioned := pkg.Versioned()
versionedPackages = append(
versionedPackages,
nix.InputFromString(versioned, d.lockfile),
)
// Only add if the package doesn't exist versioned or unversioned.
if !slices.Contains(d.cfg.Packages, pkg.Raw) && !slices.Contains(d.cfg.Packages, versioned) {
d.cfg.Packages = append(d.cfg.Packages, versioned)

// If exact versioned package is already in the config, skip.
if slices.Contains(d.cfg.Packages, versioned) {
continue
}

// On the other hand, if there's a package with same canonical name, replace
// it. Ignore error (which is either missing or more than one). We search by
// CanonicalName so any legacy or versioned packages will be removed if they
// match.
if name, _ := d.findPackageByName(pkg.CanonicalName()); name != "" {
if err := d.Remove(ctx, name); err != nil {
return err
}
}

pkgs = append(pkgs, nix.InputFromString(versioned, d.lockfile))
d.cfg.Packages = append(d.cfg.Packages, versioned)
}
pkgs = versionedPackages

// Check packages are valid before adding.
for _, pkg := range pkgs {
Expand Down
18 changes: 18 additions & 0 deletions testscripts/add/add_replace.test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Testscript for exercising adding packages

exec devbox init

exec devbox add [email protected]
devboxjson.packages.contains devbox.json [email protected]
! devboxjson.packages.contains devbox.json [email protected]

exec devbox add [email protected]
! devboxjson.packages.contains devbox.json [email protected]
devboxjson.packages.contains devbox.json [email protected]

-- devbox.json --
{
"packages": [
"[email protected]"
]
}
26 changes: 26 additions & 0 deletions testscripts/testrunner/assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/rogpeppe/go-internal/testscript"

"go.jetpack.io/devbox/internal/devconfig"
"go.jetpack.io/devbox/internal/envir"
)

Expand All @@ -33,6 +34,31 @@ func assertPathLength(script *testscript.TestScript, neg bool, args []string) {
}
}

func assertDevboxJSONPackagesContains(script *testscript.TestScript, neg bool, args []string) {
if len(args) != 2 {
script.Fatalf("usage: json.list.contains list.json value")
}

data := script.ReadFile(args[0])
list := devconfig.Config{}
err := json.Unmarshal([]byte(data), &list)
script.Check(err)

expected := args[1]
for _, actual := range list.Packages {
if actual == expected {
if neg {
script.Fatalf("value '%s' found in '%s'", expected, list.Packages)
}
return
}
}

if !neg {
script.Fatalf("value '%s' not found in '%s'", expected, list.Packages)
}
}

// Usage: json.superset superset.json subset.json
// Checks that the JSON in superset.json contains all the keys and values
// present in subset.json.
Expand Down
9 changes: 5 additions & 4 deletions testscripts/testrunner/testrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ func getTestscriptParams(t *testing.T, dir string) testscript.Params {
TestWork: false, // Set to true if you're trying to debug a test.
Setup: func(env *testscript.Env) error { return setupTestEnv(t, env) },
Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){
"env.path.len": assertPathLength,
"json.superset": assertJSONSuperset,
"path.order": assertPathOrder,
"source.path": sourcePath,
"env.path.len": assertPathLength,
"devboxjson.packages.contains": assertDevboxJSONPackagesContains,
"json.superset": assertJSONSuperset,
"path.order": assertPathOrder,
"source.path": sourcePath,
},
}
}