diff --git a/SOURCES/0001-Add-flag-to-use-strip-g-instead-of-full-strip-on-DSO.patch b/SOURCES/0001-Add-flag-to-use-strip-g-instead-of-full-strip-on-DSO.patch
new file mode 100644
index 0000000..43dfe47
--- /dev/null
+++ b/SOURCES/0001-Add-flag-to-use-strip-g-instead-of-full-strip-on-DSO.patch
@@ -0,0 +1,93 @@
+From 1da9e839bb573b9187403983f5a69853ab364306 Mon Sep 17 00:00:00 2001
+From: Pavlina Moravcova Varekova <pmoravco@redhat.com>
+Date: Sun, 17 Mar 2019 06:47:26 +0100
+Subject: [PATCH] Add flag to use strip -g instead of full strip on DSOs
+ (RhBug:1663264)
+
+The find-debuginfo.sh flag -g had exactly this meaning. But from
+version rpm-4.13.0-alpha flag -g changes its behavior. It affects
+both libraries and executables.
+
+For some packages the original behavior was preferred. That is why
+the new find-debuginfo.sh flag --g-libs is created.
+
+Options -g and --g-libs are mutually exclusive.
+
+
+Adjusted for rpm-4.14.2 in RHEL
+
+--- rpm-4.14.2/scripts/find-debuginfo.sh.orig	2019-04-24 15:14:29.351010878 +0200
++++ rpm-4.14.2/scripts/find-debuginfo.sh	2019-04-24 15:19:42.296240705 +0200
+@@ -4,6 +4,7 @@
+ #
+ # Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] [-n]
+ #			   [--keep-section SECTION] [--remove-section SECTION]
++#			   [--g-libs]
+ #	 		   [-j N] [--jobs N]
+ #	 		   [-o debugfiles.list]
+ #	 		   [-S debugsourcefiles.list]
+@@ -16,6 +17,8 @@
+ #			   [builddir]
+ #
+ # The -g flag says to use strip -g instead of full strip on DSOs or EXEs.
++# The --g-libs flag says to use strip -g instead of full strip ONLY on DSOs.
++# Options -g and --g-libs are mutually exclusive.
+ # The -r flag says to use eu-strip --reloc-debug-sections.
+ # Use --keep-section SECTION or --remove-section SECTION to explicitly
+ # keep a (non-allocated) section in the main executable or explicitly
+@@ -68,6 +71,9 @@
+ # With -g arg, pass it to strip on libraries or executables.
+ strip_g=false
+ 
++# With --g-libs arg, pass it to strip on libraries.
++strip_glibs=false
++
+ # with -r arg, pass --reloc-debug-sections to eu-strip.
+ strip_r=false
+ 
+@@ -135,6 +141,9 @@
+     unique_debug_src_base=$2
+     shift
+     ;;
++  --g-libs)
++    strip_glibs=true
++    ;;
+   -g)
+     strip_g=true
+     ;;
+@@ -204,6 +213,11 @@
+   exit 2
+ fi
+ 
++if ("$strip_g" = "true") && ("$strip_glibs" = "true"); then
++  echo >&2 "*** ERROR: -g  and --g-libs cannot be used together"
++  exit 2
++fi
++
+ i=0
+ while ((i < nout)); do
+   outs[$i]="$BUILDDIR/${outs[$i]}"
+@@ -237,6 +251,9 @@
+   application/x-executable*) g=-g ;;
+   application/x-pie-executable*) g=-g ;;
+   esac
++  $strip_glibs && case "$(file -bi "$2")" in
++    application/x-sharedlib*) g=-g ;;
++  esac
+   eu-strip --remove-comment $r $g ${keep_remove_args} -f "$1" "$2" || exit
+   chmod 444 "$1" || exit
+ }
+@@ -409,8 +426,12 @@
+   # libraries. Other executable ELF files (like kernel modules) don't need it.
+   if [ "$include_minidebug" = "true" -a "$strip_g" = "false" ]; then
+     skip_mini=true
++    if [ "$strip_glibs" = "false" ]; then
++      case "$(file -bi "$f")" in
++        application/x-sharedlib*) skip_mini=false ;;
++      esac
++    fi
+     case "$(file -bi "$f")" in
+-      application/x-sharedlib*) skip_mini=false ;;
+       application/x-executable*) skip_mini=false ;;
+     esac
+     $skip_mini || add_minidebug "${debugfn}" "$f"
diff --git a/SOURCES/0001-Correct-rpm-ql-exit-value-when-optional-p-is-omitted.patch b/SOURCES/0001-Correct-rpm-ql-exit-value-when-optional-p-is-omitted.patch
new file mode 100644
index 0000000..9f123ba
--- /dev/null
+++ b/SOURCES/0001-Correct-rpm-ql-exit-value-when-optional-p-is-omitted.patch
@@ -0,0 +1,38 @@
+From ce11f04ed529cd84de8981b82c1185c0a30dfdcf Mon Sep 17 00:00:00 2001
+From: Pavlina Moravcova Varekova <pmoravco@redhat.com>
+Date: Thu, 14 Mar 2019 13:23:13 +0100
+Subject: [PATCH] Correct rpm -ql exit value when optional -p is omitted
+ (RhBug:1680610)
+
+---
+ lib/query.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/lib/query.c b/lib/query.c
+index e47189ed0..e5408e211 100644
+--- a/lib/query.c
++++ b/lib/query.c
+@@ -568,16 +568,18 @@ int rpmcliArgIter(rpmts ts, QVA_t qva, ARGV_const_t argv)
+ 	break;
+     default:
+ 	for (ARGV_const_t arg = argv; arg && *arg; arg++) {
++	    int ecLocal;
+ 	    rpmdbMatchIterator mi = initQueryIterator(qva, ts, *arg);
+-	    ec += rpmcliShowMatches(qva, ts, mi);
++	    ecLocal = rpmcliShowMatches(qva, ts, mi);
+ 	    if (mi == NULL && qva->qva_source == RPMQV_PACKAGE) {
+ 		size_t l = strlen(*arg);
+ 		if (l > 4 && !strcmp(*arg + l - 4, ".rpm")) {
+ 		    rpmgi gi = rpmgiNew(ts, giFlags, argv);
+-		    ec += rpmgiShowMatches(qva, ts, gi);
++		    ecLocal = rpmgiShowMatches(qva, ts, gi);
+ 		    rpmgiFree(gi);
+ 		}
+ 	    }
++	    ec += ecLocal;
+ 	    rpmdbFreeIterator(mi);
+ 	}
+ 	break;
+-- 
+2.17.2
+
diff --git a/SOURCES/0001-Fix-FA_TOUCH-on-files-with-suid-sgid-bits-and-or-cap.patch b/SOURCES/0001-Fix-FA_TOUCH-on-files-with-suid-sgid-bits-and-or-cap.patch
new file mode 100644
index 0000000..df98eaa
--- /dev/null
+++ b/SOURCES/0001-Fix-FA_TOUCH-on-files-with-suid-sgid-bits-and-or-cap.patch
@@ -0,0 +1,152 @@
+From 13f70e3710b2df49a923cc6450ff4a8f86e65666 Mon Sep 17 00:00:00 2001
+Message-Id: <13f70e3710b2df49a923cc6450ff4a8f86e65666.1555050140.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 20 Mar 2019 12:38:00 +0200
+Subject: [PATCH] Fix FA_TOUCH on files with suid/sgid bits and/or capabilities
+
+FA_TOUCH used to set suffix to "" instead of NULL which causes fsmCommit()
+to rename the file onto itself, which is a bit dumb but mostly harmless
+with regular permission. On suid/sgid/capabilities we strip any extra
+privileges on rename to make sure hardlinks are neutered, and because
+rename occurs after other permissions etc setting, on FA_TOUCH those
+extra privileges are stripped and much brokenness will follow.
+
+A more minimal fix would be a strategically placed strcmp(), but NULL
+is what the rest of the fsm expects for no suffix and differentiating
+between empty and NULL suffix is too subtle for its own good as
+witnessed here. So now, NULL suffix is no suffix again and the rest
+of the code will do the right thing except where related to creation,
+and creation is what FA_TOUCH wont do so lets just explicitly skip it
+and restore the original code otherwise. The goto is ugly but reindenting
+gets even uglier, shrug. Add a test-case to go with it.
+
+This has been broken since its introduction in commit
+79ca74e15e15c1d91a9a31a9ee90abc91736f390 so all current 4.14.x versions
+are affected.
+---
+ lib/fsm.c                         | 17 ++++++++++----
+ tests/data/SPECS/replacetest.spec |  2 +-
+ tests/rpmverify.at                | 38 ++++++++++++++++++++++++++++++-
+ 3 files changed, 50 insertions(+), 7 deletions(-)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index 8eb2c185c..432bcbd90 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -898,12 +898,12 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ 
+ 	action = rpmfsGetAction(fs, rpmfiFX(fi));
+ 	skip = XFA_SKIPPING(action);
+-	suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
+ 	if (action != FA_TOUCH) {
+-	    fpath = fsmFsPath(fi, suffix);
++	    suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
+ 	} else {
+-	    fpath = fsmFsPath(fi, "");
++	    suffix = NULL;
+ 	}
++	fpath = fsmFsPath(fi, suffix);
+ 
+ 	/* Remap file perms, owner, and group. */
+ 	rc = rpmfiStat(fi, 1, &sb);
+@@ -926,6 +926,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+         if (!skip) {
+ 	    int setmeta = 1;
+ 
++	    /* When touching we don't need any of this... */
++	    if (action == FA_TOUCH)
++		goto touch;
++
+ 	    /* Directories replacing something need early backup */
+ 	    if (!suffix) {
+ 		rc = fsmBackup(fi, action);
+@@ -934,7 +938,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ 	    if (!suffix) {
+ 		rc = fsmVerify(fpath, fi);
+ 	    } else {
+-		rc = (action == FA_TOUCH) ? 0 : RPMERR_ENOENT;
++		rc = RPMERR_ENOENT;
+ 	    }
+ 
+             if (S_ISREG(sb.st_mode)) {
+@@ -970,11 +974,14 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+                 if (!IS_DEV_LOG(fpath))
+                     rc = RPMERR_UNKNOWN_FILETYPE;
+             }
++
++touch:
+ 	    /* Set permissions, timestamps etc for non-hardlink entries */
+ 	    if (!rc && setmeta) {
+ 		rc = fsmSetmeta(fpath, fi, plugins, action, &sb, nofcaps);
+ 	    }
+         } else if (firsthardlink >= 0 && rpmfiArchiveHasContent(fi)) {
++	    /* On FA_TOUCH no hardlinks are created thus this is skipped. */
+ 	    /* we skip the hard linked file containing the content */
+ 	    /* write the content to the first used instead */
+ 	    char *fn = rpmfilesFN(files, firsthardlink);
+@@ -987,7 +994,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+         if (rc) {
+             if (!skip) {
+                 /* XXX only erase if temp fn w suffix is in use */
+-                if (suffix && (action != FA_TOUCH)) {
++                if (suffix) {
+ 		    (void) fsmRemove(fpath, sb.st_mode);
+                 }
+                 errno = saveerrno;
+diff --git a/tests/data/SPECS/replacetest.spec b/tests/data/SPECS/replacetest.spec
+index 54974567b..d5a1729d3 100644
+--- a/tests/data/SPECS/replacetest.spec
++++ b/tests/data/SPECS/replacetest.spec
+@@ -46,4 +46,4 @@ rm -rf $RPM_BUILD_ROOT
+ 
+ %files
+ %defattr(-,%{user},%{grp},-)
+-/opt/*
++%{?fileattr} /opt/*
+diff --git a/tests/rpmverify.at b/tests/rpmverify.at
+index 52ee2abfb..f7dd57531 100644
+--- a/tests/rpmverify.at
++++ b/tests/rpmverify.at
+@@ -575,3 +575,39 @@
+ ],
+ [])
+ AT_CLEANUP
++
++AT_SETUP([Upgraded verification with min_writes 5 (suid files)])
++AT_KEYWORDS([upgrade verify min_writes])
++AT_CHECK([
++RPMDB_CLEAR
++RPMDB_INIT
++tf="${RPMTEST}"/opt/foo
++rm -rf "${tf}" "${tf}".rpm*
++rm -rf "${TOPDIR}"
++
++for v in "1.0" "2.0"; do
++    runroot rpmbuild --quiet -bb \
++        --define "ver $v" \
++	--define "filetype file" \
++	--define "filedata foo" \
++	--define "fileattr %attr(2755,-,-)" \
++          /data/SPECS/replacetest.spec
++done
++
++runroot rpm -U /build/RPMS/noarch/replacetest-1.0-1.noarch.rpm
++runroot rpm -Va --nouser --nogroup replacetest
++runroot rpm -U \
++	--define "_minimize_writes 1" \
++	 /build/RPMS/noarch/replacetest-2.0-1.noarch.rpm
++runroot rpm -Va --nouser --nogroup replacetest
++chmod 777 "${tf}"
++runroot rpm -U \
++	--oldpackage \
++	--define "_minimize_writes 1" \
++	 /build/RPMS/noarch/replacetest-1.0-1.noarch.rpm
++runroot rpm -Va --nouser --nogroup replacetest
++],
++[0],
++[],
++[])
++AT_CLEANUP
+-- 
+2.20.1
+
diff --git a/SOURCES/0001-Fix-a-blindingly-obvious-memleak-in-package-verify-s.patch b/SOURCES/0001-Fix-a-blindingly-obvious-memleak-in-package-verify-s.patch
new file mode 100644
index 0000000..0dc7f30
--- /dev/null
+++ b/SOURCES/0001-Fix-a-blindingly-obvious-memleak-in-package-verify-s.patch
@@ -0,0 +1,26 @@
+From 788935c9ea9d2f469f24be10a9fa998594046731 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 7 Sep 2018 11:52:33 +0300
+Subject: [PATCH] Fix a blindingly obvious memleak in package verify step
+
+Erm. Introduced in commit 765e2c72ae8be369ada41d4747b8999519a0e327,
+but how on earth did this go unnoticed... *blush*
+---
+ lib/transaction.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/transaction.c b/lib/transaction.c
+index 205c3f388..3969ad3fc 100644
+--- a/lib/transaction.c
++++ b/lib/transaction.c
+@@ -1261,6 +1261,7 @@ static int verifyPackageFiles(rpmts ts, rpm_loff_t total)
+ 	    rpmteAddProblem(p, RPMPROB_VERIFY, NULL, vd.msg, 0);
+ 
+ 	vd.msg = _free(vd.msg);
++	rpmvsFree(vs);
+     }
+     rpmtsNotify(ts, NULL, RPMCALLBACK_VERIFY_STOP, total, total);
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-Fix-ancient-python-GIL-locking-bug-on-callback-RhBug.patch b/SOURCES/0001-Fix-ancient-python-GIL-locking-bug-on-callback-RhBug.patch
new file mode 100644
index 0000000..494634d
--- /dev/null
+++ b/SOURCES/0001-Fix-ancient-python-GIL-locking-bug-on-callback-RhBug.patch
@@ -0,0 +1,46 @@
+From 531dc8495cd3aabd3f659ecab604106fdbacbe98 Mon Sep 17 00:00:00 2001
+Message-Id: <531dc8495cd3aabd3f659ecab604106fdbacbe98.1554974459.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 3 Oct 2018 11:51:38 +0300
+Subject: [PATCH] Fix ancient python GIL locking bug on callback
+ (RhBug:1632488)
+
+Introduced in commit c7881d801745b4c156a8aa2afc17b95f97481e34 back in 2002,
+synthesizing a python object for the callback occurs before retaking
+the GIL lock, which is not allowed. Somehow this has managed to stay
+latent all these years, and even now requires fairly specific conditions:
+when the callback gets called without an associated key, such as erasures
+or file trigger script start/stop events (in the case of RhBug:1632488),
+when Python 3 is running in PYTHONMALLOC=debug mode,
+it crashes with "Python memory allocator called without holding the GIL".
+
+Simply retake the lock before any Python operations take place to fix.
+---
+ python/rpmts-py.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/python/rpmts-py.c b/python/rpmts-py.c
+index e4c5e1250..1ddfc9a1e 100644
+--- a/python/rpmts-py.c
++++ b/python/rpmts-py.c
+@@ -495,6 +495,8 @@ rpmtsCallback(const void * hd, const rpmCallbackType what,
+ 
+     if (cbInfo->cb == Py_None) return NULL;
+ 
++    PyEval_RestoreThread(cbInfo->_save);
++
+     /* Synthesize a python object for callback (if necessary). */
+     if (pkgObj == NULL) {
+ 	if (h) {
+@@ -506,8 +508,6 @@ rpmtsCallback(const void * hd, const rpmCallbackType what,
+     } else
+ 	Py_INCREF(pkgObj);
+ 
+-    PyEval_RestoreThread(cbInfo->_save);
+-
+     args = Py_BuildValue("(iLLOO)", what, amount, total, pkgObj, cbInfo->data);
+     result = PyEval_CallObject(cbInfo->cb, args);
+     Py_DECREF(args);
+-- 
+2.20.1
+
diff --git a/SOURCES/0001-Fix-memleak-during-transaction-verify-step-in-the-NO.patch b/SOURCES/0001-Fix-memleak-during-transaction-verify-step-in-the-NO.patch
new file mode 100644
index 0000000..d1bb187
--- /dev/null
+++ b/SOURCES/0001-Fix-memleak-during-transaction-verify-step-in-the-NO.patch
@@ -0,0 +1,30 @@
+From 5188a7b35eb3672c9b15e96433e033ee36f8e6a8 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 6 Aug 2019 13:06:16 +0300
+Subject: [PATCH] Fix memleak during transaction verify step in the NOKEY case.
+
+Found during RhBug:1714657 QA testing.
+In addition, add a comment to clarify the fallthrough as intentional.
+---
+ lib/transaction.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/lib/transaction.c b/lib/transaction.c
+index 6e4d4be65..e51cff25a 100644
+--- a/lib/transaction.c
++++ b/lib/transaction.c
+@@ -1226,8 +1226,10 @@ static int vfyCb(struct rpmsinfo_s *sinfo, void *cbdata)
+ 	 */
+ 	if (!(vd->vfylevel & RPMSIG_SIGNATURE_TYPE))
+ 	    sinfo->rc = RPMRC_OK;
++	/* fallthrough */
+     default:
+-	vd->msg = rpmsinfoMsg(sinfo);
++	if (sinfo->rc)
++	    vd->msg = rpmsinfoMsg(sinfo);
+ 	break;
+     }
+     return (sinfo->rc == 0);
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-Fix-rpmfiles-memory-leak-on-postuntrans-file-trigger.patch b/SOURCES/0001-Fix-rpmfiles-memory-leak-on-postuntrans-file-trigger.patch
new file mode 100644
index 0000000..ff18186
--- /dev/null
+++ b/SOURCES/0001-Fix-rpmfiles-memory-leak-on-postuntrans-file-trigger.patch
@@ -0,0 +1,25 @@
+From 475af64f64cbc210c87588d425fa9a14cd9760b6 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 29 May 2019 11:38:53 +0300
+Subject: [PATCH] Fix rpmfiles memory leak on %postuntrans file trigger
+ preparation
+
+---
+ lib/rpmtriggers.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/rpmtriggers.c b/lib/rpmtriggers.c
+index cb2441c5a..b7c76e7fc 100644
+--- a/lib/rpmtriggers.c
++++ b/lib/rpmtriggers.c
+@@ -154,6 +154,7 @@ void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te)
+ 	}
+     }
+     rpmdbFreeIterator(mi);
++    rpmfilesFree(files);
+ }
+ 
+ int runPostUnTransFileTrigs(rpmts ts)
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-Fix-segfault-on-fingerprinting-symlink-round-RhBug-1.patch b/SOURCES/0001-Fix-segfault-on-fingerprinting-symlink-round-RhBug-1.patch
new file mode 100644
index 0000000..a3faebb
--- /dev/null
+++ b/SOURCES/0001-Fix-segfault-on-fingerprinting-symlink-round-RhBug-1.patch
@@ -0,0 +1,60 @@
+From 050b392f8c11d111379e0d2bac52762beb97b3ae Mon Sep 17 00:00:00 2001
+Message-Id: <050b392f8c11d111379e0d2bac52762beb97b3ae.1559645935.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 2 Apr 2019 12:57:11 +0300
+Subject: [PATCH] Fix segfault on fingerprinting symlink round (RhBug:1660232)
+
+Both yum and dnf perform a test-transaction before the real thing,
+and both neglet to check for an error code from the test-transaction
+when there are no problem objects to return. Which can happen in
+some special cases, such a using different vsflags between initial
+package read and transaction (which is what both yum and dnf do),
+which can cause the in-transaction package open fail on corrupt packages.
+And when this failed transaction is fed back to rpmtsRun(), it
+segfaults in fingerprinting as the second loop of symlink checking
+doesn't check for NULL's element files like the first loop does.
+
+Add the missing NULL check and remove bogus "can't happen" comment to fix.
+
+FWIW, the scenario with different vsflags and corrupted packages doesn't
+happen by default in rpm >= 4.14.2, the corrupt package gets caught
+in the verify stage which does create problem objects and thus both
+yum and dnf abort as they should.
+---
+ lib/fprint.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/lib/fprint.c b/lib/fprint.c
+index b810e4d2b..ab1891961 100644
+--- a/lib/fprint.c
++++ b/lib/fprint.c
+@@ -488,7 +488,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
+ 	(void) rpmsqPoll();
+ 
+ 	if ((fi = rpmteFiles(p)) == NULL)
+-	    continue;	/* XXX can't happen */
++	    continue;
+ 
+ 	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
+ 	rpmfilesFpLookup(fi, fpc);
+@@ -522,6 +522,9 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
+     while ((p = rpmtsiNext(pi, 0)) != NULL) {
+ 	(void) rpmsqPoll();
+ 
++	if ((fi = rpmteFiles(p)) == NULL)
++	    continue;
++
+ 	fs = rpmteGetFileStates(p);
+ 	fc = rpmfsFC(fs);
+ 	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
+@@ -531,6 +534,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
+ 	    fpLookupSubdir(symlinks, fpc, p, i);
+ 	}
+ 	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
++	rpmfilesFree(fi);
+     }
+     rpmtsiFree(pi);
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-Fix-testing-for-wrong-variable-in-selinux-plugin-deb.patch b/SOURCES/0001-Fix-testing-for-wrong-variable-in-selinux-plugin-deb.patch
new file mode 100644
index 0000000..7d99a49
--- /dev/null
+++ b/SOURCES/0001-Fix-testing-for-wrong-variable-in-selinux-plugin-deb.patch
@@ -0,0 +1,28 @@
+From 66e0c929b203d684a4f58135f42435fcc29cdd51 Mon Sep 17 00:00:00 2001
+Message-Id: <66e0c929b203d684a4f58135f42435fcc29cdd51.1554982695.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 10 Oct 2018 12:00:19 +0300
+Subject: [PATCH] Fix testing for wrong variable in selinux plugin debug log
+
+The strerror() case couldn't be reached as we were testing for the
+wrong rc, spotted by covscan.
+---
+ plugins/selinux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/plugins/selinux.c b/plugins/selinux.c
+index 3c9d9e4ab..accd47416 100644
+--- a/plugins/selinux.c
++++ b/plugins/selinux.c
+@@ -169,7 +169,7 @@ static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
+ 
+ 	    if (rpmIsDebug()) {
+ 		rpmlog(RPMLOG_DEBUG, "lsetfilecon: (%s, %s) %s\n",
+-		       path, scon, (rc < 0 ? strerror(errno) : ""));
++		       path, scon, (conrc < 0 ? strerror(errno) : ""));
+ 	    }
+ 
+ 	    if (conrc == 0 || (conrc < 0 && errno == EOPNOTSUPP))
+-- 
+2.20.1
+
diff --git a/SOURCES/0001-Fully-shutdown-DBUS-on-systemd_inhibit-cleanup-RhBug.patch b/SOURCES/0001-Fully-shutdown-DBUS-on-systemd_inhibit-cleanup-RhBug.patch
new file mode 100644
index 0000000..54519f0
--- /dev/null
+++ b/SOURCES/0001-Fully-shutdown-DBUS-on-systemd_inhibit-cleanup-RhBug.patch
@@ -0,0 +1,40 @@
+From d5f201345f6d27b6280750e5c6502f4418614fbc Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 29 May 2019 12:09:20 +0300
+Subject: [PATCH] Fully shutdown DBUS on systemd_inhibit cleanup
+ (RhBug:1714657)
+
+dbus_shutdown() frees internal DBUS memory allocations that will otherwise
+show up as memory leaks. This is of little consequence in practise
+but shuts up valgrind...
+---
+ plugins/systemd_inhibit.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/plugins/systemd_inhibit.c b/plugins/systemd_inhibit.c
+index e2cbcffbb..0628188ba 100644
+--- a/plugins/systemd_inhibit.c
++++ b/plugins/systemd_inhibit.c
+@@ -80,6 +80,11 @@ static rpmRC systemd_inhibit_init(rpmPlugin plugin, rpmts ts)
+     return RPMRC_NOTFOUND;
+ }
+ 
++static void systemd_inhibit_cleanup(rpmPlugin plugin)
++{
++    dbus_shutdown();
++}
++
+ static rpmRC systemd_inhibit_tsm_pre(rpmPlugin plugin, rpmts ts)
+ {
+     if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
+@@ -106,6 +111,7 @@ static rpmRC systemd_inhibit_tsm_post(rpmPlugin plugin, rpmts ts, int res)
+ 
+ struct rpmPluginHooks_s systemd_inhibit_hooks = {
+     .init = systemd_inhibit_init,
++    .cleanup = systemd_inhibit_cleanup,
+     .tsm_pre = systemd_inhibit_tsm_pre,
+     .tsm_post = systemd_inhibit_tsm_post,
+ };
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-In-Python-3-return-all-our-string-data-as-surrogate-.patch b/SOURCES/0001-In-Python-3-return-all-our-string-data-as-surrogate-.patch
new file mode 100644
index 0000000..35f12c2
--- /dev/null
+++ b/SOURCES/0001-In-Python-3-return-all-our-string-data-as-surrogate-.patch
@@ -0,0 +1,656 @@
+From 84920f898315d09a57a3f1067433eaeb7de5e830 Mon Sep 17 00:00:00 2001
+Message-Id: <84920f898315d09a57a3f1067433eaeb7de5e830.1554884444.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 22 Feb 2019 19:44:16 +0200
+Subject: [PATCH] In Python 3, return all our string data as surrogate-escaped
+ utf-8 strings
+
+In the almost ten years of rpm sort of supporting Python 3 bindings, quite
+obviously nobody has actually tried to use them. There's a major mismatch
+between what the header API outputs (bytes) and what all the other APIs
+accept (strings), resulting in hysterical TypeErrors all over the place,
+including but not limited to labelCompare() (RhBug:1631292). Also a huge
+number of other places have been returning strings and silently assuming
+utf-8 through use of Py_BuildValue("s", ...), which will just irrevocably
+fail when non-utf8 data is encountered.
+
+The politically Python 3-correct solution would be declaring all our data
+as bytes with unspecified encoding - that's exactly what it historically is.
+However doing so would by definition break every single rpm script people
+have developed on Python 2. And when 99% of the rpm content in the world
+actually is utf-8 encoded even if it doesn't say so (and in recent times
+packages even advertise themselves as utf-8 encoded), the bytes-only route
+seems a wee bit too draconian, even to this grumpy old fella.
+
+Instead, route all our string returns through a single helper macro
+which on Python 2 just does what we always did, but in Python 3 converts
+the data to surrogate-escaped utf-8 strings. This makes stuff "just work"
+out of the box pretty much everywhere even with Python 3 (including
+our own test-suite!), while still allowing to handle the non-utf8 case.
+Handling the non-utf8 case is a bit more uglier but still possible,
+which is exactly how you want corner-cases to be. There might be some
+uses for retrieving raw byte data from the header, but worrying about
+such an API is a case for some other rainy day, for now we mostly only
+care that stuff works again.
+
+Also add test-cases for mixed data source labelCompare() and
+non-utf8 insert to + retrieve from header.
+---
+ python/header-py.c     |  2 +-
+ python/rpmds-py.c      |  8 ++++----
+ python/rpmfd-py.c      |  6 +++---
+ python/rpmfi-py.c      | 24 ++++++++++++------------
+ python/rpmfiles-py.c   | 26 +++++++++++++-------------
+ python/rpmkeyring-py.c |  2 +-
+ python/rpmmacro-py.c   |  2 +-
+ python/rpmmodule.c     |  2 +-
+ python/rpmps-py.c      |  8 ++++----
+ python/rpmstrpool-py.c |  2 +-
+ python/rpmsystem-py.h  |  7 +++++++
+ python/rpmtd-py.c      |  2 +-
+ python/rpmte-py.c      | 16 ++++++++--------
+ python/rpmts-py.c      | 11 ++++++-----
+ python/spec-py.c       |  8 ++++----
+ tests/local.at         |  1 +
+ tests/rpmpython.at     | 34 ++++++++++++++++++++++++++++++++++
+ 17 files changed, 102 insertions(+), 59 deletions(-)
+
+diff --git a/python/header-py.c b/python/header-py.c
+index c9d54e869..93c241cb7 100644
+--- a/python/header-py.c
++++ b/python/header-py.c
+@@ -231,7 +231,7 @@ static PyObject * hdrFormat(hdrObject * s, PyObject * args, PyObject * kwds)
+ 	return NULL;
+     }
+ 
+-    result = Py_BuildValue("s", r);
++    result = utf8FromString(r);
+     free(r);
+ 
+     return result;
+diff --git a/python/rpmds-py.c b/python/rpmds-py.c
+index 39b26628e..ecc9af9d5 100644
+--- a/python/rpmds-py.c
++++ b/python/rpmds-py.c
+@@ -31,19 +31,19 @@ rpmds_Ix(rpmdsObject * s)
+ static PyObject *
+ rpmds_DNEVR(rpmdsObject * s)
+ {
+-    return Py_BuildValue("s", rpmdsDNEVR(s->ds));
++    return utf8FromString(rpmdsDNEVR(s->ds));
+ }
+ 
+ static PyObject *
+ rpmds_N(rpmdsObject * s)
+ {
+-    return Py_BuildValue("s", rpmdsN(s->ds));
++    return utf8FromString(rpmdsN(s->ds));
+ }
+ 
+ static PyObject *
+ rpmds_EVR(rpmdsObject * s)
+ {
+-    return Py_BuildValue("s", rpmdsEVR(s->ds));
++    return utf8FromString(rpmdsEVR(s->ds));
+ }
+ 
+ static PyObject *
+@@ -261,7 +261,7 @@ rpmds_subscript(rpmdsObject * s, PyObject * key)
+ 
+     ix = (int) PyInt_AsLong(key);
+     rpmdsSetIx(s->ds, ix);
+-    return Py_BuildValue("s", rpmdsDNEVR(s->ds));
++    return utf8FromString(rpmdsDNEVR(s->ds));
+ }
+ 
+ static PyMappingMethods rpmds_as_mapping = {
+diff --git a/python/rpmfd-py.c b/python/rpmfd-py.c
+index 85fb0cd24..4b05cce5f 100644
+--- a/python/rpmfd-py.c
++++ b/python/rpmfd-py.c
+@@ -327,17 +327,17 @@ static PyObject *rpmfd_get_closed(rpmfdObject *s)
+ static PyObject *rpmfd_get_name(rpmfdObject *s)
+ {
+     /* XXX: rpm returns non-paths with [mumble], python files use <mumble> */
+-    return Py_BuildValue("s", Fdescr(s->fd));
++    return utf8FromString(Fdescr(s->fd));
+ }
+ 
+ static PyObject *rpmfd_get_mode(rpmfdObject *s)
+ {
+-    return Py_BuildValue("s", s->mode);
++    return utf8FromString(s->mode);
+ }
+ 
+ static PyObject *rpmfd_get_flags(rpmfdObject *s)
+ {
+-    return Py_BuildValue("s", s->flags);
++    return utf8FromString(s->flags);
+ }
+ 
+ static PyGetSetDef rpmfd_getseters[] = {
+diff --git a/python/rpmfi-py.c b/python/rpmfi-py.c
+index 8d2f926d0..db405c231 100644
+--- a/python/rpmfi-py.c
++++ b/python/rpmfi-py.c
+@@ -41,19 +41,19 @@ rpmfi_DX(rpmfiObject * s, PyObject * unused)
+ static PyObject *
+ rpmfi_BN(rpmfiObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmfiBN(s->fi));
++    return utf8FromString(rpmfiBN(s->fi));
+ }
+ 
+ static PyObject *
+ rpmfi_DN(rpmfiObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmfiDN(s->fi));
++    return utf8FromString(rpmfiDN(s->fi));
+ }
+ 
+ static PyObject *
+ rpmfi_FN(rpmfiObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmfiFN(s->fi));
++    return utf8FromString(rpmfiFN(s->fi));
+ }
+ 
+ static PyObject *
+@@ -98,7 +98,7 @@ rpmfi_Digest(rpmfiObject * s, PyObject * unused)
+ {
+     char *digest = rpmfiFDigestHex(s->fi, NULL);
+     if (digest) {
+-	PyObject *dig = Py_BuildValue("s", digest);
++	PyObject *dig = utf8FromString(digest);
+ 	free(digest);
+ 	return dig;
+     } else {
+@@ -109,7 +109,7 @@ rpmfi_Digest(rpmfiObject * s, PyObject * unused)
+ static PyObject *
+ rpmfi_FLink(rpmfiObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmfiFLink(s->fi));
++    return utf8FromString(rpmfiFLink(s->fi));
+ }
+ 
+ static PyObject *
+@@ -133,13 +133,13 @@ rpmfi_FMtime(rpmfiObject * s, PyObject * unused)
+ static PyObject *
+ rpmfi_FUser(rpmfiObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmfiFUser(s->fi));
++    return utf8FromString(rpmfiFUser(s->fi));
+ }
+ 
+ static PyObject *
+ rpmfi_FGroup(rpmfiObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmfiFGroup(s->fi));
++    return utf8FromString(rpmfiFGroup(s->fi));
+ }
+ 
+ static PyObject *
+@@ -155,7 +155,7 @@ rpmfi_FClass(rpmfiObject * s, PyObject * unused)
+ 
+     if ((FClass = rpmfiFClass(s->fi)) == NULL)
+ 	FClass = "";
+-    return Py_BuildValue("s", FClass);
++    return utf8FromString(FClass);
+ }
+ 
+ static PyObject *
+@@ -208,7 +208,7 @@ rpmfi_iternext(rpmfiObject * s)
+ 	    Py_INCREF(Py_None);
+ 	    PyTuple_SET_ITEM(result, 0, Py_None);
+ 	} else
+-	    PyTuple_SET_ITEM(result,  0, Py_BuildValue("s", FN));
++	    PyTuple_SET_ITEM(result,  0, utf8FromString(FN));
+ 	PyTuple_SET_ITEM(result,  1, PyLong_FromLongLong(FSize));
+ 	PyTuple_SET_ITEM(result,  2, PyInt_FromLong(FMode));
+ 	PyTuple_SET_ITEM(result,  3, PyInt_FromLong(FMtime));
+@@ -222,12 +222,12 @@ rpmfi_iternext(rpmfiObject * s)
+ 	    Py_INCREF(Py_None);
+ 	    PyTuple_SET_ITEM(result, 10, Py_None);
+ 	} else
+-	    PyTuple_SET_ITEM(result, 10, Py_BuildValue("s", FUser));
++	    PyTuple_SET_ITEM(result, 10, utf8FromString(FUser));
+ 	if (FGroup == NULL) {
+ 	    Py_INCREF(Py_None);
+ 	    PyTuple_SET_ITEM(result, 11, Py_None);
+ 	} else
+-	    PyTuple_SET_ITEM(result, 11, Py_BuildValue("s", FGroup));
++	    PyTuple_SET_ITEM(result, 11, utf8FromString(FGroup));
+ 	PyTuple_SET_ITEM(result, 12, rpmfi_Digest(s, NULL));
+ 
+     } else
+@@ -313,7 +313,7 @@ rpmfi_subscript(rpmfiObject * s, PyObject * key)
+ 
+     ix = (int) PyInt_AsLong(key);
+     rpmfiSetFX(s->fi, ix);
+-    return Py_BuildValue("s", rpmfiFN(s->fi));
++    return utf8FromString(rpmfiFN(s->fi));
+ }
+ 
+ static PyMappingMethods rpmfi_as_mapping = {
+diff --git a/python/rpmfiles-py.c b/python/rpmfiles-py.c
+index bc07dbeaf..557246cae 100644
+--- a/python/rpmfiles-py.c
++++ b/python/rpmfiles-py.c
+@@ -41,37 +41,37 @@ static PyObject *rpmfile_dx(rpmfileObject *s)
+ static PyObject *rpmfile_name(rpmfileObject *s)
+ {
+     char * fn = rpmfilesFN(s->files, s->ix);
+-    PyObject *o = Py_BuildValue("s", fn);
++    PyObject *o = utf8FromString(fn);
+     free(fn);
+     return o;
+ }
+ 
+ static PyObject *rpmfile_basename(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesBN(s->files, s->ix));
++    return utf8FromString(rpmfilesBN(s->files, s->ix));
+ }
+ 
+ static PyObject *rpmfile_dirname(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesDN(s->files, rpmfilesDI(s->files, s->ix)));
++    return utf8FromString(rpmfilesDN(s->files, rpmfilesDI(s->files, s->ix)));
+ }
+ 
+ static PyObject *rpmfile_orig_name(rpmfileObject *s)
+ {
+     char * fn = rpmfilesOFN(s->files, s->ix);
+-    PyObject *o = Py_BuildValue("s", fn);
++    PyObject *o = utf8FromString(fn);
+     free(fn);
+     return o;
+ }
+ 
+ static PyObject *rpmfile_orig_basename(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesOBN(s->files, s->ix));
++    return utf8FromString(rpmfilesOBN(s->files, s->ix));
+ }
+ 
+ static PyObject *rpmfile_orig_dirname(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesODN(s->files, rpmfilesODI(s->files, s->ix)));
++    return utf8FromString(rpmfilesODN(s->files, rpmfilesODI(s->files, s->ix)));
+ }
+ static PyObject *rpmfile_mode(rpmfileObject *s)
+ {
+@@ -105,17 +105,17 @@ static PyObject *rpmfile_nlink(rpmfileObject *s)
+ 
+ static PyObject *rpmfile_linkto(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesFLink(s->files, s->ix));
++    return utf8FromString(rpmfilesFLink(s->files, s->ix));
+ }
+ 
+ static PyObject *rpmfile_user(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesFUser(s->files, s->ix));
++    return utf8FromString(rpmfilesFUser(s->files, s->ix));
+ }
+ 
+ static PyObject *rpmfile_group(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesFGroup(s->files, s->ix));
++    return utf8FromString(rpmfilesFGroup(s->files, s->ix));
+ }
+ 
+ static PyObject *rpmfile_fflags(rpmfileObject *s)
+@@ -145,7 +145,7 @@ static PyObject *rpmfile_digest(rpmfileObject *s)
+ 						  NULL, &diglen);
+     if (digest) {
+ 	char * hex = pgpHexStr(digest, diglen);
+-	PyObject *o = Py_BuildValue("s", hex);
++	PyObject *o = utf8FromString(hex);
+ 	free(hex);
+ 	return o;
+     }
+@@ -154,17 +154,17 @@ static PyObject *rpmfile_digest(rpmfileObject *s)
+ 
+ static PyObject *rpmfile_class(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesFClass(s->files, s->ix));
++    return utf8FromString(rpmfilesFClass(s->files, s->ix));
+ }
+ 
+ static PyObject *rpmfile_caps(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesFCaps(s->files, s->ix));
++    return utf8FromString(rpmfilesFCaps(s->files, s->ix));
+ }
+ 
+ static PyObject *rpmfile_langs(rpmfileObject *s)
+ {
+-    return Py_BuildValue("s", rpmfilesFLangs(s->files, s->ix));
++    return utf8FromString(rpmfilesFLangs(s->files, s->ix));
+ }
+ 
+ static PyObject *rpmfile_links(rpmfileObject *s)
+diff --git a/python/rpmkeyring-py.c b/python/rpmkeyring-py.c
+index d5f131e42..8968e0513 100644
+--- a/python/rpmkeyring-py.c
++++ b/python/rpmkeyring-py.c
+@@ -38,7 +38,7 @@ static PyObject *rpmPubkey_new(PyTypeObject *subtype,
+ static PyObject * rpmPubkey_Base64(rpmPubkeyObject *s)
+ {
+     char *b64 = rpmPubkeyBase64(s->pubkey);
+-    PyObject *res = Py_BuildValue("s", b64);
++    PyObject *res = utf8FromString(b64);
+     free(b64);
+     return res;
+ }
+diff --git a/python/rpmmacro-py.c b/python/rpmmacro-py.c
+index 3cb1a51f5..d8a365547 100644
+--- a/python/rpmmacro-py.c
++++ b/python/rpmmacro-py.c
+@@ -52,7 +52,7 @@ rpmmacro_ExpandMacro(PyObject * self, PyObject * args, PyObject * kwds)
+ 	if (rpmExpandMacros(NULL, macro, &str, 0) < 0)
+ 	    PyErr_SetString(pyrpmError, "error expanding macro");
+ 	else
+-	    res = Py_BuildValue("s", str);
++	    res = utf8FromString(str);
+ 	free(str);
+     }
+     return res;
+diff --git a/python/rpmmodule.c b/python/rpmmodule.c
+index 3faad23c7..05032edc7 100644
+--- a/python/rpmmodule.c
++++ b/python/rpmmodule.c
+@@ -237,7 +237,7 @@ static void addRpmTags(PyObject *module)
+ 
+ 	PyModule_AddIntConstant(module, tagname, tagval);
+ 	pyval = PyInt_FromLong(tagval);
+-	pyname = Py_BuildValue("s", shortname);
++	pyname = utf8FromString(shortname);
+ 	PyDict_SetItem(dict, pyval, pyname);
+ 	Py_DECREF(pyval);
+ 	Py_DECREF(pyname);
+diff --git a/python/rpmps-py.c b/python/rpmps-py.c
+index bdc899a60..902b2ae63 100644
+--- a/python/rpmps-py.c
++++ b/python/rpmps-py.c
+@@ -18,12 +18,12 @@ static PyObject *rpmprob_get_type(rpmProblemObject *s, void *closure)
+ 
+ static PyObject *rpmprob_get_pkgnevr(rpmProblemObject *s, void *closure)
+ {
+-    return Py_BuildValue("s", rpmProblemGetPkgNEVR(s->prob));
++    return utf8FromString(rpmProblemGetPkgNEVR(s->prob));
+ }
+ 
+ static PyObject *rpmprob_get_altnevr(rpmProblemObject *s, void *closure)
+ {
+-    return Py_BuildValue("s", rpmProblemGetAltNEVR(s->prob));
++    return utf8FromString(rpmProblemGetAltNEVR(s->prob));
+ }
+ 
+ static PyObject *rpmprob_get_key(rpmProblemObject *s, void *closure)
+@@ -38,7 +38,7 @@ static PyObject *rpmprob_get_key(rpmProblemObject *s, void *closure)
+ 
+ static PyObject *rpmprob_get_str(rpmProblemObject *s, void *closure)
+ {
+-    return Py_BuildValue("s", rpmProblemGetStr(s->prob));
++    return utf8FromString(rpmProblemGetStr(s->prob));
+ }
+ 
+ static PyObject *rpmprob_get_num(rpmProblemObject *s, void *closure)
+@@ -59,7 +59,7 @@ static PyGetSetDef rpmprob_getseters[] = {
+ static PyObject *rpmprob_str(rpmProblemObject *s)
+ {
+     char *str = rpmProblemString(s->prob);
+-    PyObject *res = Py_BuildValue("s", str);
++    PyObject *res = utf8FromString(str);
+     free(str);
+     return res;
+ }
+diff --git a/python/rpmstrpool-py.c b/python/rpmstrpool-py.c
+index 356bd1de5..a56e2b540 100644
+--- a/python/rpmstrpool-py.c
++++ b/python/rpmstrpool-py.c
+@@ -44,7 +44,7 @@ static PyObject *strpool_id2str(rpmstrPoolObject *s, PyObject *item)
+ 	const char *str = rpmstrPoolStr(s->pool, id);
+ 
+ 	if (str)
+-	    ret = PyBytes_FromString(str);
++	    ret = utf8FromString(str);
+ 	else 
+ 	    PyErr_SetObject(PyExc_KeyError, item);
+     }
+diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
+index 955d60cd3..87c750571 100644
+--- a/python/rpmsystem-py.h
++++ b/python/rpmsystem-py.h
+@@ -19,4 +19,11 @@
+ #define PyInt_AsSsize_t PyLong_AsSsize_t
+ #endif
+ 
++/* In Python 3, we return all strings as surrogate-escaped utf-8 */
++#if PY_MAJOR_VERSION >= 3
++#define utf8FromString(_s) PyUnicode_DecodeUTF8(_s, strlen(_s), "surrogateescape")
++#else
++#define utf8FromString(_s) PyBytes_FromString(_s)
++#endif
++
+ #endif	/* H_SYSTEM_PYTHON */
+diff --git a/python/rpmtd-py.c b/python/rpmtd-py.c
+index 247c7502a..23ca10517 100644
+--- a/python/rpmtd-py.c
++++ b/python/rpmtd-py.c
+@@ -17,7 +17,7 @@ PyObject * rpmtd_ItemAsPyobj(rpmtd td, rpmTagClass tclass)
+ 
+     switch (tclass) {
+     case RPM_STRING_CLASS:
+-	res = PyBytes_FromString(rpmtdGetString(td));
++	res = utf8FromString(rpmtdGetString(td));
+ 	break;
+     case RPM_NUMERIC_CLASS:
+ 	res = PyLong_FromLongLong(rpmtdGetNumber(td));
+diff --git a/python/rpmte-py.c b/python/rpmte-py.c
+index 99ff2f496..2b3745754 100644
+--- a/python/rpmte-py.c
++++ b/python/rpmte-py.c
+@@ -54,49 +54,49 @@ rpmte_TEType(rpmteObject * s, PyObject * unused)
+ static PyObject *
+ rpmte_N(rpmteObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmteN(s->te));
++    return utf8FromString(rpmteN(s->te));
+ }
+ 
+ static PyObject *
+ rpmte_E(rpmteObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmteE(s->te));
++    return utf8FromString(rpmteE(s->te));
+ }
+ 
+ static PyObject *
+ rpmte_V(rpmteObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmteV(s->te));
++    return utf8FromString(rpmteV(s->te));
+ }
+ 
+ static PyObject *
+ rpmte_R(rpmteObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmteR(s->te));
++    return utf8FromString(rpmteR(s->te));
+ }
+ 
+ static PyObject *
+ rpmte_A(rpmteObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmteA(s->te));
++    return utf8FromString(rpmteA(s->te));
+ }
+ 
+ static PyObject *
+ rpmte_O(rpmteObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmteO(s->te));
++    return utf8FromString(rpmteO(s->te));
+ }
+ 
+ static PyObject *
+ rpmte_NEVR(rpmteObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmteNEVR(s->te));
++    return utf8FromString(rpmteNEVR(s->te));
+ }
+ 
+ static PyObject *
+ rpmte_NEVRA(rpmteObject * s, PyObject * unused)
+ {
+-    return Py_BuildValue("s", rpmteNEVRA(s->te));
++    return utf8FromString(rpmteNEVRA(s->te));
+ }
+ 
+ static PyObject *
+diff --git a/python/rpmts-py.c b/python/rpmts-py.c
+index 1ddfc9a1e..96e3bb28e 100644
+--- a/python/rpmts-py.c
++++ b/python/rpmts-py.c
+@@ -230,8 +230,9 @@ rpmts_SolveCallback(rpmts ts, rpmds ds, const void * data)
+ 
+     PyEval_RestoreThread(cbInfo->_save);
+ 
+-    args = Py_BuildValue("(Oissi)", cbInfo->tso,
+-		rpmdsTagN(ds), rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
++    args = Py_BuildValue("(OiNNi)", cbInfo->tso,
++		rpmdsTagN(ds), utf8FromString(rpmdsN(ds)),
++		utf8FromString(rpmdsEVR(ds)), rpmdsFlags(ds));
+     result = PyEval_CallObject(cbInfo->cb, args);
+     Py_DECREF(args);
+ 
+@@ -409,7 +410,7 @@ rpmts_HdrCheck(rpmtsObject * s, PyObject *obj)
+     rpmrc = headerCheck(s->ts, uh, uc, &msg);
+     Py_END_ALLOW_THREADS;
+ 
+-    return Py_BuildValue("(is)", rpmrc, msg);
++    return Py_BuildValue("(iN)", rpmrc, utf8FromString(msg));
+ }
+ 
+ static PyObject *
+@@ -500,7 +501,7 @@ rpmtsCallback(const void * hd, const rpmCallbackType what,
+     /* Synthesize a python object for callback (if necessary). */
+     if (pkgObj == NULL) {
+ 	if (h) {
+-	    pkgObj = Py_BuildValue("s", headerGetString(h, RPMTAG_NAME));
++	    pkgObj = utf8FromString(headerGetString(h, RPMTAG_NAME));
+ 	} else {
+ 	    pkgObj = Py_None;
+ 	    Py_INCREF(pkgObj);
+@@ -845,7 +846,7 @@ static PyObject *rpmts_get_tid(rpmtsObject *s, void *closure)
+ 
+ static PyObject *rpmts_get_rootDir(rpmtsObject *s, void *closure)
+ {
+-    return Py_BuildValue("s", rpmtsRootDir(s->ts));
++    return utf8FromString(rpmtsRootDir(s->ts));
+ }
+ 
+ static int rpmts_set_scriptFd(rpmtsObject *s, PyObject *value, void *closure)
+diff --git a/python/spec-py.c b/python/spec-py.c
+index 4efdbf4bf..70b796531 100644
+--- a/python/spec-py.c
++++ b/python/spec-py.c
+@@ -57,7 +57,7 @@ static PyObject *pkgGetSection(rpmSpecPkg pkg, int section)
+ {
+     char *sect = rpmSpecPkgGetSection(pkg, section);
+     if (sect != NULL) {
+-        PyObject *ps = PyBytes_FromString(sect);
++        PyObject *ps = utf8FromString(sect);
+         free(sect);
+         if (ps != NULL)
+             return ps;
+@@ -158,7 +158,7 @@ static PyObject * getSection(rpmSpec spec, int section)
+ {
+     const char *sect = rpmSpecGetSection(spec, section);
+     if (sect) {
+-	return Py_BuildValue("s", sect);
++	return utf8FromString(sect);
+     }
+     Py_RETURN_NONE;
+ }
+@@ -208,8 +208,8 @@ static PyObject * spec_get_sources(specObject *s, void *closure)
+ 
+     rpmSpecSrcIter iter = rpmSpecSrcIterInit(s->spec);
+     while ((source = rpmSpecSrcIterNext(iter)) != NULL) {
+-	PyObject *srcUrl = Py_BuildValue("(sii)",
+-				rpmSpecSrcFilename(source, 1),
++	PyObject *srcUrl = Py_BuildValue("(Nii)",
++				utf8FromString(rpmSpecSrcFilename(source, 1)),
+ 				rpmSpecSrcNum(source),
+ 				rpmSpecSrcFlags(source)); 
+         if (!srcUrl) {
+diff --git a/tests/local.at b/tests/local.at
+index 02ead66c9..42eef1c75 100644
+--- a/tests/local.at
++++ b/tests/local.at
+@@ -10,6 +10,7 @@ rm -rf "${abs_builddir}"/testing`rpm --eval '%_dbpath'`/*
+ 
+ m4_define([RPMPY_RUN],[[
+ cat << EOF > test.py
++# coding=utf-8
+ import rpm, sys
+ dbpath=rpm.expandMacro('%_dbpath')
+ rpm.addMacro('_dbpath', '${abs_builddir}/testing%s' % dbpath)
+diff --git a/tests/rpmpython.at b/tests/rpmpython.at
+index ff77f868c..58f3e84a6 100644
+--- a/tests/rpmpython.at
++++ b/tests/rpmpython.at
+@@ -106,6 +106,25 @@ None
+ 'rpm.hdr' object has no attribute '__foo__']
+ )
+ 
++RPMPY_TEST([non-utf8 data in header],[
++str = u'älämölö'
++enc = 'iso-8859-1'
++b = str.encode(enc)
++h = rpm.hdr()
++h['group'] = b
++d = h['group']
++try:
++    # python 3
++    t = bytes(d, 'utf-8', 'surrogateescape')
++except TypeError:
++    # python 2
++    t = bytes(d)
++res = t.decode(enc)
++myprint(str == res)
++],
++[True]
++)
++
+ RPMPY_TEST([invalid header data],[
+ h1 = rpm.hdr()
+ h1['basenames'] = ['bing', 'bang', 'bong']
+@@ -125,6 +144,21 @@ for h in [h1, h2]:
+ /opt/bing,/opt/bang,/flopt/bong]
+ )
+ 
++RPMPY_TEST([labelCompare],[
++v = '1.0'
++r = '1'
++e = 3
++h = rpm.hdr()
++h['name'] = 'testpkg'
++h['version'] = v
++h['release'] = r
++h['epoch'] = e
++myprint(rpm.labelCompare((str(h['epoch']), h['version'], h['release']),
++			 (str(e), v, r)))
++],
++[0]
++)
++
+ RPMPY_TEST([vfyflags API],[
+ ts = rpm.ts()
+ dlv = ts.getVfyFlags()
+-- 
+2.20.1
+
diff --git a/SOURCES/0001-Log-RPMLOG_ERR-level-messages-on-actual-errors-in-se.patch b/SOURCES/0001-Log-RPMLOG_ERR-level-messages-on-actual-errors-in-se.patch
new file mode 100644
index 0000000..312d9cc
--- /dev/null
+++ b/SOURCES/0001-Log-RPMLOG_ERR-level-messages-on-actual-errors-in-se.patch
@@ -0,0 +1,86 @@
+From 8cbe8baf9c3ff4754369bcd29441df14ecc6889d Mon Sep 17 00:00:00 2001
+Message-Id: <8cbe8baf9c3ff4754369bcd29441df14ecc6889d.1554982512.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 14 Feb 2019 13:12:49 +0200
+Subject: [PATCH] Log RPMLOG_ERR level messages on actual errors in selinux
+ plugin, doh.
+
+When there's an actual error, people will want to know without having
+to rerun in verbose mode. Such as in RhBug:1641631 where configured
+selinux policy differs from what is installed - the former message
+
+    error: Plugin selinux: hook tsm_pre failed
+
+...is not particularly helpful to anybody, whereas this actually provides
+some clues now:
+
+    error: selabel_open: (/etc/selinux/ponies/contexts/files/file_contexts) No such file or directory
+    error: Plugin selinux: hook tsm_pre failed
+---
+ plugins/selinux.c | 19 +++++++++----------
+ 1 file changed, 9 insertions(+), 10 deletions(-)
+
+diff --git a/plugins/selinux.c b/plugins/selinux.c
+index accd47416..f1caf257c 100644
+--- a/plugins/selinux.c
++++ b/plugins/selinux.c
+@@ -12,6 +12,11 @@
+ 
+ static struct selabel_handle * sehandle = NULL;
+ 
++static inline rpmlogLvl loglvl(int iserror)
++{
++    return iserror ? RPMLOG_ERR : RPMLOG_DEBUG;
++}
++
+ static void sehandle_fini(int close_status)
+ {
+     if (sehandle) {
+@@ -47,7 +52,7 @@ static rpmRC sehandle_init(int open_status)
+ 
+     sehandle = selabel_open(SELABEL_CTX_FILE, opts, 1);
+ 
+-    rpmlog(RPMLOG_DEBUG, "selabel_open: (%s) %s\n",
++    rpmlog(loglvl(sehandle == NULL), "selabel_open: (%s) %s\n",
+ 	   path, (sehandle == NULL ? strerror(errno) : ""));
+ 
+     return (sehandle != NULL) ? RPMRC_OK : RPMRC_FAIL;
+@@ -125,10 +130,8 @@ static rpmRC selinux_scriptlet_fork_post(rpmPlugin plugin,
+     if ((xx = setexeccon(newcon)) == 0)
+ 	rc = RPMRC_OK;
+ 
+-    if (rpmIsDebug()) {
+-	rpmlog(RPMLOG_DEBUG, "setexeccon: (%s, %s) %s\n",
++    rpmlog(loglvl(xx < 0), "setexeccon: (%s, %s) %s\n",
+ 	       path, newcon, (xx < 0 ? strerror(errno) : ""));
+-    }
+ 
+ exit:
+     context_free(con);
+@@ -143,10 +146,8 @@ exit:
+     if ((xx = setexecfilecon(path, "rpm_script_t") == 0))
+ 	rc = RPMRC_OK;
+ 
+-    if (rpmIsDebug()) {
+-	rpmlog(RPMLOG_DEBUG, "setexecfilecon: (%s) %s\n",
++    rpmlog(loglvl(xx < 0), "setexecfilecon: (%s) %s\n",
+ 	       path, (xx < 0 ? strerror(errno) : ""));
+-    }
+ #endif
+     /* If selinux is not enforcing, we don't care either */
+     if (rc && security_getenforce() < 1)
+@@ -167,10 +168,8 @@ static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
+ 	if (selabel_lookup_raw(sehandle, &scon, dest, file_mode) == 0) {
+ 	    int conrc = lsetfilecon(path, scon);
+ 
+-	    if (rpmIsDebug()) {
+-		rpmlog(RPMLOG_DEBUG, "lsetfilecon: (%s, %s) %s\n",
++	    rpmlog(loglvl(conrc < 0), "lsetfilecon: (%s, %s) %s\n",
+ 		       path, scon, (conrc < 0 ? strerror(errno) : ""));
+-	    }
+ 
+ 	    if (conrc == 0 || (conrc < 0 && errno == EOPNOTSUPP))
+ 		rc = RPMRC_OK;
+-- 
+2.20.1
+
diff --git a/SOURCES/0001-Make-rpmsign-exit-values-more-consistent-with-our-ot.patch b/SOURCES/0001-Make-rpmsign-exit-values-more-consistent-with-our-ot.patch
new file mode 100644
index 0000000..c186017
--- /dev/null
+++ b/SOURCES/0001-Make-rpmsign-exit-values-more-consistent-with-our-ot.patch
@@ -0,0 +1,49 @@
+From 2ec0832287bd1443ebf336f8a98293f30bfa2036 Mon Sep 17 00:00:00 2001
+Message-Id: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Mon, 18 Mar 2019 15:24:54 +0200
+Subject: [PATCH 1/3] Make rpmsign exit values more consistent with our other
+ tools
+
+rpmPkgSign*() return -1 for failure, which is not that helpful when
+returned to shell and the way it was counted could easily wrap around
+when signing multiple packages. Return number of failures similarly to
+how rpm -q and frieds does, avoid overflows and xargs special value 255.
+---
+ rpmsign.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/rpmsign.c b/rpmsign.c
+index ae86f666d..1a5cd59c2 100644
+--- a/rpmsign.c
++++ b/rpmsign.c
+@@ -134,7 +134,8 @@ static int doSign(poptContext optCon, struct rpmSignArgs *sargs)
+     const char *arg;
+     rc = 0;
+     while ((arg = poptGetArg(optCon)) != NULL) {
+-	rc += rpmPkgSign(arg, sargs);
++	if (rpmPkgSign(arg, sargs) < 0)
++	    rc++;
+     }
+ 
+ exit:
+@@ -175,7 +176,8 @@ int main(int argc, char *argv[])
+     case MODE_DELSIGN:
+ 	ec = 0;
+ 	while ((arg = poptGetArg(optCon)) != NULL) {
+-	    ec += rpmPkgDelSign(arg, &sargs);
++	    if (rpmPkgDelSign(arg, &sargs) < 0)
++		ec++;
+ 	}
+ 	break;
+     case MODE_NONE:
+@@ -188,5 +190,5 @@ int main(int argc, char *argv[])
+ 
+ exit:
+     rpmcliFini(optCon);
+-    return ec;
++    return RETVAL(ec);
+ }
+-- 
+2.20.1
+
diff --git a/SOURCES/0001-Monkey-patch-.decode-method-to-our-strings-as-a-temp.patch b/SOURCES/0001-Monkey-patch-.decode-method-to-our-strings-as-a-temp.patch
new file mode 100644
index 0000000..6df9fab
--- /dev/null
+++ b/SOURCES/0001-Monkey-patch-.decode-method-to-our-strings-as-a-temp.patch
@@ -0,0 +1,89 @@
+From 13b0ebee7cdb1e4d200b3c40d0ec9440f198a1d4 Mon Sep 17 00:00:00 2001
+Message-Id: <13b0ebee7cdb1e4d200b3c40d0ec9440f198a1d4.1554886141.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 10 Apr 2019 11:24:44 +0300
+Subject: [PATCH] Monkey-patch .decode() method to our strings as a temporary
+ compat crutch
+
+As a temporary crutch to support faster deployment of the sane
+string behavior on python3, monkey-patch a decode method into all
+strings we return. This seems to be enough to fix practically all
+API users who have already adapted to the long-standing broken API
+on Python 3. API users compatible with both Python 2 and 3 never needed
+this anyway. Issue a warning with pointer to the relevant bug when the
+fake decode() method is used to alert users to the issue.
+
+This is certainly an evil thing to do and will be removed as soon as
+the critical users have been fixed to work with the new, corrected
+behavior.
+---
+ python/rpm/__init__.py |  3 +++
+ python/rpmmodule.c     |  1 +
+ python/rpmsystem-py.h  | 22 ++++++++++++++++++++--
+ 3 files changed, 24 insertions(+), 2 deletions(-)
+
+diff --git a/python/rpm/__init__.py b/python/rpm/__init__.py
+index 54728bbd4..6d69eda7b 100644
+--- a/python/rpm/__init__.py
++++ b/python/rpm/__init__.py
+@@ -61,6 +61,9 @@ except ImportError:
+ # backwards compatibility + give the same class both ways
+ ts = TransactionSet
+ 
++def _fakedecode(self, encoding='utf-8', errors='strict'):
++    warnings.warn("decode() called on unicode string, see https://bugzilla.redhat.com/show_bug.cgi?id=1693751", UnicodeWarning, stacklevel=2)
++    return self
+ 
+ def headerLoad(*args, **kwds):
+     """DEPRECATED! Use rpm.hdr() instead."""
+diff --git a/python/rpmmodule.c b/python/rpmmodule.c
+index 05032edc7..2a76cfbd0 100644
+--- a/python/rpmmodule.c
++++ b/python/rpmmodule.c
+@@ -28,6 +28,7 @@
+  */
+ 
+ PyObject * pyrpmError;
++PyObject * fakedecode = NULL;
+ 
+ static PyObject * archScore(PyObject * self, PyObject * arg)
+ {
+diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
+index 25938464a..803da0fc1 100644
+--- a/python/rpmsystem-py.h
++++ b/python/rpmsystem-py.h
+@@ -19,12 +19,29 @@
+ #define PyInt_AsSsize_t PyLong_AsSsize_t
+ #endif
+ 
++PyObject * fakedecode;
++
+ static inline PyObject * utf8FromString(const char *s)
+ {
+ /* In Python 3, we return all strings as surrogate-escaped utf-8 */
+ #if PY_MAJOR_VERSION >= 3
+-    if (s != NULL)
+-	return PyUnicode_DecodeUTF8(s, strlen(s), "surrogateescape");
++    if (s != NULL) {
++	PyObject *o = PyUnicode_DecodeUTF8(s, strlen(s), "surrogateescape");
++	/* fish the fake decode function from python side if not done yet */
++	if (fakedecode == NULL) {
++	    PyObject *n = PyUnicode_FromString("rpm");
++	    PyObject *m = PyImport_Import(n);
++	    PyObject *md = PyModule_GetDict(m);
++	    fakedecode = PyDict_GetItemString(md, "_fakedecode");
++	    Py_DECREF(m);
++	    Py_DECREF(n);
++	}
++	if (fakedecode && o) {
++	    /* monkey-patch it into the string object as "decode" */
++	    PyDict_SetItemString(Py_TYPE(o)->tp_dict, "decode", fakedecode);
++	}
++	return o;
++    }
+ #else
+     if (s != NULL)
+ 	return PyBytes_FromString(s);
+-- 
+2.20.1
+
diff --git a/SOURCES/0001-Only-read-through-payload-on-verify-if-actually-need.patch b/SOURCES/0001-Only-read-through-payload-on-verify-if-actually-need.patch
new file mode 100644
index 0000000..6da9775
--- /dev/null
+++ b/SOURCES/0001-Only-read-through-payload-on-verify-if-actually-need.patch
@@ -0,0 +1,80 @@
+From 362c4401979f896de1e69a3e18d33954953912cc Mon Sep 17 00:00:00 2001
+Message-Id: <362c4401979f896de1e69a3e18d33954953912cc.1554983588.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 11 Dec 2018 13:21:47 +0200
+Subject: [PATCH] Only read through payload on verify if actually needed
+
+If none of our verify items ranges over the payload, then why bother?
+
+To do this, add an internal rpmvs API to get it's range, and use
+that to decide whether trip over the payload is needed or not.
+In addition, the payload digest tag needs to be grabbed outside of the
+condition to avoid depending on other values. The details including
+RPMVSF_NEEDPAYLOAD will be handled internally to rpmvs which makes it
+actually nicer code-wise too.
+---
+ lib/rpmchecksig.c |  8 ++++----
+ lib/rpmvs.c       | 12 ++++++++++++
+ lib/rpmvs.h       |  3 +++
+ 3 files changed, 19 insertions(+), 4 deletions(-)
+
+diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
+index 1ba72a45e..810f7153d 100644
+--- a/lib/rpmchecksig.c
++++ b/lib/rpmchecksig.c
+@@ -187,11 +187,11 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd,
+     /* Finalize header range */
+     rpmvsFiniRange(vs, RPMSIG_HEADER);
+ 
+-    /* Unless disabled, read the payload, generating digest(s) on the fly. */
+-    if (!(rpmvsFlags(vs) & RPMVSF_NEEDPAYLOAD)) {
+-	/* Fish interesting tags from the main header. This is a bit hacky... */
+-	rpmvsAppendTag(vs, blob, RPMTAG_PAYLOADDIGEST);
++    /* Fish interesting tags from the main header. This is a bit hacky... */
++    rpmvsAppendTag(vs, blob, RPMTAG_PAYLOADDIGEST);
+ 
++    /* If needed and not explicitly disabled, read the payload as well. */
++    if (rpmvsRange(vs) & RPMSIG_PAYLOAD) {
+ 	/* Initialize digests ranging over the payload only */
+ 	rpmvsInitRange(vs, RPMSIG_PAYLOAD);
+ 
+diff --git a/lib/rpmvs.c b/lib/rpmvs.c
+index 622e48011..0d475af86 100644
+--- a/lib/rpmvs.c
++++ b/lib/rpmvs.c
+@@ -396,6 +396,18 @@ void rpmvsFiniRange(struct rpmvs_s *sis, int range)
+     }
+ }
+ 
++int rpmvsRange(struct rpmvs_s *vs)
++{
++    int range = 0;
++    for (int i = 0; i < vs->nsigs; i++) {
++	if (rpmsinfoDisabled(&vs->sigs[i], vs->vsflags))
++	    continue;
++	range |= vs->sigs[i].range;
++    }
++
++    return range;
++}
++
+ static int sinfoCmp(const void *a, const void *b)
+ {
+     const struct rpmsinfo_s *sa = a;
+diff --git a/lib/rpmvs.h b/lib/rpmvs.h
+index b27d9a612..a836d5c94 100644
+--- a/lib/rpmvs.h
++++ b/lib/rpmvs.h
+@@ -75,6 +75,9 @@ void rpmvsInitRange(struct rpmvs_s *sis, int range);
+ RPM_GNUC_INTERNAL
+ void rpmvsFiniRange(struct rpmvs_s *sis, int range);
+ 
++RPM_GNUC_INTERNAL
++int rpmvsRange(struct rpmvs_s *vs);
++
+ RPM_GNUC_INTERNAL
+ int rpmvsVerify(struct rpmvs_s *sis, int type,
+                        rpmsinfoCb cb, void *cbdata);
+-- 
+2.20.1
+
diff --git a/SOURCES/0001-Remove-capabilities-instead-of-setting-empty-caps-vi.patch b/SOURCES/0001-Remove-capabilities-instead-of-setting-empty-caps-vi.patch
new file mode 100644
index 0000000..23ddb28
--- /dev/null
+++ b/SOURCES/0001-Remove-capabilities-instead-of-setting-empty-caps-vi.patch
@@ -0,0 +1,49 @@
+From b4178c979fff344a1c5142a305f274dd9aff8f45 Mon Sep 17 00:00:00 2001
+From: Markus Linnala <markus.linnala@gmail.com>
+Date: Sun, 28 Oct 2018 14:59:52 +0200
+Subject: [PATCH] Remove capabilities instead of setting empty caps via.
+ --setcaps
+
+If a file in a package does not have any capabilities rpm --setcaps should
+remove capabilities of the file. Prior to this patch capabilities of the file
+were set as empty.
+
+Empty capabilities mean more than no capabilities. A file with no capabilities
+can inherit capabilities, but file with empty capabilities can not.
+
+When ever package does not have any capabilities set %|FILECAPS? is false.
+If some files have capabilities, %|FILECAPS? is true but %{FILECAPS} is ''
+when the file does not have capabilities and '= <capstring>' when there is some.
+
+Reported and patch created by Markus Linnala
+Commit message edited by Pavlina Moravcova Varekova and Florian Festi.
+
+Fixes #585
+Fixes #586
+---
+ rpmpopt.in | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/rpmpopt.in b/rpmpopt.in
+index 42d3416a3..557050a24 100644
+--- a/rpmpopt.in
++++ b/rpmpopt.in
+@@ -57,8 +57,13 @@ rpm	alias --setugids -q --qf \
+ 	--POPTdesc=$"set user/group ownership of files in a package"
+ 
+ rpm	alias --setcaps -q --qf \
+-	"[\[ -f %{FILENAMES:shescape} -a ! -L %{FILENAMES:shescape} \] \
+-	    && setcap %|FILECAPS?{%{FILECAPS:shescape}}:{''}| %{FILENAMES:shescape}\n]" \
++        "[if \[ -f %{FILENAMES:shescape} -a ! -L %{FILENAMES:shescape} \]; then\n\
++%|FILECAPS?{  if \[ -n %{FILECAPS:shescape} \]; then\n\
++    setcap %{FILECAPS:shescape} %{FILENAMES:shescape}\n\
++  el}:{  }|if \[ -n \"\$(getcap %{FILENAMES:shescape})\" \]; then\n\
++    setcap -r %{FILENAMES:shescape}\n\
++  fi\n\
++fi\n]" \
+ 	--pipe "sh" \
+ 	--POPTdesc=$"set capabilities of files in a package"
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-Return-NULL-string-as-None-from-utf8FromString.patch b/SOURCES/0001-Return-NULL-string-as-None-from-utf8FromString.patch
new file mode 100644
index 0000000..e91db6f
--- /dev/null
+++ b/SOURCES/0001-Return-NULL-string-as-None-from-utf8FromString.patch
@@ -0,0 +1,41 @@
+From aea53a4aead8bd71f519df35fcffd9eec76fbc01 Mon Sep 17 00:00:00 2001
+Message-Id: <aea53a4aead8bd71f519df35fcffd9eec76fbc01.1554884465.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 26 Feb 2019 11:27:51 +0200
+Subject: [PATCH] Return NULL string as None from utf8FromString()
+
+Commit 84920f898315d09a57a3f1067433eaeb7de5e830 regressed dnf install
+to segfault at the end due to some NULL string passed to strlen().
+Check for NULL and return it as None, make it an inline function
+to make this saner.
+---
+ python/rpmsystem-py.h | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
+index 87c750571..25938464a 100644
+--- a/python/rpmsystem-py.h
++++ b/python/rpmsystem-py.h
+@@ -19,11 +19,17 @@
+ #define PyInt_AsSsize_t PyLong_AsSsize_t
+ #endif
+ 
++static inline PyObject * utf8FromString(const char *s)
++{
+ /* In Python 3, we return all strings as surrogate-escaped utf-8 */
+ #if PY_MAJOR_VERSION >= 3
+-#define utf8FromString(_s) PyUnicode_DecodeUTF8(_s, strlen(_s), "surrogateescape")
++    if (s != NULL)
++	return PyUnicode_DecodeUTF8(s, strlen(s), "surrogateescape");
+ #else
+-#define utf8FromString(_s) PyBytes_FromString(_s)
++    if (s != NULL)
++	return PyBytes_FromString(s);
+ #endif
++    Py_RETURN_NONE;
++}
+ 
+ #endif	/* H_SYSTEM_PYTHON */
+-- 
+2.20.1
+
diff --git a/SOURCES/0001-Show-list-of-files-only-once-when-use-rpm-ql-and-mul.patch b/SOURCES/0001-Show-list-of-files-only-once-when-use-rpm-ql-and-mul.patch
new file mode 100644
index 0000000..863ac43
--- /dev/null
+++ b/SOURCES/0001-Show-list-of-files-only-once-when-use-rpm-ql-and-mul.patch
@@ -0,0 +1,57 @@
+From 8dd8e37acc79da1ce0a36c3f86650defa474a6a9 Mon Sep 17 00:00:00 2001
+From: Pavlina Moravcova Varekova <pmoravco@redhat.com>
+Date: Thu, 14 Mar 2019 13:56:26 +0100
+Subject: [PATCH] Show list of files only once when use rpm -ql and multiple
+ rpm files
+
+---
+ lib/query.c       |  3 ++-
+ tests/rpmquery.at | 18 ++++++++++++++++++
+ 2 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/lib/query.c b/lib/query.c
+index e5408e211..7568f67aa 100644
+--- a/lib/query.c
++++ b/lib/query.c
+@@ -574,7 +574,8 @@ int rpmcliArgIter(rpmts ts, QVA_t qva, ARGV_const_t argv)
+ 	    if (mi == NULL && qva->qva_source == RPMQV_PACKAGE) {
+ 		size_t l = strlen(*arg);
+ 		if (l > 4 && !strcmp(*arg + l - 4, ".rpm")) {
+-		    rpmgi gi = rpmgiNew(ts, giFlags, argv);
++		    char * const argFirst[2] = { arg[0], NULL };
++		    rpmgi gi = rpmgiNew(ts, giFlags, argFirst);
+ 		    ecLocal = rpmgiShowMatches(qva, ts, gi);
+ 		    rpmgiFree(gi);
+ 		}
+diff --git a/tests/rpmquery.at b/tests/rpmquery.at
+index ab7bb3c46..0dc6d78b6 100644
+--- a/tests/rpmquery.at
++++ b/tests/rpmquery.at
+@@ -61,6 +61,24 @@ hello.spec
+ [ignore])
+ AT_CLEANUP
+ 
++# ------------------------------
++AT_SETUP([rpm -ql multiple *.rpm])
++AT_KEYWORDS([query])
++AT_CHECK([
++runroot rpm \
++  -ql \
++  /data/SRPMS/hello-1.0-1.src.rpm /data/RPMS/hello-1.0-1.i386.rpm
++],
++[0],
++[hello-1.0.tar.gz
++hello.spec
++/usr/local/bin/hello
++/usr/share/doc/hello-1.0
++/usr/share/doc/hello-1.0/FAQ
++],
++[ignore])
++AT_CLEANUP
++
+ # ------------------------------
+ AT_SETUP([rpmspec -q])
+ AT_KEYWORDS([query])
+-- 
+2.17.2
+
diff --git a/SOURCES/0001-Sort-list-of-hard-linked-files-in-find-debuginfo.sh-.patch b/SOURCES/0001-Sort-list-of-hard-linked-files-in-find-debuginfo.sh-.patch
new file mode 100644
index 0000000..ae7d4e0
--- /dev/null
+++ b/SOURCES/0001-Sort-list-of-hard-linked-files-in-find-debuginfo.sh-.patch
@@ -0,0 +1,27 @@
+From 35b09eed946a7e2f2f327531b692c9f768bf9e3b Mon Sep 17 00:00:00 2001
+From: Pavlina Moravcova Varekova <pmoravco@redhat.com>
+Date: Sun, 7 Apr 2019 07:23:47 +0200
+Subject: [PATCH] Sort list of hard linked files in find-debuginfo.sh
+ (RhBug:1421272)
+
+It helps to make build results reproducible. Based on Mark Wielaard's idea.
+---
+ scripts/find-debuginfo.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh
+index c75d176ac..23286139e 100755
+--- a/scripts/find-debuginfo.sh
++++ b/scripts/find-debuginfo.sh
+@@ -350,7 +350,7 @@ trap 'rm -rf "$temp"' EXIT
+ touch "$temp/primary"
+ find "$RPM_BUILD_ROOT" ! -path "${debugdir}/*.debug" -type f \
+      		     \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \
+-		     -print |
++		     -print | LC_ALL=C sort |
+ file -N -f - | sed -n -e 's/^\(.*\):[ 	]*.*ELF.*, not stripped.*/\1/p' |
+ xargs --no-run-if-empty stat -c '%h %D_%i %n' |
+ while read nlinks inum f; do
+-- 
+2.17.2
+
diff --git a/SOURCES/0001-Use-dpbath-only-with-full-path-RhBug-1696408.patch b/SOURCES/0001-Use-dpbath-only-with-full-path-RhBug-1696408.patch
new file mode 100644
index 0000000..f753e38
--- /dev/null
+++ b/SOURCES/0001-Use-dpbath-only-with-full-path-RhBug-1696408.patch
@@ -0,0 +1,29 @@
+From d313baf1d3a4756447e398ee55f8c6760f942d50 Mon Sep 17 00:00:00 2001
+From: Pavlina Moravcova Varekova <pmoravco@redhat.com>
+Date: Wed, 24 Apr 2019 10:29:14 +0200
+Subject: [PATCH] Use --dpbath only with full path (RhBug:1696408)
+
+Before the patch rpm treats the relative path as a full path.
+The new behavior is similar to the "--root" option.
+---
+ lib/poptALL.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/lib/poptALL.c b/lib/poptALL.c
+index 9983c1e62..69fd49846 100644
+--- a/lib/poptALL.c
++++ b/lib/poptALL.c
+@@ -147,6 +147,10 @@ static void rpmcliAllArgCallback( poptContext con,
+ 	break;
+     case POPT_DBPATH:
+ 	rpmcliConfigured();
++	if (arg && arg[0] != '/') {
++	    fprintf(stderr, _("arguments to --dbpath must begin with '/'\n"));
++	    exit(EXIT_FAILURE);
++	}
+ 	rpmPushMacro(NULL, "_dbpath", NULL, arg, RMIL_CMDLINE);
+ 	break;
+     case POPT_SHOWVERSION:
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-Use-in-condition-to-avoid-sub-processes-in-find-debu.patch b/SOURCES/0001-Use-in-condition-to-avoid-sub-processes-in-find-debu.patch
new file mode 100644
index 0000000..6053ca2
--- /dev/null
+++ b/SOURCES/0001-Use-in-condition-to-avoid-sub-processes-in-find-debu.patch
@@ -0,0 +1,29 @@
+From 9aae21d7610a7e8067ae932f36d1c8bb8583fe59 Mon Sep 17 00:00:00 2001
+From: Pavlina Moravcova Varekova <pmoravco@redhat.com>
+Date: Wed, 5 Jun 2019 06:07:00 +0200
+Subject: [PATCH] Use [ ] in condition to avoid sub processes in
+ find-debuginfo.sh (#735)
+
+Introduced in commit 1da9e83, spotted by covscan.
+
+Modified to fix another covscan warning
+---
+ scripts/find-debuginfo.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh
+index 23286139e..d75da1108 100755
+--- a/scripts/find-debuginfo.sh
++++ b/scripts/find-debuginfo.sh
+@@ -213,7 +213,7 @@ if test -n "$build_id_seed" -a "$no_recompute_build_id" = "true"; then
+   exit 2
+ fi
+ 
+-if ("$strip_g" = "true") && ("$strip_glibs" = "true"); then
++if [ "$strip_g" = "true" ] && [ "$strip_glibs" = "true" ]; then
+   echo >&2 "*** ERROR: -g  and --g-libs cannot be used together"
+   exit 2
+ fi
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-rpmsign-man-page-Add-line-about-rpmsign-requiring-a-.patch b/SOURCES/0001-rpmsign-man-page-Add-line-about-rpmsign-requiring-a-.patch
new file mode 100644
index 0000000..8ddd2a3
--- /dev/null
+++ b/SOURCES/0001-rpmsign-man-page-Add-line-about-rpmsign-requiring-a-.patch
@@ -0,0 +1,28 @@
+From be3347b5bff6142e86e533174fe0ec352405d159 Mon Sep 17 00:00:00 2001
+From: Florian Festi <ffesti@redhat.com>
+Date: Thu, 18 Jul 2019 07:45:53 +0200
+Subject: [PATCH] rpmsign man page: Add line about rpmsign requiring a valid
+ checksum
+
+and the limitations in FIPS mode
+---
+ doc/rpmsign.8 | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/doc/rpmsign.8 b/doc/rpmsign.8
+index 80ffb6a32..d895a3b8c 100644
+--- a/doc/rpmsign.8
++++ b/doc/rpmsign.8
+@@ -21,6 +21,9 @@ options generate and insert new signatures for each package
+ existing signatures. There are two options for historical reasons,
+ there is no difference in behavior currently.
+ 
++To create a signature rpm needs to verify the package's checksum. As a result
++packages with a MD5/SHA1 checksums cannot be signed in FIPS mode.
++
+ \fBrpm\fR \fB--delsign\fR \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR
+ 
+ .PP
+-- 
+2.21.0
+
diff --git a/SOURCES/0002-Drop-internal-only-visibility-on-rpmvs-related-API.patch b/SOURCES/0002-Drop-internal-only-visibility-on-rpmvs-related-API.patch
new file mode 100644
index 0000000..e2212eb
--- /dev/null
+++ b/SOURCES/0002-Drop-internal-only-visibility-on-rpmvs-related-API.patch
@@ -0,0 +1,64 @@
+From 3fd79a5564df97d512be283c5c8a4da2e7ef8bce Mon Sep 17 00:00:00 2001
+Message-Id: <3fd79a5564df97d512be283c5c8a4da2e7ef8bce.1554983206.git.pmatilai@redhat.com>
+In-Reply-To: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
+References: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Mon, 18 Mar 2019 15:29:18 +0200
+Subject: [PATCH 2/3] Drop internal-only visibility on rpmvs-related API
+
+Makes it possible to use rpmvs API from eg librpmsign which we'll
+need in the next commit. We need to make select parts of this
+actually public eventually but for now...
+---
+ lib/rpmvs.h | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+diff --git a/lib/rpmvs.h b/lib/rpmvs.h
+index a836d5c94..025895500 100644
+--- a/lib/rpmvs.h
++++ b/lib/rpmvs.h
+@@ -48,41 +48,29 @@ typedef int (*rpmsinfoCb)(struct rpmsinfo_s *sinfo, void *cbdata);
+ extern "C" {
+ #endif
+ 
+-RPM_GNUC_INTERNAL
+ const char *rpmsinfoDescr(struct rpmsinfo_s *sinfo);
+ 
+-RPM_GNUC_INTERNAL
+ char *rpmsinfoMsg(struct rpmsinfo_s *sinfo);
+ 
+-RPM_GNUC_INTERNAL
+ struct rpmvs_s *rpmvsCreate(int vfylevel, rpmVSFlags vsflags, rpmKeyring keyring);
+ 
+-RPM_GNUC_INTERNAL
+ void rpmvsInit(struct rpmvs_s *vs, hdrblob blob, rpmDigestBundle bundle);
+ 
+-RPM_GNUC_INTERNAL
+ rpmVSFlags rpmvsFlags(struct rpmvs_s *vs);
+ 
+-RPM_GNUC_INTERNAL
+ struct rpmvs_s *rpmvsFree(struct rpmvs_s *sis);
+ 
+-RPM_GNUC_INTERNAL
+ void rpmvsAppendTag(struct rpmvs_s *sis, hdrblob blob, rpmTagVal tag);
+ 
+-RPM_GNUC_INTERNAL
+ void rpmvsInitRange(struct rpmvs_s *sis, int range);
+ 
+-RPM_GNUC_INTERNAL
+ void rpmvsFiniRange(struct rpmvs_s *sis, int range);
+ 
+-RPM_GNUC_INTERNAL
+ int rpmvsRange(struct rpmvs_s *vs);
+ 
+-RPM_GNUC_INTERNAL
+ int rpmvsVerify(struct rpmvs_s *sis, int type,
+                        rpmsinfoCb cb, void *cbdata);
+ 
+-RPM_GNUC_INTERNAL
+ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd,
+ 		hdrblob *sigblobp, hdrblob *blobp, char **emsg);
+ 
+-- 
+2.20.1
+
diff --git a/SOURCES/0003-Verify-packages-before-signing-RhBug-1646388.patch b/SOURCES/0003-Verify-packages-before-signing-RhBug-1646388.patch
new file mode 100644
index 0000000..c950748
--- /dev/null
+++ b/SOURCES/0003-Verify-packages-before-signing-RhBug-1646388.patch
@@ -0,0 +1,114 @@
+From df089e178da0918dc74a8572a99324b0987bce30 Mon Sep 17 00:00:00 2001
+Message-Id: <df089e178da0918dc74a8572a99324b0987bce30.1554983206.git.pmatilai@redhat.com>
+In-Reply-To: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
+References: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Mon, 18 Mar 2019 15:56:34 +0200
+Subject: [PATCH 3/3] Verify packages before signing (RhBug:1646388)
+
+Permitting corrupted packages to be signed is bad business for everybody
+involved, this is something we should've always done. Besides being an
+actual security risk, it can lead to odd results with verification
+especially with the payload digest on signed packages.
+
+One point worth noting is that this means that pre 4.14-packages cannot
+be signed in FIPS mode now because there's no way to validate the package
+payload range due to MD5 being disabled. This seems like a feature and
+not a limitation, so disabler for the verify step intentionally left out.
+
+Optimally we'd verify the package on the same read that's passed
+to gpg but for simplicitys sake that's left as an future exercise,
+now we simply read the package twice.
+---
+ sign/rpmgensig.c   | 32 ++++++++++++++++++++++++++++++++
+ tests/rpmsigdig.at | 20 ++++++++++++++++++++
+ 2 files changed, 52 insertions(+)
+
+diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
+index 2bcbab768..5be542001 100644
+--- a/sign/rpmgensig.c
++++ b/sign/rpmgensig.c
+@@ -21,6 +21,7 @@
+ 
+ #include "lib/rpmlead.h"
+ #include "lib/signature.h"
++#include "lib/rpmvs.h"
+ #include "sign/rpmsignfiles.h"
+ 
+ #include "debug.h"
+@@ -489,6 +490,31 @@ static rpmRC includeFileSignatures(Header *sigp, Header *hdrp)
+ #endif
+ }
+ 
++static int msgCb(struct rpmsinfo_s *sinfo, void *cbdata)
++{
++    char **msg = cbdata;
++    if (sinfo->rc && *msg == NULL)
++	*msg = rpmsinfoMsg(sinfo);
++    return (sinfo->rc != RPMRC_FAIL);
++}
++
++/* Require valid digests on entire package for signing. */
++static int checkPkg(FD_t fd, char **msg)
++{
++    int rc;
++    struct rpmvs_s *vs = rpmvsCreate(RPMSIG_DIGEST_TYPE, 0, NULL);
++    off_t offset = Ftell(fd);
++
++    Fseek(fd, 0, SEEK_SET);
++    rc = rpmpkgRead(vs, fd, NULL, NULL, msg);
++    if (!rc)
++	rc = rpmvsVerify(vs, RPMSIG_DIGEST_TYPE, msgCb, msg);
++    Fseek(fd, offset, SEEK_SET);
++
++    rpmvsFree(vs);
++    return rc;
++}
++
+ /** \ingroup rpmcli
+  * Create/modify elements in signature header.
+  * @param rpm		path to package
+@@ -519,6 +545,12 @@ static int rpmSign(const char *rpm, int deleting, int signfiles)
+     if (manageFile(&fd, rpm, O_RDWR))
+ 	goto exit;
+ 
++    /* Ensure package is intact before attempting to sign */
++    if ((rc = checkPkg(fd, &msg))) {
++	rpmlog(RPMLOG_ERR, "not signing corrupt package %s: %s\n", rpm, msg);
++	goto exit;
++    }
++
+     if ((rc = rpmLeadRead(fd, &msg)) != RPMRC_OK) {
+ 	rpmlog(RPMLOG_ERR, "%s: %s\n", rpm, msg);
+ 	goto exit;
+diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
+index 413c3d2c8..e93420306 100644
+--- a/tests/rpmsigdig.at
++++ b/tests/rpmsigdig.at
+@@ -472,3 +472,23 @@ run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64-sign
+ [],
+ [])
+ AT_CLEANUP
++
++AT_SETUP([rpmsign --addsign <corrupted>])
++AT_KEYWORDS([rpmsign signature])
++AT_CHECK([
++RPMDB_CLEAR
++RPMDB_INIT
++rm -rf "${TOPDIR}"
++
++pkg="hello-2.0-1.x86_64.rpm"
++cp "${RPMTEST}"/data/RPMS/${pkg} "${RPMTEST}"/tmp/${pkg}
++dd if=/dev/zero of="${RPMTEST}"/tmp/${pkg} \
++   conv=notrunc bs=1 seek=333 count=4 2> /dev/null
++run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}/tmp/${pkg}"
++],
++[1],
++[/home/pmatilai/repos/rpm/tests/testing/tmp/hello-2.0-1.x86_64.rpm:
++],
++[error: not signing corrupt package /home/pmatilai/repos/rpm/tests/testing/tmp/hello-2.0-1.x86_64.rpm: MD5 digest: BAD (Expected 007ca1d8b35cca02a1854ba301c5432e != 137ca1d8b35cca02a1854ba301c5432e)
++])
++AT_CLEANUP
+-- 
+2.20.1
+
diff --git a/SOURCES/rpm-4.14.2-unversioned-python.patch b/SOURCES/rpm-4.14.2-unversioned-python.patch
new file mode 100644
index 0000000..7e9ba8d
--- /dev/null
+++ b/SOURCES/rpm-4.14.2-unversioned-python.patch
@@ -0,0 +1,12 @@
+diff -up rpm-4.14.2/macros.in.pyerror rpm-4.14.2/macros.in
+--- rpm-4.14.2/macros.in.pyerror	2019-06-04 13:33:48.450727270 +0300
++++ rpm-4.14.2/macros.in	2019-06-04 13:34:09.717695822 +0300
+@@ -50,7 +50,7 @@
+ %__mv			@__MV@
+ %__patch		@__PATCH@
+ %__perl			@__PERL@
+-%__python		@__PYTHON@
++%__python		%{error:attempt to use unversioned python, define %%__python to %{_bindir}/python2 or %{_bindir}/python3 explicitly}
+ %__restorecon		@__RESTORECON@
+ %__rm			@__RM@
+ %__rsh			@__RSH@
diff --git a/SPECS/rpm.spec b/SPECS/rpm.spec
index d5455fe..9675ce1 100644
--- a/SPECS/rpm.spec
+++ b/SPECS/rpm.spec
@@ -30,7 +30,7 @@
 
 %global rpmver 4.14.2
 #global snapver rc2
-%global rel 11
+%global rel 25
 
 %global srcver %{version}%{?snapver:-%{snapver}}
 %global srcdir %{?snapver:testing}%{!?snapver:%{name}-%(echo %{version} | cut -d'.' -f1-2).x}
@@ -77,8 +77,35 @@ Patch101: rpm-4.14.2-RPMTAG_MODULARITYLABEL.patch
 Patch102: 0001-Document-noverify-in-the-man-page-RhBug-1646458.patch
 Patch103: 0001-Handle-unsupported-digests-the-same-as-disabled-ones.patch
 Patch104: 0001-Mark-elements-with-associated-problems-as-failed.patch
-Patch105: 0001-Fix-packages-getting-erased-on-failed-update-with-dn.patch
-Patch106: 0001-Fix-off-by-one-in-hdrblobGet-making-last-entry-unrea.patch
+Patch105: 0001-Fix-ancient-python-GIL-locking-bug-on-callback-RhBug.patch
+Patch106: 0001-Fix-testing-for-wrong-variable-in-selinux-plugin-deb.patch
+Patch107: 0001-Log-RPMLOG_ERR-level-messages-on-actual-errors-in-se.patch
+Patch108: 0001-Only-read-through-payload-on-verify-if-actually-need.patch
+Patch109: 0001-Make-rpmsign-exit-values-more-consistent-with-our-ot.patch
+Patch110: 0002-Drop-internal-only-visibility-on-rpmvs-related-API.patch
+Patch111: 0003-Verify-packages-before-signing-RhBug-1646388.patch
+Patch112: 0001-Fix-FA_TOUCH-on-files-with-suid-sgid-bits-and-or-cap.patch
+Patch113: 0001-Sort-list-of-hard-linked-files-in-find-debuginfo.sh-.patch
+Patch114: 0001-Correct-rpm-ql-exit-value-when-optional-p-is-omitted.patch
+Patch115: 0001-Show-list-of-files-only-once-when-use-rpm-ql-and-mul.patch
+Patch116: 0001-Add-flag-to-use-strip-g-instead-of-full-strip-on-DSO.patch
+Patch117: 0001-Fix-segfault-on-fingerprinting-symlink-round-RhBug-1.patch
+Patch118: 0001-Fix-packages-getting-erased-on-failed-update-with-dn.patch
+Patch119: 0001-Use-in-condition-to-avoid-sub-processes-in-find-debu.patch
+Patch120: 0001-rpmsign-man-page-Add-line-about-rpmsign-requiring-a-.patch
+Patch121: 0001-Use-dpbath-only-with-full-path-RhBug-1696408.patch
+Patch122: 0001-Fix-a-blindingly-obvious-memleak-in-package-verify-s.patch
+Patch123: 0001-Fix-rpmfiles-memory-leak-on-postuntrans-file-trigger.patch
+Patch124: 0001-Fully-shutdown-DBUS-on-systemd_inhibit-cleanup-RhBug.patch
+Patch125: 0001-Remove-capabilities-instead-of-setting-empty-caps-vi.patch
+Patch126: 0001-Fix-off-by-one-in-hdrblobGet-making-last-entry-unrea.patch
+Patch127: 0001-Fix-memleak-during-transaction-verify-step-in-the-NO.patch
+
+# Python 3 string API sanity
+Patch500: 0001-In-Python-3-return-all-our-string-data-as-surrogate-.patch
+Patch501: 0001-Return-NULL-string-as-None-from-utf8FromString.patch
+# Temporary compat crutch, not upstream
+Patch502: 0001-Monkey-patch-.decode-method-to-our-strings-as-a-temp.patch
 
 # These are not yet upstream
 # Audit support
@@ -96,6 +123,8 @@ Patch1000: disable-python-extra.patch
 # Compile Python 3.6 stuff with /usr/libexec/platform-python instead of
 # /usr/bin/python3.6
 Patch1001: compile-with-Platform-Python-binary-where-relevant.patch
+# make unversioned %%__python an error unless explicitly overridden
+Patch1002: rpm-4.14.2-unversioned-python.patch
 
 # Partially GPL/LGPL dual-licensed and some bits with BSD
 # SourceLicense: (GPLv2+ and LGPLv2+ with exceptions) and BSD 
@@ -618,11 +647,60 @@ make check || cat tests/rpmtests.log
 %doc doc/librpm/html/*
 
 %changelog
-* Fri Aug 16 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-11
-- Fix off-by-one in hdrblobGet() breaking large package verification (#1736821)
+* Wed Aug 07 2019 Florian Festi <ffesti@redhat.com> - 4.14.2-25
+- Fix memory leak in verify code (#1714657)
 
-* Wed Jun 12 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-10
-- Fix packages getting removed on failed update via dnf (#1718236)
+* Wed Jul 31 2019 Florian Festi <ffesti@redhat.com> - 4.14.2-24
+- Fix off-by-one in hdrblobGet() breaking large packages (#1722921)
+
+* Thu Jul 25 2019 Florian Festi <ffesti@redhat.com> - 4.14.2-23
+- Use --dpbath only with full path (#1696408)
+- Fix memory leaks (#1714657)
+- Remove capabilities instead of setting empty caps via. --setcaps (#1700920)
+- Fix bash warning from solution for #1689810
+
+* Thu Jul 18 2019 Florian Festi <ffesti@redhat.com> - 4.14.2-22
+- Add information about FIPS mode to rpmsign man page (#1726678)
+
+* Wed Jul 03 2019 Florian Festi <ffesti@redhat.com> - 4.14.2-21
+- Fix bash warning from solution for #1689810
+
+* Thu Jun 06 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-20
+- Fix packages getting removed on failed update via dnf (#1710346)
+
+* Tue Jun 04 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-19
+- Fix rare segfault in fingerprinting symlink round (#1660232)
+
+* Tue Jun 04 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-18
+- Make use of unversioned %%__python macro an error (#1645663)
+
+* Wed Apr 24 2019 Florian Festi <ffesti@redhat.com> - 4.14.2-17
+- Add flag to use strip -g instead of full strip on DSOs (#1689810)
+
+* Wed Apr 24 2019 Florian Festi <ffesti@redhat.com> - 4.14.2-16
+- Sort list of hard linked files in find-debuginfo.sh (#1421272)
+- Correct rpm -ql exit value when optional -p is omitted (#1680610)
+- Show list of files only once when use rpm -ql and multiple rpm files (#1689898)
+
+* Fri Apr 12 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-15
+- Fix %_minimize_writes stripping suid/sgid bits and capabilities (#1690876)
+
+* Thu Apr 11 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-14
+- Verify packages before signing (#1646388)
+- Make rpmsign exist values more consistent with our other tools
+
+* Thu Apr 11 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-13
+- Report meaningful errors from SElinux plugin (#1679028)
+
+* Thu Apr 11 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-12
+- Fix an ancient GIL locking bug, required for the .decode() trick
+
+* Thu Apr 11 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-11
+- Revised patch for Py3 string data as surrogate-escaped utf-8 (#1631292)
+- Add a .decode() method to returned Py3 strings for compatibility
+
+* Wed Mar 06 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-10
+- Return all string data as surrogate-escaped utf-8 in Python 3 (#1631292)
 
 * Thu Dec 20 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-9
 - Mark elements with associated problems as failed (needed for audit)