Skip to content

Commit 4004501

Browse files
committed
Packages: unifies Nix package detection code
Fixes: #1893
1 parent a0265c3 commit 4004501

File tree

5 files changed

+212
-229
lines changed

5 files changed

+212
-229
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ if(LINUX)
547547
src/detection/opengl/opengl_linux.c
548548
src/detection/os/os_linux.c
549549
src/detection/packages/packages_linux.c
550+
src/detection/packages/packages_nix.c
550551
src/detection/poweradapter/poweradapter_linux.c
551552
src/detection/processes/processes_linux.c
552553
src/detection/gtk_qt/qt.c
@@ -939,6 +940,7 @@ elseif(APPLE)
939940
src/detection/opengl/opengl_apple.c
940941
src/detection/os/os_apple.m
941942
src/detection/packages/packages_apple.c
943+
src/detection/packages/packages_nix.c
942944
src/detection/poweradapter/poweradapter_apple.c
943945
src/detection/processes/processes_bsd.c
944946
src/detection/sound/sound_apple.c

src/detection/packages/packages.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ const char* ffDetectPackages(FFPackagesResult* result, FFPackagesOptions* option
5555
bool ffPackagesReadCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, const char* filePath, const char* packageId, uint32_t* result);
5656
bool ffPackagesWriteCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, uint32_t num_elements);
5757

58+
#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__APPLE__)
59+
uint32_t ffPackagesGetNix(FFstrbuf* baseDir, const char* dirname);
60+
#endif
5861
#ifndef _WIN32
5962
uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir);
6063
#endif

src/detection/packages/packages_apple.c

Lines changed: 47 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -4,91 +4,66 @@
44
#include "common/processing.h"
55
#include "util/stringUtils.h"
66

7-
static void countBrewPackages(const char* dirname, FFPackagesResult* result)
7+
static void countBrewPackages(FFstrbuf* baseDir, FFPackagesResult* result)
88
{
9-
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(dirname);
109

11-
uint32_t baseDirLength = baseDir.length;
12-
13-
ffStrbufAppendS(&baseDir, "/Caskroom");
14-
result->brewCask += ffPackagesGetNumElements(baseDir.chars, true);
15-
ffStrbufSubstrBefore(&baseDir, baseDirLength);
16-
17-
ffStrbufAppendS(&baseDir, "/Cellar");
18-
result->brew += ffPackagesGetNumElements(baseDir.chars, true);
19-
ffStrbufSubstrBefore(&baseDir, baseDirLength);
20-
}
21-
22-
static void getBrewPackages(FFPackagesResult* result)
23-
{
24-
const char* prefix = getenv("HOMEBREW_PREFIX");
25-
if(ffStrSet(prefix))
26-
return countBrewPackages(prefix, result);
27-
28-
countBrewPackages(FASTFETCH_TARGET_DIR_ROOT "/opt/homebrew", result);
29-
countBrewPackages(FASTFETCH_TARGET_DIR_USR "/local", result);
30-
}
31-
32-
static uint32_t countMacPortsPackages(const char* dirname)
33-
{
34-
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(dirname);
35-
ffStrbufAppendS(&baseDir, "/var/macports/software");
36-
37-
return ffPackagesGetNumElements(baseDir.chars, true);
38-
}
39-
40-
static uint32_t getMacPortsPackages()
41-
{
42-
const char* prefix = getenv("MACPORTS_PREFIX");
43-
if(ffStrSet(prefix))
44-
return countMacPortsPackages(prefix);
45-
46-
return countMacPortsPackages(FASTFETCH_TARGET_DIR_ROOT "/opt/local");
47-
}
48-
49-
static uint32_t getNixPackagesImpl(const char* path)
50-
{
51-
//Nix detection is kinda slow, so we only do it if the dir exists
52-
if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY))
53-
return 0;
54-
55-
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(128);
56-
57-
//https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222
58-
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(255);
59-
ffStrbufAppendS(&command, "for x in $(nix-store --query --requisites ");
60-
ffStrbufAppendS(&command, path);
61-
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");
10+
uint32_t baseDirLength = baseDir->length;
6211

63-
ffProcessAppendStdOut(&output, (char* const[]) {
64-
FASTFETCH_TARGET_DIR_ROOT "/bin/sh",
65-
"-c",
66-
command.chars,
67-
NULL
68-
});
12+
ffStrbufAppendS(baseDir, "/Caskroom");
13+
result->brewCask += ffPackagesGetNumElements(baseDir->chars, true);
14+
ffStrbufSubstrBefore(baseDir, baseDirLength);
6915

70-
return (uint32_t) strtoul(output.chars, NULL, 10);
16+
ffStrbufAppendS(baseDir, "/Cellar");
17+
result->brew += ffPackagesGetNumElements(baseDir->chars, true);
18+
ffStrbufSubstrBefore(baseDir, baseDirLength);
7119
}
7220

73-
static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname)
21+
static uint32_t getMacPortsPackages(FFstrbuf* baseDir)
7422
{
75-
uint32_t baseDirLength = baseDir->length;
76-
ffStrbufAppendS(baseDir, dirname);
77-
uint32_t num_elements = getNixPackagesImpl(baseDir->chars);
78-
ffStrbufSubstrBefore(baseDir, baseDirLength);
79-
return num_elements;
23+
ffStrbufAppendS(baseDir, "/var/macports/software");
24+
return ffPackagesGetNumElements(baseDir->chars, true);
8025
}
8126

8227
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
8328
{
84-
if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT)) getBrewPackages(result);
85-
if (!(options->disabled & FF_PACKAGES_FLAG_MACPORTS_BIT)) result->macports = getMacPortsPackages();
29+
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreate();
30+
if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT))
31+
{
32+
const char* prefix = getenv("HOMEBREW_PREFIX");
33+
if (ffStrSet(prefix))
34+
{
35+
ffStrbufSetS(&baseDir, prefix);
36+
}
37+
else
38+
{
39+
#ifdef __aarch64__
40+
ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_ROOT "/opt/homebrew");
41+
#else
42+
ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_USR "/local");
43+
#endif
44+
}
45+
countBrewPackages(&baseDir, result);
46+
}
47+
if (!(options->disabled & FF_PACKAGES_FLAG_MACPORTS_BIT))
48+
{
49+
const char* prefix = getenv("MACPORTS_PREFIX");
50+
if (ffStrSet(prefix))
51+
{
52+
ffStrbufSetS(&baseDir, prefix);
53+
}
54+
else
55+
{
56+
ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_ROOT "/opt/local");
57+
}
58+
59+
result->macports = getMacPortsPackages(&baseDir);
60+
}
8661
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
8762
{
88-
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT);
89-
result->nixDefault += getNixPackages(&baseDir, "/nix/var/nix/profiles/default");
90-
result->nixSystem += getNixPackages(&baseDir, "/run/current-system");
63+
ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
64+
result->nixDefault += ffPackagesGetNix(&baseDir, "/nix/var/nix/profiles/default");
65+
result->nixSystem += ffPackagesGetNix(&baseDir, "/run/current-system");
9166
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
92-
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
67+
result->nixUser = ffPackagesGetNix(&baseDir, "/.nix-profile");
9368
}
9469
}

src/detection/packages/packages_linux.c

Lines changed: 5 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include "packages.h"
22
#include "common/io/io.h"
33
#include "common/parsing.h"
4-
#include "common/processing.h"
54
#include "common/properties.h"
65
#include "common/settings.h"
76
#include "detection/os/os.h"
@@ -124,157 +123,6 @@ static uint32_t countFilesRecursive(FFstrbuf* baseDir, const char* dirname, cons
124123
return sum;
125124
}
126125

127-
static bool isValidNixPkg(FFstrbuf* pkg)
128-
{
129-
if (!ffPathExists(pkg->chars, FF_PATHTYPE_DIRECTORY))
130-
return false;
131-
132-
ffStrbufSubstrAfterLastC(pkg, '/');
133-
if (
134-
ffStrbufStartsWithS(pkg, "nixos-system-nixos-") ||
135-
ffStrbufEndsWithS(pkg, "-doc") ||
136-
ffStrbufEndsWithS(pkg, "-man") ||
137-
ffStrbufEndsWithS(pkg, "-info") ||
138-
ffStrbufEndsWithS(pkg, "-dev") ||
139-
ffStrbufEndsWithS(pkg, "-bin")
140-
) return false;
141-
142-
enum { START, DIGIT, DOT, MATCH } state = START;
143-
144-
for (uint32_t i = 0; i < pkg->length; i++)
145-
{
146-
char c = pkg->chars[i];
147-
switch (state)
148-
{
149-
case START:
150-
if (ffCharIsDigit(c))
151-
state = DIGIT;
152-
break;
153-
case DIGIT:
154-
if (ffCharIsDigit(c))
155-
continue;
156-
if (c == '.')
157-
state = DOT;
158-
else
159-
state = START;
160-
break;
161-
case DOT:
162-
if (ffCharIsDigit(c))
163-
state = MATCH;
164-
else
165-
state = START;
166-
break;
167-
case MATCH:
168-
break;
169-
}
170-
}
171-
172-
return state == MATCH;
173-
}
174-
175-
static bool checkNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t* count)
176-
{
177-
if (!ffPathExists(cacheDir->chars, FF_PATHTYPE_FILE))
178-
return false;
179-
180-
FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreate();
181-
if (!ffReadFileBuffer(cacheDir->chars, &cacheContent))
182-
return false;
183-
184-
// Format: <hash>\n<count>
185-
uint32_t split = ffStrbufFirstIndexC(&cacheContent, '\n');
186-
if (split == cacheContent.length)
187-
return false;
188-
189-
ffStrbufSetNS(hash, split, cacheContent.chars);
190-
*count = (uint32_t)atoi(cacheContent.chars + split + 1);
191-
192-
return true;
193-
}
194-
195-
static bool writeNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t count)
196-
{
197-
FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreateCopy(hash);
198-
ffStrbufAppendF(&cacheContent, "\n%u", count);
199-
return ffWriteFileBuffer(cacheDir->chars, &cacheContent);
200-
}
201-
202-
static uint32_t getNixPackagesImpl(char* path)
203-
{
204-
//Nix detection is kinda slow, so we only do it if the dir exists
205-
if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY))
206-
return 0;
207-
208-
FF_STRBUF_AUTO_DESTROY cacheDir = ffStrbufCreateCopy(&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;
228-
229-
//Cache is invalid, recompute the count
230-
count = 0;
231-
232-
//Implementation based on bash script from here:
233-
//https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222
234-
235-
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(1024);
236-
237-
ffProcessAppendStdOut(&output, (char* const[]) {
238-
"nix-store",
239-
"--query",
240-
"--requisites",
241-
path,
242-
NULL
243-
});
244-
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;
267-
}
268-
269-
static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname)
270-
{
271-
uint32_t baseDirLength = baseDir->length;
272-
ffStrbufAppendS(baseDir, dirname);
273-
uint32_t num_elements = getNixPackagesImpl(baseDir->chars);
274-
ffStrbufSubstrBefore(baseDir, baseDirLength);
275-
return num_elements;
276-
}
277-
278126
static uint32_t getXBPSImpl(FFstrbuf* baseDir)
279127
{
280128
DIR* dir = opendir(baseDir->chars);
@@ -572,8 +420,8 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
572420
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getFlatpakPackages(baseDir, "/var/lib");
573421
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
574422
{
575-
packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default");
576-
packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system");
423+
packageCounts->nixDefault += ffPackagesGetNix(baseDir, "/nix/var/nix/profiles/default");
424+
packageCounts->nixSystem += ffPackagesGetNix(baseDir, "/run/current-system");
577425
}
578426
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", true);
579427
if (!(options->disabled & FF_PACKAGES_FLAG_LPKGBUILD_BIT)) packageCounts->lpkgbuild += getNumElements(baseDir, "/opt/Loc-OS-LPKG/lpkgbuild/remove", false);
@@ -673,7 +521,7 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
673521
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
674522
{
675523
// Count packages from $HOME/.nix-profile
676-
result->nixUser += getNixPackages(&baseDir, ".nix-profile");
524+
result->nixUser += ffPackagesGetNix(&baseDir, ".nix-profile");
677525

678526
// Check in $XDG_STATE_HOME/nix/profile
679527
FF_STRBUF_AUTO_DESTROY stateHome = ffStrbufCreate();
@@ -688,11 +536,11 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
688536
ffStrbufSet(&stateHome, &instance.state.platform.homeDir);
689537
ffStrbufAppendS(&stateHome, ".local/state/");
690538
}
691-
result->nixUser += getNixPackages(&stateHome, "nix/profile");
539+
result->nixUser += ffPackagesGetNix(&stateHome, "nix/profile");
692540

693541
// Check in /etc/profiles/per-user/$USER
694542
FF_STRBUF_AUTO_DESTROY userPkgsDir = ffStrbufCreateStatic("/etc/profiles/per-user/");
695-
result->nixUser += getNixPackages(&userPkgsDir, instance.state.platform.userName.chars);
543+
result->nixUser += ffPackagesGetNix(&userPkgsDir, instance.state.platform.userName.chars);
696544
}
697545

698546
if (!(options->disabled & FF_PACKAGES_FLAG_GUIX_BIT))

0 commit comments

Comments
 (0)