From f13b04201dbb3aa49229e16004d23c10d0c338c7 Mon Sep 17 00:00:00 2001 From: Tomas Mlcoch Date: Mon, 14 Oct 2013 16:54:43 +0200 Subject: [PATCH] Add cr_repomd_sort_records() function. --- deltarepo/deltarepo/applicator.py | 1 + deltarepo/deltarepo/generator.py | 1 + src/createrepo_c.c | 2 ++ src/python/repomd-py.c | 14 +++++++++++ src/repomd.c | 51 +++++++++++++++++++++++++++++++++++++++ src/repomd.h | 7 ++++++ 6 files changed, 76 insertions(+) diff --git a/deltarepo/deltarepo/applicator.py b/deltarepo/deltarepo/applicator.py index 110bbf1..a5bfa6e 100644 --- a/deltarepo/deltarepo/applicator.py +++ b/deltarepo/deltarepo/applicator.py @@ -282,6 +282,7 @@ class DeltaRepoApplicator(LoggingInterface): # Prepare and write out the new repomd.xml self._debug("Preparing repomd.xml ...") self.new_repomd.set_repoid(self.new_id, self.repoid_type_str) + self.new_repomd.sort_records() new_repomd_xml = self.new_repomd.xml_dump() self._debug("Writing repomd.xml ...") diff --git a/deltarepo/deltarepo/generator.py b/deltarepo/deltarepo/generator.py index d89d924..d69e69d 100644 --- a/deltarepo/deltarepo/generator.py +++ b/deltarepo/deltarepo/generator.py @@ -295,6 +295,7 @@ class DeltaRepoGenerator(LoggingInterface): deltarepoid = "{0}-{1}".format(self.bundle["old_repoid"], self.bundle["new_repoid"]) self.delta_repomd.set_repoid(deltarepoid, self.repoid_type_str) + self.delta_repomd.sort_records() delta_repomd_xml = self.delta_repomd.xml_dump() self._debug("Writing repomd.xml ...") diff --git a/src/createrepo_c.c b/src/createrepo_c.c index 497d7af..9f52838 100644 --- a/src/createrepo_c.c +++ b/src/createrepo_c.c @@ -1391,6 +1391,8 @@ main(int argc, char **argv) if (cmd_options->revision) cr_repomd_set_revision(repomd_obj, cmd_options->revision); + cr_repomd_sort_records(repomd_obj); + char *repomd_xml = cr_xml_dump_repomd(repomd_obj, &tmp_err); assert(repomd_xml || tmp_err); cr_repomd_free(repomd_obj); diff --git a/src/python/repomd-py.c b/src/python/repomd-py.c index 3bdd79d..25b8a1c 100644 --- a/src/python/repomd-py.c +++ b/src/python/repomd-py.c @@ -213,6 +213,18 @@ add_content_tag(_RepomdObject *self, PyObject *args) Py_RETURN_NONE; } +PyDoc_STRVAR(sort_records__doc__, +"sort_records() -> str\n\n" +"Sort repomd records to the createrepo_c prefered order"); + +static PyObject * +sort_records(_RepomdObject *self, void *nothing) +{ + CR_UNUSED(nothing); + cr_repomd_sort_records(self->repomd); + Py_RETURN_NONE; +} + PyDoc_STRVAR(xml_dump__doc__, "xml_dump() -> str\n\n" "Generate xml representation of the repomd"); @@ -246,6 +258,8 @@ static struct PyMethodDef repomd_methods[] = { add_repo_tag__doc__}, {"add_content_tag", (PyCFunction)add_content_tag, METH_VARARGS, add_content_tag__doc__}, + {"sort_records", (PyCFunction)sort_records, METH_NOARGS, + sort_records__doc__}, {"xml_dump", (PyCFunction)xml_dump, METH_NOARGS, xml_dump__doc__}, {NULL} /* sentinel */ diff --git a/src/repomd.c b/src/repomd.c index 63ef93d..1f3b98e 100644 --- a/src/repomd.c +++ b/src/repomd.c @@ -704,3 +704,54 @@ cr_repomd_get_record(cr_Repomd *repomd, const char *type) } return NULL; } + +static gint +record_type_value(const char *type) { + if (!g_strcmp0(type, "primary")) + return 1; + if (!g_strcmp0(type, "filelists")) + return 2; + if (!g_strcmp0(type, "other")) + return 3; + if (!g_strcmp0(type, "primary_db")) + return 4; + if (!g_strcmp0(type, "filelists_db")) + return 5; + if (!g_strcmp0(type, "other_db")) + return 6; + return 7; +} + +static gint +record_cmp(gconstpointer _a, gconstpointer _b) +{ + const cr_RepomdRecord *a = _a; + const cr_RepomdRecord *b = _b; + + gint a_val = record_type_value(a->type); + gint b_val = record_type_value(b->type); + + // Keep base metadata files sorted by logical order (primary, filelists, ..) + if (a_val < b_val) return -1; + if (a_val > b_val) return 1; + + // Other metadta sort by the type + gint ret = g_strcmp0(a->type, b->type); + if (ret) + return ret; + + // If even the type is not sufficient, use location href + ret = g_strcmp0(a->location_href, b->location_href); + + // If even the location href is not sufficient, use the location base + return ret ? ret : g_strcmp0(a->location_base, b->location_base); +} + +void +cr_repomd_sort_records(cr_Repomd *repomd) +{ + if (!repomd) + return; + + repomd->records = g_slist_sort(repomd->records, record_cmp); +} diff --git a/src/repomd.h b/src/repomd.h index 2b056c7..442a679 100644 --- a/src/repomd.h +++ b/src/repomd.h @@ -238,6 +238,13 @@ cr_RepomdRecord *cr_repomd_get_record(cr_Repomd *repomd, const char *type); */ void cr_repomd_detach_record(cr_Repomd *repomd, cr_RepomdRecord *rec); +/** Records are stored in order they were added to the repomd. + * Because sometimes deterministic output is desirable this function + * exists. + * @param repomd cr_Repomd object + */ +void cr_repomd_sort_records(cr_Repomd *repomd); + /** Frees cr_Repomd object and all its cr_RepomdRecord objects * @param repomd cr_Repomd object */ -- 2.7.4