diff --git a/SOURCES/BZ-1194915-add-logging-for-bad-notice-dupes.patch b/SOURCES/BZ-1194915-add-logging-for-bad-notice-dupes.patch
new file mode 100644
index 0000000..3505e21
--- /dev/null
+++ b/SOURCES/BZ-1194915-add-logging-for-bad-notice-dupes.patch
@@ -0,0 +1,84 @@
+diff -up yum-3.4.3/yum/update_md.py.org yum-3.4.3/yum/update_md.py
+--- yum-3.4.3/yum/update_md.py.org	2017-01-24 18:55:03.529842775 +0100
++++ yum-3.4.3/yum/update_md.py	2017-01-24 18:55:57.213511475 +0100
+@@ -58,7 +58,7 @@ class UpdateNotice(object):
+     A single update notice (for instance, a security fix).
+     """
+ 
+-    def __init__(self, elem=None):
++    def __init__(self, elem=None, repoid=None, vlogger=None):
+         self._md = {
+             'from'             : '',
+             'type'             : '',
+@@ -83,6 +83,9 @@ class UpdateNotice(object):
+         if elem:
+             self._parse(elem)
+ 
++        self._repoid = repoid
++        self._vlogger = vlogger
++
+     def __getitem__(self, item):
+         """ Allows scriptable metadata access (ie: un['update_id']). """
+         if type(item) is int:
+@@ -103,6 +106,24 @@ class UpdateNotice(object):
+         #  Tests to see if it's "the same data", which means that the
+         # packages can be different (see add_notice).
+ 
++        def _rid(un):
++            if hasattr(un, '_repoid') and un._repoid is not None:
++                return un._repoid
++            else:
++                return '<unknown>'
++
++        def _log_failure(data):
++            """Log the mismatched data similarly to conflict markers in git."""
++            if self._vlogger is None:
++                return
++            msg = _('Duplicate of %s differs in some fields:\n')
++            msg %= other._md['update_id']
++            msg += '<<<<<<< %s:%s\n' % (_rid(other), data)
++            msg += '%r\n=======\n%r\n' % (other._md[data], self._md[data])
++            msg += '>>>>>>> %s:%s' % (_rid(self), data)
++            # --verbose mode enables this
++            self._vlogger.log(logginglevels.DEBUG_3, msg)
++
+         if not other or not hasattr(other, '_md'):
+             return False
+ 
+@@ -113,6 +134,7 @@ class UpdateNotice(object):
+             if data == 'status': # FIXME: See below...
+                 continue
+             if self._md[data] != other._md[data]:
++                _log_failure(data)
+                 return False
+         # FIXME: Massive hack, Fedora is really broken and gives status=stable
+         # and status=testing for updateinfo notices, just depending on which
+@@ -120,8 +142,10 @@ class UpdateNotice(object):
+         data = 'status'
+         if self._md[data] != other._md[data]:
+             if self._md[data]  not in ('stable', 'testing'):
++                _log_failure(data)
+                 return False
+             if other._md[data] not in ('stable', 'testing'):
++                _log_failure(data)
+                 return False
+             # They are both really "stable" ...
+             self._md[data]  = 'stable'
+@@ -574,7 +598,7 @@ class UpdateMetadata(object):
+         for event, elem in safe_iterparse(infile, logger=self._logger):
+             if elem.tag == 'update':
+                 try:
+-                    un = UpdateNotice(elem)
++                    un = UpdateNotice(elem, repoid, self._vlogger)
+                 except UpdateNoticeException, e:
+                     msg = _("An update notice%s is broken, skipping.") % _rid(repoid)
+                     if self._vlogger:
+@@ -587,6 +611,8 @@ class UpdateMetadata(object):
+                     msg = _("Update notice %s%s is broken, or a bad duplicate, skipping.") % (un['update_id'], _rid(repoid))
+                     if not have_dup:
+                         msg += _('\nYou should report this problem to the owner of the %srepository.') % _rid(repoid, "%s ")
++                        msg += _('\nIf you are the owner, consider re-running the same command with --verbose to see the '
++                                 'exact data that caused the conflict.')
+                     have_dup = True
+                     if self._vlogger:
+                         self._vlogger.warn("%s", msg)
diff --git a/SOURCES/BZ-1343690-add-payload-gpgcheck-opt.patch b/SOURCES/BZ-1343690-add-payload-gpgcheck-opt.patch
new file mode 100644
index 0000000..025cc20
--- /dev/null
+++ b/SOURCES/BZ-1343690-add-payload-gpgcheck-opt.patch
@@ -0,0 +1,129 @@
+diff -up yum-3.4.3/docs/yum.conf.5.orig yum-3.4.3/docs/yum.conf.5
+--- yum-3.4.3/docs/yum.conf.5.orig	2017-03-23 13:48:19.700471026 +0100
++++ yum-3.4.3/docs/yum.conf.5	2017-03-23 13:48:21.455461060 +0100
+@@ -105,6 +105,31 @@ signature check on the repodata. When th
+ default for all repositories. The default is `0'.
+ 
+ .IP
++\fBpayload_gpgcheck\fR
++Either `1' or `0'. This tells yum whether or not it should also perform a GPG
++signature check on the payload (part of a package holding the actual files that
++comprise the package).
++
++By default, yum only performs GPG signature checks on package headers.
++Thus, if the payload data has been tampered with or corrupted, yum will fail in
++the middle of the transaction due to an RPM unpacking error, after some
++unverified scriptlets might have already run, and possibly leave the package in
++question partly installed.
++
++To prevent all of that, you can enable this option to extend the signature
++check to also include the payload, so that yum can avoid running the
++transaction in case of payload corruption.
++This slightly improves security, however at the expense of significantly
++increased transaction time, so you may want to only use this option when
++package corruption is a concern.
++
++For this option to have effect, make sure to also enable gpgcheck (or
++localpkg_gpgcheck for local packages).
++
++When this option is set in the [main] section it sets the default for all
++repositories. The default is `0'.
++
++.IP
+ \fBskip_broken\fR
+ Either `1' or `0'. Resolve depsolve problems by removing packages that
+ are causing problems from the transaction.
+diff -up yum-3.4.3/rpmUtils/miscutils.py.orig yum-3.4.3/rpmUtils/miscutils.py
+--- yum-3.4.3/rpmUtils/miscutils.py.orig	2011-06-28 22:27:22.000000000 +0200
++++ yum-3.4.3/rpmUtils/miscutils.py	2017-03-23 13:48:21.455461060 +0100
+@@ -58,11 +58,16 @@ def compareVerOnly(v1, v2):
+     """compare version strings only using rpm vercmp"""
+     return compareEVR(('', v1, ''), ('', v2, ''))
+     
+-def checkSig(ts, package):
+-    """Takes a transaction set and a package, check it's sigs, 
++def checkSig(ts, package, payload=False):
++    """Takes a transaction set and a package, check it's sigs.
++
++    By default, only RPMv4 sigs (header-only) will be verified (faster).  By
++    setting payload to True, RPMv3 sigs (header+payload) will also be verified
++    (slower).
++
+     return 0 if they are all fine
+     return 1 if the gpg key can't be found
+-    return 2 if the header is in someway damaged
++    return 2 if the header or payload is in someway damaged
+     return 3 if the key is not trusted 
+     return 4 if the pkg is not gpg or pgp signed"""
+     
+@@ -89,6 +94,24 @@ def checkSig(ts, package):
+         else:
+             del hdr
+ 
++    # Don't perform the payload check if the header check failed, otherwise we
++    # could mask the reason stored in "value" (we only return one integer from
++    # this function and shouldn't change that).
++    if payload and value == 0:
++        os.lseek(fdno, 0, 0)
++        # We don't want the OK message to pollute the output but we do want the
++        # BAD message (verbose version) in case of a failure, which is only
++        # possible by running _verifySigs() twice (temporary hack until we have
++        # the proper API for payload verification in RPM).
++        rpm.setVerbosity(rpm.RPMLOG_WARNING)
++        valid = ts._verifySigs(fdno, package)
++        if not valid:
++            value = 2
++            os.lseek(fdno, 0, 0)
++            rpm.setVerbosity(rpm.RPMLOG_INFO)
++            ts._verifySigs(fdno, package)
++        rpm.setVerbosity(rpm.RPMLOG_NOTICE)
++
+     try:
+         os.close(fdno)
+     except OSError, e: # if we're not opened, don't scream about it
+diff -up yum-3.4.3/rpmUtils/transaction.py.orig yum-3.4.3/rpmUtils/transaction.py
+--- yum-3.4.3/rpmUtils/transaction.py.orig	2017-03-23 13:48:19.441472497 +0100
++++ yum-3.4.3/rpmUtils/transaction.py	2017-03-23 13:48:21.455461060 +0100
+@@ -35,7 +35,8 @@ class TransactionWrapper:
+                          'setProbFilter',
+                          'hdrFromFdno',
+                          'next',
+-                         'clean']
++                         'clean',
++                         '_verifySigs']
+         self.tsflags = []
+         self.open = True
+ 
+diff -up yum-3.4.3/yum/config.py.orig yum-3.4.3/yum/config.py
+--- yum-3.4.3/yum/config.py.orig	2017-03-23 13:48:19.701471020 +0100
++++ yum-3.4.3/yum/config.py	2017-03-23 13:48:21.456461055 +0100
+@@ -46,6 +46,7 @@ from misc import get_uuid, read_in_items
+ # Alter/patch these to change the default checking...
+ __pkgs_gpgcheck_default__ = False
+ __repo_gpgcheck_default__ = False
++__payload_gpgcheck_default__ = False
+ __main_multilib_policy_default__ = 'all'
+ __main_failovermethod_default__ = 'roundrobin'
+ __main_installonly_limit_default__ = 0
+@@ -786,6 +787,7 @@ class YumConf(StartupConf):
+     gpgcheck = BoolOption(__pkgs_gpgcheck_default__)
+     repo_gpgcheck = BoolOption(__repo_gpgcheck_default__)
+     localpkg_gpgcheck = BoolOption(__pkgs_gpgcheck_default__)
++    payload_gpgcheck = BoolOption(__payload_gpgcheck_default__)
+     obsoletes = BoolOption(True)
+     showdupesfromrepos = BoolOption(False)
+     enabled = BoolOption(True)
+diff -up yum-3.4.3/yum/__init__.py.orig yum-3.4.3/yum/__init__.py
+--- yum-3.4.3/yum/__init__.py.orig	2017-03-23 13:48:19.731470850 +0100
++++ yum-3.4.3/yum/__init__.py	2017-03-23 13:48:21.456461055 +0100
+@@ -2755,7 +2755,9 @@ much more problems).
+         
+         if check:
+             ts = self.rpmdb.readOnlyTS()
+-            sigresult = rpmUtils.miscutils.checkSig(ts, po.localPkg())
++            sigresult = rpmUtils.miscutils.checkSig(
++                ts, po.localPkg(), payload=self.conf.payload_gpgcheck,
++            )
+             localfn = os.path.basename(po.localPkg())
+             
+             if sigresult == 0:
diff --git a/SOURCES/BZ-1352585-detect-installed-provide.patch b/SOURCES/BZ-1352585-detect-installed-provide.patch
new file mode 100644
index 0000000..42a1272
--- /dev/null
+++ b/SOURCES/BZ-1352585-detect-installed-provide.patch
@@ -0,0 +1,48 @@
+commit ed2a41fe646a1dcfc4f216f8babf25f93fde40e3
+Author: Michal Domonkos <mdomonko@redhat.com>
+Date:   Fri Feb 3 18:24:37 2017 +0100
+
+    Detect installed virtual provide in install(). BZ 1352585
+    
+    Normally, when the user tries to install something that's already
+    installed, we exit gracefully with 0.  However, that's not the case if
+    what we're looking for is a provide that, despite being installed, is
+    not available in any of the enabled repos, in which case we error out.
+    This commit makes sure we exit gracefully in that case too.
+    
+    The old code path for "yum install foo" looks like this:
+    
+    1) Look for foo in pkgSack
+    2) If no success, look for a package in pkgSack providing foo
+    3) If no success, look for foo in rpmdb
+    4) If no success, error out with "No package foo available." and exit
+       code 1
+    
+    What we're adding with this commit is the following in between 3 and 4:
+    
+    - If no success, look for a package in rpmdb providing foo
+    
+    Note that we only search for the provide in pkgSack if the kwarg
+    'pattern' is set, so let's adhere to this with the newly added rpmdb
+    search too.
+
+diff --git a/yum/__init__.py b/yum/__init__.py
+index 9780d96..451b2b8 100644
+--- a/yum/__init__.py
++++ b/yum/__init__.py
+@@ -4910,8 +4910,14 @@ much more problems).
+             # Do we still want to return errors here?
+             # We don't in the cases below, so I didn't here...
+             if 'pattern' in kwargs:
+-                pkgs = self.rpmdb.returnPackages(patterns=[kwargs['pattern']],
++                arg = kwargs['pattern']
++                pkgs = self.rpmdb.returnPackages(patterns=[arg],
+                                                  ignore_case=False)
++                if not pkgs:
++                    self.verbose_logger.debug(
++                        _('Checking for installed virtual provide or file-provide for %s'),
++                        arg)
++                    pkgs = self.returnInstalledPackagesByDep(arg)
+             if 'name' in kwargs:
+                 pkgs = self.rpmdb.searchNevra(name=kwargs['name'])
+             if 'pkgtup' in kwargs:
diff --git a/SOURCES/BZ-1357083-clean-all-add-hint-rm-rf.patch b/SOURCES/BZ-1357083-clean-all-add-hint-rm-rf.patch
new file mode 100644
index 0000000..f0938b9
--- /dev/null
+++ b/SOURCES/BZ-1357083-clean-all-add-hint-rm-rf.patch
@@ -0,0 +1,34 @@
+commit 01a6780fd310cbf0027e98fad97aca324f952196
+Author: Michal Domonkos <mdomonko@redhat.com>
+Date:   Thu Mar 9 14:02:25 2017 +0100
+
+    Add hint about rm -rf for yum clean all. BZ 1357083
+
+diff --git a/cli.py b/cli.py
+index 862992b..5f7c4ae 100755
+--- a/cli.py
++++ b/cli.py
+@@ -1718,6 +1718,23 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+         if 'all' in userlist:
+             self.verbose_logger.log(yum.logginglevels.INFO_2,
+                 _('Cleaning up everything'))
++
++            # Print a "maybe you want rm -rf" hint to compensate for the fact
++            # that yum clean all is often misunderstood.  Don't do that,
++            # however, if cachedir is non-default as we would have to replace
++            # arbitrary yum vars with * and that could produce a harmful
++            # command, e.g. for /mydata/$myvar we would say rm -rf /mydata/*
++            cachedir = self.conf.cachedir
++            if cachedir.startswith(('/var/cache/yum', '/var/tmp/yum-')):
++                # Take just the first 3 path components
++                rmdir = '/'.join(cachedir.split('/')[:4])
++                self.verbose_logger.log(
++                    yum.logginglevels.INFO_2,
++                    _('Maybe you want: rm -rf %s, to also free up space taken '
++                      'by orphaned data from disabled or removed repos'
++                      % rmdir),
++                )
++
+             pkgcode, pkgresults = self.cleanPackages()
+             hdrcode, hdrresults = self.cleanHeaders()
+             xmlcode, xmlresults = self.cleanMetadata()
diff --git a/SOURCES/BZ-1369389-dont-recommend-makecache-if-running.patch b/SOURCES/BZ-1369389-dont-recommend-makecache-if-running.patch
new file mode 100644
index 0000000..23d84a6
--- /dev/null
+++ b/SOURCES/BZ-1369389-dont-recommend-makecache-if-running.patch
@@ -0,0 +1,98 @@
+commit 79591f49db4faec56a846ddf16a77004b8579ee7
+Author: Michal Domonkos <mdomonko@redhat.com>
+Date:   Thu Dec 15 16:23:10 2016 +0100
+
+    Don't recommend makecache if just running. BZ 1369389
+    
+    Also includes any other commands that would result in all repos obeying
+    metadata_expire such as "yum install" (depending on the actual value of
+    metadata_expire_filter).
+
+diff --git a/cli.py b/cli.py
+index 54a2e81..862992b 100755
+--- a/cli.py
++++ b/cli.py
+@@ -450,11 +450,21 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+ 
+         if not ts_min:
+             cacheReq = 'write'
+-        elif warning and (time.time() - ts_max) > (60 * 60 * 24 * 14):
+-            self.logger.warning(_("Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast"))
+ 
++        all_obey = True
+         for repo in self.repos.sort():
+             repo._metadata_cache_req = cacheReq
++            if repo._matchExpireFilter():
++                all_obey = False
++
++        if warning and ts_min and (time.time() - ts_max) > (60 * 60 * 24 * 14):
++            # The warning makes no sense if we're already running a command
++            # that requires current repodata across all repos (such as "yum
++            # makecache" or others, depending on metadata_expire_filter), so
++            # don't give it if that's the case.
++            if all_obey:
++                return
++            self.logger.warning(_("Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast"))
+ 
+     def _shell_history_write(self):
+         if not hasattr(self, '_shell_history_cmds'):
+diff --git a/yum/yumRepo.py b/yum/yumRepo.py
+index c6bed82..0c63de3 100644
+--- a/yum/yumRepo.py
++++ b/yum/yumRepo.py
+@@ -1145,33 +1145,39 @@ Insufficient space in download directory %s
+             self._metadataCurrent = False
+         return self._metadataCurrent
+ 
+-    def withinCacheAge(self, myfile, expiration_time, expire_req_filter=True):
+-        """check if any file is older than a certain amount of time. Used for
+-           the cachecookie and the mirrorlist
+-           return True if w/i the expiration time limit
+-           false if the time limit has expired
+-
+-           Additionally compare the file to age of the newest .repo or yum.conf
+-           file. If any of them are newer then invalidate the cache
+-           """
+-
++    def _matchExpireFilter(self):
++        """Return whether cache_req matches metadata_expire_filter."""
+         # Never/write means we just skip this...
+-        if (expire_req_filter and hasattr(self, '_metadata_cache_req') and
+-            self._metadata_cache_req.startswith("read-only:") and
+-            self.metadata_expire_filter.startswith("read-only:")):
++        if (hasattr(self, '_metadata_cache_req') and
++                self._metadata_cache_req.startswith("read-only:") and
++                self.metadata_expire_filter.startswith("read-only:")):
+ 
+             cache_filt = self.metadata_expire_filter[len("read-only:"):]
+             cache_req  = self._metadata_cache_req[len("read-only:"):]
+ 
+             if cache_filt == 'future':
+                 assert cache_req in ('past', 'present', 'future')
+-                expiration_time = -1
++                return True
+             if cache_filt == 'present':
+                 if cache_req in ('past', 'present'):
+-                    expiration_time = -1
++                    return True
+             if cache_filt == 'past':
+                 if cache_req == 'past':
+-                    expiration_time = -1
++                    return True
++        return False
++
++    def withinCacheAge(self, myfile, expiration_time, expire_req_filter=True):
++        """check if any file is older than a certain amount of time. Used for
++           the cachecookie and the mirrorlist
++           return True if w/i the expiration time limit
++           false if the time limit has expired
++
++           Additionally compare the file to age of the newest .repo or yum.conf
++           file. If any of them are newer then invalidate the cache
++           """
++
++        if expire_req_filter and self._matchExpireFilter():
++            expiration_time = -1
+ 
+         # -1 is special and should never get refreshed
+         if expiration_time == -1 and os.path.exists(myfile):
diff --git a/SOURCES/BZ-1370134-yum-check-ignore-self-conflicts.patch b/SOURCES/BZ-1370134-yum-check-ignore-self-conflicts.patch
new file mode 100644
index 0000000..86b9470
--- /dev/null
+++ b/SOURCES/BZ-1370134-yum-check-ignore-self-conflicts.patch
@@ -0,0 +1,26 @@
+commit 1ff69afbb78e9303a0d9859d941371eaedbb6842
+Author: James Antill <james@and.org>
+Date:   Mon Sep 22 16:22:42 2014 -0400
+
+    Have "yum check" ignore self conflicts.
+
+diff --git a/yum/rpmsack.py b/yum/rpmsack.py
+index 2d718c1..229e1a1 100644
+--- a/yum/rpmsack.py
++++ b/yum/rpmsack.py
+@@ -1576,6 +1576,15 @@ class RPMDBPackageSack(PackageSackBase):
+ 
+                 (req, flags, ver) = creq
+                 res = self.getProvides(req, flags, ver)
++
++                # Filter this pkg out, as self conflicts are allowed.
++                nres = {}
++                for conflicting_po in res:
++                    if conflicting_po.pkgtup[0] == pkg.pkgtup[0] and conflicting_po.pkgtup[2:] == pkg.pkgtup[2:]:
++                        continue
++                    nres[conflicting_po] = res[conflicting_po]
++                res = nres
++
+                 if not res:
+                     continue
+                 flags = yum.depsolve.flags.get(flags, flags)
diff --git a/SOURCES/BZ-1389816-include-repoid-in-timestamp-error.patch b/SOURCES/BZ-1389816-include-repoid-in-timestamp-error.patch
new file mode 100644
index 0000000..7dd6ad8
--- /dev/null
+++ b/SOURCES/BZ-1389816-include-repoid-in-timestamp-error.patch
@@ -0,0 +1,24 @@
+commit 5a836edd592fc0adf2e1bb3883387e48cf77f548
+Author: Michal Domonkos <mdomonko@redhat.com>
+Date:   Mon Jan 2 12:40:46 2017 +0100
+
+    Include repo-id in repomd.xml timestamp error. BZ 1389816
+
+diff --git a/yum/yumRepo.py b/yum/yumRepo.py
+index c6bed82..419545d 100644
+--- a/yum/yumRepo.py
++++ b/yum/yumRepo.py
+@@ -1378,10 +1378,11 @@ Insufficient space in download directory %s
+ 
+         if (self.timestamp_check and
+             old_repo_XML.timestamp > self.repoXML.timestamp):
+-            logger.warning("Not using downloaded repomd.xml because it is "
++            logger.warning("Not using downloaded %s/repomd.xml because it is "
+                            "older than what we have:\n"
+                            "  Current   : %s\n  Downloaded: %s" %
+-                           (time.ctime(old_repo_XML.timestamp),
++                           (self.id,
++                            time.ctime(old_repo_XML.timestamp),
+                             time.ctime(self.repoXML.timestamp)))
+             return False
+         return True
diff --git a/SOURCES/BZ-1391507-fix-filelist-queries-for-dup-pkgs.patch b/SOURCES/BZ-1391507-fix-filelist-queries-for-dup-pkgs.patch
new file mode 100644
index 0000000..90f8c66
--- /dev/null
+++ b/SOURCES/BZ-1391507-fix-filelist-queries-for-dup-pkgs.patch
@@ -0,0 +1,69 @@
+diff -up yum-3.4.3/yum/sqlitesack.py.orig yum-3.4.3/yum/sqlitesack.py
+--- yum-3.4.3/yum/sqlitesack.py.orig	2017-02-08 18:13:03.646086042 +0100
++++ yum-3.4.3/yum/sqlitesack.py	2017-02-08 18:13:16.270073910 +0100
+@@ -173,6 +173,21 @@ def _excluder_match(excluder, match, reg
+ 
+     return False
+ 
++def _deduplicate(cur, field):
++    """Eliminate duplicate rows from cursor based on field.
++
++    Assuming the result set can be divided into one or more equivalent groups
++    of rows based on the given field, this wrapper will yield rows from only
++    one of the groups, avoiding duplicates.
++    """
++    first_val = None
++    for ob in cur:
++        if first_val is None:
++            first_val = ob[field]
++        elif ob[field] != first_val:
++            continue
++        yield ob
++
+ 
+ class YumAvailablePackageSqlite(YumAvailablePackage, PackageObject, RpmBase):
+     def __init__(self, repo, db_obj):
+@@ -283,6 +298,14 @@ class YumAvailablePackageSqlite(YumAvail
+         setattr(self, varname, value)
+             
+         return value
++
++    # Note that we use pkgId instead of pkgKey to filter the files and
++    # changelog entries since we can't guarantee that pkgKeys in primarydb and
++    # filelistsdb are in sync (since self.pkgKey is obtained from primarydb).
++    #
++    # Also, because of that, we must make sure not to return duplicate entries
++    # in case we have some duplicate packages (i.e. same checksums), so we use
++    # _deduplicate().
+         
+     def _loadFiles(self):
+         if self._loadedfiles:
+@@ -293,10 +316,10 @@ class YumAvailablePackageSqlite(YumAvail
+         #FIXME - this should be try, excepting
+         self.sack.populate(self.repo, mdtype='filelists')
+         cur = self._sql_MD('filelists',
+-                           "SELECT dirname, filetypes, filenames " \
++                           "SELECT pkgKey, dirname, filetypes, filenames " \
+                            "FROM   filelist JOIN packages USING(pkgKey) " \
+                            "WHERE  packages.pkgId = ?", (self.pkgId,))
+-        for ob in cur:
++        for ob in _deduplicate(cur, 'pkgKey'):
+             dirname = ob['dirname']
+             if dirname == '.':
+                 dirname = ''
+@@ -323,13 +346,13 @@ class YumAvailablePackageSqlite(YumAvail
+                     self._changelog = result
+                     return
+             cur = self._sql_MD('other',
+-                               "SELECT date, author, changelog " \
++                               "SELECT pkgKey, date, author, changelog " \
+                                "FROM   changelog JOIN packages USING(pkgKey) " \
+                                "WHERE  pkgId = ? ORDER BY date DESC",
+                                (self.pkgId,))
+             # Check count(pkgId) here, the same way we do in searchFiles()?
+             # Failure mode is much less of a problem.
+-            for ob in cur:
++            for ob in _deduplicate(cur, 'pkgKey'):
+                 # Note: Atm. rpm only does days, where (60 * 60 * 24) == 86400
+                 #       and we have the hack in _dump_changelog() to keep the
+                 #       order the same, so this is a quick way to get rid of
diff --git a/SOURCES/BZ-1397829-fix-reget-simple-md-fnames.patch b/SOURCES/BZ-1397829-fix-reget-simple-md-fnames.patch
new file mode 100644
index 0000000..9d190b6
--- /dev/null
+++ b/SOURCES/BZ-1397829-fix-reget-simple-md-fnames.patch
@@ -0,0 +1,64 @@
+diff -up yum-3.4.3/yum/yumRepo.py.orig yum-3.4.3/yum/yumRepo.py
+--- yum-3.4.3/yum/yumRepo.py.orig	2017-03-10 14:16:36.769105433 +0100
++++ yum-3.4.3/yum/yumRepo.py	2017-03-10 14:16:39.457093071 +0100
+@@ -358,6 +358,7 @@ class YumRepository(Repository, config.R
+         # holder for stuff we've grabbed
+         self.retrieved = { 'primary':0, 'filelists':0, 'other':0, 'group':0,
+                            'updateinfo':0, 'prestodelta':0}
++        self._preloaded_repomd = False
+ 
+         # callbacks
+         self.callback = None  # for the grabber
+@@ -743,7 +744,8 @@ class YumRepository(Repository, config.R
+                 
+         # if we're using a cachedir that's not the system one, copy over these
+         # basic items from the system one
+-        self._preload_md_from_system_cache('repomd.xml')
++        if self._preload_md_from_system_cache('repomd.xml'):
++            self._preloaded_repomd = True
+         self._preload_md_from_system_cache('cachecookie')
+         self._preload_md_from_system_cache('mirrorlist.txt')
+         self._preload_md_from_system_cache('metalink.xml')
+@@ -1829,6 +1831,12 @@ Insufficient space in download directory
+             # got it, move along
+             return local
+ 
++        # Having preloaded the repomd means we should first try preloading this
++        # file as well (forcing it this way is only needed when dealing with
++        # simple filenames).
++        if self._preloaded_repomd:
++            misc.unlink_f(local)
++
+         if (os.path.exists(local) or
+             self._preload_md_from_system_cache(os.path.basename(local))):
+             if self._checkMD(local, mdtype, check_can_fail=True):
+@@ -1844,6 +1852,20 @@ Insufficient space in download directory
+                 msg = "Caching enabled but no local cache of %s from %s" % (local, self.ui_id)
+             raise Errors.RepoError, msg
+ 
++        # Given the file already exists, is it a partial download of thisdata
++        # that we can try to reget?  With unique filenames, that's always.
++        # With simple filenames, use the old expected checksum to verify
++        # (assuming the existing file or part represents the old data but it
++        # usually does).
++        partial = True
++        orepomd = self._oldRepoMDData.get('old_repo_XML')
++        if orepomd is not None:
++            odata = orepomd.repoData.get(mdtype)
++            if odata is not None:
++                ofname = os.path.basename(odata.location[1])
++                partial = (fname != ofname or
++                           thisdata.checksum == odata.checksum)
++
+         try:
+             def checkfunc(obj):
+                 try:
+@@ -1856,7 +1878,7 @@ Insufficient space in download directory
+                     raise
+                 self.retrieved[mdtype] = 1
+             text = "%s/%s" % (self.ui_id, mdtype)
+-            if thisdata.size is None:
++            if thisdata.size is None or not partial:
+                 reget = None
+             else:
+                 reget = 'simple'
diff --git a/SOURCES/BZ-1399628-updateinfo-fix-wrong-pkg-count.patch b/SOURCES/BZ-1399628-updateinfo-fix-wrong-pkg-count.patch
new file mode 100644
index 0000000..2094cca
--- /dev/null
+++ b/SOURCES/BZ-1399628-updateinfo-fix-wrong-pkg-count.patch
@@ -0,0 +1,76 @@
+commit 9474b6a7be57cd1c83da4a5db3fc0f48c61f6056
+Author: Valentina Mukhamedzhanova <vmukhame@redhat.com>
+Date:   Wed Oct 26 13:42:04 2016 +0200
+
+    Filter duplicate packages from different repos in doPackageLists(pkgnarrow='obsoletes').
+
+diff --git a/yum/__init__.py b/yum/__init__.py
+index 9e38320..9780d96 100644
+--- a/yum/__init__.py
++++ b/yum/__init__.py
+@@ -3109,9 +3109,13 @@ much more problems).
+                 pkgs = self.pkgSack.searchNevra(name=n, arch=a, ver=v, rel=r, epoch=e)
+                 pkgs = misc.filter_pkgs_repoid(pkgs, repoid)
+                 instpo = self.getInstalledPackageObject(instTup)
+-                for po in pkgs:
+-                    obsoletes.append(po)
+-                    obsoletesTuples.append((po, instpo))
++                if len(pkgs) > 1:
++                    self.verbose_logger.log(logginglevels.DEBUG_1,
++                        _('More than one identical match in sack for %s'),
++                        pkgs[0])
++                if len(pkgs) >= 1:
++                    obsoletes.append(pkgs[0])
++                    obsoletesTuples.append((pkgs[0], instpo))
+             if patterns:
+                 exactmatch, matched, unmatched = \
+                    parsePackages(obsoletes, patterns, casematch=not ignore_case)
+
+commit 400e248d3334d54fcf98d106d1cd84acae2e6e15
+Author: Valentina Mukhamedzhanova <vmukhame@redhat.com>
+Date:   Mon Oct 31 10:28:04 2016 +0100
+
+    Filter duplicates when counting security updates.
+
+diff --git a/yum/updateinfo.py b/yum/updateinfo.py
+index 5dcd7df..35e4c0f 100644
+--- a/yum/updateinfo.py
++++ b/yum/updateinfo.py
+@@ -456,8 +456,8 @@ def exclude_updates(base, filters=None):
+         for p in base.doPackageLists(pkgnarrow='available', patterns=pkgs_to_del, showdups=True).available:
+             ysp_del_pkg(p)
+ 
+-    cnt = len(base.doPackageLists(pkgnarrow='updates').updates) + \
+-          len(base.doPackageLists(pkgnarrow='obsoletes').obsoletes)
++    cnt = len(set(base.doPackageLists(pkgnarrow='updates').updates + \
++                  base.doPackageLists(pkgnarrow='obsoletes').obsoletes))
+ 
+     _ysp_chk_used_map(used_map, lambda x: base.verbose_logger.warn("%s", x))
+ 
+
+commit 02753215c8e28dbc75aacff678c33343d0539b33
+Author: Michal Domonkos <mdomonko@redhat.com>
+Date:   Wed Feb 15 16:51:57 2017 +0100
+
+    updateinfo: filter pkg dupes from total count. BZ 1399628
+    
+    This complements commit 400e248.
+
+diff --git a/yum/updateinfo.py b/yum/updateinfo.py
+index 35e4c0f..b6a42ea 100644
+--- a/yum/updateinfo.py
++++ b/yum/updateinfo.py
+@@ -436,11 +436,8 @@ def exclude_updates(base, filters=None):
+ 
+     used_map = _ysp_gen_used_map(opts)
+ 
+-    upds = base.doPackageLists(pkgnarrow='updates')
+-    tot = len(upds.updates)
+-    # In theory we don't need to do this in some cases, but meh.
+-    upds = base.doPackageLists(pkgnarrow='obsoletes')
+-    tot += len(upds.obsoletes)
++    tot = len(set(base.doPackageLists(pkgnarrow='updates').updates + \
++                  base.doPackageLists(pkgnarrow='obsoletes').obsoletes))
+ 
+     pkgs = base.pkgSack.returnPackages()
+     name2tup = _get_name2oldpkgtup(base)
diff --git a/SOURCES/BZ1410326-Fix-for-history-package-list.patch b/SOURCES/BZ1410326-Fix-for-history-package-list.patch
new file mode 100644
index 0000000..b607687
--- /dev/null
+++ b/SOURCES/BZ1410326-Fix-for-history-package-list.patch
@@ -0,0 +1,28 @@
+From 895f884671924f4c259911eb6d4a4207ab215596 Mon Sep 17 00:00:00 2001
+From: Amit Upadhye <upadhyeammit@gmail.com>
+Date: Wed, 4 Jan 2017 14:36:34 +0530
+Subject: [PATCH] Fix for 'history package-list'
+
+---
+ yum/history.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/yum/history.py b/yum/history.py
+index f1295de..5e2c035 100644
+--- a/yum/history.py
++++ b/yum/history.py
+@@ -1471,9 +1471,9 @@ class YumHistory:
+         params = list(pkgtupids)
+         tids = set()
+         if len(params) > yum.constants.PATTERNS_INDEXED_MAX:
+-            executeSQL(cur, """SELECT tid FROM trans_data_pkgs""")
++            executeSQL(cur, """SELECT tid,pkgtupid FROM trans_data_pkgs""")
+             for row in cur:
+-                if row[0] in params:
++                if row[1] in params:
+                     tids.add(row[0])
+             return tids
+         if not params:
+-- 
+2.4.11
+
diff --git a/SOURCES/centos-branding-yum.patch b/SOURCES/centos-branding-yum.patch
deleted file mode 100644
index 6cfdcbb..0000000
--- a/SOURCES/centos-branding-yum.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-diff -uNrp yum-3.4.3.orig/yum/constants.py yum-3.4.3/yum/constants.py
---- yum-3.4.3.orig/yum/constants.py	2015-12-03 09:06:24.365442687 -0600
-+++ yum-3.4.3/yum/constants.py	2015-12-03 09:17:09.268462350 -0600
-@@ -127,18 +127,18 @@ ERRORS_TO_KBASE_ARTICLES = {
- 
- https://access.redhat.com/articles/1320623
- 
--If above article doesn't help to resolve this issue please open a ticket with Red Hat Support.
-+If above article doesn't help to resolve this issue please create a bug on https://bugs.centos.org/
- """,
-     403: """To address this issue please refer to the below knowledge base article
- 
- https://access.redhat.com/solutions/69319
- 
--If above article doesn't help to resolve this issue please open a ticket with Red Hat Support.
-+If above article doesn't help to resolve this issue please create a bug on https://bugs.centos.org/
- """,
--    60: """It was impossible to connect to the Red Hat servers.
-+    60: """It was impossible to connect to the CentOS servers.
- This could mean a connectivity issue in your environment, such as the requirement to configure a proxy,
- or a transparent proxy that tampers with TLS security, or an incorrect system clock.
- Please collect information about the specific failure that occurs in your environment,
--using the instructions in: https://access.redhat.com/solutions/1527033 and open a ticket with Red Hat Support.
-+using the instructions in: https://access.redhat.com/solutions/1527033 and create a bug on https://bugs.centos.org/
- """
--}
-\ No newline at end of file
-+}
diff --git a/SOURCES/yum-distro-configs.patch b/SOURCES/yum-distro-configs.patch
index f014c7d..10a1ae3 100644
--- a/SOURCES/yum-distro-configs.patch
+++ b/SOURCES/yum-distro-configs.patch
@@ -1,10 +1,10 @@
-diff -ru yum-3.4.3-orig/yum/config.py yum-3.4.3/yum/config.py
---- yum-3.4.3-orig/yum/config.py	2011-12-02 15:45:41.617448597 -0500
-+++ yum-3.4.3/yum/config.py	2011-12-02 15:46:20.576285275 -0500
-@@ -49,14 +49,11 @@
- # Alter/patch these to change the default checking...
+diff -up yum-3.4.3/yum/config.py.orig yum-3.4.3/yum/config.py
+--- yum-3.4.3/yum/config.py.orig	2017-03-22 19:51:54.287816405 +0100
++++ yum-3.4.3/yum/config.py	2017-03-22 19:54:47.582779907 +0100
+@@ -47,14 +47,11 @@ from misc import get_uuid, read_in_items
  __pkgs_gpgcheck_default__ = False
  __repo_gpgcheck_default__ = False
+ __payload_gpgcheck_default__ = False
 -__main_multilib_policy_default__ = 'all'
 -__main_failovermethod_default__ = 'roundrobin'
 -__main_installonly_limit_default__ = 0
@@ -18,12 +18,13 @@ diff -ru yum-3.4.3-orig/yum/config.py yum-3.4.3/yum/config.py
 +__main_installonly_limit_default__ = 3
 +__group_command_default__ = 'objects'
 +__exactarchlist_default__ = []
-
+ 
  class Option(object):
      """
---- a/docs/yum.conf.5.orig	2010-06-21 17:39:17.000000000 -0400
-+++ b/docs/yum.conf.5	2010-09-14 12:11:40.897615896 -0400
-@@ -141,7 +141,7 @@
+diff -up yum-3.4.3/docs/yum.conf.5.orig yum-3.4.3/docs/yum.conf.5
+--- yum-3.4.3/docs/yum.conf.5.orig	2017-03-22 19:52:59.025429202 +0100
++++ yum-3.4.3/docs/yum.conf.5	2017-03-22 19:53:41.624174414 +0100
+@@ -205,7 +205,7 @@ providing that is updated like any other
  .IP
  \fBinstallonly_limit \fR
  Number of packages listed in installonlypkgs to keep installed at the same
@@ -32,7 +33,7 @@ diff -ru yum-3.4.3-orig/yum/config.py yum-3.4.3/yum/config.py
  functionality used to be in the "installonlyn" plugin, where this option was
  altered via tokeep.
  Note that as of version 3.2.24, yum will now look in the yumdb for a installonly
-@@ -267,7 +267,7 @@ group, and won't remove those on "group remove".
+@@ -302,7 +302,7 @@ group, and won't remove those on "group
  Running "yum upgrade" will also run "yum group upgrade" (thus. adding new
  packages for all groups).
  
diff --git a/SOURCES/yum.conf.centos b/SOURCES/yum.conf.centos
deleted file mode 100644
index 367126f..0000000
--- a/SOURCES/yum.conf.centos
+++ /dev/null
@@ -1,26 +0,0 @@
-[main]
-cachedir=/var/cache/yum/$basearch/$releasever
-keepcache=0
-debuglevel=2
-logfile=/var/log/yum.log
-exactarch=1
-obsoletes=1
-gpgcheck=1
-plugins=1
-installonly_limit=5
-bugtracker_url=http://bugs.centos.org/set_project.php?project_id=23&ref=http://bugs.centos.org/bug_report_page.php?category=yum
-distroverpkg=centos-release
-
-
-#  This is the default, if you make this bigger yum won't see if the metadata
-# is newer on the remote and so you'll "gain" the bandwidth of not having to
-# download the new metadata and "pay" for it by yum not having correct
-# information.
-#  It is esp. important, to have correct metadata, for distributions like
-# Fedora which don't keep old packages around. If you don't like this checking
-# interupting your command line usage, it's much better to have something
-# manually check the metadata once an hour (yum-updatesd will do this).
-# metadata_expire=90m
-
-# PUT YOUR REPOS HERE OR IN separate files named file.repo
-# in /etc/yum.repos.d
diff --git a/SPECS/yum.spec b/SPECS/yum.spec
index e4533ec..9614337 100644
--- a/SPECS/yum.spec
+++ b/SPECS/yum.spec
@@ -32,11 +32,11 @@
 Summary: RPM package installer/updater/manager
 Name: yum
 Version: 3.4.3
-Release: 150%{?dist}
+Release: 154%{?dist}
 License: GPLv2+
 Group: System Environment/Base
 Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz
-Source1: yum.conf.centos
+Source1: yum.conf.fedora
 Source2: yum-updatesd.conf.fedora
 Patch1: yum-distro-configs.patch
 Patch5: geode-arch.patch
@@ -92,8 +92,6 @@ Patch164: BZ-1233152-pvm-api-lv_attr.patch
 Patch165: BZ-1244119-fssnapshot-automatic-percentage-manpage.patch
 Patch166: BZ-1259837-igroups-empty-lines.patch
 
-Patch1000: centos-branding-yum.patch
-
 # rhel-7.3
 Patch200: BZ-1267234-groupinstall-fail-on-non-existent.patch
 Patch201: BZ-1274211-skip-missing-names.patch
@@ -135,6 +133,19 @@ Patch236: BZ-1335250-fssnapshot-handle-lvm-errors.patch
 Patch237: BZ-1356797-silent-exception.patch
 Patch238: BZ-1377328-_metadata_cache_req.patch
 
+# rhel-7.4
+Patch250: BZ-1389816-include-repoid-in-timestamp-error.patch
+Patch251: BZ-1369389-dont-recommend-makecache-if-running.patch
+Patch252: BZ-1194915-add-logging-for-bad-notice-dupes.patch
+Patch253: BZ1410326-Fix-for-history-package-list.patch
+Patch254: BZ-1399628-updateinfo-fix-wrong-pkg-count.patch
+Patch255: BZ-1391507-fix-filelist-queries-for-dup-pkgs.patch
+Patch256: BZ-1343690-add-payload-gpgcheck-opt.patch
+Patch257: BZ-1357083-clean-all-add-hint-rm-rf.patch
+Patch258: BZ-1370134-yum-check-ignore-self-conflicts.patch
+Patch259: BZ-1352585-detect-installed-provide.patch
+Patch260: BZ-1397829-fix-reget-simple-md-fnames.patch
+
 URL: http://yum.baseurl.org/
 BuildArchitectures: noarch
 BuildRequires: python
@@ -152,8 +163,7 @@ BuildRequires: pygpgme
 # End of CheckRequires
 Conflicts: pirut < 1.1.4
 Requires: python >= 2.4
-Requires: yum-plugin-fastestmirror
-Requires: rpm-python, rpm >= 0:4.4.2
+Requires: rpm-python, rpm >= 0:4.11.3-22
 Requires: python-iniparse
 Requires: python-sqlite
 Requires: python-urlgrabber >= 3.10-8
@@ -351,7 +361,18 @@ Install this package if you want auto yum updates nightly via cron.
 %patch237 -p1
 %patch238 -p1
 
-%patch1000 -p1
+# rhel-7.4
+%patch250 -p1
+%patch251 -p1
+%patch252 -p1
+%patch253 -p1
+%patch254 -p1
+%patch255 -p1
+%patch256 -p1
+%patch257 -p1
+%patch258 -p1
+%patch259 -p1
+%patch260 -p1
 
 # Do distro config. changes after everything else.
 %patch1 -p1
@@ -583,12 +604,35 @@ exit 0
 %endif
 
 %changelog
-* Thu Nov 03 2016 CentOS Sources <bugs@centos.org> - 3.4.3-150.el7.centos
-- CentOS yum config
--  use the CentOS bug tracker url
--  retain installonly limit of 5
--  ensure distrover is always from centos-release
-- Make yum require yum-plugin-fastestmirror
+* Mon Mar 27 2017 Valentina Mukhamedzhanova <vmukhame@redhat.com> - 3.4.3-154
+- Add payload_gpgcheck option.
+- Resolves: bug#1343690
+- Add hint about rm -rf for yum clean all.
+- Resolves: bug#1357083
+- Have "yum check" ignore self conflicts.
+- Resolves: bug#1370134
+- Detect installed virtual provide in install().
+- Resolves: bug#1352585
+- Fix reget problems with simple md filenames.
+- Resolves: bug#1397829
+
+* Thu Mar 02 2017 Valentina Mukhamedzhanova <vmukhame@redhat.com> - 3.4.3-153
+- Filter duplicates when counting security updates.
+- Resolves: bug#1399628
+- sqlitesack: fix filelist queries for duplicate pkgs.
+- Resolves: bug#1391507
+
+* Mon Feb 06 2017 Valentina Mukhamedzhanova <vmukhame@redhat.com> - 3.4.3-152
+- Fix 'history package-list'.
+- Resolves: bug#1410326
+
+* Thu Feb 02 2017 Valentina Mukhamedzhanova <vmukhame@redhat.com> - 3.4.3-151
+- Add repo-id to repomd timestamp error message.
+- Resolves: bug#1389816
+- Don't recommend makecache if just running.
+- Resolves: bug#1369389
+- Add logging of bad update notice duplicates.
+- Resolves: bug#1194915
 
 * Mon Sep 19 2016 Valentina Mukhamedzhanova <vmukhame@redhat.com> - 3.4.3-150
 - Check for _metadata_cache_req properly.