@@ -118,28 +118,152 @@ static uint32_t countFilesRecursive(FFstrbuf* baseDir, const char* dirname, cons
118
118
return sum ;
119
119
}
120
120
121
+ static bool isValidNixPkg (FFstrbuf * pkg )
122
+ {
123
+ if (!ffPathExists (pkg -> chars , FF_PATHTYPE_DIRECTORY ))
124
+ return false;
125
+
126
+ ffStrbufSubstrAfterLastC (pkg , '/' );
127
+ if (
128
+ ffStrbufStartsWithS (pkg , "nixos-system-nixos-" ) ||
129
+ ffStrbufEndsWithS (pkg , "-doc" ) ||
130
+ ffStrbufEndsWithS (pkg , "-man" ) ||
131
+ ffStrbufEndsWithS (pkg , "-info" ) ||
132
+ ffStrbufEndsWithS (pkg , "-dev" ) ||
133
+ ffStrbufEndsWithS (pkg , "-bin" )
134
+ ) return false;
135
+
136
+ enum { START , DIGIT , DOT , MATCH } state = START ;
137
+
138
+ for (uint32_t i = 0 ; i < pkg -> length ; i ++ )
139
+ {
140
+ char c = pkg -> chars [i ];
141
+ switch (state )
142
+ {
143
+ case START :
144
+ if (c >= '0' && c <= '9' )
145
+ state = DIGIT ;
146
+ break ;
147
+ case DIGIT :
148
+ if (c >= '0' && c <= '9' )
149
+ continue ;
150
+ if (c == '.' )
151
+ state = DOT ;
152
+ else
153
+ state = START ;
154
+ break ;
155
+ case DOT :
156
+ if (c >= '0' && c <= '9' )
157
+ state = MATCH ;
158
+ else
159
+ state = START ;
160
+ break ;
161
+ case MATCH :
162
+ break ;
163
+ }
164
+ }
165
+
166
+ return state == MATCH ;
167
+ }
168
+
169
+ static bool checkNixCache (FFstrbuf * cacheDir , FFstrbuf * hash , uint32_t * count )
170
+ {
171
+ if (!ffPathExists (cacheDir -> chars , FF_PATHTYPE_FILE ))
172
+ return false;
173
+
174
+ FF_STRBUF_AUTO_DESTROY cacheContent ;
175
+ ffStrbufInit (& cacheContent );
176
+ if (!ffReadFileBuffer (cacheDir -> chars , & cacheContent ))
177
+ return false;
178
+
179
+ // Format: <hash>\n<count>
180
+ uint32_t split = ffStrbufFirstIndexC (& cacheContent , '\n' );
181
+ if (split == cacheContent .length )
182
+ return false;
183
+
184
+ ffStrbufSetNS (hash , split , cacheContent .chars );
185
+ * count = (uint32_t )atoi (cacheContent .chars + split + 1 );
186
+
187
+ return true;
188
+ }
189
+
190
+ static bool writeNixCache (FFstrbuf * cacheDir , FFstrbuf * hash , uint32_t count )
191
+ {
192
+ FF_STRBUF_AUTO_DESTROY cacheContent ;
193
+ ffStrbufInit (& cacheContent );
194
+ ffStrbufAppend (& cacheContent , hash );
195
+ ffStrbufAppendC (& cacheContent , '\n' );
196
+ ffStrbufAppendF (& cacheContent , "%u" , count );
197
+ return ffWriteFileBuffer (cacheDir -> chars , & cacheContent );
198
+ }
199
+
121
200
static uint32_t getNixPackagesImpl (char * path )
122
201
{
123
202
//Nix detection is kinda slow, so we only do it if the dir exists
124
203
if (!ffPathExists (path , FF_PATHTYPE_DIRECTORY ))
125
204
return 0 ;
126
205
127
- FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA (128 );
206
+ FF_STRBUF_AUTO_DESTROY cacheDir ;
207
+ ffStrbufInit (& cacheDir );
208
+ ffStrbufAppend (& cacheDir , & instance .state .platform .cacheDir );
209
+ ffStrbufEnsureEndsWithC (& cacheDir , '/' );
210
+ ffStrbufAppendS (& cacheDir , "fastfetch/packages/nix" );
211
+ ffStrbufAppendS (& cacheDir , path );
212
+
213
+ //Check the hash first to determine if we need to recompute the count
214
+ FF_STRBUF_AUTO_DESTROY hash = ffStrbufCreateA (64 );
215
+ FF_STRBUF_AUTO_DESTROY cacheHash = ffStrbufCreateA (64 );
216
+ uint32_t count = 0 ;
217
+
218
+ ffProcessAppendStdOut (& hash , (char * const []) {
219
+ "nix-store" ,
220
+ "--query" ,
221
+ "--hash" ,
222
+ path ,
223
+ NULL
224
+ });
225
+
226
+ if (checkNixCache (& cacheDir , & cacheHash , & count ) && ffStrbufEqual (& hash , & cacheHash ))
227
+ return count ;
128
228
229
+ //Cache is invalid, recompute the count
230
+ count = 0 ;
231
+
232
+ //Implementation based on bash script from here:
129
233
//https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222
130
- FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA (255 );
131
- ffStrbufAppendS (& command , "for x in $(nix-store --query --requisites " );
132
- ffStrbufAppendS (& command , path );
133
- ffStrbufAppendS (& command , "); do if [ -d $x ]; then echo $x ; fi ; done | cut -d- -f2- | egrep '([0-9]{1,}\\.)+[0-9]{1,}' | egrep -v '\\-doc$|\\-man$|\\-info$|\\-dev$|\\-bin$|^nixos-system-nixos-' | uniq | wc -l" );
234
+
235
+ FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA (1024 );
134
236
135
237
ffProcessAppendStdOut (& output , (char * const []) {
136
- "sh" ,
137
- "-c" ,
138
- command .chars ,
238
+ "nix-store" ,
239
+ "--query" ,
240
+ "--requisites" ,
241
+ path ,
139
242
NULL
140
243
});
141
244
142
- return (uint32_t ) strtol (output .chars , NULL , 10 );
245
+ uint32_t lineLength = 0 ;
246
+ for (uint32_t i = 0 ; i < output .length ; i ++ )
247
+ {
248
+ if (output .chars [i ] != '\n' )
249
+ {
250
+ lineLength ++ ;
251
+ continue ;
252
+ }
253
+
254
+ output .chars [i ] = '\0' ;
255
+ FFstrbuf line = {
256
+ .allocated = 0 ,
257
+ .length = lineLength ,
258
+ .chars = output .chars + i - lineLength
259
+ };
260
+ if (isValidNixPkg (& line ))
261
+ count ++ ;
262
+ lineLength = 0 ;
263
+ }
264
+
265
+ writeNixCache (& cacheDir , & hash , count );
266
+ return count ;
143
267
}
144
268
145
269
static uint32_t getNixPackages (FFstrbuf * baseDir , const char * dirname )
0 commit comments