diff -Nru update-manager-16.10.2/debian/changelog update-manager-16.10.3/debian/changelog --- update-manager-16.10.2/debian/changelog 2016-07-21 21:29:15.000000000 +0000 +++ update-manager-16.10.3/debian/changelog 2016-07-27 18:14:58.000000000 +0000 @@ -1,3 +1,11 @@ +update-manager (1:16.10.3) yakkety; urgency=medium + + [Nicolas Delvaux] + * Attempt to retrieve Changelogs from PPA sources (LP: #253119) + * Correctly detect the usage of a username in changelog URIs + + -- Brian Murray Wed, 27 Jul 2016 11:14:53 -0700 + update-manager (1:16.10.2) yakkety; urgency=medium * Include HWE support tools and information. (LP: #1498059) diff -Nru update-manager-16.10.2/debian/control update-manager-16.10.3/debian/control --- update-manager-16.10.2/debian/control 2016-07-21 21:27:22.000000000 +0000 +++ update-manager-16.10.3/debian/control 2016-07-27 17:36:23.000000000 +0000 @@ -42,6 +42,7 @@ ${misc:Depends}, python3-apt (>= 0.8.5~), python3-distupgrade, + python3-launchpadlib, lsb-release Description: python 3.x module for update-manager Python module for update-manager (UpdateManager). diff -Nru update-manager-16.10.2/UpdateManager/Core/MyCache.py update-manager-16.10.3/UpdateManager/Core/MyCache.py --- update-manager-16.10.2/UpdateManager/Core/MyCache.py 2014-08-05 22:45:20.000000000 +0000 +++ update-manager-16.10.3/UpdateManager/Core/MyCache.py 2016-07-27 17:36:23.000000000 +0000 @@ -43,6 +43,7 @@ import re import DistUpgrade.DistUpgradeCache from gettext import gettext as _ +from launchpadlib.launchpad import Launchpad SYNAPTIC_PINFILE = "/var/lib/synaptic/preferences" CHANGELOGS_POOL = "http://changelogs.ubuntu.com/changelogs/pool/" @@ -79,6 +80,7 @@ self.saveDistUpgrade() assert (self._depcache.broken_count == 0 and self._depcache.del_count == 0) + self.launchpad = None def _dpkgJournalDirty(self): """ @@ -222,7 +224,7 @@ # and so its possible to do a man-in-the-middle attack to steal the # credentials res = urlsplit(uri) - if res.scheme == "https" and res.username != "": + if res.scheme == "https" and res.username: raise HttpsChangelogsUnsupportedError( "https locations with username/password are not" "supported to fetch changelogs") @@ -268,6 +270,48 @@ alllines = alllines + line return alllines + def _extract_ppa_changelog_uri(self, name): + """Return the changelog URI from the Launchpad API + + Return None in case of an error. + """ + cdt = self[name].candidate + for uri in cdt.uris: + if urlsplit(uri).hostname != 'ppa.launchpad.net': + continue + match = re.search('http.*/(.*)/(.*)/ubuntu/.*', uri) + if match is not None: + user, ppa = match.group(1), match.group(2) + break + else: + logging.error("Unable to find a valid PPA candidate URL.") + return + + # Login on launchpad if we are not already + if self.launchpad is None: + self.launchpad = Launchpad.login_anonymously('update-manager', + 'production', + version='devel') + + + archive = self.launchpad.archives.getByReference( + reference='~%s/ubuntu/%s' % (user, ppa) + ) + if archive is None: + logging.error("Unable to retrieve the archive from the Launchpad " + "API.") + return + + spphs = archive.getPublishedSources(source_name=cdt.source_name, + exact_match=True, + version=cdt.version) + if not spphs: + logging.error("No published sources were retrieved from the " + "Launchpad API.") + return + + return spphs[0].changelogUrl() + def _guess_third_party_changelogs_uri_by_source(self, name): pkg = self[name] deb_uri = pkg.candidate.uri @@ -314,14 +358,25 @@ if news: self.all_news[name] = news - def _fetch_changelog_for_third_party_package(self, name): + def _fetch_changelog_for_third_party_package(self, name, origins): + # Special case for PPAs + changelogs_uri_ppa = None + for origin in origins: + if origin.origin.startswith('LP-PPA-'): + try: + changelogs_uri_ppa = self._extract_ppa_changelog_uri(name) + break + except Exception: + logging.exception("Unable to connect to the Launchpad API.") # Try non official changelog location changelogs_uri_binary = \ self._guess_third_party_changelogs_uri_by_binary(name) changelogs_uri_source = \ self._guess_third_party_changelogs_uri_by_source(name) error_message = "" - for changelogs_uri in [changelogs_uri_binary, changelogs_uri_source]: + for changelogs_uri in [changelogs_uri_ppa, + changelogs_uri_binary, + changelogs_uri_source]: if changelogs_uri: try: changelog = self._get_changelog_or_news( @@ -349,7 +404,7 @@ (name, getattr(self[name].installed, "version", None), self[name].candidate.version) if self.CHANGELOG_ORIGIN not in [o.origin for o in origins]: - self._fetch_changelog_for_third_party_package(name) + self._fetch_changelog_for_third_party_package(name, origins) return # fixup epoch handling version srcpkg = self[name].candidate.source_name