Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/detection/packages/packages.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#pragma once

#include "common/processing.h"
#include "fastfetch.h"
#include "modules/packages/option.h"

typedef struct FFPackagesResult
{
typedef struct FFPackagesResult {
uint32_t amSystem;
uint32_t amUser;
uint32_t apk;
Expand Down Expand Up @@ -47,7 +47,7 @@ typedef struct FFPackagesResult
uint32_t winget;
uint32_t xbps;

uint32_t all; //Make sure this goes last
uint32_t all; // Make sure this goes last

FFstrbuf pacmanBranch;
} FFPackagesResult;
Expand All @@ -57,7 +57,17 @@ bool ffPackagesReadCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, const char*
bool ffPackagesWriteCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, uint32_t num_elements);

#if defined(__linux__) || defined(__APPLE__) || defined(__GNU__)
void getNixPackagesMultiImpl(char* paths[], uint32_t counts[], FFProcessHandle handle[], uint8_t length);
uint32_t ffPackagesGetNix(FFstrbuf* baseDir, const char* dirname);
#define ffPackagesGetNixMulti(dirs, counts, N) \
do { \
FFProcessHandle _handles[N]; \
char* _paths[N]; \
for (uint8_t i = 0; i < N; i++) { \
_paths[i] = dirs[i]->chars; \
} \
Comment on lines +62 to +68
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent formatting with extra spaces. The macro definition should have consistent spacing. Consider aligning the backslashes at a consistent column or removing extra spaces between tokens.

Suggested change
#define ffPackagesGetNixMulti(dirs, counts, N) \
do { \
FFProcessHandle _handles[N]; \
char* _paths[N]; \
for (uint8_t i = 0; i < N; i++) { \
_paths[i] = dirs[i]->chars; \
} \
#define ffPackagesGetNixMulti(dirs, counts, N) \
do { \
FFProcessHandle _handles[N]; \
char* _paths[N]; \
for (uint8_t i = 0; i < N; i++) { \
_paths[i] = dirs[i]->chars; \
} \

Copilot uses AI. Check for mistakes.
getNixPackagesMultiImpl(_paths, counts, _handles, N); \
} while (0)
#endif
#ifndef _WIN32
uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir);
Expand Down
20 changes: 16 additions & 4 deletions src/detection/packages/packages_apple.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
#include "common/io/io.h"
#include "common/parsing.h"
#include "common/processing.h"
#include "util/FFstrbuf.h"
#include "util/stringUtils.h"
#include <stdint.h>

static void countBrewPackages(FFstrbuf* baseDir, FFPackagesResult* result)
{
Expand Down Expand Up @@ -61,9 +63,19 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
{
ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
result->nixDefault += ffPackagesGetNix(&baseDir, "/nix/var/nix/profiles/default");
result->nixSystem += ffPackagesGetNix(&baseDir, "/run/current-system");
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
result->nixUser = ffPackagesGetNix(&baseDir, "/.nix-profile");
ffStrbufAppendS(&baseDir, "/nix/var/nix/profiles/default");

FF_STRBUF_AUTO_DESTROY dir2 = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT);
ffStrbufAppendS(&dir2, "/run/current-system");

FF_STRBUF_AUTO_DESTROY dir3 = ffStrbufCreateCopy(&instance.state.platform.homeDir);
ffStrbufAppendS(&dir3, "/.nix-profile");

FFstrbuf* dirs[] = {&baseDir, &dir2, &dir3};
uint32_t counts[3] = {0};
ffPackagesGetNixMulti(dirs, counts, 3);
result->nixDefault = counts[0];
result->nixSystem = counts[1];
result->nixUser = counts[2];
}
}
48 changes: 48 additions & 0 deletions src/detection/packages/packages_nix.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "common/io/io.h"
#include "common/processing.h"
#include "util/stringUtils.h"
#include <stdint.h>

static bool isValidNixPkg(FFstrbuf* pkg)
{
Expand Down Expand Up @@ -51,6 +52,53 @@ static bool isValidNixPkg(FFstrbuf* pkg)
return state == MATCH;
}

void getNixPackagesMultiImpl(char* paths[], uint32_t counts[], FFProcessHandle handle[], uint8_t length)
{
//Implementation based on bash script from here:
//https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222
// no need to use hash, it is not faster
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment has inconsistent spacing. Should have two spaces after '//' to match the project's comment style as seen in line 62.

Suggested change
// no need to use hash, it is not faster
// no need to use hash, it is not faster

Copilot uses AI. Check for mistakes.
for (uint8_t i = 0; i < length; i++){
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after closing brace in for loop. Should be for (uint8_t i = 0; i < length; i++) { to be consistent with the project's coding style seen in line 73 and throughout the codebase.

Copilot uses AI. Check for mistakes.
handle[i].pid = 0;
// Nix detection is kinda slow, so we only do it if the dir exists
if(ffPathExists(paths[i], FF_PATHTYPE_DIRECTORY)){
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect spacing in if statement. Should have a space after 'if' to match the project's coding style as seen in line 75 and throughout the codebase. Should be if (ffPathExists(paths[i], FF_PATHTYPE_DIRECTORY)) {.

Suggested change
if(ffPathExists(paths[i], FF_PATHTYPE_DIRECTORY)){
if (ffPathExists(paths[i], FF_PATHTYPE_DIRECTORY)) {

Copilot uses AI. Check for mistakes.
ffProcessSpawn((char* const[]) {
"nix-store",
"--query",
"--requisites",
paths[i],
NULL
}, false, &handle[i]);
Comment on lines +64 to +70
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value of ffProcessSpawn is not checked for errors. According to the function signature in processing.h, this function returns a const char* error message that should be checked. If the process fails to spawn, handle[i].pid might still be set to a non-zero value (depending on implementation), leading to attempts to read output from a non-existent process. The error should be checked and if non-null, handle[i].pid should remain 0.

Suggested change
ffProcessSpawn((char* const[]) {
"nix-store",
"--query",
"--requisites",
paths[i],
NULL
}, false, &handle[i]);
const char* error = ffProcessSpawn((char* const[]) {
"nix-store",
"--query",
"--requisites",
paths[i],
NULL
}, false, &handle[i]);
if (error != NULL)
handle[i].pid = 0;

Copilot uses AI. Check for mistakes.
}
}
for (uint8_t i = 0; i < length; i++){
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after closing brace in for loop. Should be for (uint8_t i = 0; i < length; i++) { to be consistent with the project's coding style.

Copilot uses AI. Check for mistakes.
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(1024);
if (!handle[i].pid){
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect spacing in if statement. Should have a space after 'if' to match the project's coding style. Should be if (!handle[i].pid) {.

Suggested change
if (!handle[i].pid){
if (!handle[i].pid) {

Copilot uses AI. Check for mistakes.
counts[i] = 0;
continue;
}
ffProcessReadOutput(&handle[i], &output);
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value of ffProcessReadOutput is not checked for errors. According to the function signature in processing.h, this function returns a const char* error message that should be checked. If the process fails or returns an error, the output buffer may be incomplete or invalid, leading to incorrect package counts. The error should be checked and handled appropriately.

Suggested change
ffProcessReadOutput(&handle[i], &output);
const char* error = ffProcessReadOutput(&handle[i], &output);
if (error != NULL)
{
counts[i] = 0;
continue;
}

Copilot uses AI. Check for mistakes.
uint32_t lineLength = 0;
for (uint32_t j = 0; j < output.length; j++)
{
if (output.chars[j] != '\n')
{
lineLength++;
continue;
}

output.chars[j] = '\0';
FFstrbuf line = {
.allocated = 0,
.length = lineLength,
.chars = output.chars + j - lineLength
};
if (isValidNixPkg(&line))
counts[i] += 1;
lineLength = 0;
}
}
}

static bool checkNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t* count)
{
if (!ffPathExists(cacheDir->chars, FF_PATHTYPE_FILE))
Expand Down