Replace glib data structures with STL
This commit is contained in:
+118
-149
@@ -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]);
|
||||
(*repo)->install(job_data, tokens[0].c_str());
|
||||
}
|
||||
g_strfreev(tokens);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user