Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/rpm-software-management/createrepo_c.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Alley <dalley@redhat.com>2022-06-22 06:48:44 +0300
committeramatej <matej.ales@seznam.cz>2022-06-28 09:27:56 +0300
commit8fb99cde21ba409ed9d12c40e020038974032ba1 (patch)
tree9ee71daa9e84af3ab227a4f2a221747af6cc6cf5
parent32971377b7fa4e999b039c58b4a0c9ae8c5ac95e (diff)
createrepo_c shouldn't silently produce duplicate-NEVRA repos
Return an error code and print a message when more than one package have the same NEVRA. closes #307
-rw-r--r--src/createrepo_c.c57
-rw-r--r--src/dumper_thread.c13
-rw-r--r--src/dumper_thread.h4
3 files changed, 73 insertions, 1 deletions
diff --git a/src/createrepo_c.c b/src/createrepo_c.c
index ff8ce82..ad99ff6 100644
--- a/src/createrepo_c.c
+++ b/src/createrepo_c.c
@@ -553,6 +553,31 @@ load_old_metadata(cr_Metadata **md,
g_hash_table_size(cr_metadata_hashtable(*md)));
}
+// Sorting function for location_href strings, by length.
+// Compatible with g_array_sort()
+static int strlensort(gconstpointer a, gconstpointer b)
+{
+ // Function is supposed to take a double-pointer so unfortunately you cannot pass a
+ // string-comparison function directly.
+ gchar **a_ptr = (gchar **)a;
+ gchar **b_ptr = (gchar **)b;
+
+ int a_len = strnlen(*a_ptr, 4096);
+ int b_len = strnlen(*b_ptr, 4096);
+ if (a_len > b_len)
+ {
+ return 1;
+ }
+ else if (b_len > a_len)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
int
main(int argc, char **argv)
{
@@ -1276,6 +1301,7 @@ main(int argc, char **argv)
user_data.repodir_name_len = strlen(in_dir);
user_data.task_count = task_count;
user_data.package_count = 0;
+ user_data.nevra_table = g_hash_table_new(g_str_hash, g_str_equal);
user_data.skip_stat = cmd_options->skip_stat;
user_data.old_metadata = old_metadata;
user_data.id_pri = 0;
@@ -1290,6 +1316,7 @@ main(int argc, char **argv)
user_data.had_errors = 0;
user_data.output_pkg_list = output_pkg_list;
+ g_mutex_init(&(user_data.mutex_nevra_table));
g_mutex_init(&(user_data.mutex_output_pkg_list));
g_mutex_init(&(user_data.mutex_pri));
g_mutex_init(&(user_data.mutex_fil));
@@ -1310,9 +1337,36 @@ main(int argc, char **argv)
// Wait until pool is finished
g_thread_pool_free(pool, FALSE, TRUE);
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init(&iter, user_data.nevra_table);
+ while (g_hash_table_iter_next(&iter, &key, &value))
+ {
+ gchar *nevra = (gchar *) key;
+ GArray *locations = (GArray *) value;
+ if (locations->len > 1) {
+ g_warning("Package '%s' has duplicate metadata entries, only one should exist", nevra);
+
+ g_array_sort(locations, strlensort);
+
+ for (int i=0; i<locations->len; i++) {
+ g_warning(" Sourced from location: \'%s\'", g_array_index(locations, gchar *, i));
+ }
+ }
+
+ g_hash_table_iter_steal(&iter);
+ g_free(nevra);
+ for (int i = 0; i < locations->len; i++) {
+ g_free(g_array_index(locations, gchar *, i));
+ }
+ g_array_free(locations, TRUE);
+ }
+ g_hash_table_destroy(user_data.nevra_table);
+
// if there were any errors, exit nonzero
if ( user_data.had_errors ) {
- exit_val = 2;
+ exit_val = 2;
}
g_message("Pool finished%s", (user_data.had_errors ? " with errors" : ""));
@@ -1453,6 +1507,7 @@ main(int argc, char **argv)
}
g_queue_free(user_data.buffer);
+ g_mutex_clear(&(user_data.mutex_nevra_table));
g_mutex_clear(&(user_data.mutex_output_pkg_list));
g_mutex_clear(&(user_data.mutex_pri));
g_mutex_clear(&(user_data.mutex_fil));
diff --git a/src/dumper_thread.c b/src/dumper_thread.c
index c94f26e..b949ffb 100644
--- a/src/dumper_thread.c
+++ b/src/dumper_thread.c
@@ -551,6 +551,19 @@ cr_dumper_thread(gpointer data, gpointer user_data)
}
#endif
+ // Allow checking that the same package (NEVRA) isn't present multiple times in the metadata
+ // Keep a hashtable of NEVRA mapped to an array-list of location_href values
+ g_mutex_lock(&(udata->mutex_nevra_table));
+ gchar *nevra = cr_package_nevra(pkg);
+ GArray *pkg_locations = g_hash_table_lookup(udata->nevra_table, nevra);
+ if (!pkg_locations) {
+ pkg_locations = g_array_new(FALSE, TRUE, sizeof(gchar *));
+ g_hash_table_insert(udata->nevra_table, nevra, pkg_locations);
+ }
+ gchar *location = g_strdup(pkg->location_href);
+ g_array_append_val(pkg_locations, location);
+ g_mutex_unlock(&(udata->mutex_nevra_table));
+
// Buffering stuff
g_mutex_lock(&(udata->mutex_buffer));
diff --git a/src/dumper_thread.h b/src/dumper_thread.h
index 60f984d..fb815cb 100644
--- a/src/dumper_thread.h
+++ b/src/dumper_thread.h
@@ -69,6 +69,10 @@ struct UserData {
long task_count; // Total number of task to process
long package_count; // Total number of packages processed
+ // Duplicate package error checking
+ GMutex mutex_nevra_table; // Mutex for the table of NEVRAs
+ GHashTable *nevra_table; // Table of NEVRAs, with a list of location_href as key
+
// Update stuff
gboolean skip_stat; // Skip stat() while updating
cr_Metadata *old_metadata; // Loaded metadata