Skip to content

Commit 1c4b8a9

Browse files
authored
[nix.System] call EnsureNixInstalled from devbox.Open, and cleanup function API (#1374)
## Summary `nix.System` is widely used. So, in #1357 we wanted to change its API to just return `string` instead of `string, error`. To do so, we cache the result in a `nix` package variable. And populate it during `EnsureNixInstalled`. However, `EnsureNixInstalled` was only called from Cobra command functions. But `devbox` as a library also now needs to call it. IMO, it should always have called it since we do rely on `nix` being installed. This PR adds this. It also fixes up the API to: `System: string` and `ComputeSystem: (string, error)`. NOTE: inside `System`, I still do a best-effort to avoid panic by calling `ComputeSystem`. This can happen in edge-cases like some tests `generate_test/TestWriteFromTemplate` that exercise internal functions reliant on `nix.System` without calling `devbox.Open`. ## How was it tested? tests should pass
1 parent 2710805 commit 1c4b8a9

File tree

12 files changed

+34
-67
lines changed

12 files changed

+34
-67
lines changed

.github/workflows/cli-tests.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ jobs:
9090
- run-devbox-json-tests: true
9191
os: macos-latest
9292
runs-on: ${{ matrix.os }}
93-
timeout-minutes: ${{ (github.ref == 'refs/heads/main' || inputs.run-mac-tests) && 37 || 20 }}
93+
timeout-minutes: ${{ (github.ref == 'refs/heads/main' || inputs.run-mac-tests) && 37 || 25 }}
9494
steps:
9595
- uses: actions/checkout@v3
9696
- uses: actions/setup-go@v4
@@ -119,7 +119,7 @@ jobs:
119119
DEVBOX_DEBUG: ${{ (!matrix.run-devbox-json-tests || inputs.example-debug) && '1' || '0' }}
120120
DEVBOX_RUN_DEVBOX_JSON_TESTS: ${{ matrix.run-devbox-json-tests }}
121121
# Used in `go test -timeout` flag. Needs a value that time.ParseDuration can parse.
122-
DEVBOX_GOLANG_TEST_TIMEOUT: "${{ (github.ref == 'refs/heads/main' || inputs.run-mac-tests) && '35m' || '20m' }}"
122+
DEVBOX_GOLANG_TEST_TIMEOUT: "${{ (github.ref == 'refs/heads/main' || inputs.run-mac-tests) && '35m' || '25m' }}"
123123
run: |
124124
echo "::group::Nix version"
125125
nix --version

internal/devconfig/packages.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ func NewPackage(name string, values map[string]any) Package {
249249
// If the package has a list of excluded platforms, it is enabled on all platforms
250250
// except those.
251251
func (p *Package) IsEnabledOnPlatform() bool {
252-
platform := nix.MustGetSystem()
252+
platform := nix.System()
253253
if len(p.Platforms) > 0 {
254254
for _, plt := range p.Platforms {
255255
if plt == platform {

internal/devpkg/package.go

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,8 @@ func (p *Package) NormalizedDevboxPackageReference() (string, error) {
227227
}
228228

229229
if path != "" {
230-
s, err := nix.System()
231-
if err != nil {
232-
return "", err
233-
}
234230
url, fragment, _ := strings.Cut(path, "#")
235-
return fmt.Sprintf("%s#legacyPackages.%s.%s", url, s, fragment), nil
231+
return fmt.Sprintf("%s#legacyPackages.%s.%s", url, nix.System(), fragment), nil
236232
}
237233

238234
return "", nil
@@ -480,17 +476,12 @@ func (p *Package) IsInBinaryCache() (bool, error) {
480476
return false, err
481477
}
482478

483-
userSystem, err := nix.System()
484-
if err != nil {
485-
return false, err
486-
}
487-
488479
if entry.Systems == nil {
489480
return false, nil
490481
}
491482

492483
// Check if the user's system's info is present in the lockfile
493-
_, ok := entry.Systems[userSystem]
484+
_, ok := entry.Systems[nix.System()]
494485
if !ok {
495486
return false, nil
496487
}
@@ -519,12 +510,7 @@ func (p *Package) InputAddressedPath() (string, error) {
519510
return "", err
520511
}
521512

522-
userSystem, err := nix.System()
523-
if err != nil {
524-
return "", err
525-
}
526-
527-
sysInfo := entry.Systems[userSystem]
513+
sysInfo := entry.Systems[nix.System()]
528514
return sysInfo.StorePath, nil
529515
}
530516

internal/impl/devbox.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ type Devbox struct {
7373
var legacyPackagesWarningHasBeenShown = false
7474

7575
func Open(opts *devopt.Opts) (*Devbox, error) {
76+
7677
projectDir, err := findProjectDir(opts.Dir)
7778
if err != nil {
7879
return nil, err
@@ -128,6 +129,10 @@ func Open(opts *devopt.Opts) (*Devbox, error) {
128129
)
129130
}
130131

132+
if err := nix.EnsureNixInstalled(box.writer, func() *bool { return nil } /*withDaemonFunc*/); err != nil {
133+
return nil, err
134+
}
135+
131136
return box, nil
132137
}
133138

internal/impl/update.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,12 @@ func (d *Devbox) mergeResolvedPackageToLockfile(
126126

127127
// Add any missing system infos for packages whose versions did not change.
128128
if featureflag.RemoveNixpkgs.Enabled() {
129-
userSystem, err := nix.System()
130-
if err != nil {
131-
return err
132-
}
133129

134130
if lockfile.Packages[pkg.Raw].Systems == nil {
135131
lockfile.Packages[pkg.Raw].Systems = map[string]*lock.SystemInfo{}
136132
}
137133

134+
userSystem := nix.System()
138135
updated := false
139136
for sysName, newSysInfo := range resolved.Systems {
140137
if sysName == userSystem {

internal/impl/update_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,7 @@ func TestUpdateOtherSysInfoIsReplaced(t *testing.T) {
156156
require.Equal(t, "store_path2", lockfile.Packages[raw].Systems[sys2].StorePath)
157157
}
158158

159-
func currentSystem(t *testing.T) string {
160-
sys, err := nix.System() // NOTE: we could mock this too, if it helps.
161-
require.NoError(t, err)
159+
func currentSystem(_t *testing.T) string {
160+
sys := nix.System() // NOTE: we could mock this too, if it helps.
162161
return sys
163162
}

internal/lock/resolve.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,7 @@ func (f *File) FetchResolvedPackage(pkg string) (*Package, error) {
6161
}
6262

6363
func selectForSystem(pkg *searcher.PackageVersion) (searcher.PackageInfo, error) {
64-
currentSystem, err := nix.System()
65-
if err != nil {
66-
return searcher.PackageInfo{}, err
67-
}
68-
if pi, ok := pkg.Systems[currentSystem]; ok {
64+
if pi, ok := pkg.Systems[nix.System()]; ok {
6965
return pi, nil
7066
}
7167
if pi, ok := pkg.Systems["x86_64-linux"]; ok {

internal/nix/install.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,9 @@ func isRoot() bool {
9898
func EnsureNixInstalled(writer io.Writer, withDaemonFunc func() *bool) (err error) {
9999
defer func() {
100100
if err == nil {
101-
// call System to ensure its value is internally cached so we can rely on MustGetSystem
102-
_, err = System()
101+
// call ComputeSystem to ensure its value is internally cached so other
102+
// callers can rely on just calling System
103+
err = ComputeSystem()
103104
}
104105
}()
105106

internal/nix/nix.go

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -118,44 +118,42 @@ func ExperimentalFlags() []string {
118118
}
119119
}
120120

121-
// TODO: rename to System
122-
func MustGetSystem() string {
121+
func System() string {
123122
if cachedSystem == "" {
124-
// For internal calls (during tests), this may not be initialized properly
125-
// so do a best-effort attempt to initialize it.
126-
_, err := System()
127-
if err != nil {
128-
panic("MustGetSystem called before being initialized by System")
123+
// While this should have been initialized, we do a best-effort to avoid
124+
// a panic.
125+
if err := ComputeSystem(); err != nil {
126+
panic("System called before being initialized by ComputeSystem")
129127
}
130128
}
131129
return cachedSystem
132130
}
133131

134132
var cachedSystem string
135133

136-
// TODO: rename to ComputeSystem or ComputePlatform?
137-
func System() (string, error) {
134+
func ComputeSystem() error {
138135
// For Savil to debug "remove nixpkgs" feature. The Search api lacks x86-darwin info.
139136
// So, I need to fake that I am x86-linux and inspect the output in generated devbox.lock
140137
// and flake.nix files.
141138
// This is also used by unit tests.
139+
if cachedSystem != "" {
140+
return nil
141+
}
142142
override := os.Getenv("__DEVBOX_NIX_SYSTEM")
143143
if override != "" {
144-
return override, nil
145-
}
146-
147-
if cachedSystem == "" {
144+
cachedSystem = override
145+
} else {
148146
cmd := exec.Command(
149147
"nix", "eval", "--impure", "--raw", "--expr", "builtins.currentSystem",
150148
)
151149
cmd.Args = append(cmd.Args, ExperimentalFlags()...)
152150
out, err := cmd.Output()
153151
if err != nil {
154-
return "", errors.WithStack(err)
152+
return err
155153
}
156154
cachedSystem = string(out)
157155
}
158-
return cachedSystem, nil
156+
return nil
159157
}
160158

161159
// version is the cached output of `nix --version`.

internal/nix/nixprofile/profile.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,7 @@ func ProfileInstall(args *ProfileInstallArgs) error {
265265
if exists, err := input.ValidateInstallsOnSystem(); err != nil {
266266
return err
267267
} else if !exists {
268-
platform, err := nix.System()
269-
if err != nil {
270-
platform = ""
271-
} else {
272-
platform = " " + platform
273-
}
268+
platform := " " + nix.System()
274269
return usererr.New(
275270
"package %s cannot be installed on your platform%s. "+
276271
"Run `devbox add %[1]s --exclude-platform%[2]s` and re-try.",

0 commit comments

Comments
 (0)