diff options
Diffstat (limited to 'backend/job.cpp')
| -rw-r--r-- | backend/job.cpp | 776 |
1 files changed, 776 insertions, 0 deletions
diff --git a/backend/job.cpp b/backend/job.cpp new file mode 100644 index 0000000..669e02a --- /dev/null +++ b/backend/job.cpp @@ -0,0 +1,776 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +module; + +#include "config.h" +#include <filesystem> +#include <gio/gio.h> +#include <cstdint> +#include <stdlib.h> +#include <iostream> +#include <zlib.h> +#include <curl/curl.h> +#include <glib/gstdio.h> +#include <sqlite3.h> + +export module katja.job; + +import katja.utils; +import katja.pkgtools; +import katja.slackpkg; + +namespace katja +{ +static GSList *repos = nullptr; + +void pk_backend_initialize(GKeyFile *conf) +{ + char *path, **groups; + int ret; + gushort i; + gsize groups_len; + GFile *conf_file; + GFileInfo *file_info; + GKeyFile *key_conf; + GError *err = nullptr; + void *repo = nullptr; + sqlite3 *db; + sqlite3_stmt *stmt; + + g_debug("backend: initialize"); + 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", "PackageKit", "metadata", "metadata.db", nullptr); + if (sqlite3_open(path, &db) != SQLITE_OK) + { + g_error("%s: %s", path, 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); + if (err) + { + g_error("%s: %s", path, err->message); + g_error_free(err); + } + + conf_file = g_file_new_for_path(path); + if (!(file_info = g_file_query_info(conf_file, + "time::modified-usec", + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + nullptr, + &err))) + { + g_error("%s", err->message); + g_error_free(err); + } + + if ((ret = sqlite3_prepare_v2(db, + "UPDATE cache_info SET value = ? WHERE key LIKE 'last_modification'", + -1, + &stmt, + nullptr)) == SQLITE_OK) { + ret = sqlite3_bind_int(stmt, 1, g_file_info_get_attribute_uint32(file_info, "time::modified-usec")); + if (ret == SQLITE_OK) + { + ret = sqlite3_step(stmt); + } + sqlite3_finalize(stmt); + } + if ((ret != SQLITE_OK) && (ret != SQLITE_DONE)) + { + g_error("%s: %s", path, sqlite3_errstr(ret)); + } + else if (!sqlite3_changes(db)) + { + g_error("Failed to update database: %s", path); + } + + 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); + for (i = 0; i < groups_len; i++) + { + char *blacklist = g_key_file_get_string(key_conf, groups[i], "Blacklist", nullptr); + char *mirror = g_key_file_get_string(key_conf, groups[i], "Mirror", nullptr); + + if (g_key_file_has_key(key_conf, groups[i], "Priority", nullptr)) + { + repo = new Slackpkg(groups[i], mirror, i + 1, blacklist, + g_key_file_get_string_list(key_conf, groups[i], "Priority", nullptr, nullptr)); + repos = g_slist_append(repos, repo); + } + g_free(mirror); + g_free(blacklist); + } + g_free(groups); + + g_key_file_free(key_conf); +} + +void pk_backend_destroy() +{ + g_debug("backend: destroy"); + + for (GSList *l = repos; l; l = g_slist_next(l)) + { + delete static_cast<Pkgtools *>(l->data); + } + + g_slist_free(repos); + curl_global_cleanup(); +} + +JobData *pk_backend_start_job() +{ + char *db_filename = nullptr; + JobData *job_data = g_new0(JobData, 1); + + db_filename = g_build_filename(LOCALSTATEDIR, "cache", "PackageKit", "metadata", "metadata.db", nullptr); + if (sqlite3_open(db_filename, &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; +} + +void pk_backend_stop_job(JobData *job_data) +{ + if (job_data->curl) + { + curl_easy_cleanup(job_data->curl); + } + + sqlite3_close(job_data->db); + g_free(job_data); +} + +void pk_backend_search_thread(JobData *job_data, GVariant *params, 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); + + 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); + + sqlite3_stmt *stmt; + if ((sqlite3_prepare_v2(job_data->db, query, -1, &stmt, nullptr) == SQLITE_OK)) + { + /* Now we're ready to output all packages */ + while (sqlite3_step(stmt) == SQLITE_ROW) + { + katja::Info info = katja::is_installed( + reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2))); + + if ((info == katja::Info::installed || info == katja::Info::updating) + && filters != -1) + { + job_data->package(katja::Info::installed, + reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), + reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1))); + } + else if (info == katja::Info::installing && filters != 1) + { + job_data->package(katja::Info::available, + reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), + reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1))); + } + } + sqlite3_finalize(stmt); + } + else + { + 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) +{ + char *search; + char *query; + sqlite3_stmt *stmt; + Info ret; + + search = g_strjoinv("%", 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); + + if ((sqlite3_prepare_v2(job_data->db, query, -1, &stmt, nullptr) == SQLITE_OK)) + { + /* Now we're ready to output all packages */ + while (sqlite3_step(stmt) == SQLITE_ROW) + { + ret = is_installed((char*) sqlite3_column_text(stmt, 2)); + if ((ret == Info::installed) || (ret == Info::updating)) + { + job_data->package(katja::Info::installed, + (char*) sqlite3_column_text(stmt, 0), + (char*) sqlite3_column_text(stmt, 1)); + } + else if (ret == katja::Info::installing) + { + job_data->package(katja::Info::available, + (char*) sqlite3_column_text(stmt, 0), + (char*) sqlite3_column_text(stmt, 1)); + } + } + sqlite3_finalize(stmt); + } + else + { + 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; + gsize i; + GString *desc; + GRegex *expr; + GMatchInfo *match_info; + GError *err = nullptr; + sqlite3_stmt *stmt; + + if ((sqlite3_prepare_v2(job_data->db, + "SELECT p.desc, p.cat, p.uncompressed FROM pkglist AS p NATURAL JOIN repos AS r " + "WHERE name LIKE @name AND r.repo LIKE @repo", + -1, + &stmt, + nullptr) != SQLITE_OK)) { + 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); + + if (sqlite3_step(stmt) != SQLITE_ROW) + { + goto out; + } + desc = g_string_new((char *) sqlite3_column_text(stmt, 0)); + + /* Regular expression for searching a homepage */ + expr = g_regex_new("(?:http|ftp):\\/\\/[[:word:]\\/\\-\\.]+[[:word:]\\/](?=\\.?$)", + (GRegexCompileFlags)(G_REGEX_OPTIMIZE | G_REGEX_DUPNAMES), + (GRegexMatchFlags)(0), + &err); + if (err) + { + std::cerr << err->message << std::endl; + g_error_free(err); + goto out; + } + if (g_regex_match(expr, desc->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--) + { + if ((desc->str[i - 1] == '.') && (desc->str[i] == ' ')) + { + g_string_truncate(desc, i); + break; + } + } + g_match_info_free(match_info); + } + g_regex_unref(expr); + + /* Ready */ + job_data->details(package_ids[0], + (char *) sqlite3_column_text(stmt, 1), + desc->str, + homepage, + sqlite3_column_int(stmt, 2)); + + g_free(homepage); + if (desc) + { + g_string_free(desc, true); + } + +out: + sqlite3_finalize(stmt); +} + +void pk_backend_resolve(JobData *job_data, char **packages) +{ + char **val; + sqlite3_stmt *stmt; + + if ((sqlite3_prepare_v2(job_data->db, + "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.name LIKE @search AND p1.repo_order = " + "(SELECT MIN(p2.repo_order) FROM pkglist AS p2 WHERE p2.name = p1.name GROUP BY p2.name)", + -1, + &stmt, + nullptr) == SQLITE_OK)) { + /* Output packages matching each pattern */ + for (val = packages; *val; val++) + { + sqlite3_bind_text(stmt, 1, *val, -1, SQLITE_TRANSIENT); + + while (sqlite3_step(stmt) == SQLITE_ROW) + { + job_data->package(katja::Info::available, + (char *) sqlite3_column_text(stmt, 0), + (char *) sqlite3_column_text(stmt, 1)); + } + + sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); + } + sqlite3_finalize(stmt); + } + else + { + std::cerr << sqlite3_errmsg(job_data->db) << std::endl; + } +} + +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; + + if ((sqlite3_prepare_v2(job_data->db, + "SELECT summary, (full_name || '.' || ext) FROM pkglist NATURAL JOIN repos " + "WHERE name LIKE @name AND ver LIKE @ver AND arch LIKE @arch AND repo LIKE @repo", + -1, + &stmt, + nullptr) != SQLITE_OK)) + { + std::cerr << sqlite3_errmsg(job_data->db) << std::endl; + goto out; + } + + for (i = 0; package_ids[i]; ++i) + { + char **tokens = g_strsplit(package_ids[i], ";", 4); + + 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); + if (sqlite3_step(stmt) == SQLITE_ROW) + { + GSList *repo; + if ((repo = g_slist_find_custom(repos, tokens[3], cmp_repo))) + { + static_cast<Pkgtools *>(repo->data)->download(job_data, directory, tokens[0]); + path = g_build_filename(directory, (char *) sqlite3_column_text(stmt, 1), nullptr); + to_strv[0] = 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) +{ + char *dest_dir_name; + unsigned i; + gdouble percent_step; + GSList *install_list = nullptr, *l; + sqlite3_stmt *pkglist_stmt = nullptr, *collection_stmt = nullptr; + + if ((sqlite3_prepare_v2(job_data->db, + "SELECT summary, cat FROM pkglist NATURAL JOIN repos " + "WHERE name LIKE @name AND ver LIKE @ver AND arch LIKE @arch AND repo LIKE @repo", + -1, + &pkglist_stmt, + nullptr) != SQLITE_OK) || + (sqlite3_prepare_v2(job_data->db, + "SELECT (c.collection_pkg || ';' || p.ver || ';' || p.arch || ';' || r.repo), p.summary, " + "p.full_name, p.ext FROM collections AS c " + "JOIN pkglist AS p ON c.collection_pkg = p.name " + "JOIN repos AS r ON p.repo_order = r.repo_order " + "WHERE c.name LIKE @name AND r.repo LIKE @repo", + -1, + &collection_stmt, + nullptr) != SQLITE_OK)) + { + std::cerr << sqlite3_errmsg(job_data->db) << std::endl; + goto out; + } + + for (i = 0; package_ids[i]; i++) + { + 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); + + if (sqlite3_step(pkglist_stmt) == SQLITE_ROW) + { + /* If it isn't a collection */ + if (g_strcmp0((char *) sqlite3_column_text(pkglist_stmt, 1), "collections")) + { + install_list = g_slist_append(install_list, g_strdup(package_ids[i])); + } + else + { + sqlite3_bind_text(collection_stmt, 1, tokens[0], -1, SQLITE_TRANSIENT); + sqlite3_bind_text(collection_stmt, 2, tokens[3], -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))); + } + } + sqlite3_clear_bindings(collection_stmt); + sqlite3_reset(collection_stmt); + } + } + + sqlite3_clear_bindings(pkglist_stmt); + sqlite3_reset(pkglist_stmt); + g_strfreev(tokens); + } + + if (install_list) + { + /* / 2 means total percentage for installing and for downloading */ + percent_step = 100.0 / g_slist_length(install_list) / 2; + + /* Download the packages */ + dest_dir_name = g_build_filename(LOCALSTATEDIR, "cache", "PackageKit", "downloads", nullptr); + for (l = install_list, i = 0; l; l = g_slist_next(l), i++) + { + char **tokens; + GSList *repo; + + job_data->set_percentage(percent_step * i); + tokens = g_strsplit((char *)(l->data), ";", 4); + repo = g_slist_find_custom(repos, tokens[3], cmp_repo); + + if (repo) + { + static_cast<Pkgtools *>(repo->data)->download(job_data, dest_dir_name, tokens[0]); + } + g_strfreev(tokens); + } + g_free(dest_dir_name); + + /* Install the packages */ + for (l = install_list; l; l = g_slist_next(l), i++) + { + char **tokens; + GSList *repo; + + job_data->set_percentage(percent_step * i); + tokens = g_strsplit((char *)(l->data), ";", 4); + repo = g_slist_find_custom(repos, tokens[3], cmp_repo); + + if (repo) + { + static_cast<Pkgtools *>(repo->data)->install(job_data, tokens[0]); + } + 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) +{ + char *cmd_line; + unsigned i; + gdouble 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++) + { + char **tokens; + + job_data->set_percentage(percent_step * i); + tokens = g_strsplit(package_ids[i], ";", 4); + cmd_line = g_strconcat("/sbin/removepkg ", tokens[0], nullptr); + + /* Pkgtools return always 0 */ + g_spawn_command_line_sync(cmd_line, nullptr, nullptr, nullptr, &err); + + g_free(cmd_line); + g_strfreev(tokens); + + if (err) + { + std::cerr << err->message << std::endl; + g_error_free(err); + + return; + } + + job_data->set_percentage(100); + } +} + +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; + GFileInfo *pkg_metadata_file_info; + GError *err = nullptr; + sqlite3_stmt *stmt; + + if ((sqlite3_prepare_v2(job_data->db, + "SELECT p1.full_name, p1.name, p1.ver, p1.arch, r.repo, p1.summary, p1.ext " + "FROM pkglist AS p1 NATURAL JOIN repos AS r " + "WHERE p1.name LIKE @name AND p1.repo_order = " + "(SELECT MIN(p2.repo_order) FROM pkglist AS p2 WHERE p2.name = p1.name GROUP BY p2.name)", + -1, + &stmt, + nullptr) != SQLITE_OK)) + { + std::cerr << sqlite3_errmsg(job_data->db) << std::endl; + goto out; + } + + /* Read the package metadata directory and comprare all installed packages with ones in the cache */ + pkg_metadata_dir = g_file_new_for_path("/var/log/packages"); + pkg_metadata_enumerator = g_file_enumerate_children(pkg_metadata_dir, "standard::name", + G_FILE_QUERY_INFO_NONE, + nullptr, + &err); + g_object_unref(pkg_metadata_dir); + if (err) + { + std::cerr << "/var/log/packages: " << err->message << std::endl; + g_error_free(err); + goto out; + } + + 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); + + /* Select the package from the database */ + sqlite3_bind_text(stmt, 1, tokens[0], -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) + || g_slist_find_custom(repos, ((char *) sqlite3_column_text(stmt, 4)), cmp_repo)) + { + + full_name = g_strdup((char *) sqlite3_column_text(stmt, 0)); + + if (g_strcmp0(pkg_metadata_filename, full_name)) + { /* 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)); + + job_data->package(katja::Info::updating, pkg_id, desc); + + g_free(desc); + g_free(pkg_id); + } + 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); + +out: + sqlite3_finalize(stmt); +} + +void pk_backend_update_packages(JobData *job_data, char **package_ids) +{ + char *dest_dir_name, *cmd_line; + unsigned i; + + /* Download the packages */ + dest_dir_name = g_build_filename(LOCALSTATEDIR, "cache", "PackageKit", "downloads", nullptr); + for (i = 0; package_ids[i]; i++) + { + char **tokens = g_strsplit(package_ids[i], ";", 4); + GSList *repo = g_slist_find_custom(repos, tokens[3], cmp_repo); + + if (repo) + { + static_cast<Pkgtools *>(repo->data)->download(job_data, dest_dir_name, tokens[0]); + } + 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); + GSList *repo = g_slist_find_custom(repos, tokens[3], cmp_repo); + + if (repo) + { + static_cast<Pkgtools *>(repo->data)->install(job_data, tokens[0]); + } + g_strfreev(tokens); + } +} + +void pk_backend_refresh_cache(JobData *job_data, bool force) +{ + char *tmp_dir_name, *db_err, *path = nullptr; + int ret; + GSList *file_list = nullptr; + GFile *db_file = nullptr; + GFileInfo *file_info = nullptr; + GError *err = nullptr; + sqlite3_stmt *stmt = nullptr; + + /* Create temporary directory */ + tmp_dir_name = g_dir_make_tmp("PackageKit.XXXXXX", &err); + if (!tmp_dir_name) + { + std::cerr << err->message << std::endl; + g_error_free(err); + return; + } + + /* Force the complete cache refresh if the read configuration file is newer than the metadata cache */ + if (!force) + { + path = g_build_filename(LOCALSTATEDIR, "cache", "PackageKit", "metadata", "metadata.db", nullptr); + db_file = g_file_new_for_path(path); + file_info = g_file_query_info(db_file, "time::modified-usec", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr, &err); + if (err) + { + std::cerr << path << ": " << err->message; + g_error_free(err); + goto out; + } + ret = sqlite3_prepare_v2(job_data->db, + "SELECT value FROM cache_info WHERE key LIKE 'last_modification'", + -1, + &stmt, + nullptr); + if ((ret != SQLITE_OK) || ((ret = sqlite3_step(stmt)) != SQLITE_ROW)) + { + std::cerr << path << ": " << sqlite3_errstr(ret) << std::endl; + goto out; + } + if ((std::uint32_t) sqlite3_column_int(stmt, 0) > g_file_info_get_attribute_uint32(file_info, "time::modified-usec")) + { + force = true; + } + } + if (force) /* It should empty all tables */ + { + if (sqlite3_exec(job_data->db, "DELETE FROM repos", nullptr, 0, &db_err) != SQLITE_OK) + { + std::cerr << db_err << std::endl; + sqlite3_free(db_err); + goto out; + } + } + + // Get list of files that should be downloaded. + for (GSList *l = repos; l; l = g_slist_next(l)) + { + file_list = g_slist_concat(file_list, + static_cast<Pkgtools *>(l->data)->collect_cache_info(tmp_dir_name)); + } + + /* Download repository */ + for (GSList *l = file_list; l; l = g_slist_next(l)) + { + get_file(&job_data->curl, static_cast<char **>(l->data)[0], + static_cast<char **>(l->data)[1]); + } + g_slist_free_full(file_list, (GDestroyNotify) g_strfreev); + + /* Refresh cache */ + for (GSList *l = repos; l; l = g_slist_next(l)) + { + static_cast<Pkgtools *>(l->data)->generate_cache(job_data, tmp_dir_name); + } + +out: + sqlite3_finalize(stmt); + if (file_info) + { + g_object_unref(file_info); + } + if (db_file) + { + g_object_unref(db_file); + } + g_free(path); + + std::filesystem::remove_all(tmp_dir_name); + g_rmdir(tmp_dir_name); + g_free(tmp_dir_name); +} +} |
