diff options
| -rw-r--r-- | apt/package.py | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/apt/package.py b/apt/package.py index f1ea02c5..b664769d 100644 --- a/apt/package.py +++ b/apt/package.py @@ -19,13 +19,19 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA +import httplib import sys import random import re +import socket import string +import urllib2 import apt_pkg +# Set a timeout for the changelog download +socket.setdefaulttimeout(2) + #from gettext import gettext as _ import gettext def _(s): return gettext.dgettext("python-apt", s) @@ -70,6 +76,7 @@ class Package(object): self._pkg = pkgiter self._list = sourcelist # sourcelist self._pcache = pcache # python cache in cache.py + self._changelog = "" # Cached changelog pass # helper @@ -367,6 +374,141 @@ class Package(object): return 0 return ver.InstalledSize installedSize = property(installedSize) + + def getChangelog(self, uri=None, cancel_lock=None): + """ + Download the changelog of the package and return it as unicode + string + + uri: Is the uri to the changelog file. The following named variables + will be substituted: src_section, prefix, src_pkg and src_ver + For example the Ubuntu changelog: + uri = "http://changelogs.ubuntu.com/changelogs/pool" \\ + "/%(src_section)s/%(prefix)s/%(src_pkg)s" \\ + "/%(src_pkg)s_%(src_ver)s/changelog" + cancel_lock: If this threading.Lock() is set, the download will be + canceled + """ + # Return a cached changelog if available + if self._changelog != "": + return self._changelog + + if uri == None: + if self.candidateOrigin[0].origin == "Debian": + uri = "http://packages.debian.org/changelogs/pool" \ + "/%(src_section)s/%(prefix)s/%(src_pkg)s" \ + "/%(src_pkg)s_%(src_ver)s/changelog" + elif self.candidateOrigin[0].origin == "Ubuntu": + uri = "http://changelogs.ubuntu.com/changelogs/pool" \ + "/%(src_section)s/%(prefix)s/%(src_pkg)s" \ + "/%(src_pkg)s_%(src_ver)s/changelog" + else: + return _("The list of changes is not available") + + # get the src package name + src_pkg = self.sourcePackageName + + # assume "main" section + src_section = "main" + # use the section of the candidate as a starting point + section = self._depcache.GetCandidateVer(self._pkg).Section + + # get the source version, start with the binaries version + bin_ver = self.candidateVersion + src_ver = self.candidateVersion + #print "bin: %s" % binver + try: + # try to get the source version of the pkg, this differs + # for some (e.g. libnspr4 on ubuntu) + # this feature only works if the correct deb-src are in the + # sources.list + # otherwise we fall back to the binary version number + src_records = apt_pkg.GetPkgSrcRecords() + src_rec = src_records.Lookup(src_pkg) + if src_rec: + src_ver = src_records.Version + #if apt_pkg.VersionCompare(binver, srcver) > 0: + # srcver = binver + if not src_ver: + src_ver = bin_ver + #print "srcver: %s" % src_ver + section = src_records.Section + #print "srcsect: %s" % section + else: + # fail into the error handler + raise SystemError + except SystemError, e: + src_ver = bin_ver + + l = section.split("/") + if len(l) > 1: + src_section = l[0] + + # lib is handled special + prefix = src_pkg[0] + if src_pkg.startswith("lib"): + prefix = "lib" + src_pkg[3] + + # stip epoch + l = string.split(src_ver,":") + if len(l) > 1: + src_ver = "".join(l[1:]) + + uri = uri % {"src_section" : src_section, + "prefix" : prefix, + "src_pkg" : src_pkg, + "src_ver" : src_ver} + try: + # Check if the download was canceled + if cancel_lock and cancel_lock.isSet(): return "" + changelog_file = urllib2.urlopen(uri) + # do only get the lines that are new + changelog = "" + regexp = "^%s \((.*)\)(.*)$" % (re.escape(src_pkg)) + + i=0 + while True: + # Check if the download was canceled + if cancel_lock and cancel_lock.isSet(): return "" + # Read changelog line by line + line_raw = changelog_file.readline() + if line_raw == "": + break + # The changelog is encoded in utf-8, but since there isn't any + # http header, urllib2 seems to treat it as ascii + line = line_raw.decode("utf-8") + + #print line.encode('utf-8') + match = re.match(regexp, line) + if match: + # strip epoch from installed version + # and from changelog too + installed = self.installedVersion + if installed and ":" in installed: + installed = installed.split(":",1)[1] + changelog_ver = match.group(1) + if changelog_ver and ":" in changelog_ver: + changelog_ver = changelog_ver.split(":", 1)[1] + if installed and \ + apt_pkg.VersionCompare(changelog_ver, installed) <= 0: + break + # EOF (shouldn't really happen) + changelog += line + + # Print an error if we failed to extract a changelog + if len(changelog) == 0: + changelog = _("The list of changes is not available") + self._changelog = changelog + except urllib2.HTTPError,e: + return _("The list of changes is not available yet.\n\n" + "Please use http://launchpad.net/ubuntu/+source/%s/%s/" + "+changelog\n" + "until the changes become available or try again " + "later.") % (srcpkg, srcver), + except IOError, httplib.BadStatusLine: + return _("Failed to download the list of changes. \nPlease " + "check your Internet connection.") + return self._changelog # canidate origin class Origin: |
