From 9a3354a2b43ec2c3ab2aae03985fa72a19c07b23 Mon Sep 17 00:00:00 2001 From: Savil Srivastava <676452+savil@users.noreply.github.com> Date: Wed, 9 Aug 2023 16:48:27 -0700 Subject: [PATCH] generate devpkg.Package from Config --- internal/devconfig/packages.go | 24 +++++++------ internal/devpkg/package.go | 29 +++++++++++++++- internal/impl/devbox.go | 61 +++++++++++++++++++++++++--------- 3 files changed, 87 insertions(+), 27 deletions(-) diff --git a/internal/devconfig/packages.go b/internal/devconfig/packages.go index 3889a960340..8029126a0d0 100644 --- a/internal/devconfig/packages.go +++ b/internal/devconfig/packages.go @@ -36,20 +36,11 @@ type Packages struct { func (pkgs *Packages) VersionedNames() []string { result := make([]string, 0, len(pkgs.Collection)) for _, p := range pkgs.Collection { - name := p.name - if p.Version != "" { - name += "@" + p.Version - } - result = append(result, name) + result = append(result, p.VersionedName()) } return result } -func (pkgs *Packages) VersionedNamesForPlatform() ([]string, error) { - // TODO savil. Next PR will update this implementation - return pkgs.VersionedNames(), nil -} - // Add adds a package to the list of packages func (pkgs *Packages) Add(versionedName string) { name, version := parseVersionedName(versionedName) @@ -159,6 +150,19 @@ func NewPackage(name string, values map[string]any) Package { } } +func (p *Package) VersionedName() string { + name := p.name + if p.Version != "" { + name += "@" + p.Version + } + return name +} + +func (p *Package) IsEnabledOnPlatform() (bool, error) { + // TODO savil. Next PR will update this implementation + return true, nil +} + func (p *Package) UnmarshalJSON(data []byte) error { // First, attempt to unmarshal as a version-only string var version string diff --git a/internal/devpkg/package.go b/internal/devpkg/package.go index f5749ad97cc..bea8b3e7726 100644 --- a/internal/devpkg/package.go +++ b/internal/devpkg/package.go @@ -18,6 +18,7 @@ import ( "go.jetpack.io/devbox/internal/boxcli/featureflag" "go.jetpack.io/devbox/internal/boxcli/usererr" "go.jetpack.io/devbox/internal/cuecfg" + "go.jetpack.io/devbox/internal/devconfig" "go.jetpack.io/devbox/internal/lock" "go.jetpack.io/devbox/internal/nix" "go.jetpack.io/devbox/internal/vercheck" @@ -46,6 +47,9 @@ type Package struct { // example: github:nixos/nixpkgs/5233fd2ba76a3accb5aaa999c00509a11fd0793c#hello Raw string + // isInstallable is true if the package may be enabled on the current platform. + isInstallable bool + normalizedPackageAttributePathCache string // memoized value from normalizedPackageAttributePath() } @@ -59,9 +63,26 @@ func PackageFromStrings(rawNames []string, l lock.Locker) []*Package { return packages } +func PackagesFromConfig(config *devconfig.Config, l lock.Locker) ([]*Package, error) { + result := []*Package{} + for _, pkg := range config.Packages.Collection { + isInstallable, err := pkg.IsEnabledOnPlatform() + if err != nil { + return nil, err + } + result = append(result, newPackage(pkg.VersionedName(), isInstallable, l)) + } + return result, nil +} + // PackageFromString constructs Package from the raw name provided. // The raw name corresponds to a devbox package from the devbox.json config. func PackageFromString(raw string, locker lock.Locker) *Package { + // Packages are installable by default. + return newPackage(raw, true /*isInstallable*/, locker) +} + +func newPackage(raw string, isInstallable bool, locker lock.Locker) *Package { // TODO: We should handle this error // TODO: URL might not be best representation since most packages are not urls pkgURL, _ := url.Parse(raw) @@ -79,7 +100,7 @@ func PackageFromString(raw string, locker lock.Locker) *Package { pkgURL, _ = url.Parse(normalizedURL) } - return &Package{URL: *pkgURL, lockfile: locker, Raw: raw} + return &Package{URL: *pkgURL, lockfile: locker, Raw: raw, isInstallable: isInstallable} } // isLocal specifies whether this package is a local flake. @@ -146,6 +167,12 @@ func (p *Package) URLForFlakeInput() string { return p.urlWithoutFragment() } +// IsInstallable returns whether this package is installable. Not to be confused +// with the Installable() method which returns the corresponding nix concept. +func (p *Package) IsInstallable() bool { + return p.isInstallable +} + // Installable for this package. Installable is a nix concept defined here: // https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html#installables func (p *Package) Installable() (string, error) { diff --git a/internal/impl/devbox.go b/internal/impl/devbox.go index 33ed9a60705..54396539102 100644 --- a/internal/impl/devbox.go +++ b/internal/impl/devbox.go @@ -110,9 +110,14 @@ func Open(opts *devopt.Opts) (*Devbox, error) { ) box.lockfile = lock + hasDeprecated, err := box.HasDeprecatedPackages() + if err != nil { + return nil, err + } + if !opts.IgnoreWarnings && !legacyPackagesWarningHasBeenShown && - box.HasDeprecatedPackages() { + hasDeprecated { legacyPackagesWarningHasBeenShown = true globalPath, err := GlobalDataPath() if err != nil { @@ -138,7 +143,11 @@ func (d *Devbox) Config() *devconfig.Config { } func (d *Devbox) ConfigHash() (string, error) { - pkgHashes := lo.Map(d.ConfigPackages(), func(i *devpkg.Package, _ int) string { return i.Hash() }) + pkgs, err := d.ConfigPackages() + if err != nil { + return "", err + } + pkgHashes := lo.Map(pkgs, func(i *devpkg.Package, _ int) string { return i.Hash() }) includeHashes := lo.Map(d.Includes(), func(i plugin.Includable, _ int) string { return i.Hash() }) h, err := d.cfg.Hash() if err != nil { @@ -934,28 +943,41 @@ func (d *Devbox) nixFlakesFilePath() string { // ConfigPackageNames returns the package names as defined in devbox.json func (d *Devbox) ConfigPackageNames() []string { + // TODO savil: centralize implementation by calling d.ConfigPackages and getting pkg.Raw + // Skipping for now to avoid propagating the error value. return d.cfg.Packages.VersionedNames() } // InstallablePackageNames returns the names of packages that are to be installed func (d *Devbox) InstallablePackageNames() ([]string, error) { - // TODO: next PR replaces this implementation - return d.cfg.Packages.VersionedNamesForPlatform() + pkgs, err := d.InstallablePackages() + if err != nil { + return nil, err + } + return lo.Map(pkgs, func(pkg *devpkg.Package, _ int) string { + return pkg.Raw + }), nil } // ConfigPackages returns the packages that are defined in devbox.json // NOTE: the return type is different from devconfig.Packages -func (d *Devbox) ConfigPackages() []*devpkg.Package { - return devpkg.PackageFromStrings(d.ConfigPackageNames(), d.lockfile) +func (d *Devbox) ConfigPackages() ([]*devpkg.Package, error) { + pkgs, err := devpkg.PackagesFromConfig(d.cfg, d.lockfile) + if err != nil { + return nil, err + } + return pkgs, nil } // InstallablePackages returns the packages that are to be installed func (d *Devbox) InstallablePackages() ([]*devpkg.Package, error) { - names, err := d.InstallablePackageNames() + pkgs, err := d.ConfigPackages() if err != nil { return nil, err } - return devpkg.PackageFromStrings(names, d.lockfile), nil + return lo.Filter(pkgs, func(pkg *devpkg.Package, _ int) bool { + return pkg.IsInstallable() + }), nil } func (d *Devbox) Includes() []plugin.Includable { @@ -968,21 +990,28 @@ func (d *Devbox) Includes() []plugin.Includable { return includes } -func (d *Devbox) HasDeprecatedPackages() bool { - for _, pkg := range d.ConfigPackages() { +func (d *Devbox) HasDeprecatedPackages() (bool, error) { + pkgs, err := d.ConfigPackages() + if err != nil { + return false, err + } + for _, pkg := range pkgs { if pkg.IsLegacy() { - return true + return true, nil } } - return false + return false, nil } func (d *Devbox) findPackageByName(name string) (string, error) { + pkgs, err := d.ConfigPackages() + if err != nil { + return "", err + } results := map[string]bool{} - for _, pkg := range d.ConfigPackageNames() { - i := devpkg.PackageFromString(pkg, d.lockfile) - if i.String() == name || i.CanonicalName() == name { - results[i.String()] = true + for _, pkg := range pkgs { + if pkg.String() == name || pkg.CanonicalName() == name { + results[pkg.String()] = true } } if len(results) > 1 {