Packages: add ability to disable specified package manager

Fix #729
This commit is contained in:
李通洲 2024-02-21 15:56:52 +08:00
parent 4e9ee9aa03
commit 15bb5bfb24
No known key found for this signature in database
GPG Key ID: 269AD4F5325A22A3
8 changed files with 208 additions and 80 deletions

View File

@ -1469,10 +1469,10 @@
"const": "packages",
"description": "List installed package managers and count of installed packages"
},
"winget": {
"description": "Set if winget package count should be detected.\nNote this is very slow operation. Please make sure `winget list` works before enable this option\nWindows only",
"type": "boolean",
"default": false
"disabled": {
"description": "A colon separated list of package managers to be disabled when detecting",
"type": "string",
"default": "winget"
},
"key": {
"$ref": "#/$defs/key"

View File

@ -1013,17 +1013,16 @@
}
},
{
"long": "packages-winget",
"desc": "Set if winget package count should be detected",
"long": "packages-disabled",
"desc": "A colon separated list of package managers to be disabled when detecting",
"remark": [
"This option is extremely slow.",
"Some detection methods can be very slow.",
"You may need to increase value of '--processing-timeout' to make it actually work.",
"Windows only"
"Use `--packages-disabled none` to enable all."
],
"arg": {
"type": "bool",
"optional": true,
"default": false
"type": "string",
"default": "winget"
}
},
{

View File

@ -99,14 +99,16 @@ static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname)
return num_elements;
}
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
{
getBrewPackages(result);
result->macports = getMacPortsPackages();
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT);
result->nixDefault += getNixPackages(&baseDir, "/nix/var/nix/profiles/default");
result->nixSystem += getNixPackages(&baseDir, "/run/current-system");
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT)) getBrewPackages(result);
if (!(options->disabled & FF_PACKAGES_FLAG_MACPORTS_BIT)) result->macports = getMacPortsPackages();
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT);
result->nixDefault += getNixPackages(&baseDir, "/nix/var/nix/profiles/default");
result->nixSystem += getNixPackages(&baseDir, "/run/current-system");
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
}
}

View File

@ -4,5 +4,6 @@
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
{
result->pkg = (uint32_t) ffSettingsGetSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg/local.sqlite", "SELECT count(*) FROM packages");
if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT))
result->pkg = (uint32_t) ffSettingsGetSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg/local.sqlite", "SELECT count(*) FROM packages");
}

View File

@ -253,38 +253,47 @@ static uint32_t getRpmFromLibrpm(void)
#endif //FF_HAVE_RPM
static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts)
static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
{
packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q");
packageCounts->dpkg += getNumStrings(baseDir, "/var/lib/dpkg/status", "Status: install ok installed");
packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE");
packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", DT_DIR);
packageCounts->flatpakSystem += getFlatpak(baseDir, "/var/lib/flatpak");
packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default");
packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system");
packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", DT_DIR);
packageCounts->pkgtool += getNumElements(baseDir, "/var/log/packages", DT_REG);
packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(*) FROM Packages");
packageCounts->snap += getSnap(baseDir);
packageCounts->xbps += getXBPS(baseDir, "/var/db/xbps");
packageCounts->brewCask += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Caskroom", DT_DIR);
packageCounts->brew += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Cellar", DT_DIR);
packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2");
packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:"); // openwrt
if (!(options->disabled & FF_PACKAGES_FLAG_APK_BIT)) packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q");
if (!(options->disabled & FF_PACKAGES_FLAG_DPKG_BIT)) packageCounts->dpkg += getNumStrings(baseDir, "/var/lib/dpkg/status", "Status: install ok installed");
if (!(options->disabled & FF_PACKAGES_FLAG_EMERGE_BIT)) packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE");
if (!(options->disabled & FF_PACKAGES_FLAG_EOPKG_BIT)) packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", DT_DIR);
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getFlatpak(baseDir, "/var/lib/flatpak");
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
{
packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default");
packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system");
}
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", DT_DIR);
if (!(options->disabled & FF_PACKAGES_FLAG_PKGTOOL_BIT)) packageCounts->pkgtool += getNumElements(baseDir, "/var/log/packages", DT_REG);
if (!(options->disabled & FF_PACKAGES_FLAG_RPM_BIT)) packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(*) FROM Packages");
if (!(options->disabled & FF_PACKAGES_FLAG_SNAP_BIT)) packageCounts->snap += getSnap(baseDir);
if (!(options->disabled & FF_PACKAGES_FLAG_XBPS_BIT)) packageCounts->xbps += getXBPS(baseDir, "/var/db/xbps");
if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT))
{
packageCounts->brewCask += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Caskroom", DT_DIR);
packageCounts->brew += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Cellar", DT_DIR);
}
if (!(options->disabled & FF_PACKAGES_FLAG_PALUDIS_BIT)) packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2");
if (!(options->disabled & FF_PACKAGES_FLAG_OPKG_BIT)) packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:"); // openwrt
}
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts)
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
{
getPackageCounts(baseDir, packageCounts);
getPackageCounts(baseDir, packageCounts, options);
uint32_t baseDirLength = baseDir->length;
ffStrbufAppendS(baseDir, FASTFETCH_TARGET_DIR_ETC "/pacman-mirrors.conf");
if(ffParsePropFile(baseDir->chars, "Branch =", &packageCounts->pacmanBranch) && packageCounts->pacmanBranch.length == 0)
ffStrbufAppendS(&packageCounts->pacmanBranch, "stable");
ffStrbufSubstrBefore(baseDir, baseDirLength);
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT))
{
uint32_t baseDirLength = baseDir->length;
ffStrbufAppendS(baseDir, FASTFETCH_TARGET_DIR_ETC "/pacman-mirrors.conf");
if(ffParsePropFile(baseDir->chars, "Branch =", &packageCounts->pacmanBranch) && packageCounts->pacmanBranch.length == 0)
ffStrbufAppendS(&packageCounts->pacmanBranch, "stable");
ffStrbufSubstrBefore(baseDir, baseDirLength);
}
}
static void getPackageCountsBedrock(FFstrbuf* baseDir, FFPackagesResult* packageCounts)
static void getPackageCountsBedrock(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
{
uint32_t baseDirLength = baseDir->length;
@ -309,32 +318,34 @@ static void getPackageCountsBedrock(FFstrbuf* baseDir, FFPackagesResult* package
continue;
ffStrbufAppendS(baseDir, entry->d_name);
getPackageCounts(baseDir, packageCounts);
getPackageCounts(baseDir, packageCounts, options);
ffStrbufSubstrBefore(baseDir, baseDirLength2);
}
ffStrbufSubstrBefore(baseDir, baseDirLength);
}
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(512);
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
if(ffStrbufIgnCaseEqualS(&ffDetectOS()->id, "bedrock"))
getPackageCountsBedrock(&baseDir, result);
getPackageCountsBedrock(&baseDir, result, options);
else
getPackageCountsRegular(&baseDir, result);
getPackageCountsRegular(&baseDir, result, options);
// If SQL failed, we can still try with librpm.
// This is needed on openSUSE, which seems to use a proprietary database file
// This method doesn't work on bedrock, so we do it here.
#ifdef FF_HAVE_RPM
if(result->rpm == 0)
if(!(options->disabled & FF_PACKAGES_FLAG_RPM_BIT) && result->rpm == 0)
result->rpm = getRpmFromLibrpm();
#endif
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
result->flatpakUser = getFlatpak(&baseDir, "/.local/share/flatpak");
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT))
result->flatpakUser = getFlatpak(&baseDir, "/.local/share/flatpak");
}

View File

@ -107,9 +107,8 @@ static void detectWinget(FFPackagesResult* result)
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
{
detectScoop(result);
detectChoco(result);
detectPacman(result);
if (options->winget)
detectWinget(result);
if (!(options->disabled & FF_PACKAGES_FLAG_SCOOP_BIT)) detectScoop(result);
if (!(options->disabled & FF_PACKAGES_FLAG_CHOCO_BIT)) detectChoco(result);
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) detectPacman(result);
if (!(options->disabled & FF_PACKAGES_FLAG_WINGET_BIT)) detectWinget(result);
}

View File

@ -4,12 +4,34 @@
#include "common/option.h"
typedef enum FFPackagesFlags
{
FF_PACKAGES_FLAG_NONE = 0,
FF_PACKAGES_FLAG_APK_BIT = 1 << 0,
FF_PACKAGES_FLAG_BREW_BIT = 1 << 1,
FF_PACKAGES_FLAG_CHOCO_BIT = 1 << 2,
FF_PACKAGES_FLAG_DPKG_BIT = 1 << 3,
FF_PACKAGES_FLAG_EMERGE_BIT = 1 << 4,
FF_PACKAGES_FLAG_EOPKG_BIT = 1 << 5,
FF_PACKAGES_FLAG_FLATPAK_BIT = 1 << 6,
FF_PACKAGES_FLAG_NIX_BIT = 1 << 7,
FF_PACKAGES_FLAG_OPKG_BIT = 1 << 8,
FF_PACKAGES_FLAG_PACMAN_BIT = 1 << 9,
FF_PACKAGES_FLAG_PALUDIS_BIT = 1 << 10,
FF_PACKAGES_FLAG_PKG_BIT = 1 << 11,
FF_PACKAGES_FLAG_PKGTOOL_BIT = 1 << 12,
FF_PACKAGES_FLAG_MACPORTS_BIT = 1 << 13,
FF_PACKAGES_FLAG_RPM_BIT = 1 << 14,
FF_PACKAGES_FLAG_SCOOP_BIT = 1 << 15,
FF_PACKAGES_FLAG_SNAP_BIT = 1 << 16,
FF_PACKAGES_FLAG_WINGET_BIT = 1 << 17,
FF_PACKAGES_FLAG_XBPS_BIT = 1 << 18,
} FFPackagesFlags;
typedef struct FFPackagesOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
#ifdef _WIN32
bool winget;
#endif
FFPackagesFlags disabled;
} FFPackagesOptions;

View File

@ -40,9 +40,8 @@ void ffPrintPackages(FFPackagesOptions* options)
if(counts.pacmanBranch.length > 0)
printf("[%s]", counts.pacmanBranch.chars);
if((all -= counts.pacman) > 0)
fputs(", ", stdout);
printf(", ");
};
FF_PRINT_PACKAGE(dpkg)
FF_PRINT_PACKAGE(rpm)
FF_PRINT_PACKAGE(emerge)
@ -109,13 +108,52 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key,
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
#ifdef _WIN32
if(ffStrEqualsIgnCase(subKey, "winget"))
if (ffStrEqualsIgnCase(subKey, "disabled"))
{
options->winget = ffOptionParseBoolean(value);
options->disabled = FF_PACKAGES_FLAG_NONE;
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
ffOptionParseString(key, value, &buffer);
char *start = buffer.chars, *end = strchr(start, ':');
while (true)
{
if (end)
*end = '\0';
#define FF_TEST_PACKAGE_NAME(name) else if (ffStrEqualsIgnCase(start, #name)) { options->disabled |= FF_PACKAGES_FLAG_ ## name ## _BIT; }
if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(BREW)
FF_TEST_PACKAGE_NAME(CHOCO)
FF_TEST_PACKAGE_NAME(DPKG)
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
FF_TEST_PACKAGE_NAME(FLATPAK)
FF_TEST_PACKAGE_NAME(NIX)
FF_TEST_PACKAGE_NAME(OPKG)
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PALUDIS)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(MACPORTS)
FF_TEST_PACKAGE_NAME(RPM)
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
#undef FF_TEST_PACKAGE_NAME
if (end)
{
start = end + 1;
end = strchr(end, ':');
}
else
break;
}
return true;
}
#endif
return false;
}
@ -127,19 +165,55 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
yyjson_obj_foreach(module, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if(ffStrEqualsIgnCase(key, "type"))
if (ffStrEqualsIgnCase(key, "type"))
continue;
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
#ifdef _WIN32
if (ffStrEqualsIgnCase(key, "winget"))
if (ffStrEqualsIgnCase(key, "disabled"))
{
options->winget = yyjson_get_bool(val);
continue;
if (!yyjson_is_null(val) && !yyjson_is_arr(val))
{
ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, "Invalid JSON value for %s", key);
continue;
}
options->disabled = FF_PACKAGES_FLAG_NONE;
if (yyjson_is_arr(val))
{
yyjson_val* flagObj;
size_t flagIdx, flagMax;
yyjson_arr_foreach(val, flagIdx, flagMax, flagObj)
{
const char* flag = yyjson_get_str(flagObj);
#define FF_TEST_PACKAGE_NAME(name) else if (ffStrEqualsIgnCase(flag, #name)) { options->disabled |= FF_PACKAGES_FLAG_ ## name ## _BIT; }
if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(BREW)
FF_TEST_PACKAGE_NAME(CHOCO)
FF_TEST_PACKAGE_NAME(DPKG)
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
FF_TEST_PACKAGE_NAME(FLATPAK)
FF_TEST_PACKAGE_NAME(NIX)
FF_TEST_PACKAGE_NAME(OPKG)
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PALUDIS)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(MACPORTS)
FF_TEST_PACKAGE_NAME(RPM)
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
#undef FF_TEST_PACKAGE_NAME
}
}
}
#endif
ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
@ -152,10 +226,32 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
#ifdef _WIN32
if (options->winget != defaultOptions.winget)
yyjson_mut_obj_add_bool(doc, module, "winget", options->winget);
#endif
if (options->disabled != defaultOptions.disabled)
{
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "disabled");
#define FF_TEST_PACKAGE_NAME(name) else if ((options->disabled & FF_PACKAGES_FLAG_ ## name ## _BIT) != (defaultOptions.disabled & FF_PACKAGES_FLAG_ ## name ## _BIT)) { yyjson_mut_arr_add_str(doc, arr, #name); }
if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(BREW)
FF_TEST_PACKAGE_NAME(CHOCO)
FF_TEST_PACKAGE_NAME(DPKG)
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
FF_TEST_PACKAGE_NAME(FLATPAK)
FF_TEST_PACKAGE_NAME(NIX)
FF_TEST_PACKAGE_NAME(OPKG)
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PALUDIS)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(MACPORTS)
FF_TEST_PACKAGE_NAME(RPM)
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
#undef FF_TEST_PACKAGE_NAME
}
}
void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@ -248,9 +344,7 @@ void ffInitPackagesOptions(FFPackagesOptions* options)
);
ffOptionInitModuleArg(&options->moduleArgs);
#ifdef _WIN32
options->winget = false;
#endif
options->disabled = FF_PACKAGES_FLAG_WINGET_BIT;
}
void ffDestroyPackagesOptions(FFPackagesOptions* options)