Skip to content

devbox add fallthrough and fallback for packages not handled by search #1264

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 3 commits into from
Jul 11, 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
2 changes: 1 addition & 1 deletion internal/devpkg/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ func (p *Package) Versioned() string {
}

func (p *Package) IsLegacy() bool {
return p.isDevboxPackage() && !p.isVersioned()
return p.isDevboxPackage() && !p.isVersioned() && p.lockfile.Source(p.Raw) == ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another possible API could be

p.lockfile.Get(p.Raw).Source() to have lock packages themselves respond to source()

(and just default Source() to be empty string if not set or if package is nil)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I like p.lockfile.Get(p.Raw).Source() better. I'll follow up with a separate PR

}

func (p *Package) LegacyToVersioned() string {
Expand Down
4 changes: 4 additions & 0 deletions internal/devpkg/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ func (l *lockfile) LegacyNixpkgsPath(pkg string) string {
)
}

func (l *lockfile) Source(pkg string) string {
return ""
}

func (l *lockfile) Resolve(pkg string) (*lock.Package, error) {
switch {
case strings.Contains(pkg, "path:"):
Expand Down
25 changes: 10 additions & 15 deletions internal/impl/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ func (d *Devbox) Add(ctx context.Context, pkgsNames ...string) error {
// replace it.
pkgs := []*devpkg.Package{}
for _, pkg := range devpkg.PackageFromStrings(lo.Uniq(pkgsNames), d.lockfile) {
versioned := pkg.Versioned()

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

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

pkgs = append(pkgs, devpkg.PackageFromString(versioned, d.lockfile))
d.cfg.Packages = append(d.cfg.Packages, versioned)
}

// Check packages are valid before adding.
for _, pkg := range pkgs {
ok, err := pkg.ValidateExists()
if err != nil {
return err
}
if !ok {
return errors.Wrap(nix.ErrPackageNotFound, pkg.Raw)
// validate that the versioned package exists in the search endpoint.
// if not, fallback to legacy vanilla nix.
versionedPkg := devpkg.PackageFromString(pkg.Versioned(), d.lockfile)
ok, err := versionedPkg.ValidateExists()
if err == nil && ok {
d.cfg.Packages = append(d.cfg.Packages, pkg.Versioned())
} else {
// fallthrough and treat package as a legacy package.
d.cfg.Packages = append(d.cfg.Packages, pkg.Raw)
}
}

Expand Down
10 changes: 4 additions & 6 deletions internal/impl/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,10 @@ func (d *Devbox) Update(ctx context.Context, pkgs ...string) error {
if err := d.Remove(ctx, pkg.Raw); err != nil {
return err
}
if err := d.lockfile.ResolveToCurrentNixpkgCommitHash(
pkg.LegacyToVersioned(),
); err != nil {
return err
}
if err := d.Add(ctx, pkg.LegacyToVersioned()); err != nil {
// Calling Add function with the original package names, since
// Add will automatically append @latest if search is able to handle that.
// If not, it will fallback to the nixpkg format.
if err := d.Add(ctx, pkg.Raw); err != nil {
return err
}
} else {
Expand Down
1 change: 1 addition & 0 deletions internal/lock/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ type Locker interface {
LegacyNixpkgsPath(string) string
ProjectDir() string
Resolve(string) (*Package, error)
Source(string) string
}
29 changes: 17 additions & 12 deletions internal/lock/lockfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import (
)

const lockFileVersion = "1"
const (
nixpkgSource string = "nixpkg"
devboxSearchSource string = "devbox-search"
)

// Lightly inspired by package-lock.json
type File struct {
Expand All @@ -32,6 +36,7 @@ type Package struct {
LastModified string `json:"last_modified,omitempty"`
PluginVersion string `json:"plugin_version,omitempty"`
Resolved string `json:"resolved,omitempty"`
Source string `json:"source,omitempty"`
Version string `json:"version,omitempty"`
// Systems is keyed by the system name
Systems map[string]*SystemInfo `json:"systems,omitempty"`
Expand Down Expand Up @@ -97,7 +102,10 @@ func (l *File) Resolve(pkg string) (*Package, error) {
} else if IsLegacyPackage(pkg) {
// These are legacy packages without a version. Resolve to nixpkgs with
// whatever hash is in the devbox.json
locked = &Package{Resolved: l.LegacyNixpkgsPath(pkg)}
locked = &Package{
Resolved: l.LegacyNixpkgsPath(pkg),
Source: nixpkgSource,
}
}
l.Packages[pkg] = locked
}
Expand All @@ -110,17 +118,6 @@ func (l *File) ForceResolve(pkg string) (*Package, error) {
return l.Resolve(pkg)
}

func (l *File) ResolveToCurrentNixpkgCommitHash(pkg string) error {
name, version, found := strings.Cut(pkg, "@")
if found && version != "latest" {
return errors.New(
"only allowed version is @latest. Otherwise we can't guarantee the " +
"version will resolve")
}
l.Packages[pkg] = &Package{Resolved: l.LegacyNixpkgsPath(name)}
return nil
}

func (l *File) Save() error {
return cuecfg.WriteFile(lockFilePath(l.devboxProject), l)
}
Expand All @@ -133,6 +130,14 @@ func (l *File) LegacyNixpkgsPath(pkg string) string {
)
}

func (l *File) Source(pkg string) string {
entry, hasEntry := l.Packages[pkg]
if !hasEntry || entry.Resolved == "" {
return ""
}
return entry.Source
}

// This probably belongs in input.go but can't add it there because it will
// create a circular dependency. We could move Input into own package.
func IsLegacyPackage(pkg string) bool {
Expand Down
1 change: 1 addition & 0 deletions internal/lock/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func (l *File) FetchResolvedPackage(pkg string) (*Package, error) {
packageInfo.AttrPaths[0],
),
Version: packageInfo.Version,
Source: devboxSearchSource,
Systems: sysInfos,
}, nil
}
Expand Down