summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt/package.py142
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: