Skip to content

Commit f6f94fe

Browse files
authored
devbox add fallthrough and fallback for packages not handled by search (#1264)
## Summary `devbox add` fallthrough and fallback for packages not handled by search. This PR does not do the following: 1. Print a warning that a package is in a fallthrough case (I'm unclear if a warning is needed?) 2. Accept an alternative nixpkg commit hash for that specific package (I'm unclear if we are deprecating `nixpkg` commit field in `devbox.json` immediately?) I'd like to address those two things above if needed in a separate PR as a follow up. Example lockfile: ``` { "lockfile_version": "1", "packages": { "python310": { "plugin_version": "0.0.1", "resolved": "github:NixOS/nixpkgs/f80ac848e3d6f0c12c52758c0f25c10c97ca3b62#python310", "source": "nixpkg" }, "python310Packages.pip@latest": { "last_modified": "2023-05-06T16:57:53Z", "plugin_version": "0.0.1", "resolved": "github:NixOS/nixpkgs/16b3b0c53b1ee8936739f8c588544e7fcec3fc60#python310Packages.pip", "source": "devbox-search", "version": "23.0.1" }, "stdenv.cc.cc.lib": { "resolved": "github:NixOS/nixpkgs/f80ac848e3d6f0c12c52758c0f25c10c97ca3b62#stdenv.cc.cc.lib", "source": "nixpkg" } } } ``` ## How was it tested? In the Tensorflow example: ``` devbox add stdenv.cc.cc.lib devbox add nodejs-16_x devbox update ```
1 parent dea479d commit f6f94fe

File tree

7 files changed

+38
-34
lines changed

7 files changed

+38
-34
lines changed

internal/devpkg/package.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ func (p *Package) Versioned() string {
403403
}
404404

405405
func (p *Package) IsLegacy() bool {
406-
return p.isDevboxPackage() && !p.isVersioned()
406+
return p.isDevboxPackage() && !p.isVersioned() && p.lockfile.Source(p.Raw) == ""
407407
}
408408

409409
func (p *Package) LegacyToVersioned() string {

internal/devpkg/package_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ func (l *lockfile) LegacyNixpkgsPath(pkg string) string {
119119
)
120120
}
121121

122+
func (l *lockfile) Source(pkg string) string {
123+
return ""
124+
}
125+
122126
func (l *lockfile) Resolve(pkg string) (*lock.Package, error) {
123127
switch {
124128
case strings.Contains(pkg, "path:"):

internal/impl/packages.go

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,8 @@ func (d *Devbox) Add(ctx context.Context, pkgsNames ...string) error {
4242
// replace it.
4343
pkgs := []*devpkg.Package{}
4444
for _, pkg := range devpkg.PackageFromStrings(lo.Uniq(pkgsNames), d.lockfile) {
45-
versioned := pkg.Versioned()
46-
4745
// If exact versioned package is already in the config, skip.
48-
if slices.Contains(d.cfg.Packages, versioned) {
46+
if slices.Contains(d.cfg.Packages, pkg.Versioned()) {
4947
continue
5048
}
5149

@@ -59,18 +57,15 @@ func (d *Devbox) Add(ctx context.Context, pkgsNames ...string) error {
5957
}
6058
}
6159

62-
pkgs = append(pkgs, devpkg.PackageFromString(versioned, d.lockfile))
63-
d.cfg.Packages = append(d.cfg.Packages, versioned)
64-
}
65-
66-
// Check packages are valid before adding.
67-
for _, pkg := range pkgs {
68-
ok, err := pkg.ValidateExists()
69-
if err != nil {
70-
return err
71-
}
72-
if !ok {
73-
return errors.Wrap(nix.ErrPackageNotFound, pkg.Raw)
60+
// validate that the versioned package exists in the search endpoint.
61+
// if not, fallback to legacy vanilla nix.
62+
versionedPkg := devpkg.PackageFromString(pkg.Versioned(), d.lockfile)
63+
ok, err := versionedPkg.ValidateExists()
64+
if err == nil && ok {
65+
d.cfg.Packages = append(d.cfg.Packages, pkg.Versioned())
66+
} else {
67+
// fallthrough and treat package as a legacy package.
68+
d.cfg.Packages = append(d.cfg.Packages, pkg.Raw)
7469
}
7570
}
7671

internal/impl/update.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,10 @@ func (d *Devbox) Update(ctx context.Context, pkgs ...string) error {
3131
if err := d.Remove(ctx, pkg.Raw); err != nil {
3232
return err
3333
}
34-
if err := d.lockfile.ResolveToCurrentNixpkgCommitHash(
35-
pkg.LegacyToVersioned(),
36-
); err != nil {
37-
return err
38-
}
39-
if err := d.Add(ctx, pkg.LegacyToVersioned()); err != nil {
34+
// Calling Add function with the original package names, since
35+
// Add will automatically append @latest if search is able to handle that.
36+
// If not, it will fallback to the nixpkg format.
37+
if err := d.Add(ctx, pkg.Raw); err != nil {
4038
return err
4139
}
4240
} else {

internal/lock/interfaces.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ type Locker interface {
1414
LegacyNixpkgsPath(string) string
1515
ProjectDir() string
1616
Resolve(string) (*Package, error)
17+
Source(string) string
1718
}

internal/lock/lockfile.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ import (
1717
)
1818

1919
const lockFileVersion = "1"
20+
const (
21+
nixpkgSource string = "nixpkg"
22+
devboxSearchSource string = "devbox-search"
23+
)
2024

2125
// Lightly inspired by package-lock.json
2226
type File struct {
@@ -32,6 +36,7 @@ type Package struct {
3236
LastModified string `json:"last_modified,omitempty"`
3337
PluginVersion string `json:"plugin_version,omitempty"`
3438
Resolved string `json:"resolved,omitempty"`
39+
Source string `json:"source,omitempty"`
3540
Version string `json:"version,omitempty"`
3641
// Systems is keyed by the system name
3742
Systems map[string]*SystemInfo `json:"systems,omitempty"`
@@ -97,7 +102,10 @@ func (l *File) Resolve(pkg string) (*Package, error) {
97102
} else if IsLegacyPackage(pkg) {
98103
// These are legacy packages without a version. Resolve to nixpkgs with
99104
// whatever hash is in the devbox.json
100-
locked = &Package{Resolved: l.LegacyNixpkgsPath(pkg)}
105+
locked = &Package{
106+
Resolved: l.LegacyNixpkgsPath(pkg),
107+
Source: nixpkgSource,
108+
}
101109
}
102110
l.Packages[pkg] = locked
103111
}
@@ -110,17 +118,6 @@ func (l *File) ForceResolve(pkg string) (*Package, error) {
110118
return l.Resolve(pkg)
111119
}
112120

113-
func (l *File) ResolveToCurrentNixpkgCommitHash(pkg string) error {
114-
name, version, found := strings.Cut(pkg, "@")
115-
if found && version != "latest" {
116-
return errors.New(
117-
"only allowed version is @latest. Otherwise we can't guarantee the " +
118-
"version will resolve")
119-
}
120-
l.Packages[pkg] = &Package{Resolved: l.LegacyNixpkgsPath(name)}
121-
return nil
122-
}
123-
124121
func (l *File) Save() error {
125122
return cuecfg.WriteFile(lockFilePath(l.devboxProject), l)
126123
}
@@ -133,6 +130,14 @@ func (l *File) LegacyNixpkgsPath(pkg string) string {
133130
)
134131
}
135132

133+
func (l *File) Source(pkg string) string {
134+
entry, hasEntry := l.Packages[pkg]
135+
if !hasEntry || entry.Resolved == "" {
136+
return ""
137+
}
138+
return entry.Source
139+
}
140+
136141
// This probably belongs in input.go but can't add it there because it will
137142
// create a circular dependency. We could move Input into own package.
138143
func IsLegacyPackage(pkg string) bool {

internal/lock/resolve.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func (l *File) FetchResolvedPackage(pkg string) (*Package, error) {
5757
packageInfo.AttrPaths[0],
5858
),
5959
Version: packageInfo.Version,
60+
Source: devboxSearchSource,
6061
Systems: sysInfos,
6162
}, nil
6263
}

0 commit comments

Comments
 (0)