control: tag -1 +patch

Hello Holger, Andreas,

New patch attached.

I'm not totally sure about the version number comparison code, because
LooseVersion doesn't understand things like "~beta2".  However, it gives
the right answer for the versions of apt in all current Debian suites.

-- 
Sean Whitton
From 2e4bf077af395829898a34bde9aa4eb967d6cc28 Mon Sep 17 00:00:00 2001
From: Sean Whitton <[email protected]>
Date: Sat, 24 Dec 2016 21:51:56 +0000
Subject: [PATCH] use apt-get install /tmp/foo.deb

---
 debian/changelog |  8 ++++++++
 piuparts.py      | 55 +++++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 9cb1565..6534322 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+piuparts (0.74) UNRELEASED; urgency=medium
+
+  * piuparts.py: use `apt-get install ./foo.deb` instead of `dpkg -i
+    ./foo.deb && apt-get install -yf` for more reliable dependency
+    resolution (Closes: #825487).
+
+ -- Sean Whitton <[email protected]>  Sat, 24 Dec 2016 21:50:21 +0000
+
 piuparts (0.73) unstable; urgency=medium
 
   * Add new option, --hard-link, and do *not* use it by default.
diff --git a/piuparts.py b/piuparts.py
index dbf2b18..06d7901 100644
--- a/piuparts.py
+++ b/piuparts.py
@@ -52,6 +52,7 @@ import subprocess
 import urllib
 import uuid
 from collections import namedtuple
+from distutils.version import LooseVersion
 from signal import alarm, signal, SIGALRM, SIGTERM, SIGKILL
 
 try:
@@ -1162,14 +1163,39 @@ class Chroot:
             self.install_packages_by_name(packages, with_scripts=with_scripts)
             return
         if package_files:
+            # We need an absolute path here so that apt-get can
+            # distinguish our deb from a request to install a package
+            # from a suite called 'tmp'
             self.copy_files(package_files, "tmp")
             tmp_files = [os.path.basename(a) for a in package_files]
-            tmp_files = [os.path.join("tmp", name) for name in tmp_files]
+            tmp_files = [os.path.join("/tmp", name) for name in tmp_files]
+
+            # Check whether apt can install debs
+            #
+            # If it can, this is preferable to the traditional `dpkg
+            # -i foo.deb && apt-get install -yf` approach:
+            #
+            # - the traditional approach can 'resolve' the dependency
+            #   by removing the package we are trying to install
+            #
+            # - the new approach successfully handles simultaneously
+            #   installing a new binary package and its transitional
+            #   dummy package
+            (status, output) = run(["dpkg-query", "-f", "${Version}\n", "-W", "apt"], ignore_errors=True)
+            apt_can_install_debs = LooseVersion(output.strip()) >= LooseVersion("1.1")
 
             if with_scripts:
                 self.run_scripts("pre_install")
 
-            apt_get_install = ["apt-get", "-yf"]
+            if apt_can_install_debs:
+                # --allow-downgrades is required in order to permit
+                # installing a deb with the same version as that
+                # already installed, which we need to do at various
+                # points in piuparts testing
+                apt_get_install = ["apt-get", "-y", "--allow-downgrades"]
+            else:
+                apt_get_install = ["apt-get", "-yf"]
+
             apt_get_install.extend(settings.distro_config.get_target_flags(
                 os.environ["PIUPARTS_DISTRIBUTION"]))
             apt_get_install.append("install")
@@ -1177,18 +1203,23 @@ class Chroot:
             if settings.list_installed_files:
                 pre_info = self.save_meta_data()
 
-            (ret, out) = self.run(["dpkg", "-i"] + tmp_files, ignore_errors=True)
-            if ret != 0:
-                if "dependency problems - leaving unconfigured" in out:
-                    pass
-                else:
-                    logging.error("Installation failed")
-                    panic()
+            if apt_can_install_debs:
+                self.run(apt_get_install + tmp_files)
+            else:
+                logging.info("apt too old; falling back to dpkg -i && apt-get install -yf")
 
-            if settings.list_installed_files:
-                self.list_installed_files(pre_info, self.save_meta_data())
+                (ret, out) = self.run(["dpkg", "-i"] + tmp_files, ignore_errors=True)
+                if ret != 0:
+                    if "dependency problems - leaving unconfigured" in out:
+                        pass
+                    else:
+                        logging.error("Installation failed")
+                        panic()
+
+                if settings.list_installed_files:
+                    self.list_installed_files(pre_info, self.save_meta_data())
 
-            self.run(apt_get_install)
+                self.run(apt_get_install)
 
             if settings.list_installed_files:
                 self.list_installed_files(pre_info, self.save_meta_data())
-- 
2.10.2

Attachment: signature.asc
Description: PGP signature

Reply via email to