1
0

Replace glib data structures with STL

This commit is contained in:
2026-06-15 00:30:14 +02:00
parent 6719ed7ed3
commit 8140da6d6e
4 changed files with 162 additions and 177 deletions
+119 -150
View File
@@ -16,7 +16,11 @@ module;
#include <glib/gstdio.h>
#include <sqlite3.h>
#include <forward_list>
#include <array>
#include <string>
#include <list>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
export module katja.job;
@@ -30,7 +34,7 @@ static std::forward_list<std::unique_ptr<Pkgtools>> repos;
void pk_backend_initialize(GKeyFile *conf)
{
char *path, **groups;
char **groups;
int ret;
std::uint8_t i;
std::size_t groups_len;
@@ -45,24 +49,23 @@ void pk_backend_initialize(GKeyFile *conf)
curl_global_init(CURL_GLOBAL_DEFAULT);
/* Open the database. We will need it to save the time the configuration file was last modified. */
path = g_build_filename(LOCALSTATEDIR, "cache", "katja", "metadata.db", nullptr);
if (sqlite3_open(path, &db) != SQLITE_OK)
auto path = std::filesystem::path(LOCALSTATEDIR) / "cache" / "katja" / "metadata.db";
if (sqlite3_open(path.c_str(), &db) != SQLITE_OK)
{
g_error("%s: %s", path, sqlite3_errmsg(db));
g_error("%s: %s", path.c_str(), sqlite3_errmsg(db));
}
g_free(path);
/* Read the configuration file */
key_conf = g_key_file_new();
path = g_build_filename(SYSCONFDIR, "PackageKit", "Slackware.conf", nullptr);
g_key_file_load_from_file(key_conf, path, G_KEY_FILE_NONE, &err);
path = std::filesystem::path(SYSCONFDIR) / "PackageKit" / "Slackware.conf";
g_key_file_load_from_file(key_conf, path.c_str(), G_KEY_FILE_NONE, &err);
if (err)
{
g_error("%s: %s", path, err->message);
g_error("%s: %s", path.c_str(), err->message);
g_error_free(err);
}
conf_file = g_file_new_for_path(path);
conf_file = g_file_new_for_path(path.c_str());
if (!(file_info = g_file_query_info(conf_file,
"time::modified-usec",
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
@@ -87,17 +90,16 @@ void pk_backend_initialize(GKeyFile *conf)
}
if ((ret != SQLITE_OK) && (ret != SQLITE_DONE))
{
g_error("%s: %s", path, sqlite3_errstr(ret));
g_error("%s: %s", path.c_str(), sqlite3_errstr(ret));
}
else if (!sqlite3_changes(db))
{
g_error("Failed to update database: %s", path);
g_error("Failed to update database: %s", path.c_str());
}
g_object_unref(file_info);
g_object_unref(conf_file);
sqlite3_close_v2(db);
g_free(path);
/* Initialize an object for each well-formed repository */
groups = g_key_file_get_groups(key_conf, &groups_len);
@@ -130,22 +132,16 @@ void pk_backend_destroy()
JobData *pk_backend_start_job()
{
char *db_filename = nullptr;
JobData *job_data = g_new0(JobData, 1);
JobData *job_data = new DummyJobData();
auto db_filename = std::filesystem::path(LOCALSTATEDIR) / "cache" / "katja" / "metadata.db";
db_filename = g_build_filename(LOCALSTATEDIR, "cache", "katja", "metadata.db", nullptr);
if (sqlite3_open(db_filename, &job_data->db) == SQLITE_OK) { /* Some SQLite settings */
if (sqlite3_open(db_filename.native().c_str(), &job_data->db) == SQLITE_OK) { /* Some SQLite settings */
sqlite3_exec(job_data->db, "PRAGMA foreign_keys = ON", nullptr, nullptr, nullptr);
}
else
{
std::cerr << db_filename << ": " << sqlite3_errmsg(job_data->db) << std::endl;
goto out;
}
out:
g_free(db_filename);
return job_data;
}
@@ -157,22 +153,19 @@ void pk_backend_stop_job(JobData *job_data)
}
sqlite3_close(job_data->db);
g_free(job_data);
delete job_data;
}
void pk_backend_search_thread(JobData *job_data, GVariant *params, const char *user_data)
// for filters -1 means requesting not installed, 1 - installed, 0 - no filters.
void pk_backend_search_thread(JobData *job_data, std::uint64_t filters, const std::vector<std::string>& vals,
const char *user_data)
{
char **vals;
// -1 means requesting not installed, 1 - installed, 0 - no filters.
guint64 filters;
g_variant_get(params, "(t^a&s)", &filters, &vals);
char *search = g_strjoinv("%", vals);
std::string search = boost::algorithm::join(vals, "%");
const char *generate_query = "SELECT (p1.name || ';' || p1.ver || ';' || p1.arch || ';' || r.repo), p1.summary, "
"p1.full_name FROM pkglist AS p1 NATURAL JOIN repos AS r "
"WHERE p1.%s LIKE '%%%q%%' AND p1.ext NOT LIKE 'obsolete' AND p1.repo_order = "
"(SELECT MIN(p2.repo_order) FROM pkglist AS p2 WHERE p2.name = p1.name GROUP BY p2.name)";
char *query = sqlite3_mprintf(generate_query, user_data, search);
char *query = sqlite3_mprintf(generate_query, user_data, search.c_str());
sqlite3_stmt *stmt;
if ((sqlite3_prepare_v2(job_data->db, query, -1, &stmt, nullptr) == SQLITE_OK))
@@ -204,21 +197,19 @@ void pk_backend_search_thread(JobData *job_data, GVariant *params, const char *u
std::cerr << sqlite3_errmsg(job_data->db) << std::endl;
}
sqlite3_free(query);
g_free(search);
}
void pk_backend_search_files(JobData *job_data, char **values)
void pk_backend_search_files(JobData *job_data, const std::vector<std::string>& values)
{
char *search;
char *query;
sqlite3_stmt *stmt;
Info ret;
search = g_strjoinv("%", values);
std::string search = boost::algorithm::join(values, "%");
query = sqlite3_mprintf("SELECT (p.name || ';' || p.ver || ';' || p.arch || ';' || r.repo), p.summary, "
"p.full_name FROM filelist AS f NATURAL JOIN pkglist AS p NATURAL JOIN repos AS r "
"WHERE f.filename LIKE '%%%q%%' GROUP BY f.full_name", search);
"WHERE f.filename LIKE '%%%q%%' GROUP BY f.full_name", search.c_str());
if ((sqlite3_prepare_v2(job_data->db, query, -1, &stmt, nullptr) == SQLITE_OK))
{
@@ -246,19 +237,20 @@ void pk_backend_search_files(JobData *job_data, char **values)
std::cerr << sqlite3_errmsg(job_data->db) << std::endl;
}
sqlite3_free(query);
g_free(search);
}
void pk_backend_get_details(JobData *job_data, char **package_ids)
{
char *homepage = nullptr;
char** tokens;
std::optional<std::string> homepage;
std::size_t i;
GString *desc;
GRegex *expr;
GMatchInfo *match_info;
GError *err = nullptr;
sqlite3_stmt *stmt;
std::string desc;
std::vector<std::string> tokens;
boost::split(tokens, package_ids[i], boost::is_any_of(";"));
if ((sqlite3_prepare_v2(job_data->db,
"SELECT p.desc, p.cat, p.uncompressed FROM pkglist AS p NATURAL JOIN repos AS r "
@@ -269,17 +261,14 @@ void pk_backend_get_details(JobData *job_data, char **package_ids)
std::cerr << sqlite3_errmsg(job_data->db) << std::endl;
goto out;
}
tokens = g_strsplit(package_ids[0], ";", 4);
sqlite3_bind_text(stmt, 1, tokens[0], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, tokens[3], -1, SQLITE_TRANSIENT);
g_strfreev(tokens);
sqlite3_bind_text(stmt, 1, tokens[0].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, tokens[3].c_str(), -1, SQLITE_TRANSIENT);
if (sqlite3_step(stmt) != SQLITE_ROW)
{
goto out;
}
desc = g_string_new((char *) sqlite3_column_text(stmt, 0));
desc = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0));
/* Regular expression for searching a homepage */
expr = g_regex_new("(?:http|ftp):\\/\\/[[:word:]\\/\\-\\.]+[[:word:]\\/](?=\\.?$)",
@@ -292,15 +281,15 @@ void pk_backend_get_details(JobData *job_data, char **package_ids)
g_error_free(err);
goto out;
}
if (g_regex_match(expr, desc->str, (GRegexMatchFlags) 0, &match_info))
if (g_regex_match(expr, desc.c_str(), (GRegexMatchFlags) 0, &match_info))
{
homepage = g_match_info_fetch(match_info, 0); /* URL */
/* Remove the last sentence with the copied URL */
for (i = desc->len - 1; i > 0; i--)
for (i = desc.size() - 1; i > 0; i--)
{
if ((desc->str[i - 1] == '.') && (desc->str[i] == ' '))
if ((desc[i - 1] == '.') && (desc[i] == ' '))
{
g_string_truncate(desc, i);
desc.erase(std::cbegin(desc) + i);
break;
}
}
@@ -311,16 +300,10 @@ void pk_backend_get_details(JobData *job_data, char **package_ids)
/* Ready */
job_data->details(package_ids[0],
(char *) sqlite3_column_text(stmt, 1),
desc->str,
homepage,
desc.c_str(),
homepage.has_value() ? homepage.value().c_str() : nullptr,
sqlite3_column_int(stmt, 2));
g_free(homepage);
if (desc)
{
g_string_free(desc, true);
}
out:
sqlite3_finalize(stmt);
}
@@ -363,7 +346,6 @@ void pk_backend_resolve(JobData *job_data, char **packages)
void pk_backend_download_packages(JobData *job_data, char **package_ids, const char *directory)
{
char *path, *to_strv[] = {nullptr, nullptr};
unsigned i;
sqlite3_stmt *stmt;
@@ -380,39 +362,38 @@ void pk_backend_download_packages(JobData *job_data, char **package_ids, const c
for (i = 0; package_ids[i]; ++i)
{
char **tokens = g_strsplit(package_ids[i], ";", 4);
std::vector<std::string> tokens;
boost::split(tokens, package_ids[i], boost::is_any_of(";"));
sqlite3_bind_text(stmt, 1, tokens[0], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, tokens[1], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, tokens[2], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, tokens[3], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 1, tokens[0].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, tokens[1].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, tokens[2].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, tokens[3].c_str(), -1, SQLITE_TRANSIENT);
if (sqlite3_step(stmt) == SQLITE_ROW)
{
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3]);
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3].c_str());
if (repo != std::end(repos))
{
(*repo)->download(job_data, directory, tokens[0]);
path = g_build_filename(directory, (char *) sqlite3_column_text(stmt, 1), nullptr);
to_strv[0] = path;
(*repo)->download(job_data, directory, tokens[0].c_str());
auto path = std::filesystem::path(directory)
/ reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
std::vector<std::string> to_strv{ path };
job_data->files(to_strv);
g_free(path);
}
}
sqlite3_clear_bindings(stmt);
sqlite3_reset(stmt);
g_strfreev(tokens);
}
out:
sqlite3_finalize(stmt);
}
void pk_backend_install_packages(JobData *job_data, char **package_ids)
void pk_backend_install_packages(JobData *job_data, const std::vector<std::string> package_ids)
{
char *dest_dir_name;
unsigned i;
gdouble percent_step;
GSList *install_list = nullptr, *l;
std::list<std::string> install_list;
sqlite3_stmt *pkglist_stmt = nullptr, *collection_stmt = nullptr;
if ((sqlite3_prepare_v2(job_data->db,
@@ -435,33 +416,35 @@ void pk_backend_install_packages(JobData *job_data, char **package_ids)
goto out;
}
for (i = 0; package_ids[i]; i++)
for (const std::string& package_id : package_ids)
{
char **tokens = g_strsplit(package_ids[i], ";", 4);
sqlite3_bind_text(pkglist_stmt, 1, tokens[0], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(pkglist_stmt, 2, tokens[1], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(pkglist_stmt, 3, tokens[2], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(pkglist_stmt, 4, tokens[3], -1, SQLITE_TRANSIENT);
std::vector<std::string> tokens;
boost::split(tokens, package_id, boost::is_any_of(";"));
sqlite3_bind_text(pkglist_stmt, 1, tokens[0].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(pkglist_stmt, 2, tokens[1].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(pkglist_stmt, 3, tokens[2].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(pkglist_stmt, 4, tokens[3].c_str(), -1, SQLITE_TRANSIENT);
if (sqlite3_step(pkglist_stmt) == SQLITE_ROW)
{
/* If it isn't a collection */
if (g_strcmp0((char *) sqlite3_column_text(pkglist_stmt, 1), "collections"))
if (strcmp(reinterpret_cast<const char *>(sqlite3_column_text(pkglist_stmt, 1)), "collections"))
{
install_list = g_slist_append(install_list, g_strdup(package_ids[i]));
install_list.push_back(package_id);
}
else
{
sqlite3_bind_text(collection_stmt, 1, tokens[0], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(collection_stmt, 2, tokens[3], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(collection_stmt, 1, tokens[0].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(collection_stmt, 2, tokens[3].c_str(), -1, SQLITE_TRANSIENT);
while (sqlite3_step(collection_stmt) == SQLITE_ROW)
{
katja::Info ret = is_installed((char*) sqlite3_column_text(collection_stmt, 2));
if ((ret == Info::installing) || (ret == Info::updating))
{
install_list = g_slist_append(install_list,
g_strdup((char *) sqlite3_column_text(collection_stmt, 0)));
install_list.push_back(
reinterpret_cast<const char *>(sqlite3_column_text(collection_stmt, 0)));
}
}
sqlite3_clear_bindings(collection_stmt);
@@ -471,71 +454,68 @@ void pk_backend_install_packages(JobData *job_data, char **package_ids)
sqlite3_clear_bindings(pkglist_stmt);
sqlite3_reset(pkglist_stmt);
g_strfreev(tokens);
}
if (install_list)
if (!install_list.empty())
{
/* / 2 means total percentage for installing and for downloading */
percent_step = 100.0 / g_slist_length(install_list) / 2;
percent_step = 100.0 / install_list.size() / 2;
/* Download the packages */
dest_dir_name = g_build_filename(LOCALSTATEDIR, "cache", "katja", "downloads", nullptr);
for (l = install_list, i = 0; l; l = g_slist_next(l), i++)
auto dest_dir_name = std::filesystem::path(LOCALSTATEDIR) / "cache" / "katja" / "downloads";
for (const auto& l : install_list)
{
job_data->set_percentage(percent_step * i);
char **tokens = g_strsplit((char *)(l->data), ";", 4);
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3]);
std::vector<std::string> tokens;
boost::split(tokens, l, boost::is_any_of(";"));
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3].c_str());
if (repo != std::end(repos))
{
(*repo)->download(job_data, dest_dir_name, tokens[0]);
(*repo)->download(job_data, dest_dir_name.native().c_str(), tokens[0].c_str());
}
g_strfreev(tokens);
}
g_free(dest_dir_name);
/* Install the packages */
for (l = install_list; l; l = g_slist_next(l), i++)
for (const auto& l : install_list)
{
job_data->set_percentage(percent_step * i);
char **tokens = g_strsplit((char *)(l->data), ";", 4);
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3]);
std::vector<std::string> tokens;
boost::split(tokens, l, boost::is_any_of(";"));
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3].c_str());
if (repo != std::end(repos))
{
(*repo)->install(job_data, tokens[0]);
}
g_strfreev(tokens);
(*repo)->install(job_data, tokens[0].c_str());
}
}
}
g_slist_free_full(install_list, g_free);
out:
sqlite3_finalize(pkglist_stmt);
sqlite3_finalize(collection_stmt);
}
void pk_backend_remove_packages(JobData* job_data, char **package_ids)
void pk_backend_remove_packages(JobData* job_data, const std::vector<std::string>& package_ids)
{
char *cmd_line;
unsigned i;
double percent_step;
GError *err = nullptr;
/* Add percent_step percents per removed package */
percent_step = 100.0 / g_strv_length(package_ids);
for (i = 0; package_ids[i]; i++)
percent_step = 100.0 / package_ids.size();
for (i = 0; i < package_ids[i].size(); i++)
{
job_data->set_percentage(percent_step * i);
char **tokens = g_strsplit(package_ids[i], ";", 4);
cmd_line = g_strconcat("/sbin/removepkg ", tokens[0], nullptr);
std::vector<std::string> tokens;
boost::split(tokens, package_ids[i], boost::is_any_of(";"));
std::string cmd_line = "/sbin/removepkg " + tokens[0];
/* Pkgtools return always 0 */
g_spawn_command_line_sync(cmd_line, nullptr, nullptr, nullptr, &err);
g_free(cmd_line);
g_strfreev(tokens);
g_spawn_command_line_sync(cmd_line.c_str(), nullptr, nullptr, nullptr, &err);
if (err)
{
@@ -551,7 +531,6 @@ void pk_backend_remove_packages(JobData* job_data, char **package_ids)
void pk_backend_get_updates(JobData *job_data)
{
char *pkg_id, *full_name, *desc;
const char *pkg_metadata_filename;
GFile *pkg_metadata_dir;
GFileEnumerator *pkg_metadata_enumerator;
@@ -588,44 +567,37 @@ void pk_backend_get_updates(JobData *job_data)
while ((pkg_metadata_file_info = g_file_enumerator_next_file(pkg_metadata_enumerator, nullptr, nullptr)))
{
char **tokens;
pkg_metadata_filename = g_file_info_get_name(pkg_metadata_file_info);
tokens = split_package_name(pkg_metadata_filename);
std::vector<std::string> tokens = split_package_name(pkg_metadata_filename).value();
/* Select the package from the database */
sqlite3_bind_text(stmt, 1, tokens[0], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 1, tokens[0].c_str(), -1, SQLITE_TRANSIENT);
/* If there are more packages with the same name, remember the one from the
* repository with the lowest order. */
if ((sqlite3_step(stmt) == SQLITE_ROW)
|| cmp_repo(std::begin(repos), std::end(repos), (const char *) sqlite3_column_text(stmt, 4)) != std::end(repos))
{
std::string full_name{ reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)) };
full_name = g_strdup((char *) sqlite3_column_text(stmt, 0));
if (g_strcmp0(pkg_metadata_filename, full_name))
if (full_name != pkg_metadata_filename)
{ /* Update available */
pkg_id = g_strjoin(";",
(char *) sqlite3_column_text(stmt, 1),
(char *) sqlite3_column_text(stmt, 2),
(char *) sqlite3_column_text(stmt, 3),
(char *) sqlite3_column_text(stmt, 4),
nullptr);
desc = g_strdup((char *) sqlite3_column_text(stmt, 5));
std::array<std::string, 4> id_parts{
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)),
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2)),
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 3)),
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 4))
};
std::string pkg_id = boost::algorithm::join(id_parts, ";");
std::string desc{ reinterpret_cast<const char *>(sqlite3_column_text(stmt, 5)) };
job_data->package(katja::Info::updating, pkg_id, desc);
g_free(desc);
g_free(pkg_id);
job_data->package(katja::Info::updating, pkg_id.c_str(), desc.c_str());
}
g_free(full_name);
}
sqlite3_clear_bindings(stmt);
sqlite3_reset(stmt);
g_strfreev(tokens);
g_object_unref(pkg_metadata_file_info);
}
g_object_unref(pkg_metadata_enumerator);
@@ -636,42 +608,40 @@ out:
void pk_backend_update_packages(JobData *job_data, char **package_ids)
{
char *dest_dir_name, *cmd_line;
char *cmd_line;
unsigned i;
/* Download the packages */
dest_dir_name = g_build_filename(LOCALSTATEDIR, "cache", "katja", "downloads", nullptr);
auto dest_dir_name = std::filesystem::path(LOCALSTATEDIR) / "cache" / "katja" / "downloads";
for (i = 0; package_ids[i]; i++)
{
char **tokens = g_strsplit(package_ids[i], ";", 4);
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3]);
std::vector<std::string> tokens;
boost::split(tokens, package_ids[i], boost::is_any_of(";"));
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3].c_str());
if (repo != std::end(repos))
{
(*repo)->download(job_data, dest_dir_name, tokens[0]);
(*repo)->download(job_data, dest_dir_name.c_str(), tokens[0].c_str());
}
g_strfreev(tokens);
}
g_free(dest_dir_name);
/* Install the packages */
for (i = 0; package_ids[i]; i++)
{
char **tokens = g_strsplit(package_ids[i], ";", 4);
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3]);
std::vector<std::string> tokens;
boost::split(tokens, package_ids[i], boost::is_any_of(";"));
auto repo = cmp_repo(std::begin(repos), std::end(repos), tokens[3].c_str());
if (repo != std::end(repos))
{
(*repo)->install(job_data, tokens[0]);
(*repo)->install(job_data, tokens[0].c_str());
}
g_strfreev(tokens);
}
}
void pk_backend_refresh_cache(JobData *job_data, bool force)
{
char *db_err, *path = nullptr;
std::filesystem::path tmp_dir_name;
char *db_err;
int ret;
std::forward_list<katja::cache_entry> file_list;
GFile *db_file = nullptr;
@@ -680,14 +650,15 @@ void pk_backend_refresh_cache(JobData *job_data, bool force)
sqlite3_stmt *stmt = nullptr;
/* Create temporary directory */
tmp_dir_name = std::filesystem::temp_directory_path() / boost::filesystem::unique_path("katja.%%%%%%").native();
std::filesystem::path tmp_dir_name =
std::filesystem::temp_directory_path() / boost::filesystem::unique_path("katja.%%%%%%").native();
std::filesystem::create_directories(tmp_dir_name);
/* Force the complete cache refresh if the read configuration file is newer than the metadata cache */
if (!force)
{
path = g_build_filename(LOCALSTATEDIR, "cache", "katja", "metadata.db", nullptr);
db_file = g_file_new_for_path(path);
auto path = std::filesystem::path(LOCALSTATEDIR) / "cache" / "katja" / "metadata.db";
db_file = g_file_new_for_path(path.native().c_str());
file_info = g_file_query_info(db_file, "time::modified-usec", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr, &err);
if (err)
{
@@ -748,8 +719,6 @@ out:
{
g_object_unref(db_file);
}
g_free(path);
std::filesystem::remove_all(tmp_dir_name);
}
}
+3 -3
View File
@@ -79,7 +79,7 @@ public:
*
* Returns: %TRUE on success, %FALSE otherwise.
**/
bool download(JobData *job_data, const char *dest_dir_name, char *pkg_name) noexcept
bool download(JobData *job_data, const char *dest_dir_name, const char *pkg_name) noexcept
{
std::filesystem::path dest_filename;
std::string source_url;
@@ -108,7 +108,7 @@ public:
+ "/"
+ reinterpret_cast<const char *>(sqlite3_column_text(statement, 1));
ret = g_file_test(dest_filename.native().c_str(), G_FILE_TEST_EXISTS)
ret = std::filesystem::exists(dest_filename)
|| get_file(&curl, source_url.c_str(), dest_filename.native().c_str()) == CURLE_OK;
if (curl)
@@ -128,7 +128,7 @@ public:
*
* Install a package.
**/
void install(JobData *job_data, char *pkg_name) noexcept
void install(JobData *job_data, const char *pkg_name) noexcept
{
std::filesystem::path pkg_filename;
sqlite3_stmt *statement = nullptr;
+9 -10
View File
@@ -126,7 +126,7 @@ public:
**/
void generate_cache(JobData *job_data, const std::filesystem::path& tmpl) noexcept
{
char **pkg_tokens = nullptr;
std::vector<std::string> pkg_tokens;
char *query = nullptr, *filename = nullptr, *location = nullptr, *summary = nullptr, *line;
unsigned pkg_compressed = 0, pkg_uncompressed = 0;
std::uint8_t pkg_name_len;
@@ -241,10 +241,10 @@ public:
{
summary = g_strndup(summary + 1, strlen(summary) - 2); /* Without ( ) */
}
pkg_tokens = split_package_name(filename);
pkg_name_len = strlen(pkg_tokens[0]); /* Description begins with pkg_name: */
pkg_tokens = split_package_name(filename).value();
pkg_name_len = pkg_tokens[0].size(); /* Description begins with pkg_name: */
}
else if (filename && !strncmp(line, pkg_tokens[0], pkg_name_len))
else if (filename && !strncmp(line, pkg_tokens[0].c_str(), pkg_name_len))
{
g_string_append(desc, line + pkg_name_len + 1);
}
@@ -270,23 +270,22 @@ public:
{
statement = update_statement;
}
sqlite3_bind_text(statement, 1, pkg_tokens[3], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, pkg_tokens[1], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, pkg_tokens[2], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 4, pkg_tokens[4], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 1, pkg_tokens[3].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, pkg_tokens[1].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, pkg_tokens[2].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 4, pkg_tokens[4].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 5, location, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 6, summary, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 7, desc->str, -1, SQLITE_TRANSIENT);
sqlite3_bind_int(statement, 8, pkg_compressed);
sqlite3_bind_int(statement, 9, pkg_uncompressed);
sqlite3_bind_text(statement, 10, pkg_tokens[0], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 10, pkg_tokens[0].c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(statement);
sqlite3_clear_bindings(statement);
sqlite3_reset(statement);
/* Reset for the next package */
g_strfreev(pkg_tokens);
g_free(filename);
g_free(location);
g_free(summary);
+32 -15
View File
@@ -11,6 +11,9 @@ module;
#include <gio/gio.h>
#include <curl/curl.h>
#include <sqlite3.h>
#include <string>
#include <vector>
#include <optional>
export module katja.utils;
@@ -36,12 +39,33 @@ struct JobData
CURL *curl;
virtual void package(Info info, const char *package_id, const char *summary) = 0;
virtual void files(char **) = 0;
virtual void files(const std::vector<std::string>&) = 0;
virtual void details(char *package_id,
const char *group, const char *description, const char *homepage, int uncompressed) = 0;
virtual void set_percentage(double) = 0;
};
struct DummyJobData final : JobData
{
void package(Info info, const char *package_id, const char *summary) override
{
}
void files(const std::vector<std::string>&) override
{
}
void details(char *package_id,
const char *group, const char *description, const char *homepage, int uncompressed) override
{
}
void set_percentage(double) override
{
}
};
/**
* katja::get_file:
* @curl: curl easy handle.
@@ -106,37 +130,30 @@ CURLcode get_file(CURL **curl, const char *source_url, const char *dest)
* katja::split_package_name:
* Got the name of a package, without version-arch-release data.
**/
char **split_package_name(const char *pkg_filename)
std::optional<std::vector<std::string>> split_package_name(const std::string& pkg_filename)
{
char *pkg_full_name;
char **pkg_tokens;
g_return_val_if_fail(pkg_filename != nullptr, nullptr);
int len = strlen(pkg_filename);
int len = pkg_filename.size();
if (len < 4)
{
return nullptr;
return std::nullopt;
}
std::vector<std::string> pkg_tokens(5);
if (pkg_filename[len - 4] == '.')
{
pkg_tokens = static_cast<char **>(g_malloc_n (6, sizeof (char *)));
/* Full name without extension */
len -= 4;
pkg_full_name = g_strndup(pkg_filename, len);
pkg_full_name = g_strndup(pkg_filename.data(), len);
pkg_tokens[3] = g_strdup(pkg_full_name);
/* The last 3 characters should be the file extension */
pkg_tokens[4] = g_strdup(pkg_filename + len + 1);
pkg_tokens[5] = nullptr;
pkg_tokens[4] = g_strdup(pkg_filename.data() + len + 1);
}
else
{
pkg_tokens = static_cast<char **>(g_malloc_n (4, sizeof (char *)));
pkg_full_name = g_strdup(pkg_filename);
pkg_tokens[3] = nullptr;
pkg_full_name = g_strdup(pkg_filename.c_str());
}
/* Reverse all of the bytes in the package filename to get the name, version and the architecture */