Skip to content

Commit 659ddf7

Browse files
committed
move out of nix.Search, and rename to SearchNixpkgsAttribute
1 parent 350afdf commit 659ddf7

File tree

2 files changed

+39
-16
lines changed

2 files changed

+39
-16
lines changed

internal/devpkg/package.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,25 @@ func (p *Package) NormalizedPackageAttributePath() (string, error) {
284284
return p.normalizedPackageAttributePathCache, nil
285285
}
286286

287+
// search attempts to find the package in the local nixpkgs. It may be an expensive
288+
// call, if it is has not been cached.
289+
func (p *Package) search(query string) (map[string]*nix.Info, error) {
290+
if p.IsDevboxPackage() {
291+
if strings.HasPrefix(query, "runx:") {
292+
// TODO implement runx search
293+
return map[string]*nix.Info{}, nil
294+
}
295+
// This will be slow if its the first time on the user's machine that this
296+
// query is running. Otherwise, it will be cached and fast.
297+
return nix.SearchNixpkgsAttribute(query)
298+
}
299+
300+
// fallback to the slow but generalized nix.Search
301+
return nix.Search(query)
302+
}
303+
287304
// normalizePackageAttributePath calls nix search to find the normalized attribute
288-
// path. It is an expensive call (~100ms).
305+
// path. It may be an expensive call (~100ms).
289306
func (p *Package) normalizePackageAttributePath() (string, error) {
290307
var query string
291308
if p.IsDevboxPackage() {
@@ -302,9 +319,9 @@ func (p *Package) normalizePackageAttributePath() (string, error) {
302319
query = p.String()
303320
}
304321

305-
// We prefer search over just trying to parse the URL because search will
322+
// We prefer search over just trying to parse the package's "URL" because search will
306323
// guarantee that the package exists for the current system.
307-
infos, err := nix.Search(query)
324+
infos, err := p.search(query)
308325
if err != nil {
309326
return "", err
310327
}

internal/nix/search.go

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"os"
88
"os/exec"
99
"path/filepath"
10-
"strings"
1110

1211
"github.com/pkg/errors"
1312
"go.jetpack.io/devbox/internal/debug"
@@ -33,11 +32,7 @@ func (i *Info) String() string {
3332
}
3433

3534
func Search(url string) (map[string]*Info, error) {
36-
if strings.HasPrefix(url, "runx:") {
37-
// TODO implement runx search
38-
return map[string]*Info{}, nil
39-
}
40-
return searchSystemUsingCache(url, "")
35+
return searchSystem(url, "" /* system */)
4136
}
4237

4338
func parseSearchResults(data []byte) map[string]*Info {
@@ -110,21 +105,27 @@ func searchSystem(url, system string) (map[string]*Info, error) {
110105
return parseSearchResults(out), nil
111106
}
112107

108+
// searchSystemCache is a machine-wide cache of search results. It is shared by all
109+
// Devbox projects on the current machine. It is stored in the XDG cache directory.
113110
type searchSystemCache struct {
114111
QueryToInfo map[string]map[string]*Info `json:"query_to_info"`
115112
}
116113

117114
const (
115+
// searchSystemCacheSubDir is a sub-directory of the XDG cache directory
118116
searchSystemCacheSubDir = "devbox/nix"
119117
searchSystemCacheFileName = "search-system-cache.json"
120118
)
121119

122120
var cache = searchSystemCache{}
123121

124-
func searchSystemUsingCache(url, system string) (map[string]*Info, error) {
125-
if system != "" {
126-
return searchSystem(url, system)
127-
}
122+
// SearchNixpkgsAttribute is a wrapper around searchSystem that caches results.
123+
// NOTE: we should be very conservative in where we use this function. `nix search`
124+
// accepts generalized `installable regex` as arguments but is slow. For certain
125+
// queries of the form `nixpkgs/<commit-hash>#attribute`, we can know for sure that
126+
// once `nix search` returns a valid result, it will always be the very same result.
127+
// Hence we can cache it locally and answer future queries fast, by not calling `nix search`.
128+
func SearchNixpkgsAttribute(query string) (map[string]*Info, error) {
128129

129130
if cache.QueryToInfo == nil {
130131
contents, err := readSearchSystemCacheFile()
@@ -134,16 +135,16 @@ func searchSystemUsingCache(url, system string) (map[string]*Info, error) {
134135
cache.QueryToInfo = contents
135136
}
136137

137-
if result := cache.QueryToInfo[url]; result != nil {
138+
if result := cache.QueryToInfo[query]; result != nil {
138139
return result, nil
139140
}
140141

141-
info, err := searchSystem(url, system)
142+
info, err := searchSystem(query, "" /*system*/)
142143
if err != nil {
143144
return nil, err
144145
}
145146

146-
cache.QueryToInfo[url] = info
147+
cache.QueryToInfo[query] = info
147148
if err := writeSearchSystemCacheFile(cache.QueryToInfo); err != nil {
148149
return nil, err
149150
}
@@ -155,10 +156,12 @@ func readSearchSystemCacheFile() (map[string]map[string]*Info, error) {
155156
contents, err := os.ReadFile(xdg.CacheSubpath(filepath.Join(searchSystemCacheSubDir, searchSystemCacheFileName)))
156157
if err != nil {
157158
if os.IsNotExist(err) {
159+
// If the file doesn't exist, return an empty map. This will hopefully be filled and written to disk later.
158160
return make(map[string]map[string]*Info), nil
159161
}
160162
return nil, err
161163
}
164+
162165
var result map[string]map[string]*Info
163166
if err := json.Unmarshal(contents, &result); err != nil {
164167
return nil, err
@@ -167,17 +170,20 @@ func readSearchSystemCacheFile() (map[string]map[string]*Info, error) {
167170
}
168171

169172
func writeSearchSystemCacheFile(contents map[string]map[string]*Info) error {
173+
// Print as a human-readable JSON file i.e. use nice indentation and newlines.
170174
buf := bytes.Buffer{}
171175
enc := json.NewEncoder(&buf)
172176
enc.SetIndent("", " ")
173177
err := enc.Encode(contents)
174178
if err != nil {
175179
return err
176180
}
181+
177182
dir := xdg.CacheSubpath(searchSystemCacheSubDir)
178183
if err := os.MkdirAll(dir, 0o755); err != nil {
179184
return err
180185
}
186+
181187
path := filepath.Join(dir, searchSystemCacheFileName)
182188
return os.WriteFile(path, buf.Bytes(), 0o644)
183189
}

0 commit comments

Comments
 (0)