Files
katja/backend/dl.cc
Eugen Wissner 97efcb4faa
Some checks failed
Test / build (push) Failing after 27s
Add currently existing PackageKit backend
2026-02-03 14:50:26 +01:00

289 lines
8.0 KiB
C++

#include <sqlite3.h>
#include <stdlib.h>
#include "dl.h"
#include "utils.h"
namespace slack {
/**
* slack::Dl::collect_cache_info:
* @tmpl: temporary directory for downloading the files.
*
* Download files needed to get the information like the list of packages
* in available repositories, updates, package descriptions and so on.
*
* Returns: List of files needed for building the cache.
**/
GSList *
Dl::collect_cache_info (const gchar *tmpl) noexcept
{
CURL *curl = NULL;
GSList *file_list = NULL;
GFile *tmp_dir, *repo_tmp_dir;
/* Create the temporary directory for the repository */
tmp_dir = g_file_new_for_path(tmpl);
repo_tmp_dir = g_file_get_child(tmp_dir, this->get_name ());
g_file_make_directory(repo_tmp_dir, NULL, NULL);
/* There is no ChangeLog yet to check if there are updates or not. Just mark the index file for download */
auto source_dest = static_cast<gchar **> (g_malloc_n(3, sizeof(gchar *)));
source_dest[0] = g_strdup(this->index_file);
source_dest[1] = g_build_filename(tmpl,
this->get_name (),
"IndexFile",
NULL);
source_dest[2] = NULL;
/* Check if the remote file can be found */
if (get_file(&curl, source_dest[0], NULL))
{
g_strfreev(source_dest);
}
else
{
file_list = g_slist_append(file_list, source_dest);
}
g_object_unref(repo_tmp_dir);
g_object_unref(tmp_dir);
if (curl)
{
curl_easy_cleanup(curl);
}
return file_list;
}
/**
* slack::Dl::generate_cache:
* @job: A #PkBackendJob.
* @tmpl: temporary directory for downloading the files.
*
* Download files needed to get the information like the list of packages
* in available repositories, updates, package descriptions and so on.
*
* Returns: List of files needed for building the cache.
**/
void
Dl::generate_cache(PkBackendJob *job, const gchar *tmpl) noexcept
{
gchar **line_tokens, **pkg_tokens, *line, *collection_name = NULL, *list_filename;
gboolean skip = FALSE;
GFile *list_file;
GFileInputStream *fin;
GDataInputStream *data_in = NULL;
sqlite3_stmt *stmt = NULL;
auto job_data = static_cast<JobData *> (pk_backend_job_get_user_data(job));
/* Check if the temporary directory for this repository exists. If so the file metadata have to be generated */
list_filename = g_build_filename(tmpl,
this->get_name (),
"IndexFile",
NULL);
list_file = g_file_new_for_path(list_filename);
if (!(fin = g_file_read(list_file, NULL, NULL)))
{
goto out;
}
data_in = g_data_input_stream_new(G_INPUT_STREAM(fin));
/* Remove the old entries from this repository */
if (sqlite3_prepare_v2(job_data->db,
"DELETE FROM repos WHERE repo LIKE @repo",
-1,
&stmt,
NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, this->get_name (), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
if (sqlite3_prepare_v2(job_data->db,
"INSERT INTO repos (repo_order, repo) VALUES (@repo_order, @repo)",
-1,
&stmt,
NULL) != SQLITE_OK)
{
goto out;
}
sqlite3_bind_int(stmt, 1, this->get_order ());
sqlite3_bind_text(stmt, 2, this->get_name (), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
if (sqlite3_finalize(stmt) != SQLITE_OK)
{
goto out;
}
/* Insert new records */
if ((sqlite3_prepare_v2(job_data->db,
"INSERT INTO pkglist (full_name, name, ver, arch, "
"summary, desc, compressed, uncompressed, cat, repo_order, ext) "
"VALUES (@full_name, @name, @ver, @arch, @summary, "
"@desc, @compressed, @uncompressed, @cat, @repo_order, @ext)",
-1,
&stmt,
NULL) != SQLITE_OK))
{
goto out;
}
sqlite3_exec(job_data->db, "BEGIN TRANSACTION", NULL, NULL, NULL);
while ((line = g_data_input_stream_read_line(data_in, NULL, NULL, NULL)))
{
line_tokens = g_strsplit(line, ":", 0);
if ((g_strv_length(line_tokens) > 6)
&& !this->is_blacklisted (line_tokens[0]))
{
pkg_tokens = split_package_name(line_tokens[0]);
/* If the split_package_name doesn't return a full name and an
* extension, it is a collection. We save its name in this case */
if (pkg_tokens[3])
{
sqlite3_bind_text(stmt, 1, pkg_tokens[3], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 9, "desktop-gnome", -1, SQLITE_STATIC);
if (g_strcmp0(line_tokens[1], "obsolete"))
{
sqlite3_bind_text(stmt, 11, pkg_tokens[4], -1, SQLITE_TRANSIENT);
}
else
{
sqlite3_bind_text(stmt, 11, "obsolete", -1, SQLITE_STATIC);
}
}
else if (!collection_name)
{
collection_name = g_strdup(pkg_tokens[0]);
sqlite3_bind_text(stmt, 1, line_tokens[0], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 9, "collections", -1, SQLITE_STATIC);
sqlite3_bind_null(stmt, 11);
}
else
{
skip = TRUE; /* Skip other candidates for collections */
}
if (skip)
{
skip = FALSE;
}
else
{
sqlite3_bind_text(stmt, 2, pkg_tokens[0], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, pkg_tokens[1], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, pkg_tokens[2], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, line_tokens[2], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, line_tokens[2], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 7, atoi(line_tokens[5]));
sqlite3_bind_int(stmt, 8, atoi(line_tokens[5]));
sqlite3_bind_int(stmt, 10, this->get_order ());
sqlite3_step(stmt);
sqlite3_clear_bindings(stmt);
sqlite3_reset(stmt);
}
g_strfreev(pkg_tokens);
}
g_strfreev(line_tokens);
g_free(line);
}
/* Create a collection entry */
if (collection_name && g_seekable_seek(G_SEEKABLE(data_in), 0, G_SEEK_SET, NULL, NULL)
&& (sqlite3_prepare_v2(job_data->db,
"INSERT INTO collections (name, repo_order, collection_pkg) "
"VALUES (@name, @repo_order, @collection_pkg)",
-1,
&stmt,
NULL) == SQLITE_OK))
{
while ((line = g_data_input_stream_read_line(data_in, NULL, NULL, NULL)))
{
line_tokens = g_strsplit(line, ":", 0);
if ((g_strv_length(line_tokens) > 6)
&& !this->is_blacklisted (line_tokens[0]))
{
pkg_tokens = split_package_name(line_tokens[0]);
/* If not a collection itself */
if (pkg_tokens[3]) /* Save this package as a part of the collection */
{
sqlite3_bind_text(stmt, 1, collection_name, -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 2, this->get_order ());
sqlite3_bind_text(stmt, 3, pkg_tokens[0], -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_clear_bindings(stmt);
sqlite3_reset(stmt);
}
g_strfreev(pkg_tokens);
}
g_strfreev(line_tokens);
g_free(line);
}
sqlite3_finalize(stmt);
}
g_free(collection_name);
sqlite3_exec(job_data->db, "END TRANSACTION", NULL, NULL, NULL);
out:
if (data_in)
{
g_object_unref(data_in);
}
if (fin)
{
g_object_unref(fin);
}
g_object_unref(list_file);
g_free(list_filename);
}
Dl::~Dl () noexcept
{
if (this->blacklist)
{
g_regex_unref (this->blacklist);
}
g_free (this->name);
g_free (this->mirror);
g_free (this->index_file);
}
/**
* slack::Dl::Dl:
* @name: Repository name.
* @mirror: Repository mirror.
* @order: Repository order.
* @blacklist: Repository blacklist.
* @index_file: The index file URL.
*
* Constructor.
*
* Return value: New #slack::Dl.
**/
Dl::Dl (const gchar *name, const gchar *mirror,
guint8 order, const gchar *blacklist, gchar *index_file) noexcept
{
GRegex *regex;
if (blacklist)
{
regex = static_cast<GRegex *> (g_regex_new (blacklist,
G_REGEX_OPTIMIZE, static_cast<GRegexMatchFlags> (0), NULL));
}
else
{
regex = NULL;
}
this->name = g_strdup (name);
this->mirror = g_strdup (mirror);
this->order = order;
this->blacklist = regex;
this->index_file = index_file;
}
}