Skip to content

[lockfile] add lockfile.Tidy and call from ensurePackagesAreInstalled #1109

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 6 commits into from
Jun 7, 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
3 changes: 3 additions & 0 deletions internal/impl/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ func (d *Devbox) ensurePackagesAreInstalled(ctx context.Context, mode installMod
return err
}

// Ensure we clean out packages that are no longer needed.
d.lockfile.Tidy()

if err = d.lockfile.Save(); err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion internal/lock/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package lock
type devboxProject interface {
ConfigHash() (string, error)
NixPkgsCommitHash() string
Packages() []string
ProjectDir() string
}

Expand All @@ -14,7 +15,7 @@ type resolver interface {
}

type Locker interface {
devboxProject
resolver
LegacyNixpkgsPath(string) string
ProjectDir() string
}
11 changes: 9 additions & 2 deletions internal/lock/lockfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"path/filepath"
"strings"

"github.com/samber/lo"
"go.jetpack.io/devbox/internal/boxcli/featureflag"
"go.jetpack.io/devbox/internal/cuecfg"
)
Expand Down Expand Up @@ -99,7 +100,7 @@ func (l *File) Save() error {
return nil
}

return cuecfg.WriteFile(lockFilePath(l), l)
return cuecfg.WriteFile(lockFilePath(l.devboxProject), l)
}

func (l *File) LegacyNixpkgsPath(pkg string) string {
Expand All @@ -121,12 +122,18 @@ func IsLegacyPackage(pkg string) bool {
return !IsVersionedPackage(pkg) &&
!strings.Contains(pkg, ":") &&
// We don't support absolute paths without "path:" prefix, but adding here
// just inc ase we ever do.
// just in case we ever do.
// Landau note: I don't think we should support it, it's hard to read and a
// bit ambiguous.
!strings.HasPrefix(pkg, "/")
}

// Tidy ensures that the lockfile has the set of packages corresponding to the devbox.json config.
// It gets rid of older packages that are no longer needed.
func (l *File) Tidy() {
l.Packages = lo.PickByKeys(l.Packages, l.devboxProject.Packages())
}

func lockFilePath(project devboxProject) string {
return filepath.Join(project.ProjectDir(), "devbox.lock")
}
Expand Down
8 changes: 0 additions & 8 deletions internal/nix/input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,6 @@ type lockfile struct {
projectDir string
}

func (lockfile) ConfigHash() (string, error) {
return "", nil
}

func (lockfile) NixPkgsCommitHash() string {
return ""
}

func (l *lockfile) ProjectDir() string {
return l.projectDir
}
Expand Down
28 changes: 28 additions & 0 deletions testscripts/lockfile/lockfile_tidy.test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Testscript to ensure lockfile is updated to remove the older version of a package

# start with a devbox.json having [email protected]
cp devbox_original.json devbox.json
exec devbox install
devboxlock.packages.contains devbox.lock [email protected]

# change devbox.json to instead have [email protected]
cp devbox_changed.json devbox.json
exec devbox install
devboxlock.packages.contains devbox.lock [email protected]
! devboxlock.packages.contains devbox.lock [email protected]


-- devbox_original.json --
{
"packages": [
"[email protected]"
]
}

-- devbox_changed.json --
{
"packages": [
"[email protected]"
]
}

25 changes: 24 additions & 1 deletion testscripts/testrunner/assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

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

// Usage: env.path.len <number>
Expand All @@ -36,7 +37,7 @@ 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")
script.Fatalf("usage: devboxjson.packages.contains devbox.json value")
}

data := script.ReadFile(args[0])
Expand All @@ -59,6 +60,28 @@ func assertDevboxJSONPackagesContains(script *testscript.TestScript, neg bool, a
}
}

func assertDevboxLockPackagesContains(script *testscript.TestScript, neg bool, args []string) {
if len(args) != 2 {
script.Fatalf("usage: devboxlock.packages.contains devbox.lock value")
}

data := script.ReadFile(args[0])
lockfile := lock.File{}
err := json.Unmarshal([]byte(data), &lockfile)
script.Check(err)

expected := args[1]
if _, ok := lockfile.Packages[expected]; ok {
if neg {
script.Fatalf("value '%s' found in %s", expected, args[0])
}
} else {
if !neg {
script.Fatalf("value '%s' not found in '%s'", expected, args[0])
}
}
}

// 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
16 changes: 15 additions & 1 deletion testscripts/testrunner/testrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,29 @@ func globDirs(pattern string) []string {
return directories
}

// copyFileCmd enables copying files within the WORKDIR
func copyFileCmd(script *testscript.TestScript, neg bool, args []string) {
if len(args) < 2 {
script.Fatalf("usage: cp <from-file> <to-file>")
}
if neg {
script.Fatalf("neg does not make sense for this command")
}
err := script.Exec("cp", script.MkAbs(args[0]), script.MkAbs(args[1]))
script.Check(err)
}

func getTestscriptParams(t *testing.T, dir string) testscript.Params {
return testscript.Params{
Dir: dir,
RequireExplicitExec: true,
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,
"cp": copyFileCmd,
"devboxjson.packages.contains": assertDevboxJSONPackagesContains,
"devboxlock.packages.contains": assertDevboxLockPackagesContains,
"env.path.len": assertPathLength,
"json.superset": assertJSONSuperset,
"path.order": assertPathOrder,
"source.path": sourcePath,
Expand Down