Package: python-central
Version: 0.6.15
Severity: important
Tags: patch
User: vor...@debian.org
Usertags: multiarch

Hi guys,

python-central makes heavy reliance on the presence of
/var/lib/dpkg/info/$pkg.list to determine the installation status of $pkg.
In the multiarch world, this is no longer a valid assumption; status files
are going to be under /var/lib/dpkg/info/$arch/ instead for each
architecture.  On a freshly-bootstrapped chroot using a multiarch-enabled
dpkg, therefore, python-central consistently fails to find any packages,
causing maintainer script failures.

The attached patch accounts for this in the most naive way possible, by
checking both /var/lib/dpkg/info and /var/lib/dpkg/info/$main_arch for the
requested file.  There are various ways that this may still be incorrect,
but it's correct *enough* to make pycentral work again for native packages
on a multiarched system, and we're a long, long away from having to worry
about non-native python extension packages being installed (if, indeed, this
is ever permitted).

I've uploaded this change to Ubuntu with the following changelog:

  * Fix up for multiarch dpkg: /var/lib/dpkg/info/$pkg.list is now no longer
    guaranteed to exist, it may be /var/lib/dpkg/info/$arch/$pkg.list.

Please apply this ASAP to the python-central package in Debian, or let me
know if you think this needs to be fixed a different way.

Thanks,
-- 
Steve Langasek                   Give me a lever long enough and a Free OS
Debian Developer                   to set it on, and I can move the world.
Ubuntu Developer                                    http://www.debian.org/
slanga...@ubuntu.com                                     vor...@debian.org
=== modified file 'pycentral.py'
--- pycentral.py	2010-09-10 08:56:59 +0000
+++ pycentral.py	2011-03-01 04:10:43 +0000
@@ -1377,6 +1377,18 @@
     def run(self, global_opts):
         pass
 
+    def get_arch(self):
+        import subprocess
+        # a little convoluted, but we need to get the current architecture
+        # name
+        cmd = ['/usr/bin/dpkg', '--print-architecture']
+        p = subprocess.Popen(cmd, bufsize=1,
+                             shell=False, stdout=subprocess.PIPE)
+        fd = p.stdout
+        arch = fd.readline().strip().split()
+        fd.close()
+        return arch
+
 
 class ActionByteCompile(Action):
     """byte compile the *.py files in <package> using the the
@@ -1413,7 +1425,9 @@
         if not self.runtime:
             self.error("unknown runtime version %s" % self.options.version)
 
-        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname):
+        arch = self.get_arch()
+        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname) \
+           and not os.path.exists('/var/lib/dpkg/info/%s/%s.list' % (arch, self.pkgname)):
             self.error("package %s is not installed" % self.pkgname)
         self.pkg = DebPackage('package', self.pkgname, oldstyle=False,
                               default_runtime=self.runtime)
@@ -1469,7 +1483,9 @@
             self._option_parser.print_help()
             sys.exit(1)
         self.pkgname = self.args[0]
-        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname):
+        arch = self.get_arch()
+        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname) \
+           and not os.path.exists('/var/lib/dpkg/info/%s/%s.list' % (arch, self.pkgname)):
             self.error("package %s is not installed" % self.pkgname)
         return self.errors_occured
 
@@ -1619,7 +1635,9 @@
             self._option_parser.print_help()
             sys.exit(1)
         self.pkgname = self.args[0]
-        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname):
+        arch = self.get_arch()
+        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname) \
+           and not os.path.exists('/var/lib/dpkg/info/%s/%s.list' % (arch, self.pkgname)):
             self.error("package %s is not installed" % self.pkgname)
         return self.errors_occured
 
@@ -1645,7 +1663,9 @@
             self._option_parser.print_help()
             sys.exit(1)
         self.pkgname = self.args[0]
-        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname):
+        arch = self.get_arch()
+        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname) \
+           and not os.path.exists('/var/lib/dpkg/info/%s/%s.list' % (arch, self.pkgname)):
             self.error("package %s is not installed" % self.pkgname)
         return self.errors_occured
 
@@ -1675,7 +1695,9 @@
             self._option_parser.print_help()
             sys.exit(1)
         self.pkgname = self.args[0]
-        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname):
+        arch = self.get_arch()
+        if not os.path.exists('/var/lib/dpkg/info/%s.list' % self.pkgname) \
+           and not os.path.exists('/var/lib/dpkg/info/%s/%s.list' % (arch, self.pkgname)):
             self.error("package %s is not installed" % self.pkgname)
         return self.errors_occured
 
@@ -1793,7 +1815,8 @@
         needed_packages = []
         import subprocess
         for pkgname, vstring in packages:
-            if not os.path.exists('/var/lib/dpkg/info/%s.list' % pkgname):
+            if not os.path.exists('/var/lib/dpkg/info/%s.list' % pkgname) \
+               and not os.path.exists('/var/lib/dpkg/info/%s/%s.list' % (arch, pkgname)):
                 # already removed, but /var/lib/dpkg/status not yet updated
                 continue
             cmd = ['/usr/bin/dpkg-query', '-W', '-f', '${Status}\n', pkgname]

Reply via email to