[Piuparts-commits] rev 121 - in trunk: . debian

John Wright jsw at alioth.debian.org
Sat Jan 5 09:56:16 UTC 2008


Author: jsw
Date: 2008-01-05 09:56:16 +0000 (Sat, 05 Jan 2008)
New Revision: 121

Modified:
   trunk/debian/changelog
   trunk/debian/control
   trunk/piuparts.docbook
   trunk/piuparts.py
Log:
* Change the --warn-on-others implementation to create a dummy metapackage
  with the needed dependencies and install it in the chroot, rather than
  using "apt-get install package package-".  The previous implementation
  had issues when the package was already installed (and especially if the
  package had essential packages in its reverse dependencies).  This has
  the pleasant side-effect of making --warn-on-others work both with and
  without --apt. (Closes: #458929)
* Fix a bug in check_for_broken_symlinks(): the targets for the broken
  symlinks (used for logging) were being read from files on the real root
  filesystem, rather than in the chroot.

Modified: trunk/debian/changelog
===================================================================
--- trunk/debian/changelog	2007-12-23 13:19:41 UTC (rev 120)
+++ trunk/debian/changelog	2008-01-05 09:56:16 UTC (rev 121)
@@ -26,8 +26,20 @@
   * Bumped policy version to 3.7.3.
   * Updated download location in debian/copyright.
 
- -- Holger Levsen <holger at debian.org>  Sun, 23 Dec 2007 14:17:33 +0100
+  [ John Wright ]
+  * Change the --warn-on-others implementation to create a dummy metapackage
+    with the needed dependencies and install it in the chroot, rather than
+    using "apt-get install package package-".  The previous implementation
+    had issues when the package was already installed (and especially if the
+    package had essential packages in its reverse dependencies).  This has
+    the pleasant side-effect of making --warn-on-others work both with and
+    without --apt. (Closes: #458929)
+  * Fix a bug in check_for_broken_symlinks(): the targets for the broken
+    symlinks (used for logging) were being read from files on the real root
+    filesystem, rather than in the chroot.
 
+ -- John Wright <jsw at debian.org>  Sat, 05 Jan 2008 02:30:15 -0700
+
 piuparts (0.28) unstable; urgency=low
 
   * Fix an UnboundLocalError introduced in the --warn-on-others fix that would

Modified: trunk/debian/control
===================================================================
--- trunk/debian/control	2007-12-23 13:19:41 UTC (rev 120)
+++ trunk/debian/control	2008-01-05 09:56:16 UTC (rev 121)
@@ -12,7 +12,7 @@
 
 Package: piuparts
 Architecture: all
-Depends: apt, python (>> 2.3), debootstrap (>= 0.3.3), lsof, lsb-release
+Depends: apt, python (>> 2.3), debootstrap (>= 0.3.3), lsof, lsb-release, python-debian (>= 0.1.4)
 Description: .deb package installation, upgrading, and removal testing tool
  piuparts tests that .deb packages (as used by Debian) handle
  installation, upgrading, and removal correctly. It does this by

Modified: trunk/piuparts.docbook
===================================================================
--- trunk/piuparts.docbook	2007-12-23 13:19:41 UTC (rev 120)
+++ trunk/piuparts.docbook	2008-01-05 09:56:16 UTC (rev 121)
@@ -290,10 +290,11 @@
                     fail because of it (but a warning message will be
                     printed).</para>
 
-                    <para>Currently, this option only works in conjunction
-                    with <option>--apt</option>, and errors in packages
-                    with circular dependencies with specified packages will
-                    be treated as errors rather than warnings.</para>
+                    <para>Behavior with multple packages given on the
+                    command-line could be problematic, particularly if the
+                    dependency tree of one package in the list includes
+                    another in the list.  Therefore, it is recommended to
+                    use this option with one package at a time.</para>
 
                 </listitem>
             

Modified: trunk/piuparts.py
===================================================================
--- trunk/piuparts.py	2007-12-23 13:19:41 UTC (rev 120)
+++ trunk/piuparts.py	2008-01-05 09:56:16 UTC (rev 121)
@@ -48,6 +48,7 @@
 import sets
 import subprocess
 import unittest
+from debian_bundle import deb822
 
 
 class Defaults:
@@ -391,6 +392,38 @@
             panic()
 
 
+def make_metapackage(name, depends, conflicts):
+    """Return the path to a .deb created just for satisfying dependencies
+    
+    Caller is responsible for removing the temporary directory containing the
+    .deb when finished.
+    """
+    # Inspired by pbuilder's pbuilder-satisfydepends-aptitude
+
+    tmpdir = tempfile.mkdtemp(dir=settings.tmpdir)
+    os.makedirs(os.path.join(tmpdir, name, 'DEBIAN'))
+    control = deb822.Deb822()
+    control['Package'] = name
+    control['Version'] = '0.invalid.0'
+    control['Architecture'] = 'all'
+    control['Maintainer'] = ('piuparts developers team '
+                             '<piuparts-devel at lists.alioth.debian.org>')
+    control['Description'] = ('Dummy package to satisfy dependencies - '
+                              'created by piuparts\n'
+                              ' This package was creaetd automatically by '
+                              'piuparts and can safely be removed')
+    if depends:
+        control['Depends'] = depends
+    if conflicts:
+        control['Conflicts'] = conflicts
+
+    create_file(os.path.join(tmpdir, name, 'DEBIAN', 'control'),
+                control.dump())
+
+    run(['dpkg-deb', '-b', os.path.join(tmpdir, name)])
+    return os.path.join(tmpdir, name) + '.deb'
+
+
 def is_broken_symlink(root, dirpath, filename):
     """Is symlink dirpath+filename broken?
     
@@ -844,7 +877,7 @@
                         target = os.readlink(full_name)
                     except os.error:
                         target = "<unknown>"
-                    broken.append("%s -> %s" % (name, os.readlink(name)))
+                    broken.append("%s -> %s" % (name, target))
         if broken:
             logging.error("Broken symlinks:\n%s" % 
                           indent_string("\n".join(broken)))
@@ -1089,24 +1122,54 @@
 
     # Install packages into the chroot.
     chroot.mount_proc()
+
+    if settings.warn_on_others:
+        # Create a metapackage with dependencies from the given packages
+        if args:
+            control_infos = []
+            # We were given package files, so let's get the Depends and
+            # Conflicts directly from the .debs
+            for deb in args:
+                returncode, output = run(["dpkg", "-f", deb])
+                control = deb822.Deb822(output)
+                control_infos.append(control)
+        else:
+            # We have package names.  Use apt to get all their control
+            # information.
+            apt_cache_args = ["apt-cache", "show"]
+            apt_cache_args.extend(packages)
+            returncode, output = chroot.run(apt_cache_args)
+            control_infos = deb822.Deb822.iter_paragraphs(output.splitlines())
+            
+        depends = []
+        conflicts = []
+        for control in control_infos:
+            if control.get("depends"):
+                depends.append(control["depends"])
+            if control.get("conflicts"):
+                conflicts.append(control["conflicts"])
+        all_depends = ", ".join(depends)
+        all_conflicts = ", ".join(conflicts)
+        metapackage = make_metapackage("piuparts-depends-dummy",
+                                       all_depends, all_conflicts)
+        
+        # Install the metapackage
+        chroot.install_package_files([metapackage])
+        # Now remove it
+        metapackagename = os.path.basename(metapackage)[:-4]
+        chroot.remove_or_purge("purge", [metapackagename])
+        shutil.rmtree(os.path.dirname(metapackage))
+
+        # Save the file ownership information so we can tell which
+        # modifications were caused by the actual packages we are testing,
+        # rather than by their dependencies.
+        deps_info = chroot.save_meta_data()
+    else:
+        deps_info = None
+
     if args:
         chroot.install_package_files(args)
-        deps_info = None
     else:
-        if settings.warn_on_others:
-            # First install only the dependencies.  We do this by giving
-            # apt-get the list of packages to install, and following that list
-            # with the same packages with '-' appended to the end.  Then,
-            # apt-get ensures that the packages never actually get installed,
-            # but kindly installs their dependencies for us.  Once we've got
-            # the dependencies installed, save the file ownership information
-            # so we can tell which modifications were caused by the actual
-            # packages we are testing, rather than by their dependencies.
-            chroot.install_packages_by_name(packages +
-                                            ["%s-" % p for p in packages])
-            deps_info = chroot.save_meta_data()
-        else:
-            deps_info = None
         chroot.install_packages_by_name(packages)
         chroot.run(["apt-get", "clean"])
 
@@ -1334,11 +1397,12 @@
                       help="Print a warning rather than failing if "
                            "files are left behind, modified, or removed "
                            "by a package that was not given on the "
-                           "command-line.  This currently only works in "
-                           "conjunction with --apt, and errors in "
-                           "packages with circular dependencies with "
-                           "specified packages will be treated as "
-                           "errors rather than warnings.")
+                           "command-line.  Behavior with multple packages "
+                           "given could be problematic, particularly if the "
+                           "dependency tree of one package in the list "
+                           "includes another in the list.  Therefore, it is "
+                           "recommended to use this option with one package "
+                           "at a time.")
 			   
     parser.add_option("--skip-minimize", 
                       action="store_true", default=False,
@@ -1459,11 +1523,6 @@
                       "and only one distribution")
         exit = 1
 
-    if settings.warn_on_others and settings.args_are_package_files:
-        logging.error("--warn-on-others currently only works in conjunction "
-                      "with --apt")
-        exit = 1
-    
     if not args:
         logging.error("Need command line arguments: " +
                       "names of packages or package files")




More information about the Piuparts-commits mailing list