diff --git a/.createrepo_c.metadata b/.createrepo_c.metadata
index 5f0bcc7..3341249 100644
--- a/.createrepo_c.metadata
+++ b/.createrepo_c.metadata
@@ -1 +1 @@
-60f5c59be623b10b8a7282d251c496cd49083268 SOURCES/createrepo_c-0.11.0.tar.gz
+e85178e66ca8c2157ef2da31cb8c25ff456631fd SOURCES/createrepo_c-0.15.1.tar.gz
diff --git a/.gitignore b/.gitignore
index 7b723f4..81a3d81 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/createrepo_c-0.11.0.tar.gz
+SOURCES/createrepo_c-0.15.1.tar.gz
diff --git a/SOURCES/0001-Consistently-produce-valid-URLs-by-prepending-protocol-RhBug1632121.patch b/SOURCES/0001-Consistently-produce-valid-URLs-by-prepending-protocol-RhBug1632121.patch
deleted file mode 100644
index 72cdf63..0000000
--- a/SOURCES/0001-Consistently-produce-valid-URLs-by-prepending-protocol-RhBug1632121.patch
+++ /dev/null
@@ -1,121 +0,0 @@
-From f67be7b6045fb4be42ad226d0054edd685d33b9f Mon Sep 17 00:00:00 2001
-From: Aleš Matěj <amatej@redhat.com>
-Date: Tue, 12 Feb 2019 12:59:14 +0100
-Subject: [PATCH] Consistently produce valid URLs by prepending protocol. (RhBug:1632121)
-
----
- src/mergerepo_c.c      | 17 ++---------------
- src/xml_dump.c         |  8 ++++++++
- src/xml_dump.h         |  8 ++++++++
- src/xml_dump_primary.c |  6 ++++--
- 4 files changed, 22 insertions(+), 17 deletions(-)
-
-diff --git a/src/mergerepo_c.c b/src/mergerepo_c.c
-index 94b929c..1ae3a9b 100644
---- a/src/mergerepo_c.c
-+++ b/src/mergerepo_c.c
-@@ -496,17 +496,6 @@ cr_srpm_val_destroy(gpointer data)
- }
- 
- 
--/** Prepend protocol if necessary
-- */
--static gchar *
--prepend_protocol(const gchar *url)
--{
--    if (url && *url == '/')
--        return g_strconcat("file://", url, NULL);
--    return g_strdup(url);
--}
--
--
- int
- koji_stuff_prepare(struct KojiMergedReposStuff **koji_stuff_ptr,
-                    struct CmdOptions *cmd_options,
-@@ -820,9 +809,7 @@ add_package(cr_Package *pkg,
-     if (!list) {
-         list = g_slist_prepend(list, pkg);
-         if ((!pkg->location_base || *pkg->location_base == '\0') && repopath) {
--            _cleanup_free_ gchar *repopath_with_protocol = NULL;
--            repopath_with_protocol = prepend_protocol(repopath);
--            pkg->location_base = cr_safe_string_chunk_insert(pkg->chunk, repopath_with_protocol);
-+            pkg->location_base = cr_safe_string_chunk_insert(pkg->chunk, repopath);
-         }
-         g_hash_table_insert (merged, (gpointer) pkg->name, (gpointer) list);
-         return 1;
-@@ -1039,7 +1026,7 @@ merge_repos(GHashTable *merged,
-                     // Koji-mergerepos specific behaviour -----------
-                     if (koji_stuff && koji_stuff->pkgorigins) {
-                         _cleanup_free_ gchar *nvra = cr_package_nvra(pkg);
--                        _cleanup_free_ gchar *url = prepend_protocol(ml->original_url);
-+                        _cleanup_free_ gchar *url = cr_prepend_protocol(ml->original_url);
- 
-                         cr_printf(NULL,
-                                   koji_stuff->pkgorigins,
-diff --git a/src/xml_dump.c b/src/xml_dump.c
-index 3fbb422..7a93231 100644
---- a/src/xml_dump.c
-+++ b/src/xml_dump.c
-@@ -53,6 +53,14 @@ gboolean cr_hascontrollchars(const unsigned char *str)
-     return FALSE;
- }
- 
-+gchar *
-+cr_prepend_protocol(const gchar *url)
-+{
-+    if (url && *url == '/')
-+        return g_strconcat("file://", url, NULL);
-+    return g_strdup(url);
-+}
-+
- void
- cr_latin1_to_utf8(const unsigned char *in, unsigned char *out)
- {
-diff --git a/src/xml_dump.h b/src/xml_dump.h
-index 8bb11ed..4289fc2 100644
---- a/src/xml_dump.h
-+++ b/src/xml_dump.h
-@@ -167,6 +167,14 @@ void cr_latin1_to_utf8(const unsigned char *in,
-  */
- gboolean cr_hascontrollchars(const unsigned char *str);
- 
-+/**
-+ * Prepend protocol if necessary
-+ *
-+ * @param url           input url
-+ * @return              output string, must be freed
-+ */
-+gchar *cr_prepend_protocol(const gchar *url);
-+
- /** @} */
- 
- #ifdef __cplusplus
-diff --git a/src/xml_dump_primary.c b/src/xml_dump_primary.c
-index 5695e06..1f0292b 100644
---- a/src/xml_dump_primary.c
-+++ b/src/xml_dump_primary.c
-@@ -30,7 +30,6 @@
- 
- #define ERR_DOMAIN      CREATEREPO_C_ERROR
- 
--
- typedef enum {
-     PCO_TYPE_PROVIDES,
-     PCO_TYPE_CONFLICTS,
-@@ -279,9 +278,12 @@ cr_xml_dump_primary_base_items(xmlNodePtr root, cr_Package *package)
- 
-     // Write location attribute base
-     if (package->location_base && package->location_base[0] != '\0') {
-+        gchar *location_base_with_protocol = NULL;
-+        location_base_with_protocol = cr_prepend_protocol(package->location_base);
-         cr_xmlNewProp(location,
-                       BAD_CAST "xml:base",
--                      BAD_CAST package->location_base);
-+                      BAD_CAST location_base_with_protocol);
-+        g_free(location_base_with_protocol);
-     }
- 
-     // Write location attribute href
---
-libgit2 0.27.8
-
diff --git a/SOURCES/0001-Libmagic-to-follow-symlinks-RhBug1776399.patch b/SOURCES/0001-Libmagic-to-follow-symlinks-RhBug1776399.patch
new file mode 100644
index 0000000..5221458
--- /dev/null
+++ b/SOURCES/0001-Libmagic-to-follow-symlinks-RhBug1776399.patch
@@ -0,0 +1,60 @@
+From 566311457542d08f48507b0ab7bd68cb848594e9 Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha@redhat.com>
+Date: Fri, 29 Nov 2019 09:47:29 +0100
+Subject: [PATCH 1/2] Libmagic to follow symlinks (RhBug:1776399)
+
+If the input metadata file for modifyrepo_c was a symlink the
+program failed to detect compression type. This patch instructs
+libmagic to follow the symlinks when guessing the mime type.
+
+Let modules.yaml be a symlink:
+
+$ modifyrepo_c ./modules.yaml ./repodata
+Cannot open ./modules.yaml: Cannot detect compression type
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1776399
+---
+ src/compression_wrapper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/compression_wrapper.c b/src/compression_wrapper.c
+index d04ab24..6fdb8ea 100644
+--- a/src/compression_wrapper.c
++++ b/src/compression_wrapper.c
+@@ -166,7 +166,7 @@ cr_detect_compression(const char *filename, GError **err)
+ 
+     // No success? Let's get hardcore... (Use magic bytes)
+ 
+-    magic_t myt = magic_open(MAGIC_MIME);
++    magic_t myt = magic_open(MAGIC_MIME | MAGIC_SYMLINK);
+     if (myt == NULL) {
+         g_set_error(err, ERR_DOMAIN, CRE_MAGIC,
+                     "magic_open() failed: Cannot allocate the magic cookie");
+
+From b1b849c3bd63424760152981f96031ef578d752c Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha@redhat.com>
+Date: Fri, 29 Nov 2019 10:53:25 +0100
+Subject: [PATCH 2/2] Add shortcut to detect *.yaml files as not compressed
+
+---
+ src/compression_wrapper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/compression_wrapper.c b/src/compression_wrapper.c
+index 6fdb8ea..56d1dc5 100644
+--- a/src/compression_wrapper.c
++++ b/src/compression_wrapper.c
+@@ -158,12 +158,12 @@ cr_detect_compression(const char *filename, GError **err)
+         return CR_CW_ZCK_COMPRESSION;
+     } else if (g_str_has_suffix(filename, ".xml") ||
+                g_str_has_suffix(filename, ".tar") ||
++               g_str_has_suffix(filename, ".yaml") ||
+                g_str_has_suffix(filename, ".sqlite"))
+     {
+         return CR_CW_NO_COMPRESSION;
+     }
+ 
+-
+     // No success? Let's get hardcore... (Use magic bytes)
+ 
+     magic_t myt = magic_open(MAGIC_MIME | MAGIC_SYMLINK);
diff --git a/SOURCES/0002-Add-reboot_suggested-to-UpdateRecord-RhBug1772466.patch b/SOURCES/0002-Add-reboot_suggested-to-UpdateRecord-RhBug1772466.patch
new file mode 100644
index 0000000..ed4f49b
--- /dev/null
+++ b/SOURCES/0002-Add-reboot_suggested-to-UpdateRecord-RhBug1772466.patch
@@ -0,0 +1,458 @@
+From af9c8b4575749c3d03afe6c704060661622199bb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
+Date: Tue, 3 Dec 2019 09:21:27 +0100
+Subject: [PATCH 1/3] Add reboot_suggested field to UpdateRecord
+ (RhBug:1772466)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1772466
+---
+ src/python/updaterecord-py.c | 35 +++++++++++++++++++++++++++++++++++
+ src/updateinfo.c             |  1 +
+ src/updateinfo.h             |  1 +
+ src/xml_dump_updateinfo.c    |  3 +++
+ src/xml_parser_updateinfo.c  |  9 +++++++++
+ 5 files changed, 49 insertions(+)
+
+diff --git a/src/python/updaterecord-py.c b/src/python/updaterecord-py.c
+index 4f41019..b74bcb8 100644
+--- a/src/python/updaterecord-py.c
++++ b/src/python/updaterecord-py.c
+@@ -248,6 +248,16 @@ static ListConvertor list_convertors[] = {
+ 
+ #define OFFSET(member) (void *) offsetof(cr_UpdateRecord, member)
+ 
++static PyObject *
++get_int(_UpdateRecordObject *self, void *member_offset)
++{
++    if (check_UpdateRecordStatus(self))
++        return NULL;
++    cr_UpdateRecord *rec = self->record;
++    gint64 val = *((int *) ((size_t) rec + (size_t) member_offset));
++    return PyLong_FromLongLong((long long) val);
++}
++
+ static PyObject *
+ get_str(_UpdateRecordObject *self, void *member_offset)
+ {
+@@ -311,6 +321,29 @@ get_list(_UpdateRecordObject *self, void *conv)
+     return list;
+ }
+ 
++static int
++set_int(_UpdateRecordObject *self, PyObject *value, void *member_offset)
++{
++    long val;
++    if (check_UpdateRecordStatus(self))
++        return -1;
++    if (PyLong_Check(value)) {
++        val = PyLong_AsLong(value);
++    } else if (PyFloat_Check(value)) {
++        val = (long long) PyFloat_AS_DOUBLE(value);
++#if PY_MAJOR_VERSION < 3
++    } else if (PyInt_Check(value)) {
++        val = PyInt_AS_LONG(value);
++#endif
++    } else {
++        PyErr_SetString(PyExc_TypeError, "Number expected!");
++        return -1;
++    }
++    cr_UpdateRecord *rec = self->record;
++    *((int *) ((size_t) rec + (size_t) member_offset)) = (int) val;
++    return 0;
++}
++
+ static int
+ set_str(_UpdateRecordObject *self, PyObject *value, void *member_offset)
+ {
+@@ -388,6 +421,8 @@ static PyGetSetDef updaterecord_getsetters[] = {
+         "List of UpdateReferences", &(list_convertors[0])},
+     {"collections",                 (getter)get_list, (setter)NULL,
+         "List of UpdateCollections", &(list_convertors[1])},
++    {"reboot_suggested",            (getter)get_int, (setter)set_int,
++        "Suggested reboot",         OFFSET(reboot_suggested)},
+     {NULL, NULL, NULL, NULL, NULL} /* sentinel */
+ };
+ 
+diff --git a/src/updateinfo.c b/src/updateinfo.c
+index cdc4747..bef06f2 100644
+--- a/src/updateinfo.c
++++ b/src/updateinfo.c
+@@ -249,6 +249,7 @@ cr_updaterecord_copy(const cr_UpdateRecord *orig)
+     rec->summary = cr_safe_string_chunk_insert(rec->chunk, orig->summary);
+     rec->description = cr_safe_string_chunk_insert(rec->chunk, orig->description);
+     rec->solution = cr_safe_string_chunk_insert(rec->chunk, orig->solution);
++    rec->reboot_suggested = orig->reboot_suggested;
+ 
+     if (orig->references) {
+         GSList *newlist = NULL;
+diff --git a/src/updateinfo.h b/src/updateinfo.h
+index 38883e0..2a69384 100644
+--- a/src/updateinfo.h
++++ b/src/updateinfo.h
+@@ -92,6 +92,7 @@ typedef struct {
+     gchar *summary;     /*!< Short summary */
+     gchar *description; /*!< Update description */
+     gchar *solution;    /*!< Solution */
++    gboolean reboot_suggested; /*!< Reboot suggested */
+ 
+     GSList *references; /*!< List of cr_UpdateReference */
+     GSList *collections;/*!< List of cr_UpdateCollection */
+diff --git a/src/xml_dump_updateinfo.c b/src/xml_dump_updateinfo.c
+index fafe686..0beed96 100644
+--- a/src/xml_dump_updateinfo.c
++++ b/src/xml_dump_updateinfo.c
+@@ -165,6 +165,9 @@ cr_xml_dump_updateinforecord_internal(xmlNodePtr root, cr_UpdateRecord *rec)
+     cr_xmlNewTextChild_c(update, NULL, BAD_CAST "description", BAD_CAST rec->description);
+     cr_xmlNewTextChild_c(update, NULL, BAD_CAST "solution", BAD_CAST rec->solution);
+ 
++    if (rec->reboot_suggested)
++        xmlNewChild(update, NULL, BAD_CAST "reboot_suggested", NULL);
++
+     // References
+     cr_xml_dump_updateinforecord_references(update, rec->references);
+ 
+diff --git a/src/xml_parser_updateinfo.c b/src/xml_parser_updateinfo.c
+index 5a2715a..3e458ec 100644
+--- a/src/xml_parser_updateinfo.c
++++ b/src/xml_parser_updateinfo.c
+@@ -58,6 +58,7 @@ typedef enum {
+     STATE_PACKAGE,
+     STATE_FILENAME,
+     STATE_SUM,
++    STATE_UPDATERECORD_REBOOTSUGGESTED,
+     STATE_REBOOTSUGGESTED,
+     STATE_RESTARTSUGGESTED, // Not implemented
+     STATE_RELOGINSUGGESTED, // Not implemented
+@@ -86,6 +87,7 @@ static cr_StatesSwitch stateswitches[] = {
+     { STATE_UPDATE,     "message",           STATE_MESSAGE,           1 }, // NI
+     { STATE_UPDATE,     "references",        STATE_REFERENCES,        0 },
+     { STATE_UPDATE,     "pkglist",           STATE_PKGLIST,           0 },
++    { STATE_UPDATE,     "reboot_suggested",  STATE_UPDATERECORD_REBOOTSUGGESTED,0 },
+     { STATE_REFERENCES, "reference",         STATE_REFERENCE,         0 },
+     { STATE_PKGLIST,    "collection",        STATE_COLLECTION,        0 },
+     { STATE_COLLECTION, "package",           STATE_PACKAGE,           0 },
+@@ -360,6 +362,12 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
+             package->sum_type = cr_checksum_type(val);
+         break;
+ 
++    case STATE_UPDATERECORD_REBOOTSUGGESTED:
++        assert(pd->updateinfo);
++        assert(pd->updaterecord);
++        rec->reboot_suggested = TRUE;
++        break;
++
+     case STATE_REBOOTSUGGESTED:
+         assert(pd->updateinfo);
+         assert(pd->updaterecord);
+@@ -406,6 +414,7 @@ cr_end_handler(void *pdata, G_GNUC_UNUSED const char *element)
+     case STATE_MODULE:
+     case STATE_PKGLIST:
+     case STATE_REBOOTSUGGESTED:
++    case STATE_UPDATERECORD_REBOOTSUGGESTED:
+         // All elements with no text data and without need of any
+         // post processing should go here
+         break;
+-- 
+2.24.1
+
+
+From d4fb876b4475c7ede4b49219229638bf32e9574d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
+Date: Tue, 3 Dec 2019 09:32:18 +0100
+Subject: [PATCH 2/3] Extend unit tests with reboot_suggested for UpdateRecord
+
+---
+ tests/python/tests/test_updateinfo.py             | 6 ++++++
+ tests/python/tests/test_updaterecord.py           | 5 +++++
+ tests/test_xml_parser_updateinfo.c                | 8 ++++++++
+ tests/testdata/updateinfo_files/updateinfo_01.xml | 1 +
+ tests/testdata/updateinfo_files/updateinfo_03.xml | 2 ++
+ 5 files changed, 22 insertions(+)
+
+diff --git a/tests/python/tests/test_updateinfo.py b/tests/python/tests/test_updateinfo.py
+index 727b707..7feaae9 100644
+--- a/tests/python/tests/test_updateinfo.py
++++ b/tests/python/tests/test_updateinfo.py
+@@ -36,6 +36,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+         rec.summary = "summary"
+         rec.description = "description"
+         rec.solution = "solution"
++        rec.reboot_suggested = True
+ 
+         ui.append(rec)
+ 
+@@ -57,6 +58,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+         self.assertEqual(rec.summary, "summary")
+         self.assertEqual(rec.description, "description")
+         self.assertEqual(rec.solution, "solution")
++        self.assertEqual(rec.reboot_suggested, True)
+         self.assertEqual(len(rec.references), 0)
+         self.assertEqual(len(rec.collections), 0)
+ 
+@@ -92,6 +94,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+         rec.summary = "summary"
+         rec.description = "description"
+         rec.solution = "solution"
++        rec.reboot_suggested = True
+ 
+         ui.append(rec)
+         xml = ui.xml_dump()
+@@ -111,6 +114,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+     <summary>summary</summary>
+     <description>description</description>
+     <solution>solution</solution>
++    <reboot_suggested/>
+     <references/>
+     <pkglist/>
+   </update>
+@@ -349,6 +353,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+         rec.summary = "summary"
+         rec.description = "description"
+         rec.solution = "solution"
++        rec.reboot_suggested = True
+         rec.append_collection(col)
+         rec.append_reference(ref)
+ 
+@@ -372,6 +377,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+     <summary>summary</summary>
+     <description>description</description>
+     <solution>solution</solution>
++    <reboot_suggested/>
+     <references>
+       <reference href="href" id="id" type="type" title="title"/>
+     </references>
+diff --git a/tests/python/tests/test_updaterecord.py b/tests/python/tests/test_updaterecord.py
+index 6777f04..7a1a191 100644
+--- a/tests/python/tests/test_updaterecord.py
++++ b/tests/python/tests/test_updaterecord.py
+@@ -32,6 +32,7 @@ class TestCaseUpdateRecord(unittest.TestCase):
+         self.assertEqual(rec.severity, None)
+         self.assertEqual(rec.summary, None)
+         self.assertEqual(rec.description, None)
++        self.assertEqual(rec.reboot_suggested, 0)
+         self.assertEqual(rec.solution, None)
+         self.assertEqual(rec.references, [])
+         self.assertEqual(rec.collections, [])
+@@ -60,6 +61,7 @@ class TestCaseUpdateRecord(unittest.TestCase):
+         rec.severity = "severity"
+         rec.summary = "summary"
+         rec.description = "description"
++        rec.reboot_suggested = True
+         rec.solution = "solution"
+         rec.append_reference(ref)
+         rec.append_collection(col)
+@@ -77,6 +79,7 @@ class TestCaseUpdateRecord(unittest.TestCase):
+         self.assertEqual(rec.pushcount, "pushcount")
+         self.assertEqual(rec.severity, "severity")
+         self.assertEqual(rec.summary, "summary")
++        self.assertEqual(rec.reboot_suggested, True)
+         self.assertEqual(rec.description, "description")
+         self.assertEqual(rec.solution, "solution")
+         self.assertEqual(len(rec.references), 1)
+@@ -115,6 +118,7 @@ class TestCaseUpdateRecord(unittest.TestCase):
+         rec.summary = "summary"
+         rec.description = "description"
+         rec.solution = "solution"
++        rec.reboot_suggested = True
+ 
+         xml = cr.xml_dump_updaterecord(rec)
+         self.assertEqual(xml,
+@@ -130,6 +134,7 @@ class TestCaseUpdateRecord(unittest.TestCase):
+     <summary>summary</summary>
+     <description>description</description>
+     <solution>solution</solution>
++    <reboot_suggested/>
+     <references/>
+     <pkglist/>
+   </update>
+diff --git a/tests/test_xml_parser_updateinfo.c b/tests/test_xml_parser_updateinfo.c
+index 976922e..07ef50e 100644
+--- a/tests/test_xml_parser_updateinfo.c
++++ b/tests/test_xml_parser_updateinfo.c
+@@ -76,6 +76,7 @@ test_cr_xml_parse_updateinfo_01(void)
+     g_assert_cmpstr(update->summary, ==, "summary_1");
+     g_assert_cmpstr(update->description, ==, "description_1");
+     g_assert_cmpstr(update->solution, ==, "solution_1");
++    g_assert(update->reboot_suggested);
+ 
+     g_assert_cmpint(g_slist_length(update->references), ==, 1);
+     ref = update->references->data;
+@@ -137,6 +138,7 @@ test_cr_xml_parse_updateinfo_02(void)
+     g_assert(!update->pushcount);
+     g_assert(!update->severity);
+     g_assert(!update->summary);
++    g_assert(!update->reboot_suggested);
+     g_assert(!update->description);
+     g_assert(!update->solution);
+ 
+@@ -186,6 +188,10 @@ test_cr_xml_parse_updateinfo_03(void)
+     g_assert_cmpint(ret, ==, CRE_OK);
+ 
+     g_assert_cmpint(g_slist_length(ui->updates), ==, 6);
++
++    update = g_slist_nth_data(ui->updates, 2);
++    g_assert(!update->reboot_suggested);
++
+     update = g_slist_nth_data(ui->updates, 3);
+ 
+     g_assert_cmpstr(update->from, ==, "errata@redhat.com");
+@@ -195,6 +201,7 @@ test_cr_xml_parse_updateinfo_03(void)
+     g_assert_cmpstr(update->id, ==, "RHEA-2012:0058");
+     g_assert_cmpstr(update->title, ==, "Gorilla_Erratum");
+     g_assert_cmpstr(update->description, ==, "Gorilla_Erratum");
++    g_assert(update->reboot_suggested);
+ 
+     update = g_slist_nth_data(ui->updates, 4);
+ 
+@@ -204,6 +211,7 @@ test_cr_xml_parse_updateinfo_03(void)
+     g_assert_cmpstr(update->issued_date, ==, "2018-01-27 16:08:09");
+     g_assert_cmpstr(update->updated_date, ==, "2018-07-20 06:00:01 UTC");
+     g_assert_cmpstr(update->release, ==, "1");
++    g_assert(update->reboot_suggested);
+ 
+     g_assert_cmpint(g_slist_length(update->references), ==, 0);
+ 
+diff --git a/tests/testdata/updateinfo_files/updateinfo_01.xml b/tests/testdata/updateinfo_files/updateinfo_01.xml
+index b757ef8..415140e 100644
+--- a/tests/testdata/updateinfo_files/updateinfo_01.xml
++++ b/tests/testdata/updateinfo_files/updateinfo_01.xml
+@@ -12,6 +12,7 @@
+     <summary>summary_1</summary>
+     <description>description_1</description>
+     <solution>solution_1</solution>
++    <reboot_suggested>True</reboot_suggested>
+     <references>
+         <reference href="https://foobar/foobarupdate_1" id="1" type="self" title="update_1"/>
+     </references>
+diff --git a/tests/testdata/updateinfo_files/updateinfo_03.xml b/tests/testdata/updateinfo_files/updateinfo_03.xml
+index ddbd99b..39dfbef 100644
+--- a/tests/testdata/updateinfo_files/updateinfo_03.xml
++++ b/tests/testdata/updateinfo_files/updateinfo_03.xml
+@@ -70,6 +70,7 @@
+   <issued date="2013-01-27 16:08:09"/>
+   <updated date="2014-07-20 06:00:01 UTC"/>
+   <description>Gorilla_Erratum</description>
++  <reboot_suggested>True</reboot_suggested>
+   <pkglist>
+     <collection short="">
+       <name>1</name>
+@@ -87,6 +88,7 @@
+   <issued date="2018-01-27 16:08:09"/>
+   <updated date="2018-07-20 06:00:01 UTC"/>
+   <description>Duck_Kangaro_Erratum description</description>
++  <reboot_suggested/>
+   <pkglist>
+     <collection short="">
+       <name>coll_name1</name>
+-- 
+2.24.1
+
+
+From c1ec192d14d751eed298ffff13fbbc76917d0b0e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
+Date: Thu, 9 Jan 2020 08:52:22 +0100
+Subject: [PATCH 3/3] Switch updateinfo to explicitly include bool values
+ (RhBug:1772466)
+
+Elements <restart_suggested> and both <reboot_suggested> were previously
+outputed just as an empty element which meant they are true, this patch
+changes it to explicitly output:
+<reboot_suggested>True</reboot_suggested>.
+
+However we still don't output False values, in that case the element is
+simply omitted.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1772466
+---
+ src/xml_dump_updateinfo.c               |  4 ++--
+ tests/python/tests/test_updateinfo.py   | 10 +++++-----
+ tests/python/tests/test_updaterecord.py |  2 +-
+ 3 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/src/xml_dump_updateinfo.c b/src/xml_dump_updateinfo.c
+index 0beed96..6974285 100644
+--- a/src/xml_dump_updateinfo.c
++++ b/src/xml_dump_updateinfo.c
+@@ -61,7 +61,7 @@ cr_xml_dump_updatecollectionpackages(xmlNodePtr collection, GSList *packages)
+         }
+ 
+         if (pkg->reboot_suggested)
+-            xmlNewChild(package, NULL, BAD_CAST "reboot_suggested", NULL);
++            xmlNewChild(package, NULL, BAD_CAST "reboot_suggested", "True");
+     }
+ }
+ 
+@@ -166,7 +166,7 @@ cr_xml_dump_updateinforecord_internal(xmlNodePtr root, cr_UpdateRecord *rec)
+     cr_xmlNewTextChild_c(update, NULL, BAD_CAST "solution", BAD_CAST rec->solution);
+ 
+     if (rec->reboot_suggested)
+-        xmlNewChild(update, NULL, BAD_CAST "reboot_suggested", NULL);
++        xmlNewChild(update, NULL, BAD_CAST "reboot_suggested", "True");
+ 
+     // References
+     cr_xml_dump_updateinforecord_references(update, rec->references);
+diff --git a/tests/python/tests/test_updateinfo.py b/tests/python/tests/test_updateinfo.py
+index 7feaae9..f5becfe 100644
+--- a/tests/python/tests/test_updateinfo.py
++++ b/tests/python/tests/test_updateinfo.py
+@@ -114,7 +114,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+     <summary>summary</summary>
+     <description>description</description>
+     <solution>solution</solution>
+-    <reboot_suggested/>
++    <reboot_suggested>True</reboot_suggested>
+     <references/>
+     <pkglist/>
+   </update>
+@@ -207,7 +207,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+         <package name="foo" version="1.2" release="3" epoch="0" arch="x86" src="foo.src.rpm">
+           <filename>foo.rpm</filename>
+           <sum type="sha1">abcdef</sum>
+-          <reboot_suggested/>
++          <reboot_suggested>True</reboot_suggested>
+         </package>
+       </collection>
+     </pkglist>
+@@ -293,7 +293,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+         <package name="foo" version="1.2" release="3" epoch="0" arch="x86" src="foo.src.rpm">
+           <filename>foo.rpm</filename>
+           <sum type="sha1">abcdef</sum>
+-          <reboot_suggested/>
++          <reboot_suggested>True</reboot_suggested>
+         </package>
+       </collection>
+     </pkglist>
+@@ -377,7 +377,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+     <summary>summary</summary>
+     <description>description</description>
+     <solution>solution</solution>
+-    <reboot_suggested/>
++    <reboot_suggested>True</reboot_suggested>
+     <references>
+       <reference href="href" id="id" type="type" title="title"/>
+     </references>
+@@ -388,7 +388,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
+         <package name="foo" version="1.2" release="3" epoch="0" arch="x86" src="foo.src.rpm">
+           <filename>foo.rpm</filename>
+           <sum type="sha1">abcdef</sum>
+-          <reboot_suggested/>
++          <reboot_suggested>True</reboot_suggested>
+         </package>
+       </collection>
+     </pkglist>
+diff --git a/tests/python/tests/test_updaterecord.py b/tests/python/tests/test_updaterecord.py
+index 7a1a191..e8bc789 100644
+--- a/tests/python/tests/test_updaterecord.py
++++ b/tests/python/tests/test_updaterecord.py
+@@ -134,7 +134,7 @@ class TestCaseUpdateRecord(unittest.TestCase):
+     <summary>summary</summary>
+     <description>description</description>
+     <solution>solution</solution>
+-    <reboot_suggested/>
++    <reboot_suggested>True</reboot_suggested>
+     <references/>
+     <pkglist/>
+   </update>
+-- 
+2.24.1
+
diff --git a/SOURCES/0002-modifyrepo_c-Prevent-doubling-of-compression-testgzgz-RhBug1639287.patch b/SOURCES/0002-modifyrepo_c-Prevent-doubling-of-compression-testgzgz-RhBug1639287.patch
deleted file mode 100644
index 97a5599..0000000
--- a/SOURCES/0002-modifyrepo_c-Prevent-doubling-of-compression-testgzgz-RhBug1639287.patch
+++ /dev/null
@@ -1,130 +0,0 @@
-From a535b3f25e4391f23d1cee46028827285e221de3 Mon Sep 17 00:00:00 2001
-From: Aleš Matěj <amatej@redhat.com>
-Date: Tue, 18 Jun 2019 13:49:27 +0200
-Subject: [PATCH] modifyrepo_c: Prevent doubling of compression (test.gz.gz) (RhBug:1639287)
-
----
- src/compression_wrapper.c |  3 ++-
- src/misc.c                | 22 +++++++---------------
- src/modifyrepo_shared.c   | 22 +++++++++++++++++++++-
- 3 files changed, 30 insertions(+), 17 deletions(-)
-
-diff --git a/src/compression_wrapper.c b/src/compression_wrapper.c
-index adc2f39..efb075c 100644
---- a/src/compression_wrapper.c
-+++ b/src/compression_wrapper.c
-@@ -148,7 +148,8 @@ cr_detect_compression(const char *filename, GError **err)
-     } else if (g_str_has_suffix(filename, ".xz"))
-     {
-         return CR_CW_XZ_COMPRESSION;
--    } else if (g_str_has_suffix(filename, ".xml"))
-+    } else if (g_str_has_suffix(filename, ".xml") ||
-+               g_str_has_suffix(filename, ".sqlite"))
-     {
-         return CR_CW_NO_COMPRESSION;
-     }
-diff --git a/src/misc.c b/src/misc.c
-index 9937480..c5ccd12 100644
---- a/src/misc.c
-+++ b/src/misc.c
-@@ -437,7 +437,7 @@ cr_compress_file_with_stat(const char *src,
-     int ret = CRE_OK;
-     int readed;
-     char buf[BUFFER_SIZE];
--    FILE *orig = NULL;
-+    CR_FILE *orig = NULL;
-     CR_FILE *new = NULL;
-     gchar *dst = (gchar *) in_dst;
-     GError *tmp_err = NULL;
-@@ -466,7 +466,7 @@ cr_compress_file_with_stat(const char *src,
-                           NULL);
-     }
- 
--    orig = fopen(src, "rb");
-+    orig = cr_open(src, CR_CW_MODE_READ, CR_CW_AUTO_DETECT_COMPRESSION, &tmp_err);
-     if (orig == NULL) {
-         g_debug("%s: Cannot open source file %s (%s)", __func__, src,
-                 g_strerror(errno));
-@@ -484,21 +484,13 @@ cr_compress_file_with_stat(const char *src,
-         goto compress_file_cleanup;
-     }
- 
--    while ((readed = fread(buf, 1, BUFFER_SIZE, orig)) > 0) {
--        if (readed != BUFFER_SIZE && ferror(orig)) {
--            g_debug("%s: Error while copy %s -> %s (%s)", __func__, src,
--                    dst, g_strerror(errno));
--            g_set_error(err, ERR_DOMAIN, CRE_IO,
--                        "Error while read %s: %s", src, g_strerror(errno));
--            ret = CRE_IO;
--            goto compress_file_cleanup;
--        }
--
--        cr_write(new, buf, readed, &tmp_err);
-+    while ((readed = cr_read(orig, buf, BUFFER_SIZE, &tmp_err)) > 0) {
-+        if (!tmp_err)
-+            cr_write(new, buf, readed, &tmp_err);
-         if (tmp_err) {
-             g_debug("%s: Error while copy %s -> %s", __func__, src, dst);
-             g_propagate_prefixed_error(err, tmp_err,
--                    "Error while read %s: ", dst);
-+                    "Error while copy to %s: ", dst);
-             ret = CRE_IO;
-             goto compress_file_cleanup;
-         }
-@@ -510,7 +502,7 @@ compress_file_cleanup:
-         g_free(dst);
- 
-     if (orig)
--        fclose(orig);
-+        cr_close(orig, NULL);
- 
-     if (new)
-         cr_close(new, NULL);
-diff --git a/src/modifyrepo_shared.c b/src/modifyrepo_shared.c
-index 805c894..91e56e8 100644
---- a/src/modifyrepo_shared.c
-+++ b/src/modifyrepo_shared.c
-@@ -50,6 +50,23 @@ cr_modifyrepotask_free(cr_ModifyRepoTask *task)
-     g_free(task);
- }
- 
-+gchar *
-+remove_compression_suffix_if_present(gchar* name, GError **err)
-+{
-+    cr_CompressionType src_fn_com_type = cr_detect_compression(name, err);
-+    if (src_fn_com_type != CR_CW_NO_COMPRESSION && src_fn_com_type != CR_CW_UNKNOWN_COMPRESSION){
-+        const gchar *src_suffix = cr_compression_suffix(src_fn_com_type);
-+        if (src_suffix){
-+            if (g_str_has_suffix(name, src_suffix)){
-+                int name_len = strlen(name);
-+                int suffix_len = strlen(src_suffix);
-+                return g_strndup(name, name_len - suffix_len);
-+            }
-+        }
-+    }
-+    return g_strdup(name);
-+}
-+
- gboolean
- cr_modifyrepo(GSList *modifyrepotasks, gchar *repopath, GError **err)
- {
-@@ -192,12 +209,15 @@ cr_modifyrepo(GSList *modifyrepotasks, gchar *repopath, GError **err)
-             suffix = cr_compression_suffix(compress_type);
-         }
- 
-+        char* sufixless_src_fn = remove_compression_suffix_if_present(task->path, err);
-+
-         // Prepare dst filename - Get basename
-         _cleanup_free_ gchar *filename = NULL;
-         if (task->new_name)
-             filename = g_path_get_basename(task->new_name);
-         else
--            filename = g_path_get_basename(src_fn);
-+            filename = g_path_get_basename(sufixless_src_fn);
-+        g_free(sufixless_src_fn);
- 
-         // Prepare dst filename - Add suffix
-         if (suffix) {
---
-libgit2 0.27.8
-
diff --git a/SOURCES/0003-Correct-pkg-count-in-headers-if-there-were-invalid-pkgs-RhBug1596211.patch b/SOURCES/0003-Correct-pkg-count-in-headers-if-there-were-invalid-pkgs-RhBug1596211.patch
deleted file mode 100644
index e546c4b..0000000
--- a/SOURCES/0003-Correct-pkg-count-in-headers-if-there-were-invalid-pkgs-RhBug1596211.patch
+++ /dev/null
@@ -1,466 +0,0 @@
-From dfe7218f07ffa70b73c51c71b0f051be926b6d92 Mon Sep 17 00:00:00 2001
-From: Aleš Matěj <amatej@redhat.com>
-Date: Tue, 14 May 2019 16:48:13 +0200
-Subject: [PATCH] Correct pkg count in headers if there were invalid pkgs (RhBug:1596211)
-
----
- src/createrepo_c.c  | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
- src/dumper_thread.c |   4 +++-
- src/dumper_thread.h |   3 ++-
- src/threads.c       |  23 +++++++++++++++++++++++
- src/threads.h       |   5 +++++
- src/xml_file.c      | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/xml_file.h      |  15 +++++++++++++++
- 7 files changed, 260 insertions(+), 16 deletions(-)
-
-diff --git a/src/createrepo_c.c b/src/createrepo_c.c
-index e16ae34..67c2752 100644
---- a/src/createrepo_c.c
-+++ b/src/createrepo_c.c
-@@ -124,7 +124,7 @@ fill_pool(GThreadPool *pool,
-           struct CmdOptions *cmd_options,
-           GSList **current_pkglist,
-           FILE *output_pkg_list,
--          long *package_count,
-+          long *task_count,
-           int  media_id)
- {
-     GQueue queue = G_QUEUE_INIT;
-@@ -259,13 +259,13 @@ fill_pool(GThreadPool *pool,
- 
-     // Push sorted tasks into the thread pool
-     while ((task = g_queue_pop_head(&queue)) != NULL) {
--        task->id = *package_count;
-+        task->id = *task_count;
-         task->media_id = media_id;
-         g_thread_pool_push(pool, task, NULL);
--        ++*package_count;
-+        ++*task_count;
-     }
- 
--    return *package_count;
-+    return *task_count;
- }
- 
- 
-@@ -321,6 +321,27 @@ prepare_cache_dir(struct CmdOptions *cmd_options,
-     return TRUE;
- }
- 
-+/** Check if task finished without error, if yes
-+ *  use content stats of the new file
-+ *
-+ * @param task          Rewrite pkg count task
-+ * @param filename      Name of file with wrong package count
-+ * @param exit_val      If errors occured set createrepo_c exit value
-+ * @param content_stat  Content stats for filename
-+ *
-+ */
-+static void
-+error_check_and_set_content_stat(cr_CompressionTask *task, char *filename, int *exit_val, cr_ContentStat **content_stat){
-+    if (task->err) {
-+        g_critical("Cannot rewrite pkg count in %s: %s",
-+                   filename, task->err->message);
-+        *exit_val = 2;
-+    }else{
-+        cr_contentstat_free(*content_stat, NULL);
-+        *content_stat = task->stat;
-+        task->stat = NULL;
-+    }
-+}
- 
- int
- main(int argc, char **argv)
-@@ -478,7 +499,7 @@ main(int argc, char **argv)
-                                           NULL);
-     g_debug("Thread pool ready");
- 
--    long package_count = 0;
-+    long task_count = 0;
-     GSList *current_pkglist = NULL;
-     /* ^^^ List with basenames of files which will be processed */
- 
-@@ -490,26 +511,26 @@ main(int argc, char **argv)
-                   cmd_options,
-                   &current_pkglist,
-                   output_pkg_list,
--                  &package_count,
-+                  &task_count,
-                   media_id);
-         g_free(tmp_in_dir);
-     }
- 
--    g_debug("Package count: %ld", package_count);
--    g_message("Directory walk done - %ld packages", package_count);
-+    g_debug("Package count: %ld", task_count);
-+    g_message("Directory walk done - %ld packages", task_count);
- 
-     if (output_pkg_list)
-         fclose(output_pkg_list);
- 
- 
-     // Load old metadata if --update
-     cr_Metadata *old_metadata = NULL;
-     struct cr_MetadataLocation *old_metadata_location = NULL;
- 
--    if (!package_count)
-+    if (!task_count)
-         g_debug("No packages found - skipping metadata loading");
- 
--    if (package_count && cmd_options->update) {
-+    if (task_count && cmd_options->update) {
-         int ret;
-         old_metadata = cr_metadata_new(CR_HT_KEY_FILENAME, 1, current_pkglist);
-         cr_metadata_set_dupaction(old_metadata, CR_HT_DUPACT_REMOVEALL);
-@@ -741,9 +762,9 @@ main(int argc, char **argv)
- 
-     // Set number of packages
-     g_debug("Setting number of packages");
--    cr_xmlfile_set_num_of_pkgs(pri_cr_file, package_count, NULL);
--    cr_xmlfile_set_num_of_pkgs(fil_cr_file, package_count, NULL);
--    cr_xmlfile_set_num_of_pkgs(oth_cr_file, package_count, NULL);
-+    cr_xmlfile_set_num_of_pkgs(pri_cr_file, task_count, NULL);
-+    cr_xmlfile_set_num_of_pkgs(fil_cr_file, task_count, NULL);
-+    cr_xmlfile_set_num_of_pkgs(oth_cr_file, task_count, NULL);
- 
-     // Open sqlite databases
-     gchar *pri_db_filename = NULL;
-@@ -832,7 +853,8 @@ main(int argc, char **argv)
-     user_data.checksum_cachedir = cmd_options->checksum_cachedir;
-     user_data.skip_symlinks     = cmd_options->skip_symlinks;
-     user_data.repodir_name_len  = strlen(in_dir);
--    user_data.package_count     = package_count;
-+    user_data.task_count        = task_count;
-+    user_data.package_count     = 0;
-     user_data.skip_stat         = cmd_options->skip_stat;
-     user_data.old_metadata      = old_metadata;
-     user_data.mutex_pri         = g_mutex_new();
-@@ -876,6 +898,59 @@ main(int argc, char **argv)
-     cr_xmlfile_close(fil_cr_file, NULL);
-     cr_xmlfile_close(oth_cr_file, NULL);
- 
-+
-+    /* At the time of writing xml metadata headers we haven't yet parsed all
-+     * the packages and we don't know whether there were some invalid ones,
-+     * therefore we write the task count into the headers instead of the actual package count.
-+     * If there actually were some invalid packages we have to correct this value
-+     * that unfortunately means we have to decompress metadata files change package
-+     * count value and compress them again.
-+     */
-+    if (user_data.package_count != user_data.task_count){
-+        g_message("Warning: There were some invalid packages: we have to recompress other, filelists and primary xml metadata files in order to have correct package counts");
-+
-+        GThreadPool *rewrite_pkg_count_pool = g_thread_pool_new(cr_rewrite_pkg_count_thread,
-+                                                                &user_data, 3, FALSE, NULL);
-+
-+        cr_CompressionTask *pri_rewrite_pkg_count_task;
-+        cr_CompressionTask *fil_rewrite_pkg_count_task;
-+        cr_CompressionTask *oth_rewrite_pkg_count_task;
-+
-+        pri_rewrite_pkg_count_task = cr_compressiontask_new(pri_xml_filename,
-+                                                            NULL,
-+                                                            xml_compression,
-+                                                            cmd_options->repomd_checksum_type,
-+                                                            1,
-+                                                            &tmp_err);
-+        g_thread_pool_push(rewrite_pkg_count_pool, pri_rewrite_pkg_count_task, NULL);
-+
-+        fil_rewrite_pkg_count_task = cr_compressiontask_new(fil_xml_filename,
-+                                                            NULL,
-+                                                            xml_compression,
-+                                                            cmd_options->repomd_checksum_type,
-+                                                            1,
-+                                                            &tmp_err);
-+        g_thread_pool_push(rewrite_pkg_count_pool, fil_rewrite_pkg_count_task, NULL);
-+
-+        oth_rewrite_pkg_count_task = cr_compressiontask_new(oth_xml_filename,
-+                                                            NULL,
-+                                                            xml_compression,
-+                                                            cmd_options->repomd_checksum_type,
-+                                                            1,
-+                                                            &tmp_err);
-+        g_thread_pool_push(rewrite_pkg_count_pool, oth_rewrite_pkg_count_task, NULL);
-+
-+        g_thread_pool_free(rewrite_pkg_count_pool, FALSE, TRUE);
-+
-+        error_check_and_set_content_stat(pri_rewrite_pkg_count_task, pri_xml_filename, &exit_val, &pri_stat);
-+        error_check_and_set_content_stat(fil_rewrite_pkg_count_task, fil_xml_filename, &exit_val, &fil_stat);
-+        error_check_and_set_content_stat(oth_rewrite_pkg_count_task, oth_xml_filename, &exit_val, &oth_stat);
-+
-+        cr_compressiontask_free(pri_rewrite_pkg_count_task, NULL);
-+        cr_compressiontask_free(fil_rewrite_pkg_count_task, NULL);
-+        cr_compressiontask_free(oth_rewrite_pkg_count_task, NULL);
-+    }
-+
-     g_queue_free(user_data.buffer);
-     g_mutex_free(user_data.mutex_buffer);
-     g_cond_free(user_data.cond_pri);
-diff --git a/src/dumper_thread.c b/src/dumper_thread.c
-index fbaa5be..e282f96 100644
---- a/src/dumper_thread.c
-+++ b/src/dumper_thread.c
-@@ -74,6 +74,8 @@ write_pkg(long id,
-     g_mutex_lock(udata->mutex_pri);
-     while (udata->id_pri != id)
-         g_cond_wait (udata->cond_pri, udata->mutex_pri);
-+
-+    udata->package_count++;
-     ++udata->id_pri;
-     cr_xmlfile_add_chunk(udata->pri_f, (const char *) res.primary, &tmp_err);
-     if (tmp_err) {
-@@ -476,7 +478,7 @@ cr_dumper_thread(gpointer data, gpointer user_data)
- 
-     if (g_queue_get_length(udata->buffer) < MAX_TASK_BUFFER_LEN
-         && udata->id_pri != task->id
--        && udata->package_count > (task->id + 1))
-+        && udata->task_count > (task->id + 1))
-     {
-         // If:
-         //  * this isn't our turn
-diff --git a/src/dumper_thread.h b/src/dumper_thread.h
-index ed21053..4e18869 100644
---- a/src/dumper_thread.h
-+++ b/src/dumper_thread.h
-@@ -61,7 +61,8 @@ struct UserData {
-     cr_ChecksumType checksum_type;  // Constant representing selected checksum
-     const char *checksum_cachedir;  // Dir with cached checksums
-     gboolean skip_symlinks;         // Skip symlinks
--    long package_count;             // Total number of packages to process
-+    long task_count;                // Total number of task to process
-+    long package_count;             // Total number of packages processed
- 
-     // Update stuff
-     gboolean skip_stat;             // Skip stat() while updating
-diff --git a/src/threads.c b/src/threads.c
-index aee07d1..844e900 100644
---- a/src/threads.c
-+++ b/src/threads.c
-@@ -21,6 +21,7 @@
- #include "threads.h"
- #include "error.h"
- #include "misc.h"
-+#include "dumper_thread.h"
- 
- #define ERR_DOMAIN      CREATEREPO_C_ERROR
- 
-@@ -108,6 +109,28 @@ cr_compressing_thread(gpointer data, G_GNUC_UNUSED gpointer user_data)
-     }
- }
- 
-+void
-+cr_rewrite_pkg_count_thread(gpointer data, gpointer user_data)
-+{
-+    cr_CompressionTask *task = data;
-+    struct UserData *ud = user_data;
-+    GError *tmp_err = NULL;
-+
-+    assert(task);
-+
-+    cr_rewrite_header_package_count(task->src,
-+                                    task->type,
-+                                    ud->package_count,
-+                                    ud->task_count,
-+                                    task->stat,
-+                                    &tmp_err);
-+
-+    if (tmp_err) {
-+        // Error encountered
-+        g_propagate_error(&task->err, tmp_err);
-+    }
-+}
-+
- /** Parallel Repomd Record Fill */
- 
- cr_RepomdRecordFillTask *
-diff --git a/src/threads.h b/src/threads.h
-index 2d554cd..19ba917 100644
---- a/src/threads.h
-+++ b/src/threads.h
-@@ -150,6 +150,11 @@ cr_repomdrecordfilltask_free(cr_RepomdRecordFillTask *task, GError **err);
- void
- cr_repomd_record_fill_thread(gpointer data, gpointer user_data);
- 
-+/** Function for GThread Pool.
-+ */
-+void
-+cr_rewrite_pkg_count_thread(gpointer data, gpointer user_data);
-+
- /** @} */
- 
- #ifdef __cplusplus
-diff --git a/src/xml_file.c b/src/xml_file.c
-index 65fb945..1d670ae 100644
---- a/src/xml_file.c
-+++ b/src/xml_file.c
-@@ -18,8 +18,10 @@
-  */
- 
- #include <glib.h>
-+#include <glib/gstdio.h>
- #include <assert.h>
- #include "xml_file.h"
-+#include <errno.h>
- #include "error.h"
- #include "xml_dump.h"
- #include "compression_wrapper.h"
-@@ -40,6 +42,9 @@
- #define XML_PRESTODELTA_HEADER  XML_HEADER"<prestodelta>\n"
- #define XML_UPDATEINFO_HEADER   XML_HEADER"<updates>\n"
- 
-+#define XML_MAX_HEADER_SIZE     300
-+#define XML_RECOMPRESS_BUFFER_SIZE   8192
-+
- #define XML_PRIMARY_FOOTER      "</metadata>"
- #define XML_FILELISTS_FOOTER    "</filelists>"
- #define XML_OTHER_FOOTER        "</otherdata>"
-@@ -317,3 +322,121 @@ cr_xmlfile_close(cr_XmlFile *f, GError **err)
- 
-     return CRE_OK;
- }
-+
-+static int
-+write_modified_header(int task_count,
-+                      int package_count,
-+                      cr_XmlFile *cr_file,
-+                      gchar *header_buf,
-+                      int header_len,
-+                      GError **err)
-+{
-+    GError *tmp_err = NULL;
-+    gchar *package_count_string;
-+    gchar *task_count_string;
-+    int bytes_written = 0;
-+    int package_count_string_len = rasprintf(&package_count_string, "packages=\"%i\"", package_count);
-+    int task_count_string_len = rasprintf(&task_count_string, "packages=\"%i\"", task_count);
-+
-+    gchar *pointer_to_pkgs = strstr(header_buf, task_count_string);
-+    if (!pointer_to_pkgs){
-+        g_free(package_count_string);
-+        g_free(task_count_string);
-+        return 0;
-+    }
-+    gchar *pointer_to_pkgs_end = pointer_to_pkgs + task_count_string_len;
-+
-+    bytes_written += cr_write(cr_file->f, header_buf, pointer_to_pkgs - header_buf, &tmp_err);
-+    if (!tmp_err)
-+        bytes_written += cr_write(cr_file->f, package_count_string, package_count_string_len, &tmp_err);
-+    if (!tmp_err)
-+        bytes_written += cr_write(cr_file->f, pointer_to_pkgs_end, header_len - (pointer_to_pkgs_end - header_buf), &tmp_err);
-+    if (tmp_err) {
-+        g_propagate_prefixed_error(err, tmp_err, "Error encountered while writing header part:");
-+        g_free(package_count_string);
-+        g_free(task_count_string);
-+        return 0;
-+    }
-+    g_free(package_count_string);
-+    g_free(task_count_string);
-+    return bytes_written;
-+}
-+
-+void
-+cr_rewrite_header_package_count(gchar *original_filename,
-+                                cr_CompressionType xml_compression,
-+                                int package_count,
-+                                int task_count,
-+                                cr_ContentStat *file_stat,
-+                                GError **err)
-+{
-+    GError *tmp_err = NULL;
-+    CR_FILE *original_file = cr_open(original_filename, CR_CW_MODE_READ, CR_CW_AUTO_DETECT_COMPRESSION, &tmp_err);
-+    if (tmp_err) {
-+        g_propagate_prefixed_error(err, tmp_err, "Error encountered while reopening for reading:");
-+        return;
-+    }
-+
-+    gchar *tmp_xml_filename = g_strconcat(original_filename, ".tmp", NULL);
-+    cr_XmlFile *new_file = cr_xmlfile_sopen_primary(tmp_xml_filename,
-+                                                    xml_compression,
-+                                                    file_stat,
-+                                                    &tmp_err);
-+    if (tmp_err) {
-+        g_propagate_prefixed_error(err, tmp_err, "Error encountered while opening for writing:");
-+        cr_close(original_file, NULL);
-+        g_free(tmp_xml_filename);
-+        return;
-+    }
-+
-+    gchar header_buf[XML_MAX_HEADER_SIZE];
-+    int len_read = cr_read(original_file, header_buf, XML_MAX_HEADER_SIZE, &tmp_err);
-+    if (!tmp_err)
-+        write_modified_header(task_count, package_count, new_file, header_buf, len_read, &tmp_err);
-+    if (tmp_err) {
-+        g_propagate_prefixed_error(err, tmp_err, "Error encountered while recompressing:");
-+        cr_xmlfile_close(new_file, NULL);
-+        cr_close(original_file, NULL);
-+        g_free(tmp_xml_filename);
-+        return;
-+    }
-+    //Copy the rest of the file
-+    gchar copy_buf[XML_RECOMPRESS_BUFFER_SIZE];
-+    while(len_read)
-+    {
-+        len_read = cr_read(original_file, copy_buf, XML_RECOMPRESS_BUFFER_SIZE, &tmp_err);
-+        if (!tmp_err)
-+            cr_write(new_file->f, copy_buf, len_read, &tmp_err);
-+        if (tmp_err) {
-+            g_propagate_prefixed_error(err, tmp_err, "Error encountered while recompressing:");
-+            cr_xmlfile_close(new_file, NULL);
-+            cr_close(original_file, NULL);
-+            g_free(tmp_xml_filename);
-+            return;
-+        }
-+    }
-+
-+    new_file->header = 1;
-+    new_file->footer = 1;
-+
-+    cr_xmlfile_close(new_file, &tmp_err);
-+    if (tmp_err) {
-+        g_propagate_prefixed_error(err, tmp_err, "Error encountered while writing:");
-+        cr_close(original_file, NULL);
-+        g_free(tmp_xml_filename);
-+        return;
-+    }
-+    cr_close(original_file, &tmp_err);
-+    if (tmp_err) {
-+        g_propagate_prefixed_error(err, tmp_err, "Error encountered while writing:");
-+        g_free(tmp_xml_filename);
-+        return;
-+    }
-+
-+    if (g_rename(tmp_xml_filename, original_filename) == -1) {
-+        g_propagate_prefixed_error(err, tmp_err, "Error encountered while renaming:");
-+        g_free(tmp_xml_filename);
-+        return;
-+    }
-+    g_free(tmp_xml_filename);
-+}
-diff --git a/src/xml_file.h b/src/xml_file.h
-index 96ef5e3..6ac4c97 100644
---- a/src/xml_file.h
-+++ b/src/xml_file.h
-@@ -221,6 +221,21 @@ int cr_xmlfile_add_chunk(cr_XmlFile *f, const char *chunk, GError **err);
-  */
- int cr_xmlfile_close(cr_XmlFile *f, GError **err);
- 
-+/** Rewrite package count field in repodata header in xml file.
-+ * In order to do this we have to decompress and after the change
-+ * compress the whole file again, so entirely new file is created.
-+ * @param original_filename     Current file with wrong value in header
-+ * @param package_count         Actual package count (desired value in header)
-+ * @param task_count            Task count (current value in header)
-+ * @param file_stat             cr_ContentStat for stats of the new file, it will be modified
-+ * @param err                   **GError
-+ */
-+void cr_rewrite_header_package_count(gchar *original_filename,
-+                                     cr_CompressionType xml_compression,
-+                                     int package_count,
-+                                     int task_count,
-+                                     cr_ContentStat *file_stat,
-+                                     GError **err);
- 
- /** @} */
- 
---
-libgit2 0.27.8
-
diff --git a/SOURCES/0004-Add-support-for-modular-errata-RhBug1656584.patch b/SOURCES/0004-Add-support-for-modular-errata-RhBug1656584.patch
deleted file mode 100644
index 3765350..0000000
--- a/SOURCES/0004-Add-support-for-modular-errata-RhBug1656584.patch
+++ /dev/null
@@ -1,1329 +0,0 @@
-From a48db44b73785b5d5fbe8ae827522695fa0fd9ce Mon Sep 17 00:00:00 2001
-From: Aleš Matěj <amatej@redhat.com>
-Date: Tue, 8 Jan 2019 15:44:55 +0100
-Subject: [PATCH] Add support for modular errata (RhBug:1656584)
-
----
- src/python/CMakeLists.txt                         |   1 +
- src/python/__init__.py                            |   3 +++
- src/python/createrepo_cmodule.c                   |   8 ++++++++
- src/python/updatecollection-py.c                  |  43 +++++++++++++++++++++++++++++++++++++++++++
- src/python/updatecollectionmodule-py.c            | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/python/updatecollectionmodule-py.h            |  33 +++++++++++++++++++++++++++++++++
- src/updateinfo.c                                  |  44 ++++++++++++++++++++++++++++++++++++++++++++
- src/updateinfo.h                                  |  24 ++++++++++++++++++++++++
- src/xml_dump_updateinfo.c                         |  20 ++++++++++++++++++++
- src/xml_parser_internal.h                         |   2 ++
- src/xml_parser_updateinfo.c                       |  54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
- tests/fixtures.h                                  |   1 +
- tests/python/tests/test_updatecollection.py       |  16 ++++++++++++++++
- tests/python/tests/test_updatecollectionmodule.py |  31 +++++++++++++++++++++++++++++++
- tests/python/tests/test_updateinfo.py             | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- tests/test_xml_parser_updateinfo.c                |  86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- tests/testdata/updateinfo_files/updateinfo_03.xml | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 17 files changed, 957 insertions(+)
- create mode 100644 src/python/updatecollectionmodule-py.c
- create mode 100644 src/python/updatecollectionmodule-py.h
- create mode 100644 tests/python/tests/test_updatecollectionmodule.py
- create mode 100644 tests/testdata/updateinfo_files/updateinfo_03.xml
-
-diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt
-index 9f1ac64..ebf4d4c 100644
---- a/src/python/CMakeLists.txt
-+++ b/src/python/CMakeLists.txt
-@@ -50,6 +50,7 @@ SET (createrepo_cmodule_SRCS
-      sqlite-py.c
-      typeconversion.c
-      updatecollection-py.c
-+     updatecollectionmodule-py.c
-      updatecollectionpackage-py.c
-      updateinfo-py.c
-      updaterecord-py.c
-diff --git a/src/python/__init__.py b/src/python/__init__.py
-index 6c29e74..65d7f82 100644
---- a/src/python/__init__.py
-+++ b/src/python/__init__.py
-@@ -206,6 +206,9 @@ class OtherSqlite(Sqlite):
- 
- UpdateCollection = _createrepo_c.UpdateCollection
- 
-+# UpdateCollectionModule class
-+
-+UpdateCollectionModule = _createrepo_c.UpdateCollectionModule
- 
- # UpdateCollectionPackage class
- 
-diff --git a/src/python/createrepo_cmodule.c b/src/python/createrepo_cmodule.c
-index fe4d2ad..9be5f46 100644
---- a/src/python/createrepo_cmodule.c
-+++ b/src/python/createrepo_cmodule.c
-@@ -35,6 +35,7 @@
- #include "repomdrecord-py.h"
- #include "sqlite-py.h"
- #include "updatecollection-py.h"
-+#include "updatecollectionmodule-py.h"
- #include "updatecollectionpackage-py.h"
- #include "updateinfo-py.h"
- #include "updaterecord-py.h"
-@@ -185,6 +186,13 @@ init_createrepo_c(void)
-     PyModule_AddObject(m, "UpdateCollection",
-                        (PyObject *)&UpdateCollection_Type);
- 
-+    /* _createrepo_c.UpdateCollectionModule */
-+    if (PyType_Ready(&UpdateCollectionModule_Type) < 0)
-+        return FAILURE;
-+    Py_INCREF(&UpdateCollectionModule_Type);
-+    PyModule_AddObject(m, "UpdateCollectionModule",
-+                       (PyObject *)&UpdateCollectionModule_Type);
-+
-     /* _createrepo_c.UpdateCollectionPackage */
-     if (PyType_Ready(&UpdateCollectionPackage_Type) < 0)
-         return FAILURE;
-diff --git a/src/python/updatecollection-py.c b/src/python/updatecollection-py.c
-index 3a791be..ca97657 100644
---- a/src/python/updatecollection-py.c
-+++ b/src/python/updatecollection-py.c
-@@ -22,6 +22,7 @@
- #include <stddef.h>
- 
- #include "updatecollection-py.h"
-+#include "updatecollectionmodule-py.h"
- #include "updatecollectionpackage-py.h"
- #include "exception-py.h"
- #include "typeconversion.h"
-@@ -188,6 +189,13 @@ typedef int (*ConversionToCheckFunc)(PyObject *);
- typedef void *(*ConversionToFunc)(PyObject *, GStringChunk *);
- 
- PyObject *
-+PyObject_FromUpdateCollectionModule(cr_UpdateCollectionModule *module)
-+{
-+    return Object_FromUpdateCollectionModule(
-+                        cr_updatecollectionmodule_copy(module));
-+}
-+
-+PyObject *
- PyObject_FromUpdateCollectionPackage(cr_UpdateCollectionPackage *pkg)
- {
-     return Object_FromUpdateCollectionPackage(
-@@ -249,6 +257,23 @@ get_list(_UpdateCollectionObject *self, void *conv)
-     return list;
- }
- 
-+static PyObject *
-+get_module(_UpdateCollectionObject *self, void *member_offset)
-+{
-+    if (check_UpdateCollectionStatus(self))
-+        return NULL;
-+
-+    cr_UpdateCollection *collection = self->collection;
-+
-+    cr_UpdateCollectionModule *module = *((cr_UpdateCollectionModule **) ((size_t) collection + (size_t) member_offset));
-+    if (module == NULL)
-+        Py_RETURN_NONE;
-+
-+    PyObject *py_module = PyObject_FromUpdateCollectionModule(module);
-+
-+    return py_module;
-+}
-+
- static int
- set_str(_UpdateCollectionObject *self, PyObject *value, void *member_offset)
- {
-@@ -265,11 +290,29 @@ set_str(_UpdateCollectionObject *self, PyObject *value, void *member_offset)
-     return 0;
- }
- 
-+static int
-+set_module(_UpdateCollectionObject *self, PyObject *value, void *member_offset)
-+{
-+    if (check_UpdateCollectionStatus(self))
-+        return -1;
-+    if (!UpdateCollectionModuleObject_Check(value) && value != Py_None) {
-+        PyErr_SetString(PyExc_TypeError, "Module or None expected!");
-+        return -1;
-+    }
-+    cr_UpdateCollectionModule *module = UpdateCollectionModule_FromPyObject(value);
-+    cr_UpdateCollection *collection = self->collection;
-+    *((cr_UpdateCollectionModule **) ((size_t) collection + (size_t) member_offset)) = module;
-+
-+    return 0;
-+}
-+
- static PyGetSetDef updatecollection_getsetters[] = {
-     {"shortname",     (getter)get_str, (setter)set_str,
-         "Short name", OFFSET(shortname)},
-     {"name",          (getter)get_str, (setter)set_str,
-         "Name of the collection", OFFSET(name)},
-+    {"module",        (getter)get_module, (setter)set_module,
-+        "Module information", OFFSET(module)},
-     {"packages",       (getter)get_list, (setter)NULL,
-         "List of packages", &(list_convertors[0])},
-     {NULL, NULL, NULL, NULL, NULL} /* sentinel */
-diff --git a/src/python/updatecollectionmodule-py.c b/src/python/updatecollectionmodule-py.c
-new file mode 100644
-index 0000000..20b2d99
---- /dev/null
-+++ b/src/python/updatecollectionmodule-py.c
-@@ -0,0 +1,274 @@
-+/* createrepo_c - Library of routines for manipulation with repodata
-+ * Copyright (C) 2013  Tomas Mlcoch
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
-+ * USA.
-+ */
-+
-+#include <Python.h>
-+#include <assert.h>
-+#include <stddef.h>
-+
-+#include "updatecollectionmodule-py.h"
-+#include "exception-py.h"
-+#include "typeconversion.h"
-+#include "contentstat-py.h"
-+
-+typedef struct {
-+    PyObject_HEAD
-+    cr_UpdateCollectionModule *module;
-+} _UpdateCollectionModuleObject;
-+
-+PyObject *
-+Object_FromUpdateCollectionModule(cr_UpdateCollectionModule *mod)
-+{
-+    PyObject *py_rec;
-+
-+    if (!mod) {
-+        PyErr_SetString(PyExc_ValueError, "Expected a cr_UpdateCollectionModule pointer not NULL.");
-+        return NULL;
-+    }
-+
-+    py_rec = PyObject_CallObject((PyObject *) &UpdateCollectionModule_Type, NULL);
-+    cr_updatecollectionmodule_free(((_UpdateCollectionModuleObject *)py_rec)->module);
-+    ((_UpdateCollectionModuleObject *)py_rec)->module = mod;
-+
-+    return py_rec;
-+}
-+
-+cr_UpdateCollectionModule *
-+UpdateCollectionModule_FromPyObject(PyObject *o)
-+{
-+    if (!UpdateCollectionModuleObject_Check(o)) {
-+        PyErr_SetString(PyExc_TypeError, "Expected a UpdateCollectionModule object.");
-+        return NULL;
-+    }
-+    return ((_UpdateCollectionModuleObject *)o)->module;
-+}
-+
-+static int
-+check_UpdateCollectionModuleStatus(const _UpdateCollectionModuleObject *self)
-+{
-+    assert(self != NULL);
-+    assert(UpdateCollectionModuleObject_Check(self));
-+    if (self->module == NULL) {
-+        PyErr_SetString(CrErr_Exception, "Improper createrepo_c UpdateCollectionModule object.");
-+        return -1;
-+    }
-+    return 0;
-+}
-+
-+/* Function on the type */
-+
-+static PyObject *
-+updatecollectionmodule_new(PyTypeObject *type,
-+                    G_GNUC_UNUSED PyObject *args,
-+                    G_GNUC_UNUSED PyObject *kwds)
-+{
-+    _UpdateCollectionModuleObject *self = (_UpdateCollectionModuleObject *)type->tp_alloc(type, 0);
-+    if (self) {
-+        self->module = NULL;
-+    }
-+    return (PyObject *)self;
-+}
-+
-+PyDoc_STRVAR(updatecollectionmodule_init__doc__,
-+".. method:: __init__()\n\n");
-+
-+static int
-+updatecollectionmodule_init(_UpdateCollectionModuleObject *self,
-+                     G_GNUC_UNUSED PyObject *args,
-+                     G_GNUC_UNUSED PyObject *kwds)
-+{
-+    /* Free all previous resources when reinitialization */
-+    if (self->module)
-+        cr_updatecollectionmodule_free(self->module);
-+
-+    /* Init */
-+    self->module = cr_updatecollectionmodule_new();
-+    if (self->module == NULL) {
-+        PyErr_SetString(CrErr_Exception, "UpdateCollectionModule initialization failed");
-+        return -1;
-+    }
-+
-+    return 0;
-+}
-+
-+static void
-+updatecollectionmodule_dealloc(_UpdateCollectionModuleObject *self)
-+{
-+    if (self->module)
-+        cr_updatecollectionmodule_free(self->module);
-+    Py_TYPE(self)->tp_free(self);
-+}
-+
-+static PyObject *
-+updatecollectionmodule_repr(G_GNUC_UNUSED _UpdateCollectionModuleObject *self)
-+{
-+    return PyUnicode_FromFormat("<createrepo_c.UpdateCollectionModule object>");
-+}
-+
-+/* UpdateCollectionModule methods */
-+
-+PyDoc_STRVAR(copy__doc__,
-+"copy() -> UpdateCollectionModule\n\n"
-+"Return copy of the UpdateCollectionModule object");
-+
-+static PyObject *
-+copy_updatecollectionmodule(_UpdateCollectionModuleObject *self,
-+                             G_GNUC_UNUSED void *nothing)
-+{
-+    if (check_UpdateCollectionModuleStatus(self))
-+        return NULL;
-+    return Object_FromUpdateCollectionModule(cr_updatecollectionmodule_copy(self->module));
-+}
-+
-+static struct PyMethodDef updatecollectionmodule_methods[] = {
-+    {"copy", (PyCFunction)copy_updatecollectionmodule, METH_NOARGS,
-+        copy__doc__},
-+    {NULL} /* sentinel */
-+};
-+
-+/* getsetters */
-+
-+#define OFFSET(member) (void *) offsetof(cr_UpdateCollectionModule, member)
-+
-+static PyObject *
-+get_str(_UpdateCollectionModuleObject *self, void *member_offset)
-+{
-+    if (check_UpdateCollectionModuleStatus(self))
-+        return NULL;
-+    cr_UpdateCollectionModule *module = self->module;
-+    char *str = *((char **) ((size_t) module + (size_t) member_offset));
-+    if (str == NULL)
-+        Py_RETURN_NONE;
-+    return PyUnicode_FromString(str);
-+}
-+
-+static PyObject *
-+get_uint(_UpdateCollectionModuleObject *self, void *member_offset)
-+{
-+    if (check_UpdateCollectionModuleStatus(self))
-+        return NULL;
-+    cr_UpdateCollectionModule *module = self->module;
-+    guint64 val = *((guint64 *) ((size_t) module + (size_t) member_offset));
-+    return PyLong_FromUnsignedLongLong((guint64) val);
-+}
-+
-+static int
-+set_str(_UpdateCollectionModuleObject *self, PyObject *value, void *member_offset)
-+{
-+    if (check_UpdateCollectionModuleStatus(self))
-+        return -1;
-+    if (!PyUnicode_Check(value) && !PyBytes_Check(value) && value != Py_None) {
-+        PyErr_SetString(PyExc_TypeError, "Unicode, bytes, or None expected!");
-+        return -1;
-+    }
-+
-+    if (PyUnicode_Check(value)) {
-+        value = PyUnicode_AsUTF8String(value);
-+    }
-+
-+    cr_UpdateCollectionModule *module = self->module;
-+    char *str = cr_safe_string_chunk_insert(module->chunk,
-+                                            PyObject_ToStrOrNull(value));
-+
-+    *((char **) ((size_t) module + (size_t) member_offset)) = str;
-+    return 0;
-+}
-+
-+static int
-+set_uint(_UpdateCollectionModuleObject *self, PyObject *value, void *member_offset)
-+{
-+    if (check_UpdateCollectionModuleStatus(self))
-+        return -1;
-+    guint64 val;
-+
-+    if (PyLong_Check(value)) {
-+        val = PyLong_AsUnsignedLongLong(value);
-+    } else if (PyFloat_Check(value)) {
-+        val = (guint64) PyFloat_AS_DOUBLE(value);
-+#if PY_MAJOR_VERSION < 3
-+    } else if (PyInt_Check(value)) {
-+        val = PyInt_AS_LONG(value);
-+#endif
-+    } else {
-+        PyErr_SetString(PyExc_TypeError, "Number expected!");
-+        return -1;
-+    }
-+
-+    cr_UpdateCollectionModule *module = self->module;
-+    *((guint64 *) ((size_t) module + (size_t) member_offset)) = (guint64) val;
-+    return 0;
-+}
-+
-+static PyGetSetDef updatecollectionmodule_getsetters[] = {
-+    {"name",               (getter)get_str, (setter)set_str,
-+        "Name",            OFFSET(name)},
-+    {"stream",             (getter)get_str, (setter)set_str,
-+        "Stream",          OFFSET(stream)},
-+    {"version",            (getter)get_uint, (setter)set_uint,
-+        "Version",         OFFSET(version)},
-+    {"context",            (getter)get_str, (setter)set_str,
-+        "Context",         OFFSET(context)},
-+    {"arch",               (getter)get_str, (setter)set_str,
-+        "Arch",            OFFSET(arch)},
-+    {NULL, NULL, NULL, NULL, NULL} /* sentinel */
-+};
-+
-+/* Object */
-+
-+PyTypeObject UpdateCollectionModule_Type = {
-+    PyVarObject_HEAD_INIT(NULL, 0)
-+    "createrepo_c.UpdateCollectionModule", /* tp_name */
-+    sizeof(_UpdateCollectionModuleObject), /* tp_basicsize */
-+    0,                              /* tp_itemsize */
-+    (destructor) updatecollectionmodule_dealloc, /* tp_dealloc */
-+    0,                              /* tp_print */
-+    0,                              /* tp_getattr */
-+    0,                              /* tp_setattr */
-+    0,                              /* tp_compare */
-+    (reprfunc) updatecollectionmodule_repr,/* tp_repr */
-+    0,                              /* tp_as_number */
-+    0,                              /* tp_as_sequence */
-+    0,                              /* tp_as_mapping */
-+    0,                              /* tp_hash */
-+    0,                              /* tp_call */
-+    0,                              /* tp_str */
-+    0,                              /* tp_getattro */
-+    0,                              /* tp_setattro */
-+    0,                              /* tp_as_buffer */
-+    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
-+    updatecollectionmodule_init__doc__,    /* tp_doc */
-+    0,                              /* tp_traverse */
-+    0,                              /* tp_clear */
-+    0,                              /* tp_richcompare */
-+    0,                              /* tp_weaklistoffset */
-+    PyObject_SelfIter,              /* tp_iter */
-+    0,                              /* tp_iternext */
-+    updatecollectionmodule_methods,        /* tp_methods */
-+    0,                              /* tp_members */
-+    updatecollectionmodule_getsetters,     /* tp_getset */
-+    0,                              /* tp_base */
-+    0,                              /* tp_dict */
-+    0,                              /* tp_descr_get */
-+    0,                              /* tp_descr_set */
-+    0,                              /* tp_dictoffset */
-+    (initproc) updatecollectionmodule_init,/* tp_init */
-+    0,                              /* tp_alloc */
-+    updatecollectionmodule_new,            /* tp_new */
-+    0,                              /* tp_free */
-+    0,                              /* tp_is_gc */
-+};
-diff --git a/src/python/updatecollectionmodule-py.h b/src/python/updatecollectionmodule-py.h
-new file mode 100644
-index 0000000..5847259
---- /dev/null
-+++ b/src/python/updatecollectionmodule-py.h
-@@ -0,0 +1,33 @@
-+/* createrepo_c - Library of routines for manipulation with repodata
-+ * Copyright (C) 2013  Tomas Mlcoch
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
-+ * USA.
-+ */
-+
-+#ifndef CR_UPDATECOLLECTIONMODULE_PY_H
-+#define CR_UPDATECOLLECTIONMODULE_PY_H
-+
-+#include "src/createrepo_c.h"
-+
-+extern PyTypeObject UpdateCollectionModule_Type;
-+
-+#define UpdateCollectionModuleObject_Check(o) \
-+            PyObject_TypeCheck(o, &UpdateCollectionModule_Type)
-+
-+PyObject *Object_FromUpdateCollectionModule(cr_UpdateCollectionModule *rec);
-+cr_UpdateCollectionModule *UpdateCollectionModule_FromPyObject(PyObject *o);
-+
-+#endif
-diff --git a/src/updateinfo.c b/src/updateinfo.c
-index 6e45229..cdc4747 100644
---- a/src/updateinfo.c
-+++ b/src/updateinfo.c
-@@ -74,6 +74,46 @@ cr_updatecollectionpackage_free(cr_UpdateCollectionPackage *pkg)
- 
- 
- /*
-+ * cr_UpdateCollectionModule
-+ */
-+
-+cr_UpdateCollectionModule *
-+cr_updatecollectionmodule_new(void)
-+{
-+    cr_UpdateCollectionModule *module = g_malloc0(sizeof(*module));
-+    module->chunk = g_string_chunk_new(0);
-+    return module;
-+}
-+
-+cr_UpdateCollectionModule *
-+cr_updatecollectionmodule_copy(const cr_UpdateCollectionModule *orig)
-+{
-+    cr_UpdateCollectionModule *module;
-+
-+    if (!orig) return NULL;
-+
-+    module = cr_updatecollectionmodule_new();
-+
-+    module->name    = cr_safe_string_chunk_insert(module->chunk, orig->name);
-+    module->stream  = cr_safe_string_chunk_insert(module->chunk, orig->stream);
-+    module->version = orig->version;
-+    module->context = cr_safe_string_chunk_insert(module->chunk, orig->context);
-+    module->arch    = cr_safe_string_chunk_insert(module->chunk, orig->arch);
-+
-+    return module;
-+}
-+
-+void
-+cr_updatecollectionmodule_free(cr_UpdateCollectionModule *module)
-+{
-+    if (!module)
-+        return;
-+    g_string_chunk_free(module->chunk);
-+    g_free(module);
-+}
-+
-+
-+/*
-  * cr_UpdateCollection
-  */
- 
-@@ -97,6 +137,10 @@ cr_updatecollection_copy(const cr_UpdateCollection *orig)
-     col->shortname = cr_safe_string_chunk_insert(col->chunk, orig->shortname);
-     col->name      = cr_safe_string_chunk_insert(col->chunk, orig->name);
- 
-+    if (orig->module) {
-+      col->module = cr_updatecollectionmodule_copy(orig->module);
-+    }
-+
-     if (orig->packages) {
-         GSList *newlist = NULL;
-         for (GSList *elem = orig->packages; elem; elem = g_slist_next(elem)) {
-diff --git a/src/updateinfo.h b/src/updateinfo.h
-index dbf7807..38883e0 100644
---- a/src/updateinfo.h
-+++ b/src/updateinfo.h
-@@ -51,8 +51,19 @@ typedef struct {
- } cr_UpdateCollectionPackage;
- 
- typedef struct {
-+    gchar *name;
-+    gchar *stream;
-+    guint64 version;
-+    gchar *context;
-+    gchar *arch;
-+
-+    GStringChunk *chunk;
-+} cr_UpdateCollectionModule;
-+
-+typedef struct {
-     gchar *shortname;   /*!< e.g. rhn-tools-rhel-x86_64-server-6.5.aus */
-     gchar *name;        /*!< e.g. RHN Tools for RHEL AUS (v. 6.5 for 64-bit x86_64) */
-+    cr_UpdateCollectionModule *module;
-     GSList *packages;   /*!< List of cr_UpdateCollectionPackage */
-     GStringChunk *chunk;
- } cr_UpdateCollection;
-@@ -106,6 +117,19 @@ void
- cr_updatecollectionpackage_free(cr_UpdateCollectionPackage *pkg);
- 
- /*
-+ * cr_UpdateCollectionModule
-+ */
-+
-+cr_UpdateCollectionModule *
-+cr_updatecollectionmodule_new(void);
-+
-+cr_UpdateCollectionModule *
-+cr_updatecollectionmodule_copy(const cr_UpdateCollectionModule *orig);
-+
-+void
-+cr_updatecollectionmodule_free(cr_UpdateCollectionModule *pkg);
-+
-+/*
-  * cr_UpdateCollection
-  */
- 
-diff --git a/src/xml_dump_updateinfo.c b/src/xml_dump_updateinfo.c
-index 4fb5720..fafe686 100644
---- a/src/xml_dump_updateinfo.c
-+++ b/src/xml_dump_updateinfo.c
-@@ -66,6 +66,24 @@ cr_xml_dump_updatecollectionpackages(xmlNodePtr collection, GSList *packages)
- }
- 
- void
-+cr_xml_dump_updatecollectionmodule(xmlNodePtr collection, cr_UpdateCollectionModule *module)
-+{
-+    if (!module)
-+        return;
-+
-+    xmlNodePtr xml_module;
-+    xml_module = xmlNewChild(collection, NULL, BAD_CAST "module", NULL);
-+
-+    cr_xmlNewProp_c(xml_module, BAD_CAST "name", BAD_CAST module->name);
-+    cr_xmlNewProp_c(xml_module, BAD_CAST "stream", BAD_CAST module->stream);
-+    gchar buf[21]; //20 + '\0' is max number of chars of guint64: G_MAXUINT64 (= 18,446,744,073,709,551,615)
-+    snprintf(buf, 21, "%" G_GUINT64_FORMAT, module->version);
-+    cr_xmlNewProp_c(xml_module, BAD_CAST "version", BAD_CAST buf);
-+    cr_xmlNewProp_c(xml_module, BAD_CAST "context", BAD_CAST module->context);
-+    cr_xmlNewProp_c(xml_module, BAD_CAST "arch", BAD_CAST module->arch);
-+}
-+
-+void
- cr_xml_dump_updateinforecord_pkglist(xmlNodePtr update, GSList *collections)
- {
-     xmlNodePtr pkglist;
-@@ -83,6 +101,8 @@ cr_xml_dump_updateinforecord_pkglist(xmlNodePtr update, GSList *collections)
-                              BAD_CAST "name",
-                              BAD_CAST col->name);
- 
-+        cr_xml_dump_updatecollectionmodule(collection, col->module);
-+
-         cr_xml_dump_updatecollectionpackages(collection, col->packages);
-     }
- }
-diff --git a/src/xml_parser_internal.h b/src/xml_parser_internal.h
-index 6b400eb..e079ece 100644
---- a/src/xml_parser_internal.h
-+++ b/src/xml_parser_internal.h
-@@ -151,6 +151,8 @@ typedef struct _cr_ParserData {
-         Update record object */
-     cr_UpdateCollection *updatecollection; /*!<
-         Update collection object */
-+    cr_UpdateCollectionModule *updatecollectionmodule; /*!<
-+        Update collection module object */
-     cr_UpdateCollectionPackage *updatecollectionpackage; /*!<
-         Update collection package object */
- 
-diff --git a/src/xml_parser_updateinfo.c b/src/xml_parser_updateinfo.c
-index 18e5277..c6c6503 100644
---- a/src/xml_parser_updateinfo.c
-+++ b/src/xml_parser_updateinfo.c
-@@ -54,6 +54,7 @@ typedef enum {
-     STATE_PKGLIST,          // <pkglist> ----------------------------
-     STATE_COLLECTION,
-     STATE_NAME,
-+    STATE_MODULE,
-     STATE_PACKAGE,
-     STATE_FILENAME,
-     STATE_SUM,
-@@ -89,6 +90,7 @@ static cr_StatesSwitch stateswitches[] = {
-     { STATE_PKGLIST,    "collection",        STATE_COLLECTION,        0 },
-     { STATE_COLLECTION, "package",           STATE_PACKAGE,           0 },
-     { STATE_COLLECTION, "name",              STATE_NAME,              1 },
-+    { STATE_COLLECTION, "module",            STATE_MODULE,            0 },
-     { STATE_PACKAGE,    "filename",          STATE_FILENAME,          1 },
-     { STATE_PACKAGE,    "sum",               STATE_SUM,               1 },
-     { STATE_PACKAGE,    "reboot_suggested",  STATE_REBOOTSUGGESTED,   0 },
-@@ -141,6 +143,7 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
-     // Shortcuts
-     cr_UpdateRecord *rec = pd->updaterecord;
-     cr_UpdateCollection *collection = pd->updatecollection;
-+    cr_UpdateCollectionModule *module = pd->updatecollectionmodule;
-     cr_UpdateCollectionPackage *package = pd->updatecollectionpackage;
- 
-     switch(pd->state) {
-@@ -173,6 +176,7 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
-         assert(pd->updateinfo);
-         assert(!pd->updaterecord);
-         assert(!pd->updatecollection);
-+        assert(!pd->updatecollectionmodule);
-         assert(!pd->updatecollectionpackage);
- 
-         rec = cr_updaterecord_new();
-@@ -201,6 +205,7 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
-         assert(pd->updateinfo);
-         assert(pd->updaterecord);
-         assert(!pd->updatecollection);
-+        assert(!pd->updatecollectionmodule);
-         assert(!pd->updatecollectionpackage);
-         val = cr_find_attr("date", attr);
-         if (val)
-@@ -211,6 +216,7 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
-         assert(pd->updateinfo);
-         assert(pd->updaterecord);
-         assert(!pd->updatecollection);
-+        assert(!pd->updatecollectionmodule);
-         assert(!pd->updatecollectionpackage);
-         val = cr_find_attr("date", attr);
-         if (val)
-@@ -223,6 +229,7 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
-         assert(pd->updateinfo);
-         assert(pd->updaterecord);
-         assert(!pd->updatecollection);
-+        assert(!pd->updatecollectionmodule);
-         assert(!pd->updatecollectionpackage);
- 
-         ref = cr_updatereference_new();
-@@ -251,6 +258,7 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
-         assert(pd->updateinfo);
-         assert(pd->updaterecord);
-         assert(!pd->updatecollection);
-+        assert(!pd->updatecollectionmodule);
-         assert(!pd->updatecollectionpackage);
- 
-         collection = cr_updatecollection_new();
-@@ -263,6 +271,49 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
- 
-         break;
- 
-+    case STATE_MODULE:
-+        assert(pd->updateinfo);
-+        assert(pd->updaterecord);
-+        assert(pd->updatecollection);
-+        assert(!pd->updatecollectionmodule);
-+        assert(!pd->updatecollectionpackage);
-+
-+        module = cr_updatecollectionmodule_new();
-+        if (module)
-+            collection->module = module;
-+
-+        val = cr_find_attr("name", attr);
-+        if (val)
-+            module->name = g_string_chunk_insert(module->chunk, val);
-+
-+        val = cr_find_attr("stream", attr);
-+        if (val)
-+            module->stream = g_string_chunk_insert(module->chunk, val);
-+
-+        val = cr_find_attr("version", attr);
-+        if (val){
-+            gchar *endptr;
-+            errno = 0;
-+            module->version = strtoull(val, &endptr, 10);
-+            if ((errno == ERANGE && (module->version == ULLONG_MAX))
-+                 || (errno != 0 && module->version == 0)) {
-+                perror("strtoull error when parsing module version");
-+                module->version = 0;
-+            }
-+            if (endptr == val)
-+                module->version = 0;
-+        }
-+
-+        val = cr_find_attr("context", attr);
-+        if (val)
-+            module->context = g_string_chunk_insert(module->chunk, val);
-+
-+        val = cr_find_attr("arch", attr);
-+        if (val)
-+            module->arch = g_string_chunk_insert(module->chunk, val);
-+
-+        break;
-+
-     case STATE_PACKAGE:
-         assert(pd->updateinfo);
-         assert(pd->updaterecord);
-@@ -303,6 +354,7 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
-         assert(pd->updateinfo);
-         assert(pd->updaterecord);
-         assert(pd->updatecollection);
-+        assert(pd->updatecollectionmodule);
-         assert(pd->updatecollectionpackage);
-         val = cr_find_attr("type", attr);
-         if (val)
-@@ -313,6 +365,7 @@ cr_start_handler(void *pdata, const char *element, const char **attr)
-         assert(pd->updateinfo);
-         assert(pd->updaterecord);
-         assert(pd->updatecollection);
-+        assert(pd->updatecollectionmodule);
-         assert(pd->updatecollectionpackage);
-         package->reboot_suggested = TRUE;
-         break;
-@@ -352,6 +405,7 @@ cr_end_handler(void *pdata, G_GNUC_UNUSED const char *element)
-     case STATE_UPDATED:
-     case STATE_REFERENCES:
-     case STATE_REFERENCE:
-+    case STATE_MODULE:
-     case STATE_PKGLIST:
-     case STATE_REBOOTSUGGESTED:
-         // All elements with no text data and without need of any
-diff --git a/tests/fixtures.h b/tests/fixtures.h
-index ee374f5..8567714 100644
---- a/tests/fixtures.h
-+++ b/tests/fixtures.h
-@@ -83,5 +83,6 @@
- #define TEST_UPDATEINFO_00      TEST_UPDATEINFO_FILES_PATH"updateinfo_00.xml"
- #define TEST_UPDATEINFO_01      TEST_UPDATEINFO_FILES_PATH"updateinfo_01.xml"
- #define TEST_UPDATEINFO_02      TEST_UPDATEINFO_FILES_PATH"updateinfo_02.xml.xz"
-+#define TEST_UPDATEINFO_03      TEST_UPDATEINFO_FILES_PATH"updateinfo_03.xml"
- 
- #endif
-diff --git a/tests/python/tests/test_updatecollection.py b/tests/python/tests/test_updatecollection.py
-index f3433c0..71ac7dd 100644
---- a/tests/python/tests/test_updatecollection.py
-+++ b/tests/python/tests/test_updatecollection.py
-@@ -16,6 +16,13 @@ class TestCaseUpdateCollection(unittest.TestCase):
-         self.assertEqual(col.name, None)
-         self.assertEqual(col.packages, [])
- 
-+        module = cr.UpdateCollectionModule()
-+        module.name = "kangaroo"
-+        module.stream = "0"
-+        module.version = 20180730223407
-+        module.context = "deadbeef"
-+        module.arch = "noarch"
-+
-         pkg = cr.UpdateCollectionPackage()
-         pkg.name = "foo"
-         pkg.version = "1.2"
-@@ -30,12 +37,21 @@ class TestCaseUpdateCollection(unittest.TestCase):
- 
-         col.shortname = "short name"
-         col.name = "long name"
-+        col.module = module
-         col.append(pkg)
- 
-         self.assertEqual(col.shortname, "short name")
-         self.assertEqual(col.name, "long name")
-         self.assertEqual(len(col.packages), 1)
- 
-+        # Check if the appended module was appended properly
-+        module = col.module
-+        self.assertEqual(module.name, "kangaroo")
-+        self.assertEqual(module.stream, "0")
-+        self.assertEqual(module.version, 20180730223407)
-+        self.assertEqual(module.context, "deadbeef")
-+        self.assertEqual(module.arch, "noarch")
-+
-         # Also check if the appended package was appended properly
-         pkg = col.packages[0]
-         self.assertEqual(pkg.name, "foo")
-diff --git a/tests/python/tests/test_updatecollectionmodule.py b/tests/python/tests/test_updatecollectionmodule.py
-new file mode 100644
-index 0000000..1e92b12
---- /dev/null
-+++ b/tests/python/tests/test_updatecollectionmodule.py
-@@ -0,0 +1,31 @@
-+import unittest
-+import shutil
-+import tempfile
-+import os.path
-+import createrepo_c as cr
-+
-+from .fixtures import *
-+
-+class TestCaseUpdateCollectionModule(unittest.TestCase):
-+
-+    def test_updatecollectionmodule_setters(self):
-+        module = cr.UpdateCollectionModule()
-+        self.assertTrue(module)
-+
-+        self.assertEqual(module.name, None)
-+        self.assertEqual(module.stream, None)
-+        self.assertEqual(module.version, 0)
-+        self.assertEqual(module.context, None)
-+        self.assertEqual(module.arch, None)
-+
-+        module.name = "foo"
-+        module.stream = "0"
-+        module.version = 20180730223407
-+        module.context = "deadbeef"
-+        module.arch = "noarch"
-+
-+        self.assertEqual(module.name, "foo")
-+        self.assertEqual(module.stream, "0")
-+        self.assertEqual(module.version, 20180730223407)
-+        self.assertEqual(module.context, "deadbeef")
-+        self.assertEqual(module.arch, "noarch")
-diff --git a/tests/python/tests/test_updateinfo.py b/tests/python/tests/test_updateinfo.py
-index f3b88e1..727b707 100644
---- a/tests/python/tests/test_updateinfo.py
-+++ b/tests/python/tests/test_updateinfo.py
-@@ -123,6 +123,100 @@ class TestCaseUpdateInfo(unittest.TestCase):
-         now = datetime(now.year, now.month, now.day, now.hour, now.minute,
-                        now.second, 0)
- 
-+        mod = cr.UpdateCollectionModule()
-+        mod.name = "kangaroo"
-+        mod.stream = "0"
-+        mod.version = 18446744073709551615
-+        mod.context = "deadbeef"
-+        mod.arch = "x86"
-+
-+        pkg = cr.UpdateCollectionPackage()
-+        pkg.name = "foo"
-+        pkg.version = "1.2"
-+        pkg.release = "3"
-+        pkg.epoch = "0"
-+        pkg.arch = "x86"
-+        pkg.src = "foo.src.rpm"
-+        pkg.filename = "foo.rpm"
-+        pkg.sum = "abcdef"
-+        pkg.sum_type = cr.SHA1
-+        pkg.reboot_suggested = True
-+
-+        col = cr.UpdateCollection()
-+        col.shortname = "short name"
-+        col.name = "long name"
-+        col.module = mod
-+        col.append(pkg)
-+
-+        ref = cr.UpdateReference()
-+        ref.href = "href"
-+        ref.id = "id"
-+        ref.type = "type"
-+        ref.title = "title"
-+
-+        rec = cr.UpdateRecord()
-+        rec.fromstr = "from"
-+        rec.status = "status"
-+        rec.type = "type"
-+        rec.version = "version"
-+        rec.id = "id"
-+        rec.title = "title"
-+        rec.issued_date = now
-+        rec.updated_date = now
-+        rec.rights = "rights"
-+        rec.release = "release"
-+        rec.pushcount = "pushcount"
-+        rec.severity = "severity"
-+        rec.summary = "summary"
-+        rec.description = "description"
-+        rec.solution = "solution"
-+        rec.append_collection(col)
-+        rec.append_reference(ref)
-+
-+        ui = cr.UpdateInfo()
-+        ui.append(rec)
-+
-+        xml = ui.xml_dump()
-+
-+        self.assertEqual(xml,
-+"""<?xml version="1.0" encoding="UTF-8"?>
-+<updates>
-+  <update from="from" status="status" type="type" version="version">
-+    <id>id</id>
-+    <title>title</title>
-+    <issued date="%(now)s"/>
-+    <updated date="%(now)s"/>
-+    <rights>rights</rights>
-+    <release>release</release>
-+    <pushcount>pushcount</pushcount>
-+    <severity>severity</severity>
-+    <summary>summary</summary>
-+    <description>description</description>
-+    <solution>solution</solution>
-+    <references>
-+      <reference href="href" id="id" type="type" title="title"/>
-+    </references>
-+    <pkglist>
-+      <collection short="short name">
-+        <name>long name</name>
-+        <module name="kangaroo" stream="0" version="18446744073709551615" context="deadbeef" arch="x86"/>
-+        <package name="foo" version="1.2" release="3" epoch="0" arch="x86" src="foo.src.rpm">
-+          <filename>foo.rpm</filename>
-+          <sum type="sha1">abcdef</sum>
-+          <reboot_suggested/>
-+        </package>
-+      </collection>
-+    </pkglist>
-+  </update>
-+</updates>
-+""" % {"now": now.strftime("%Y-%m-%d %H:%M:%S")})
-+
-+    def test_updateinfo_xml_dump_04(self):
-+        now = datetime.now()
-+        # Microseconds are always 0 in updateinfo
-+        now = datetime(now.year, now.month, now.day, now.hour, now.minute,
-+                       now.second, 0)
-+
-         pkg = cr.UpdateCollectionPackage()
-         pkg.name = "foo"
-         pkg.version = "1.2"
-@@ -135,6 +229,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
-         pkg.sum_type = cr.SHA1
-         pkg.reboot_suggested = True
- 
-+        # Collection without module
-         col = cr.UpdateCollection()
-         col.shortname = "short name"
-         col.name = "long name"
-@@ -167,6 +262,99 @@ class TestCaseUpdateInfo(unittest.TestCase):
- 
-         ui = cr.UpdateInfo()
-         ui.append(rec)
-+
-+        xml = ui.xml_dump()
-+
-+        self.assertEqual(xml,
-+"""<?xml version="1.0" encoding="UTF-8"?>
-+<updates>
-+  <update from="from" status="status" type="type" version="version">
-+    <id>id</id>
-+    <title>title</title>
-+    <issued date="%(now)s"/>
-+    <updated date="%(now)s"/>
-+    <rights>rights</rights>
-+    <release>release</release>
-+    <pushcount>pushcount</pushcount>
-+    <severity>severity</severity>
-+    <summary>summary</summary>
-+    <description>description</description>
-+    <solution>solution</solution>
-+    <references>
-+      <reference href="href" id="id" type="type" title="title"/>
-+    </references>
-+    <pkglist>
-+      <collection short="short name">
-+        <name>long name</name>
-+        <package name="foo" version="1.2" release="3" epoch="0" arch="x86" src="foo.src.rpm">
-+          <filename>foo.rpm</filename>
-+          <sum type="sha1">abcdef</sum>
-+          <reboot_suggested/>
-+        </package>
-+      </collection>
-+    </pkglist>
-+  </update>
-+</updates>
-+""" % {"now": now.strftime("%Y-%m-%d %H:%M:%S")})
-+
-+    def test_updateinfo_xml_dump_05(self):
-+        now = datetime.now()
-+        # Microseconds are always 0 in updateinfo
-+        now = datetime(now.year, now.month, now.day, now.hour, now.minute,
-+                       now.second, 0)
-+
-+        # Collection module with unset fields
-+        mod = cr.UpdateCollectionModule()
-+        mod.version = 18446744073709551615
-+        mod.context = "deadbeef"
-+        mod.arch = "x86"
-+
-+        pkg = cr.UpdateCollectionPackage()
-+        pkg.name = "foo"
-+        pkg.version = "1.2"
-+        pkg.release = "3"
-+        pkg.epoch = "0"
-+        pkg.arch = "x86"
-+        pkg.src = "foo.src.rpm"
-+        pkg.filename = "foo.rpm"
-+        pkg.sum = "abcdef"
-+        pkg.sum_type = cr.SHA1
-+        pkg.reboot_suggested = True
-+
-+        col = cr.UpdateCollection()
-+        col.shortname = "short name"
-+        col.name = "long name"
-+        col.module = mod
-+        col.append(pkg)
-+
-+        ref = cr.UpdateReference()
-+        ref.href = "href"
-+        ref.id = "id"
-+        ref.type = "type"
-+        ref.title = "title"
-+
-+        rec = cr.UpdateRecord()
-+        rec.fromstr = "from"
-+        rec.status = "status"
-+        rec.type = "type"
-+        rec.version = "version"
-+        rec.id = "id"
-+        rec.title = "title"
-+        rec.issued_date = now
-+        rec.updated_date = now
-+        rec.rights = "rights"
-+        rec.release = "release"
-+        rec.pushcount = "pushcount"
-+        rec.severity = "severity"
-+        rec.summary = "summary"
-+        rec.description = "description"
-+        rec.solution = "solution"
-+        rec.append_collection(col)
-+        rec.append_reference(ref)
-+
-+        ui = cr.UpdateInfo()
-+        ui.append(rec)
-+
-         xml = ui.xml_dump()
- 
-         self.assertEqual(xml,
-@@ -190,6 +378,7 @@ class TestCaseUpdateInfo(unittest.TestCase):
-     <pkglist>
-       <collection short="short name">
-         <name>long name</name>
-+        <module version="18446744073709551615" context="deadbeef" arch="x86"/>
-         <package name="foo" version="1.2" release="3" epoch="0" arch="x86" src="foo.src.rpm">
-           <filename>foo.rpm</filename>
-           <sum type="sha1">abcdef</sum>
-diff --git a/tests/test_xml_parser_updateinfo.c b/tests/test_xml_parser_updateinfo.c
-index 94768ce..3f0cfee 100644
---- a/tests/test_xml_parser_updateinfo.c
-+++ b/tests/test_xml_parser_updateinfo.c
-@@ -168,6 +168,90 @@ test_cr_xml_parse_updateinfo_02(void)
-     cr_updateinfo_free(ui);
- }
- 
-+//Test for module support
-+static void
-+test_cr_xml_parse_updateinfo_03(void)
-+{
-+    GError *tmp_err = NULL;
-+    cr_UpdateInfo *ui = cr_updateinfo_new();
-+    cr_UpdateRecord *update;
-+    cr_UpdateReference *ref;
-+    cr_UpdateCollection *col;
-+    cr_UpdateCollectionModule *module;
-+    cr_UpdateCollectionPackage *pkg;
-+
-+    int ret = cr_xml_parse_updateinfo(TEST_UPDATEINFO_03, ui,
-+                                      NULL, NULL, &tmp_err);
-+
-+    g_assert(tmp_err == NULL);
-+    g_assert_cmpint(ret, ==, CRE_OK);
-+
-+    g_assert_cmpint(g_slist_length(ui->updates), ==, 6);
-+    update = g_slist_nth_data(ui->updates, 3);
-+
-+    g_assert_cmpstr(update->from, ==, "errata@redhat.com");
-+    g_assert_cmpstr(update->status, ==, "stable");
-+    g_assert_cmpstr(update->type, ==, "enhancement");
-+    g_assert_cmpstr(update->version, ==, "1");
-+    g_assert_cmpstr(update->id, ==, "RHEA-2012:0058");
-+    g_assert_cmpstr(update->title, ==, "Gorilla_Erratum");
-+    g_assert_cmpstr(update->description, ==, "Gorilla_Erratum");
-+
-+    update = g_slist_nth_data(ui->updates, 4);
-+
-+    g_assert_cmpstr(update->id, ==, "RHEA-2012:0059");
-+    g_assert_cmpstr(update->title, ==, "Duck_Kangaroo_Erratum");
-+    g_assert_cmpstr(update->description, ==, "Duck_Kangaro_Erratum description");
-+    g_assert_cmpstr(update->issued_date, ==, "2018-01-27 16:08:09");
-+    g_assert_cmpstr(update->updated_date, ==, "2018-07-20 06:00:01 UTC");
-+    g_assert_cmpstr(update->release, ==, "1");
-+
-+    g_assert_cmpint(g_slist_length(update->references), ==, 0);
-+
-+    g_assert_cmpint(g_slist_length(update->collections), ==, 2);
-+    col = g_slist_nth_data(update->collections, 0);
-+    g_assert_cmpstr(col->shortname, ==, "");
-+    g_assert_cmpstr(col->name, ==, "coll_name1");
-+
-+    module = col->module;
-+    g_assert_cmpstr(module->name, ==, "kangaroo");
-+    g_assert_cmpstr(module->stream, ==, "0");
-+    g_assert_cmpuint(module->version, ==, 20180730223407);
-+    g_assert_cmpstr(module->context, ==, "deadbeef");
-+    g_assert_cmpstr(module->arch, ==, "noarch");
-+
-+    g_assert_cmpint(g_slist_length(col->packages), ==, 1);
-+    pkg = col->packages->data;
-+    g_assert_cmpstr(pkg->name, ==, "kangaroo");
-+    g_assert_cmpstr(pkg->version, ==, "0.3");
-+    g_assert_cmpstr(pkg->release, ==, "1");
-+    g_assert(!pkg->epoch);
-+    g_assert_cmpstr(pkg->arch, ==, "noarch");
-+    g_assert_cmpstr(pkg->src, ==, "http://www.fedoraproject.org");
-+    g_assert_cmpstr(pkg->filename, ==, "kangaroo-0.3-1.noarch.rpm");
-+    g_assert(!pkg->sum);
-+    g_assert(!pkg->sum_type);
-+
-+    col = g_slist_nth_data(update->collections, 1);
-+    g_assert_cmpstr(col->shortname, ==, "");
-+    g_assert_cmpstr(col->name, ==, "coll_name2");
-+
-+    module = col->module;
-+    g_assert_cmpstr(module->name, ==, "duck");
-+    g_assert_cmpstr(module->stream, ==, "0");
-+    g_assert_cmpuint(module->version, ==, 20180730233102);
-+    g_assert_cmpstr(module->context, ==, "deadbeef");
-+    g_assert_cmpstr(module->arch, ==, "noarch");
-+
-+    g_assert_cmpint(g_slist_length(col->packages), ==, 1);
-+    pkg = col->packages->data;
-+    g_assert_cmpstr(pkg->name, ==, "duck");
-+    g_assert_cmpstr(pkg->version, ==, "0.7");
-+    g_assert_cmpstr(pkg->filename, ==, "duck-0.7-1.noarch.rpm");
-+
-+    cr_updateinfo_free(ui);
-+}
-+
- int
- main(int argc, char *argv[])
- {
-@@ -179,6 +263,8 @@ main(int argc, char *argv[])
-                     test_cr_xml_parse_updateinfo_01);
-     g_test_add_func("/xml_parser_updateinfo/test_cr_xml_parse_updateinfo_02",
-                     test_cr_xml_parse_updateinfo_02);
-+    g_test_add_func("/xml_parser_updateinfo/test_cr_xml_parse_updateinfo_03",
-+                    test_cr_xml_parse_updateinfo_03);
- 
-     return g_test_run();
- }
-diff --git a/tests/testdata/updateinfo_files/updateinfo_03.xml b/tests/testdata/updateinfo_files/updateinfo_03.xml
-new file mode 100644
-index 0000000..ddbd99b
---- /dev/null
-+++ b/tests/testdata/updateinfo_files/updateinfo_03.xml
-@@ -0,0 +1,128 @@
-+<?xml version="1.0"?>
-+<updates>
-+<update from="errata@redhat.com" status="stable" type="security" version="1">
-+  <id>RHEA-2012:0055</id>
-+  <title>Sea_Erratum</title>
-+  <release>1</release>
-+  <issued date="2012-01-27 16:08:06"/>
-+  <updated date="2012-01-27 16:08:06"/>
-+  <description>Sea_Erratum</description>
-+  <pkglist>
-+    <collection short="">
-+      <name>1</name>
-+      <package arch="noarch" name="walrus" release="1" src="http://www.fedoraproject.org" version="5.21">
-+        <filename>walrus-5.21-1.noarch.rpm</filename>
-+      </package>
-+      <package arch="noarch" name="penguin" release="1" src="http://www.fedoraproject.org" version="0.9.1">
-+        <filename>penguin-0.9.1-1.noarch.rpm</filename>
-+      </package>
-+      <package arch="noarch" name="shark" release="1" src="http://www.fedoraproject.org" version="0.1">
-+        <filename>shark-0.1-1.noarch.rpm</filename>
-+      </package>
-+    </collection>
-+  </pkglist>
-+</update>
-+
-+<update from="errata@redhat.com" status="stable" type="security" version="1">
-+  <id>RHEA-2012:0056</id>
-+  <title>Bird_Erratum</title>
-+  <release>1</release>
-+  <issued date="2013-01-27 16:08:08"/>
-+  <updated date="2013-02-27 17:00:00"/>
-+  <description>ParthaBird_Erratum</description>
-+  <pkglist>
-+    <collection short="">
-+      <name>1</name>
-+      <package arch="noarch" name="crow" release="1" src="http://www.fedoraproject.org" version="0.8">
-+        <filename>crow-0.8-1.noarch.rpm</filename>
-+      </package>
-+      <package arch="noarch" name="stork" release="2" src="http://www.fedoraproject.org" version="0.12">
-+        <filename>stork-0.12-2.noarch.rpm</filename>
-+      </package>
-+      <package arch="noarch" name="duck" release="1" src="http://www.fedoraproject.org" version="0.6">
-+        <filename>duck-0.6-1.noarch.rpm</filename>
-+      </package>
-+    </collection>
-+  </pkglist>
-+</update>
-+
-+<update from="errata@redhat.com" status="stable" type="security" version="1">
-+  <id>RHEA-2012:0057</id>
-+  <title>Bear_ErratumPARTHA</title>
-+  <release>1</release>
-+  <issued date="2013-01-27 16:08:05"/>
-+  <updated date="2013-01-27 16:08:05 UTC"/>
-+  <description>Bear_Erratum</description>
-+  <pkglist>
-+    <collection short="">
-+      <name>1</name>
-+      <package arch="noarch" name="bear" release="1" src="http://www.fedoraproject.org" version="4.1">
-+        <filename>bear-4.1-1.noarch.rpm</filename>
-+      </package>
-+    </collection>
-+  </pkglist>
-+</update>
-+
-+<update from="errata@redhat.com" status="stable" type="enhancement" version="1">
-+  <id>RHEA-2012:0058</id>
-+  <title>Gorilla_Erratum</title>
-+  <release>1</release>
-+  <issued date="2013-01-27 16:08:09"/>
-+  <updated date="2014-07-20 06:00:01 UTC"/>
-+  <description>Gorilla_Erratum</description>
-+  <pkglist>
-+    <collection short="">
-+      <name>1</name>
-+      <package arch="noarch" name="gorilla" release="1" src="http://www.fedoraproject.org" version="0.62">
-+        <filename>gorilla-0.62-1.noarch.rpm</filename>
-+      </package>
-+    </collection>
-+  </pkglist>
-+</update>
-+
-+<update from="errata@redhat.com" status="stable" type="enhancement" version="1">
-+  <id>RHEA-2012:0059</id>
-+  <title>Duck_Kangaroo_Erratum</title>
-+  <release>1</release>
-+  <issued date="2018-01-27 16:08:09"/>
-+  <updated date="2018-07-20 06:00:01 UTC"/>
-+  <description>Duck_Kangaro_Erratum description</description>
-+  <pkglist>
-+    <collection short="">
-+      <name>coll_name1</name>
-+      <module name="kangaroo" stream="0" version="20180730223407" context="deadbeef" arch="noarch"/>
-+      <package arch="noarch" name="kangaroo" release="1" src="http://www.fedoraproject.org"
-+               version="0.3">
-+        <filename>kangaroo-0.3-1.noarch.rpm</filename>
-+      </package>
-+    </collection>
-+    <collection short="">
-+      <name>coll_name2</name>
-+      <module name="duck" stream="0" version="20180730233102" context="deadbeef" arch="noarch"/>
-+      <package arch="noarch" name="duck" release="1" src="http://www.fedoraproject.org"
-+               version="0.7">
-+        <filename>duck-0.7-1.noarch.rpm</filename>
-+      </package>
-+    </collection>
-+  </pkglist>
-+</update>
-+
-+<update from="errata@redhat.com" status="stable" type="enhancement" version="1">
-+  <id>RHEA-2012:0060</id>
-+  <title>Duck_0.8_Erratum</title>
-+  <release>1</release>
-+  <issued date="2018-01-29 16:08:09"/>
-+  <updated date="2018-07-29 06:00:01 UTC"/>
-+  <description>Duck_0.8_Erratum description</description>
-+  <pkglist>
-+    <collection short="">
-+      <name>coll_name</name>
-+      <module name="duck" stream="0" version="201809302113907" context="deadbeef" arch="noarch"/>
-+      <package arch="noarch" name="duck" release="1" src="http://www.fedoraproject.org"
-+               version="0.8">
-+        <filename>duck-0.8-1.noarch.rpm</filename>
-+      </package>
-+    </collection>
-+  </pkglist>
-+</update>
-+</updates>
---
-libgit2 0.27.8
-
diff --git a/SOURCES/0005-Switch-off-html-timestamps-on-documentation-RhBug1731050.patch b/SOURCES/0005-Switch-off-html-timestamps-on-documentation-RhBug1731050.patch
deleted file mode 100644
index c7e5228..0000000
--- a/SOURCES/0005-Switch-off-html-timestamps-on-documentation-RhBug1731050.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From df4145ae17972b51a2f4e3ccb10c7ed0a6799209 Mon Sep 17 00:00:00 2001
-From: Marek Blaha <mblaha@redhat.com>
-Date: Mon, 29 Jul 2019 12:09:07 +0200
-Subject: [PATCH] Switch off html timestamps on documentation (RhBug:1731050)
-
-This change avoids file conflicts when installing createrepo_c-devel
-package for i686 and x86_64 architectures in parallel.
-After switching the timestamps off the documentation html files are
-identical for both builds and rpm does not consider them conflicting any
-more.
-
-https://bugzilla.redhat.com/show_bug.cgi?id=1731050
----
- doc/Doxyfile.in.in | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/doc/Doxyfile.in.in b/doc/Doxyfile.in.in
-index bd6b5a7..35a5e75 100644
---- a/doc/Doxyfile.in.in
-+++ b/doc/Doxyfile.in.in
-@@ -952,7 +952,7 @@ HTML_COLORSTYLE_GAMMA  = 80
- # page will contain the date and time when the page was generated. Setting
- # this to NO can help when comparing the output of multiple runs.
- 
--HTML_TIMESTAMP         = YES
-+HTML_TIMESTAMP         = NO
- 
- # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
- # documentation will contain sections that can be hidden and shown after the
---
-libgit2 0.28.2
-
diff --git a/SPECS/createrepo_c.spec b/SPECS/createrepo_c.spec
index ff08f69..cdc44f4 100644
--- a/SPECS/createrepo_c.spec
+++ b/SPECS/createrepo_c.spec
@@ -1,3 +1,4 @@
+%global libmodulemd_version 2.3.0
 %{!?_licensedir:%global license %%doc}
 
 # Bash completion (we need different approach for RHEL-6)
@@ -15,24 +16,33 @@
 %bcond_without drpm
 %endif
 
-%if 0%{?rhel} > 7
+%if 0%{?fedora} > 29 || 0%{?rhel} > 7
 %bcond_with python2
 %else
 %bcond_without python2
 %endif
 
+%if 0%{?rhel} || 0%{?fedora} < 29
+%bcond_with zchunk
+%else
+%bcond_without zchunk
+%endif
+
+%if 0%{?rhel} || 0%{?fedora} < 29
+%bcond_with libmodulemd
+%else
+%bcond_without libmodulemd
+%endif
+
 Summary:        Creates a common metadata repository
 Name:           createrepo_c
-Version:        0.11.0
-Release:        3%{?dist}
+Version:        0.15.1
+Release:        2%{?dist}
 License:        GPLv2+
 URL:            https://github.com/rpm-software-management/createrepo_c
 Source0:        %{url}/archive/%{version}/%{name}-%{version}.tar.gz
-Patch0:         0001-Consistently-produce-valid-URLs-by-prepending-protocol-RhBug1632121.patch
-Patch1:         0002-modifyrepo_c-Prevent-doubling-of-compression-testgzgz-RhBug1639287.patch
-Patch2:         0003-Correct-pkg-count-in-headers-if-there-were-invalid-pkgs-RhBug1596211.patch
-Patch3:         0004-Add-support-for-modular-errata-RhBug1656584.patch
-Patch4:         0005-Switch-off-html-timestamps-on-documentation-RhBug1731050.patch
+Patch1:         0001-Libmagic-to-follow-symlinks-RhBug1776399.patch
+Patch2:         0002-Add-reboot_suggested-to-UpdateRecord-RhBug1772466.patch
 
 BuildRequires:  cmake
 BuildRequires:  gcc
@@ -48,6 +58,15 @@ BuildRequires:  rpm-devel >= 4.8.0-28
 BuildRequires:  sqlite-devel
 BuildRequires:  xz-devel
 BuildRequires:  zlib-devel
+%if %{with zchunk}
+BuildRequires:  pkgconfig(zck) >= 0.9.11
+BuildRequires:  zchunk
+%endif
+%if %{with libmodulemd}
+BuildRequires:  pkgconfig(modulemd-2.0) >= %{libmodulemd_version}
+BuildRequires:  libmodulemd
+Requires:       libmodulemd%{?_isa} >= %{libmodulemd_version}
+%endif
 Requires:       %{name}-libs =  %{version}-%{release}
 %if 0%{?rhel} == 6
 Requires: rpm >= 4.8.0-28
@@ -56,10 +75,13 @@ BuildRequires:  bash-completion
 Requires: rpm >= 4.9.0
 %endif
 %if %{with drpm}
-BuildRequires:  drpm-devel >= 0.1.3
+BuildRequires:  drpm-devel >= 0.4.0
 %endif
+
+%if 0%{?fedora} || 0%{?rhel} > 7
 Obsoletes:      createrepo < 0.11.0
 Provides:       createrepo = %{version}-%{release}
+%endif
 
 %description
 C implementation of Createrepo.
@@ -88,7 +110,11 @@ Summary:        Python bindings for the createrepo_c library
 %{?python_provide:%python_provide python2-%{name}}
 BuildRequires:  python2-devel
 BuildRequires:  python2-nose
+%if 0%{?rhel} && 0%{?rhel} <= 7
+BuildRequires:  python-sphinx
+%else
 BuildRequires:  python2-sphinx
+%endif
 Requires:       %{name}-libs = %{version}-%{release}
 
 %description -n python2-%{name}
@@ -122,7 +148,7 @@ mkdir build-py3
 # Build createrepo_c with Python 2
 %if %{with python2}
 pushd build-py2
-  %cmake ../
+  %cmake .. -DPYTHON_DESIRED:FILEPATH=%{__python2} %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_libmodulemd:-DWITH_LIBMODULEMD=OFF}
   make %{?_smp_mflags} RPM_OPT_FLAGS="%{optflags}"
   %if %{without python3}
   # Build C documentation
@@ -134,7 +160,7 @@ popd
 # Build createrepo_c with Pyhon 3
 %if %{with python3}
 pushd build-py3
-  %cmake ../ -DPYTHON_DESIRED:str=3
+  %cmake .. -DPYTHON_DESIRED:FILEPATH=%{__python3} %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_libmodulemd:-DWITH_LIBMODULEMD=OFF}
   make %{?_smp_mflags} RPM_OPT_FLAGS="%{optflags}"
   # Build C documentation
   make doc-c
@@ -180,11 +206,18 @@ pushd build-py3
 popd
 %endif
 
+%if 0%{?fedora} || 0%{?rhel} > 7
 ln -sr %{buildroot}%{_bindir}/createrepo_c %{buildroot}%{_bindir}/createrepo
 ln -sr %{buildroot}%{_bindir}/mergerepo_c %{buildroot}%{_bindir}/mergerepo
 ln -sr %{buildroot}%{_bindir}/modifyrepo_c %{buildroot}%{_bindir}/modifyrepo
+%endif
 
+%if 0%{?rhel} && 0%{?rhel} <= 7
+%post libs -p /sbin/ldconfig
+%postun libs -p /sbin/ldconfig
+%else
 %ldconfig_scriptlets libs
+%endif
 
 %files
 %doc README.md
@@ -196,10 +229,13 @@ ln -sr %{buildroot}%{_bindir}/modifyrepo_c %{buildroot}%{_bindir}/modifyrepo
 %{_bindir}/createrepo_c
 %{_bindir}/mergerepo_c
 %{_bindir}/modifyrepo_c
+%{_bindir}/sqliterepo_c
+
+%if 0%{?fedora} || 0%{?rhel} > 7
 %{_bindir}/createrepo
 %{_bindir}/mergerepo
 %{_bindir}/modifyrepo
-%{_bindir}/sqliterepo_c
+%endif
 
 %files libs
 %license COPYING
@@ -218,14 +254,48 @@ ln -sr %{buildroot}%{_bindir}/modifyrepo_c %{buildroot}%{_bindir}/modifyrepo
 %if %{with python2}
 %files -n python2-%{name}
 %{python2_sitearch}/%{name}/
+%{python2_sitearch}/%{name}-%{version}-py%{python2_version}.egg-info
 %endif
 
 %if %{with python3}
 %files -n python3-%{name}
 %{python3_sitearch}/%{name}/
+%{python3_sitearch}/%{name}-%{version}-py%{python3_version}.egg-info
 %endif
 
 %changelog
+* Mon Jan 13 2020 Ales Matej <amatej@redhat.com> - 0.15.1-2
+- Add reboot_suggested to UpdateRecord (RhBug:1772466)
+- Explicitly output boolean values for updateinfo.xml (RhBug:1772466)
+- Fix modifyrepo_c with modules.yaml as a symbolic link (RhBug:1776399)
+
+* Tue Oct 22 2019 Ales Matej <amatej@redhat.com> - 0.15.1-1
+- Update to 0.15.1
+- Allow pip to see installation of python3-createrepo_c
+- Imporove documentation
+- Remove dependency on deltarpm in favour of drpm
+- Obsolete createrepo on all Fedoras again (RhBug:1702771)
+- Fix issue with createrepo_c hanging at the end (RhBug:1714666)
+- Don't include packages with forbidden control chars in repodata
+- Depend on the appropriate minimum version of libmodulemd
+- Add --pkgorigins mode for Koji
+- Prevent exiting with 0 if errors occur while finalizing repodata.
+- Add support for reading and merging module metadata
+- Update --keep-all-metadata to keep all additional metadata, not just updateinfo and groupfile (RhBug:1639287)
+- mergerepo_c: Add support for --koji simple mode
+- Fix generating corrupted sqlite files (RhBug: 1696808)
+- Do not obsolete createrepo on Fedora < 31
+- mergerepo_c: check if nevra is NULL and warn user about src.rpm naming
+- Include file timestamp in repomd.xml to allow reproducing exact metadata as produced in the past
+- Enhance support of zchunk
+- Support of zchunk
+- [spec] Fix ldconfig for rhel <= 7
+- Fix "CR_DELTA_RPM_SUPPORT" redefined warnings
+- Set to build against Python 3 by default
+- Update README
+- Add mergerepo_c --repo-prefix-search and --repo-prefix-replace.
+- Fix missing packages in mergerepo_c in case multiple VR exists for single pkg in repo.
+
 * Thu Aug 08 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.11.0-3
 - Backport patch to switch off timestamps on documentation in order to remove
   file conflicts (RhBug:1738788)