From 62aca04decc1d2df62b903e40471f47c81371634 Mon Sep 17 00:00:00 2001 From: Toni500git Date: Tue, 13 Aug 2024 17:39:07 +0200 Subject: [PATCH] general: improve codebase and perfomances --- include/config.hpp | 4 +- include/switch_fnv1a.hpp | 265 +++++++++++++++++++++++++++++++++++++++ include/taur.hpp | 8 +- include/util.hpp | 58 +++------ src/config.cpp | 6 +- src/main.cpp | 20 +-- src/taur.cpp | 81 +++++++----- src/util.cpp | 110 ++++++++-------- 8 files changed, 403 insertions(+), 149 deletions(-) create mode 100644 include/switch_fnv1a.hpp diff --git a/include/config.hpp b/include/config.hpp index fd0bcf9..0ccfd33 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -98,7 +98,7 @@ extern std::unique_ptr config; inline struct _color_t color; // we comment the default config values, just like /etc/pacman.conf -inline const constexpr std::string_view AUTOCONFIG = R"#([general] +inline constexpr std::string_view AUTOCONFIG = R"#([general] # All options are commented out with their default values listed. # If you wish to use different options values, uncomment and update those. # It's safe to remove any options you want, just remember their default value @@ -143,7 +143,7 @@ inline const constexpr std::string_view AUTOCONFIG = R"#([general] #MakepkgConf = "/etc/makepkg.conf" )#"; -inline const constexpr std::string_view AUTOTHEME = R"#([theme] +inline constexpr std::string_view AUTOTHEME = R"#([theme] red = "#ff2000" green = "#00ff00" blue = "#00aaff" diff --git a/include/switch_fnv1a.hpp b/include/switch_fnv1a.hpp new file mode 100644 index 0000000..9d1266b --- /dev/null +++ b/include/switch_fnv1a.hpp @@ -0,0 +1,265 @@ +/** + * Switch/Case strings using constexpr Fnv1-a. + * @comment References: + * @comment References: + * @maintainer xavier dot roche at algolia.com + */ + +#pragma once + +#include +#include +#include +#include + +// Traits for FNV1a +template +struct fnv1a_traits +{ + static constexpr bool Supported = false; +}; + +// Traits for 16-bit FNV1a (added by myself for customfetch) +template<> +struct fnv1a_traits<16> +{ + static constexpr bool Supported = true; + using Type = uint16_t; + + static constexpr Type Prime = 0x389; + static constexpr Type Offset = 0x9DC5; +}; + +// Traits for 32-bit FNV1a +template<> +struct fnv1a_traits<32> +{ + static constexpr bool Supported = true; + using Type = uint32_t; + + static constexpr Type Prime = 0x1000193; + static constexpr Type Offset = 0x811c9dc5; +}; + +// Traits for 64-bit FNV1a +template<> +struct fnv1a_traits<64> +{ + static constexpr bool Supported = true; + using Type = uint64_t; + + static constexpr Type Prime = 0x100000001b3; + static constexpr Type Offset = 0xcbf29ce484222325; +}; + +static constexpr __uint128_t Pack128(uint64_t high, uint64_t low) +{ + return ((__uint128_t)high << 64) + (__uint128_t)low; +} + +// Traits for 128-bit FNV1a +template<> +struct fnv1a_traits<128> +{ + static constexpr bool Supported = true; + using Type = __uint128_t; + + static constexpr Type Prime = Pack128(0x1000000, 0x000000000000013b); + static constexpr Type Offset = Pack128(0x6c62272e07bb0142, 0x62b821756295c58d); +}; + +// Generic FNV1a implementation +template +struct fnv1a +{ + static_assert(fnv1a_traits::Supported); + using Type = typename fnv1a_traits::Type; + + /** + * Compute the Fowler–Noll–Vo hash + * @comment stop An optional stop character + * @param s The string + * @param l The string size + * @return The fnv-1a hash + */ + template + static constexpr Type hash_container(T s, + const std::size_t l, + L stopLen = nullptr, + Type hash = fnv1a_traits::Offset) + { + // See + std::size_t j = 0; + for (; j < l; j++) { + const uint8_t byte = static_cast(s[j]); + if constexpr (stop != 0) { + if (byte == stop) { + if constexpr (!std::is_same::value) { + *stopLen = j + 1; + } + break; + } + } + hash ^= byte; + hash *= fnv1a_traits::Prime; + } + + return hash; + } + + /** + * Compute the Fowler–Noll–Vo hash + * @comment stop An optional stop character + * @param s The string + * @param l The string size + * @return The fnv-1a hash + */ + template + static constexpr Type hash(const C* s, + const std::size_t l, + L stopLen = nullptr, + Type hash = fnv1a_traits::Offset) + { + // Accept [ unsigned | signed ] char + static_assert(std::is_integral::value); + static_assert(sizeof(C) == 1); + return hash_container(s, l, stopLen, hash); + } + + /** + * Compute the Fowler–Noll–Vo hash + * @param s The string + * @return The fnv-1a hash + */ + template + static constexpr Type hash(const char (&s)[l]) + { + return hash(&s[0], l - 1); + } + + // Do not infer length for char arrays + template + static constexpr Type hash(char (&s)[l]) + { + return hash(&s[0]); + } + + /** + * Compute the Fowler–Noll–Vo hash + * @param s The string + * @return The fnv-1a hash + */ + static constexpr Type hash(const char* s) { return hash(s, __builtin_strlen(s)); } + + /** + * Compute the Fowler–Noll–Vo hash + * @param str The string + * @return The fnv-1a hash + */ + static constexpr Type hash(const std::string& str) { return hash(str.c_str(), str.size()); } + + /** + * Compute the Fowler–Noll–Vo hash + * @param str The string view + * @return The fnv-1a hash + */ + template + static constexpr Type hash(const std::basic_string_view& str) + { + // Accept [ unsigned | signed ] char + static_assert(std::is_integral::value); + static_assert(sizeof(C) == 1); + return hash(str.data(), str.size()); + } +}; + +using fnv1a16 = fnv1a<16>; +using fnv1a32 = fnv1a<32>; +using fnv1a64 = fnv1a<64>; +using fnv1a128 = fnv1a<128>; + +constexpr fnv1a16::Type operator"" _fnv1a16(const char* s, const std::size_t l) +{ + return fnv1a16::hash(s, l); +} +constexpr fnv1a32::Type operator"" _fnv1a32(const char* s, const std::size_t l) +{ + return fnv1a32::hash(s, l); +} +constexpr fnv1a64::Type operator"" _fnv1a64(const char* s, const std::size_t l) +{ + return fnv1a64::hash(s, l); +} +constexpr fnv1a128::Type operator"" _fnv1a128(const char* s, const std::size_t l) +{ + return fnv1a128::hash(s, l); +} + +// Static unit tests: +//static_assert("hello"_fnv1a32 == 0x4f9f2cab); +//static_assert("hello"_fnv1a64 == 0xa430d84680aabd0b); +//static_assert("hello"_fnv1a128 == Pack128(0xe3e1efd54283d94f, 0x7081314b599d31b3)); + +using strhash = fnv1a128; +constexpr strhash::Type operator"" _strhash(const char* s, const std::size_t l) +{ + return strhash::hash(s, l); +} + +// Lowercase operator[] wrapper for any operator[]-aware types +namespace strhash_lower { +template +class _lowercase_container +{ +public: + constexpr _lowercase_container(const T& container) + : _container(container) + {} + + constexpr auto operator[](std::size_t index) const + { + const auto c = _container[index]; + static_assert(std::is_integral::value); + static_assert(sizeof(c) == 1); + return c >= 'A' && c <= 'Z' ? (c + 'a' - 'A') : c; + } + +private: + const T& _container; +}; + +/** + * Hash a generic container, using a lowercase modifier, providing 'size' 8-byte characters through operator[] + */ +template +constexpr strhash::Type hash(const T& container, std::size_t size) +{ + return strhash::hash_container(strhash_lower::_lowercase_container(container), size); +} + +/** + * Hash a std::string, using a lowercase modifier + */ +/*static constexpr strhash::Type hash(const std::string& str) +{ + return hash(str, str.size()); +}*/ + +/** + * Hash a std::string, using a lowercase modifier + */ +template +static constexpr strhash::Type hash(const std::basic_string_view& str) +{ + // Accept [ unsigned | signed ] char + static_assert(std::is_integral::value); + static_assert(sizeof(C) == 1); + return hash(str.data(), str.size()); +} +} // namespace strhash_lower + +// Case-insensitive version +constexpr strhash::Type operator"" _strhash_lower(const char* s, const std::size_t l) +{ + return strhash_lower::hash(s, l); +} diff --git a/include/taur.hpp b/include/taur.hpp index 4c342d4..ec2b4a1 100644 --- a/include/taur.hpp +++ b/include/taur.hpp @@ -61,10 +61,10 @@ class TaurBackend std::vector fetch_pkgs(std::vector const& pkgs, bool returnGit); bool remove_pkgs(alpm_list_smart_pointer& pkgs); bool remove_pkg(alpm_pkg_t* pkgs, bool ownTransaction = true); - bool handle_aur_depends(TaurPkg_t pkg, path out_path, std::vector const& localPkgs, bool useGit); - bool build_pkg(std::string_view pkg_name, std::string extracted_path, bool alreadyprepared); - bool update_all_aur_pkgs(path cacheDir, bool useGit); - std::vector get_all_local_pkgs(bool aurOnly); + bool handle_aur_depends(const TaurPkg_t& pkg, path out_path, std::vector const& localPkgs, bool useGit); + bool build_pkg(std::string_view pkg_name, std::string_view extracted_path, bool alreadyprepared); + bool update_all_aur_pkgs(path cacheDir, bool useGit); + std::vector get_all_local_pkgs(bool aurOnly); }; inline std::string built_pkg, pkgs_to_install, pkgs_failed_to_build; diff --git a/include/util.hpp b/include/util.hpp index 2293a8d..6d8cf79 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -1,6 +1,7 @@ #ifndef UTIL_HPP #define UTIL_HPP +#include #include #include #include @@ -29,7 +30,7 @@ struct TaurPkg_t; class TaurBackend; #define BOLD fmt::emphasis::bold -#define BOLD_TEXT(x) (fmt::emphasis::bold | fmt::fg(x)) +#define BOLD_COLOR(x) (fmt::emphasis::bold | fmt::fg(x)) #define NOCOLOR "\033[0m" #define AUR_URL "https://aur.archlinux.org" #define AUR_URL_GIT(x) fmt::format("https://aur.archlinux.org/{}.git", x) @@ -101,6 +102,7 @@ bool commitTransactionAndRelease(bool soft = false); void printPkgInfo(TaurPkg_t& pkg, std::string_view db_name); void printLocalFullPkgInfo(alpm_pkg_t* pkg); std::string makepkg_list(std::string_view pkg_name, std::string_view path); +void getFileValue(u_short& iterIndex, const std::string& line, std::string& str, const size_t& amount); void free_list_and_internals(alpm_list_t* list); fmt::text_style getColorFromDBName(std::string_view db_name); std::vector filterAURPkgs(std::vector pkgs, alpm_list_t* syncdbs, bool inverse); @@ -109,7 +111,7 @@ std::vector filterAURPkgsNames(std::vector p std::string shell_exec(std::string_view cmd); std::vector split(std::string_view text, char delim); fmt::rgb hexStringToColor(std::string_view hexstr); -void ctrl_d_handler(); +void ctrl_d_handler(const std::istream& cin); std::string getTitleFromVotes(float votes); std::string getHomeCacheDir(); std::string getHomeConfigDir(); @@ -154,18 +156,18 @@ void _log_println(log_level log, const fmt::text_style ts, fmt::runtime_format_s switch (log) { case ERROR: - fmt::print(stderr, BOLD_TEXT(color.red), fmt::runtime(_("ERROR: "))); + fmt::print(stderr, BOLD_COLOR(color.red), fmt::runtime(_("ERROR: "))); break; case WARN: - fmt::print(BOLD_TEXT(color.yellow), fmt::runtime(_("Warning: "))); + fmt::print(BOLD_COLOR(color.yellow), fmt::runtime(_("Warning: "))); break; case INFO: - fmt::print(BOLD_TEXT(color.cyan), fmt::runtime(_("Info: "))); + fmt::print(BOLD_COLOR(color.cyan), fmt::runtime(_("Info: "))); break; case DEBUG: if (!config->debug) return; - fmt::print(BOLD_TEXT(color.magenta), "[DEBUG]: "); + fmt::print(BOLD_COLOR(color.magenta), "[DEBUG]: "); break; default: break; @@ -173,12 +175,6 @@ void _log_println(log_level log, const fmt::text_style ts, fmt::runtime_format_s fmt::println(ts, fmt, std::forward(args)...); } -template -void log_println(log_level log, const char *fmt, Args&&... args) -{ - _log_println(log, fmt::text_style(), fmt::runtime(fmt), std::forward(args)...); -} - template void log_println(log_level log, std::string_view fmt, Args&&... args) { @@ -192,13 +188,7 @@ void log_println(log_level log, const fmt::text_style ts, std::string_view fmt, } template -void log_println(log_level log, const fmt::text_style ts, const char *fmt, Args&&... args) -{ - _log_println(log, ts, fmt::runtime(fmt), std::forward(args)...); -} - -template -void die(const char *fmt, Args&&... args) +void die(const std::string_view fmt, Args&&... args) { _log_println(ERROR, fmt::text_style(), fmt::runtime(fmt), std::forward(args)...); std::exit(1); @@ -210,18 +200,18 @@ void _log_printf(log_level log, const fmt::text_style ts, fmt::runtime_format_st switch (log) { case ERROR: - fmt::print(stderr, BOLD_TEXT(color.red), fmt::runtime(_("ERROR: "))); + fmt::print(stderr, BOLD_COLOR(color.red), fmt::runtime(_("ERROR: "))); break; case WARN: - fmt::print(BOLD_TEXT(color.yellow), fmt::runtime(_("Warning: "))); + fmt::print(BOLD_COLOR(color.yellow), fmt::runtime(_("Warning: "))); break; case INFO: - fmt::print(BOLD_TEXT(color.cyan), fmt::runtime(_("Info: "))); + fmt::print(BOLD_COLOR(color.cyan), fmt::runtime(_("Info: "))); break; case DEBUG: if (!config->debug) return; - fmt::print(BOLD_TEXT(color.magenta), "[DEBUG]: "); + fmt::print(BOLD_COLOR(color.magenta), "[DEBUG]: "); break; default: break; @@ -229,12 +219,6 @@ void _log_printf(log_level log, const fmt::text_style ts, fmt::runtime_format_st fmt::print(ts, fmt, std::forward(args)...); } -template -void log_printf(log_level log, const char *fmt, Args&&... args) -{ - _log_printf(log, fmt::text_style(), fmt::runtime(fmt), std::forward(args)...); -} - template void log_printf(log_level log, std::string_view fmt, Args&&... args) { @@ -247,12 +231,6 @@ void log_printf(log_level log, const fmt::text_style ts, std::string_view fmt, A _log_printf(log, ts, fmt::runtime(fmt), std::forward(args)...); } -template -void log_printf(log_level log, const fmt::text_style ts, const char *fmt, Args&&... args) -{ - _log_printf(log, ts, fmt::runtime(fmt), std::forward(args)...); -} - // clang-format on /** Ask the user a yes or no question. * @param def the default result @@ -313,7 +291,7 @@ bool askUserYorN(bool def, prompt_yn pr, Args&&... args) while (std::getline(std::cin, result) && (result.length() > 1)) log_printf(WARN, _("Please provide a valid response {}"), inputs_str); - ctrl_d_handler(); + ctrl_d_handler(std::cin); if (result.empty()) return def; @@ -338,7 +316,7 @@ std::vector askUserForList(std::vector& list, prompt_list pr, bool require std::string result_str; for (size_t i = 0; i < list.size(); i++) - fmt::println(fmt::fg(color.index), "[{}] {}", i, fmt::format(BOLD_TEXT(fmt::color::white), "{}", list[i])); + fmt::println(fmt::fg(color.index), "[{}] {}", i, fmt::format(BOLD_COLOR(fmt::color::white), "{}", list[i])); log_println(INFO, _("{}"), sep_str); @@ -441,7 +419,7 @@ std::vector askUserForList(std::vector& list, prompt_list pr, bool require break; } - ctrl_d_handler(); + ctrl_d_handler(std::cin); return result; } @@ -460,8 +438,8 @@ T sanitize(T beg, T end) return dest; } -static inline std::vector secret = { - { "Ingredients:" }, +inline constexpr std::array secret = { + "Ingredients:", { R"#( 3/4 cup milk 1/2 cup vegetable oil diff --git a/src/config.cpp b/src/config.cpp index 798d296..3b3ccf3 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -218,11 +218,13 @@ bool addServers(alpm_db_t* db, const std::string& includeFilename, std::string_v size_t repo_pos = line.find("$repo"); if (repo_pos != std::string::npos) - line.replace(repo_pos, 5, repoName); + line.replace(repo_pos, "$repo"_len, repoName); + size_t arch_pos = line.find("$arch"); if (arch_pos != std::string::npos) - line.replace(arch_pos, 5, "x86_64"); + line.replace(arch_pos, "$arch"_len, "x86_64"); + // Each line that has a server starts with a 9 letter header line = line.substr(9); alpm_db_add_server(db, line.c_str()); diff --git a/src/main.cpp b/src/main.cpp index 036a69a..af28f2f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -105,10 +105,10 @@ void test_colors() if (fmt::disable_colors) fmt::println("Colors are disabled"); - log_println(DEBUG, _("Debug color: {}"), fmt::format(BOLD_TEXT(color.magenta), "(bold) magenta")); - log_println(INFO, _("Info color: {}"), fmt::format(BOLD_TEXT(color.cyan), "(bold) cyan")); - log_println(WARN, _("Warning color: {}"), fmt::format(BOLD_TEXT(color.yellow), "(bold) yellow")); - log_println(ERROR, _("Error color: {}"), fmt::format(BOLD_TEXT(color.red), "(bold) red")); + log_println(DEBUG, _("Debug color: {}"), fmt::format(BOLD_COLOR(color.magenta), "(bold) magenta")); + log_println(INFO, _("Info color: {}"), fmt::format(BOLD_COLOR(color.cyan), "(bold) cyan")); + log_println(WARN, _("Warning color: {}"), fmt::format(BOLD_COLOR(color.yellow), "(bold) yellow")); + log_println(ERROR, _("Error color: {}"), fmt::format(BOLD_COLOR(color.red), "(bold) red")); fmt::println(fg(color.red), "red"); fmt::println(fg(color.blue), "blue"); fmt::println(fg(color.yellow), "yellow"); @@ -124,13 +124,13 @@ void test_colors() fmt::println(getColorFromDBName("multilib"), "(bold) multilib"); fmt::println(getColorFromDBName("others"), "(bold) others"); - fmt::println(BOLD_TEXT(color.version), "\n(bold) version " VERSION); + fmt::println(BOLD_COLOR(color.version), "\n(bold) version " VERSION); fmt::println(fg(color.popularity), "Popularity: {}", pkg.popularity); fmt::println(fg(color.votes), "Votes: {} ({})", pkg.votes, getTitleFromVotes(pkg.votes)); fmt::println(fg(color.index), "index [1]"); - fmt::println(BOLD_TEXT(color.installed), "(bold) indicator [Installed]"); - fmt::println(BOLD_TEXT(color.orphan), "(bold) (un-maintained)"); - fmt::println(BOLD_TEXT(color.outofdate), "(bold) (Outdated: {})", timestr); + fmt::println(BOLD_COLOR(color.installed), "(bold) indicator [Installed]"); + fmt::println(BOLD_COLOR(color.orphan), "(bold) (un-maintained)"); + fmt::println(BOLD_COLOR(color.outofdate), "(bold) (Outdated: {})", timestr); fmt::println("\nexamples package search preview:"); printPkgInfo(pkg, pkg.db_name); @@ -321,7 +321,7 @@ int installPkg(alpm_list_t* pkgNames) continue; } - stat = backend->build_pkg(pkg.name, pkgDir, false); + stat = backend->build_pkg(pkg.name, pkgDir.string(), false); if (!stat) { @@ -595,7 +595,7 @@ bool queryPkgs(alpm_list_t* pkgNames) if (!pkgs_name[i]) continue; fmt::print(BOLD, "{} ", pkgs_name[i]); - fmt::println(BOLD_TEXT(color.green), "{}", pkgs_ver[i]); + fmt::println(BOLD_COLOR(color.green), "{}", pkgs_ver[i]); } } diff --git a/src/taur.cpp b/src/taur.cpp index 7a4c87c..7d69457 100644 --- a/src/taur.cpp +++ b/src/taur.cpp @@ -59,15 +59,12 @@ bool TaurBackend::download_pkg(std::string_view url, path out_path) return false; } -std::string getUrl(rapidjson::Value& pkgJson, bool returnGit = false) +std::string getUrl(const rapidjson::Value& pkgJson, bool returnGit = false) { - std::stringstream ss; if (returnGit) - ss << "https://aur.archlinux.org/" << pkgJson["Name"].GetString() << ".git"; - else - ss << "https://aur.archlinux.org" << pkgJson["URLPath"].GetString(); - - return ss.str(); + return fmt::format("https://aur.archlinux.org/{}.git", pkgJson["Name"].GetString()); + else // URLPath starts with a / + return fmt::format("https://aur.archlinux.org{}", pkgJson["URLPath"].GetString()); } TaurPkg_t parsePkg(rapidjson::Value& pkgJson, bool returnGit = false) @@ -187,10 +184,10 @@ std::vector TaurBackend::fetch_pkgs(std::vector const& p } /** Removes a single packages using libalpm. - @param pkgs an alpm package to remove. - @param ownTransaction a bool that dictates whether this function owns the transaction, this is used for remove_pkgs, - if not, it will not initialize it and not release it. - @return success. + * @param pkgs an alpm package to remove. + * @param ownTransaction a bool that dictates whether this function owns the transaction, this is used for remove_pkgs, + * if not, it will not initialize it and not release it. + * @return success. */ bool TaurBackend::remove_pkg(alpm_pkg_t* pkg, bool ownTransaction) { @@ -219,9 +216,9 @@ bool TaurBackend::remove_pkg(alpm_pkg_t* pkg, bool ownTransaction) /** Removes a list of packages using libalpm. * Will automatically call remove_pkg instead, if the size of pkgs is equal to 1. - @param pkgs alpm list of alpm_pkg_t pointers to remove. - @return success. -*/ + * @param pkgs alpm list of alpm_pkg_t pointers to remove. + * @return success. + */ bool TaurBackend::remove_pkgs(alpm_list_smart_pointer& pkgs) { if (!pkgs) @@ -266,10 +263,8 @@ bool TaurBackend::remove_pkgs(alpm_list_smart_pointer& pkgs) return true; } -bool TaurBackend::build_pkg(std::string_view pkg_name, std::string extracted_path, bool alreadyprepared) +bool TaurBackend::build_pkg(std::string_view pkg_name, std::string_view extracted_path, bool alreadyprepared) { - // never forget to sanitize - sanitizeStr(extracted_path); std::filesystem::current_path(extracted_path); if (!alreadyprepared) @@ -300,7 +295,7 @@ bool TaurBackend::build_pkg(std::string_view pkg_name, std::string extracted_pat } // I don't know but I feel this is shitty, atleast it works great -bool TaurBackend::handle_aur_depends(TaurPkg_t pkg, path out_path, std::vector const& localPkgs, bool useGit) +bool TaurBackend::handle_aur_depends(const TaurPkg_t& pkg, path out_path, std::vector const& localPkgs, bool useGit) { log_println(DEBUG, "pkg.name = {}", pkg.name); log_println(DEBUG, "pkg.totaldepends = {}", pkg.totaldepends); @@ -308,7 +303,10 @@ bool TaurBackend::handle_aur_depends(TaurPkg_t pkg, path out_path, std::vectorbuild_pkg(depend.name, out_path / depend.name, false); + bool installStatus = this->build_pkg(depend.name, (out_path / depend.name).string(), false); if (!installStatus) { @@ -440,6 +451,7 @@ bool TaurBackend::update_all_aur_pkgs(path cacheDir, bool useGit) return true; } + std::string line; std::vector pkgNames; pkgNames.reserve(localPkgs.size()); @@ -463,8 +475,7 @@ bool TaurBackend::update_all_aur_pkgs(path cacheDir, bool useGit) for (size_t i = 0; i < onlinePkgs.size(); i++) { TaurPkg_t& pkg = onlinePkgs[i]; - auto pkgIteratorInLocalPkgs = std::find_if( - localPkgs.begin(), localPkgs.end(), [&pkg](const TaurPkg_t& element) { return element.name == pkg.name; }); + auto pkgIteratorInLocalPkgs = std::find_if(localPkgs.begin(), localPkgs.end(), [&pkg](const TaurPkg_t& element) { return element.name == pkg.name; }); size_t pkgIndexInLocalPkgs = std::distance(localPkgs.begin(), pkgIteratorInLocalPkgs); TaurPkg_t& localPkg = localPkgs[pkgIndexInLocalPkgs]; @@ -502,8 +513,8 @@ bool TaurBackend::update_all_aur_pkgs(path cacheDir, bool useGit) // } // } - TaurPkg_t potentialUpgradeTargetTo = std::get<0>(potentialUpgrade); - TaurPkg_t potentialUpgradeTargetFrom = std::get<1>(potentialUpgrade); + const TaurPkg_t& potentialUpgradeTargetTo = std::get<0>(potentialUpgrade); + const TaurPkg_t& potentialUpgradeTargetFrom = std::get<1>(potentialUpgrade); log_println(DEBUG, "potentialUpgradeTarget.name = {}", potentialUpgradeTargetTo.name); log_println(DEBUG, "potentialUpgradeTarget.totaldepends = {}", potentialUpgradeTargetTo.totaldepends); @@ -544,7 +555,20 @@ bool TaurBackend::update_all_aur_pkgs(path cacheDir, bool useGit) makepkg_exec({ "--nobuild", "-dfA" }); } - std::string versionInfo = shell_exec("grep 'pkgver=' " + pkgDir.string() + "/PKGBUILD | cut -d= -f2"); + u_short iter_index = 0; + std::ifstream pkgbuild(pkgDir.string() + "/PKGBUILD", std::ios::in); + std::string versionInfo, pkgrel, epoch; + while (std::getline(pkgbuild, line) && iter_index < 3) + { + if (hasStart(line, "pkgver=")) + getFileValue(iter_index, line, versionInfo, "pkgver="_len); + + else if (hasStart(line, "pkgrel=")) + getFileValue(iter_index, line, pkgrel, "pkgrel"_len); + + else if (hasStart(line, "epoch=")) + getFileValue(iter_index, line, epoch, "epoch="_len); + } if (versionInfo.empty()) { @@ -555,9 +579,6 @@ bool TaurBackend::update_all_aur_pkgs(path cacheDir, bool useGit) continue; } - std::string pkgrel = shell_exec("grep 'pkgrel=' " + pkgDir.string() + "/PKGBUILD | cut -d= -f2"); - std::string epoch = shell_exec("grep 'epoch=' " + pkgDir.string() + "/PKGBUILD | cut -d= -f2"); - if (!pkgrel.empty() && pkgrel[0] != '\0') versionInfo += '-' + pkgrel; @@ -582,7 +603,7 @@ bool TaurBackend::update_all_aur_pkgs(path cacheDir, bool useGit) attemptedDownloads++; this->handle_aur_depends(potentialUpgradeTargetTo, pkgDir, this->get_all_local_pkgs(true), useGit); - bool installSuccess = this->build_pkg(potentialUpgradeTargetTo.name, pkgDir, alrprepared); + bool installSuccess = this->build_pkg(potentialUpgradeTargetTo.name, pkgDir.string(), alrprepared); if (installSuccess) { diff --git a/src/util.cpp b/src/util.cpp index 54c73f1..05dbd56 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -23,6 +23,7 @@ #pragma GCC diagnostic ignored "-Wignored-attributes" #include "config.hpp" +#include "switch_fnv1a.hpp" #include "pacman.hpp" #include "taur.hpp" #include "util.hpp" @@ -180,13 +181,13 @@ bool commitTransactionAndRelease(bool soft) log_println(INFO, _("Changes to be made:")); for (alpm_list_t* addPkgsClone = addPkgs; addPkgsClone; addPkgsClone = addPkgsClone->next) { - fmt::print(BOLD_TEXT(color.green), " ++ "); + fmt::print(BOLD_COLOR(color.green), " ++ "); fmt::println(fmt::emphasis::bold, "{}", alpm_pkg_get_name((alpm_pkg_t*)(addPkgsClone->data))); } for (alpm_list_t* removePkgsClone = removePkgs; removePkgsClone; removePkgsClone = removePkgsClone->next) { - fmt::print(BOLD_TEXT(color.red), " -- "); + fmt::print(BOLD_COLOR(color.red), " -- "); fmt::println(fmt::emphasis::bold, "{}", alpm_pkg_get_name((alpm_pkg_t*)(removePkgsClone->data))); } @@ -586,16 +587,15 @@ void free_list_and_internals(alpm_list_t* list) */ fmt::text_style getColorFromDBName(std::string_view db_name) { - if (db_name == "aur") - return BOLD_TEXT(color.aur); - else if (db_name == "extra") - return BOLD_TEXT(color.extra); - else if (db_name == "core") - return BOLD_TEXT(color.core); - else if (db_name == "multilib") - return BOLD_TEXT(color.multilib); - else - return BOLD_TEXT(color.others); + switch (fnv1a16::hash(db_name)) + { + case "aur"_fnv1a16: return BOLD_COLOR(color.aur); + case "extra"_fnv1a16: return BOLD_COLOR(color.extra); + case "core"_fnv1a16: return BOLD_COLOR(color.core); + case "multilib"_fnv1a16: return BOLD_COLOR(color.multilib); + } + + return BOLD_COLOR(color.others); } // Takes a pkg to show on search. @@ -603,7 +603,7 @@ void printPkgInfo(TaurPkg_t& pkg, std::string_view db_name) { fmt::print(getColorFromDBName(db_name), "{}/", db_name); fmt::print(BOLD, "{} ", pkg.name); - fmt::print(BOLD_TEXT(color.version), "{} ", pkg.version); + fmt::print(BOLD_COLOR(color.version), "{} ", pkg.version); // Don't print popularity and votes on system packages if (pkg.votes > -1) { @@ -612,7 +612,7 @@ void printPkgInfo(TaurPkg_t& pkg, std::string_view db_name) } if (pkg.maintainer == "\1") - fmt::print(BOLD_TEXT(color.orphan), "(un-maintained) "); + fmt::print(BOLD_COLOR(color.orphan), "(un-maintained) "); if (pkg.outofdate) { @@ -621,12 +621,12 @@ void printPkgInfo(TaurPkg_t& pkg, std::string_view db_name) if (!timestr_view.empty()) { timestr[timestr_view.length() - 1] = '\0'; // delete the last newline. - fmt::print(BOLD_TEXT(color.outofdate), "(Outdated: {}) ", timestr); + fmt::print(BOLD_COLOR(color.outofdate), "(Outdated: {}) ", timestr); } } if (pkg.installed) - fmt::println(BOLD_TEXT(color.installed), "[Installed]"); + fmt::println(BOLD_COLOR(color.installed), "[Installed]"); else fmt::print("\n"); fmt::println(" {}", pkg.desc); @@ -656,7 +656,21 @@ void printLocalFullPkgInfo(alpm_pkg_t* pkg) fmt::print("\n"); } -// faster than makepkg --packagelist +/* Get file value from a file and trim quotes and double-quotes + * @param iterIndex The iteration index used for getting the necessary value only tot times + * @param line The string used in std::getline + * @param str The string to assign the trimmed value, inline + * @param amount The amount to be used in the line.substr() (should be used with something like "foobar"_len) + */ +void getFileValue(u_short& iterIndex, const std::string& line, std::string& str, const size_t& amount) +{ + str = line.substr(amount); + str.erase(std::remove(str.begin(), str.end(), '\"'), str.end()); + str.erase(std::remove(str.begin(), str.end(), '\''), str.end()); + iterIndex++; +} + +// faster than `makepkg --packagelist` std::string makepkg_list(std::string_view pkg_name, std::string_view path) { std::ifstream pkgbuild_f(fmt::format("{}/PKGBUILD", path), std::ios::in); @@ -671,40 +685,25 @@ std::string makepkg_list(std::string_view pkg_name, std::string_view path) = shell_exec("awk -F '[()]' '/^arch=/ {gsub(/\"/,\"\",$2); print $2}' " + path + "/PKGBUILD | sed -e \"s/'//g\" -e 's/\"//g'");*/ - std::string versionInfo, pkgrel, epoch, arch_field; - std::uint8_t iterIndex = 0; + std::string versionInfo, pkgrel, epoch, arch_field; + u_short iterIndex = 0; std::string line; while (std::getline(pkgbuild_f, line) && iterIndex < 4) { if (hasStart(line, "pkgver=")) - { - versionInfo = line.substr("pkgver="_len); - versionInfo.erase(std::remove(versionInfo.begin(), versionInfo.end(), '\"'), versionInfo.end()); - versionInfo.erase(std::remove(versionInfo.begin(), versionInfo.end(), '\''), versionInfo.end()); - iterIndex++; - } + getFileValue(iterIndex, line, versionInfo, "pkgver="_len); + else if (hasStart(line, "pkgrel=")) - { - pkgrel = line.substr("pkgrel="_len); - pkgrel.erase(std::remove(pkgrel.begin(), pkgrel.end(), '\"'), pkgrel.end()); - pkgrel.erase(std::remove(pkgrel.begin(), pkgrel.end(), '\''), pkgrel.end()); - iterIndex++; - } + getFileValue(iterIndex, line, pkgrel, "pkgrel="_len); + else if (hasStart(line, "epoch=")) - { - epoch = line.substr("epoch="_len); - epoch.erase(std::remove(epoch.begin(), epoch.end(), '\"'), epoch.end()); - epoch.erase(std::remove(epoch.begin(), epoch.end(), '\''), epoch.end()); - iterIndex++; - } + getFileValue(iterIndex, line, epoch, "epoch="_len); + else if (hasStart(line, "arch=(")) { - arch_field = line.substr("arch=("_len); + getFileValue(iterIndex, line, arch_field, "arch=("_len); arch_field.pop_back(); - arch_field.erase(std::remove(arch_field.begin(), arch_field.end(), '\"'), arch_field.end()); - arch_field.erase(std::remove(arch_field.begin(), arch_field.end(), '\''), arch_field.end()); - iterIndex++; } } @@ -727,19 +726,10 @@ std::string makepkg_list(std::string_view pkg_name, std::string_view path) while (std::getline(makepkgConf, line) && iterIndex < 2) { if (hasStart(line, "CARCH=")) - { - arch = line.substr("CARCH="_len); - arch.erase(std::remove(arch.begin(), arch.end(), '\"'), arch.end()); - arch.erase(std::remove(arch.begin(), arch.end(), '\''), arch.end()); - iterIndex++; - } + getFileValue(iterIndex, line, arch, "CARCH="_len); + else if (hasStart(line, "PKGEXT=")) - { - pkgext = line.substr("PKGEXT="_len); - pkgext.erase(std::remove(pkgext.begin(), pkgext.end(), '\"'), pkgext.end()); - pkgext.erase(std::remove(pkgext.begin(), pkgext.end(), '\''), pkgext.end()); - iterIndex++; - } + getFileValue(iterIndex, line, pkgext, "PKGEXT="_len); } if (arch_field == "any") @@ -775,7 +765,7 @@ bool util_db_search(alpm_db_t* db, alpm_list_t* needles, alpm_list_t** ret) } // Function to perform binary search on a vector of std::strings -std::string_view binarySearch(const std::vector& arr, std::string_view target) +/*std::string_view binarySearch(const std::vector& arr, std::string_view target) { int left = 0, right = arr.size() - 1; @@ -791,7 +781,7 @@ std::string_view binarySearch(const std::vector& arr, std::string_v } return ""; -} +}*/ std::vector load_aur_list() { @@ -803,7 +793,7 @@ std::vector load_aur_list() std::vector aur_list; std::string pkg; - while (infile >> pkg) + while (std::getline(infile, pkg)) aur_list.push_back(pkg); return aur_list; @@ -890,7 +880,7 @@ std::optional> askUserForPkg(std::vector pkgs, do { // CTRL-D - ctrl_d_handler(); + ctrl_d_handler(std::cin); if (!input.empty()) log_println(WARN, _("Invalid input!")); @@ -928,12 +918,10 @@ std::optional> askUserForPkg(std::vector pkgs, return {}; } -void ctrl_d_handler() +void ctrl_d_handler(const std::istream& cin) { - if (std::cin.eof()) - { + if (cin.eof()) die(_("Exiting due to CTRL-D or EOF")); - } } /** Filters out/only AUR packages.