Skip to content

Commit 999f52b

Browse files
DariqqCarterLi
andauthored
Packages (Linux): Improve speed of Guix package detection. (#999)
Instead of waiting for guix to parse the manifest file of a profile parse it directly by counting "/gnu/store" entries and fitlering out duplicates. The new implementation now also accounts for propagated-inputs of packages. Co-authored-by: Carter Li <[email protected]>
1 parent eae7388 commit 999f52b

File tree

1 file changed

+26
-15
lines changed

1 file changed

+26
-15
lines changed

src/detection/packages/packages_linux.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -408,26 +408,36 @@ static uint32_t getAM(FFstrbuf* baseDir)
408408
return result;
409409
}
410410

411+
static int compareHash(const void* a, const void* b)
412+
{
413+
return memcmp(a, b, 32);
414+
}
411415

412-
static uint32_t getGuixPackagesImpl(char* path)
416+
static uint32_t getGuixPackagesImpl(char* filename)
413417
{
414-
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(1024);
418+
FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate();
419+
if (!ffAppendFileBuffer(filename, &content))
420+
return 0;
415421

416-
ffProcessAppendStdOut(&output, (char* const[]) {
417-
"guix",
418-
"package",
419-
"-p",
420-
path,
421-
"-I",
422-
NULL
423-
});
422+
// Count number of unique /gnu/store/ paths in PROFILE/manifest based on their hash value.
423+
// Contains packages explicitly installed and their propagated inputs.
424+
char* pend = content.chars;
425+
426+
for (const char* pattern = content.chars; (pattern = strstr(pattern, "/gnu/store/")); pattern += 32)
427+
{
428+
pattern += strlen("/gnu/store/");
429+
memmove(pend, pattern, 32);
430+
pend += 32;
431+
}
432+
433+
if (pend == content.chars)
434+
return 0;
424435

436+
qsort(content.chars, (size_t) (pend - content.chars) / 32, 32, compareHash);
425437

426-
//Each package is a new line in the output.
427-
// If at least one line is found, add 1 for the last line.
428-
uint32_t count = ffStrbufCountC(&output, '\n');
429-
if(count > 0)
430-
count++;
438+
uint32_t count = 1;
439+
for (const char* p = content.chars + 32; p < pend; p += 32)
440+
count += compareHash(p - 32, p) != 0;
431441

432442
return count;
433443
}
@@ -436,6 +446,7 @@ static uint32_t getGuixPackages(FFstrbuf* baseDir, const char* dirname)
436446
{
437447
uint32_t baseDirLength = baseDir->length;
438448
ffStrbufAppendS(baseDir, dirname);
449+
ffStrbufAppendS(baseDir, "/manifest");
439450
uint32_t num_elements = getGuixPackagesImpl(baseDir->chars);
440451
ffStrbufSubstrBefore(baseDir, baseDirLength);
441452
return num_elements;

0 commit comments

Comments
 (0)