7
7
"os"
8
8
"os/exec"
9
9
"path/filepath"
10
- "strings"
11
10
12
11
"github.com/pkg/errors"
13
12
"go.jetpack.io/devbox/internal/debug"
@@ -33,11 +32,7 @@ func (i *Info) String() string {
33
32
}
34
33
35
34
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 */ )
41
36
}
42
37
43
38
func parseSearchResults (data []byte ) map [string ]* Info {
@@ -110,21 +105,27 @@ func searchSystem(url, system string) (map[string]*Info, error) {
110
105
return parseSearchResults (out ), nil
111
106
}
112
107
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.
113
110
type searchSystemCache struct {
114
111
QueryToInfo map [string ]map [string ]* Info `json:"query_to_info"`
115
112
}
116
113
117
114
const (
115
+ // searchSystemCacheSubDir is a sub-directory of the XDG cache directory
118
116
searchSystemCacheSubDir = "devbox/nix"
119
117
searchSystemCacheFileName = "search-system-cache.json"
120
118
)
121
119
122
120
var cache = searchSystemCache {}
123
121
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 ) {
128
129
129
130
if cache .QueryToInfo == nil {
130
131
contents , err := readSearchSystemCacheFile ()
@@ -134,16 +135,16 @@ func searchSystemUsingCache(url, system string) (map[string]*Info, error) {
134
135
cache .QueryToInfo = contents
135
136
}
136
137
137
- if result := cache .QueryToInfo [url ]; result != nil {
138
+ if result := cache .QueryToInfo [query ]; result != nil {
138
139
return result , nil
139
140
}
140
141
141
- info , err := searchSystem (url , system )
142
+ info , err := searchSystem (query , "" /* system*/ )
142
143
if err != nil {
143
144
return nil , err
144
145
}
145
146
146
- cache .QueryToInfo [url ] = info
147
+ cache .QueryToInfo [query ] = info
147
148
if err := writeSearchSystemCacheFile (cache .QueryToInfo ); err != nil {
148
149
return nil , err
149
150
}
@@ -155,10 +156,12 @@ func readSearchSystemCacheFile() (map[string]map[string]*Info, error) {
155
156
contents , err := os .ReadFile (xdg .CacheSubpath (filepath .Join (searchSystemCacheSubDir , searchSystemCacheFileName )))
156
157
if err != nil {
157
158
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.
158
160
return make (map [string ]map [string ]* Info ), nil
159
161
}
160
162
return nil , err
161
163
}
164
+
162
165
var result map [string ]map [string ]* Info
163
166
if err := json .Unmarshal (contents , & result ); err != nil {
164
167
return nil , err
@@ -167,17 +170,20 @@ func readSearchSystemCacheFile() (map[string]map[string]*Info, error) {
167
170
}
168
171
169
172
func writeSearchSystemCacheFile (contents map [string ]map [string ]* Info ) error {
173
+ // Print as a human-readable JSON file i.e. use nice indentation and newlines.
170
174
buf := bytes.Buffer {}
171
175
enc := json .NewEncoder (& buf )
172
176
enc .SetIndent ("" , " " )
173
177
err := enc .Encode (contents )
174
178
if err != nil {
175
179
return err
176
180
}
181
+
177
182
dir := xdg .CacheSubpath (searchSystemCacheSubDir )
178
183
if err := os .MkdirAll (dir , 0o755 ); err != nil {
179
184
return err
180
185
}
186
+
181
187
path := filepath .Join (dir , searchSystemCacheFileName )
182
188
return os .WriteFile (path , buf .Bytes (), 0o644 )
183
189
}
0 commit comments