The following commit has been merged in the master branch:
commit bcba64dde3a2cb831f7175d98adf19a9b9bfed3d
Author: Guillem Jover <[email protected]>
Date:   Thu Feb 24 01:55:44 2011 +0100

    dpkg: Add multiarch to monoarch database layout downgrade support
    
    Handle the case where downgrading would lose data, i.e. when there's
    co-installed packages which the old dpkg would not be able to handle,
    and abort then.
    
    If the downgrade is safe, just convert the multiarch infodb to a
    monoarch infodb layout in two stages, first create hardlinks from the
    arch annotated control files before the upgrade starts, and then once
    the new package is in place, remove the arch annotated control file
    leftovers. This way if the upgrade got interrupted we always have a
    working database for both versions of dpkg.
    
    [[email protected]:
     - Detect arch qualified dependencies in status and available files. ]

diff --git a/debian/dpkg.postrm b/debian/dpkg.postrm
index 0659aea..dcd72ec 100755
--- a/debian/dpkg.postrm
+++ b/debian/dpkg.postrm
@@ -32,6 +32,18 @@ remove_logfile() {
     rm -f /var/log/dpkg.log /var/log/dpkg.log.* 2>/dev/null
 }
 
+# Cleanup multiarch infodb leftovers
+cleanup_multiarch_infodb()
+{
+    admindir=${DPKG_ADMINDIR:-/var/lib/dpkg}
+    pkgadmindir=$admindir/info
+
+    echo "Cleaning up the multiarch dpkg control files database ..."
+    ls $pkgadmindir | grep : | while read oldfile; do
+        rm "$pkgadmindir/$oldfile"
+    done
+    rm -f $pkgadmindir/format
+}
 
 case "$1" in
     remove)
@@ -41,7 +53,14 @@ case "$1" in
        remove_logfile
        ;;
 
-    upgrade|failed-upgrade|disappear|abort-install|abort-upgrade)
+    upgrade)
+       # Downgrade the multiarch db to a “monoarch” db layout
+       if dpkg --compare-versions "$2" lt 1.16.2~; then
+           cleanup_multiarch_infodb
+       fi
+       ;;
+
+    failed-upgrade|disappear|abort-install|abort-upgrade)
        ;;
 
 
diff --git a/debian/dpkg.prerm b/debian/dpkg.prerm
index ab51157..e8191ca 100755
--- a/debian/dpkg.prerm
+++ b/debian/dpkg.prerm
@@ -59,6 +59,66 @@ ensure_no_triggers_noawait()
     fi
 }
 
+downgrade_multiarch_infodb()
+{
+    admindir=${DPKG_ADMINDIR:-/var/lib/dpkg}
+    pkgadmindir=$admindir/info
+
+    coinst_pkgs="`ls "$pkgadmindir" | \
+        sed -n -e 's/^\([^:]\+:[^.]\+\)\..*$/\1/p' | sort -u | \
+        cut -d: -f1 | uniq -d`"
+
+    # Abort if we cannot possibly downgrade
+    if [ -n "$coinst_pkgs" ]; then
+        cat <<- MSG
+       dpkg: error: You have more than one architecture instance for some
+       installed 'Multi-Arch: same' packages, to be able to downgrade dpkg
+       you will need to have only one instance installed per package.
+
+       List of co-installed packages:
+
+       $coinst_pkgs
+       MSG
+        exit 1
+    fi
+
+    bad_dep_pkgs=$(dpkg-query -f '${Package}\t${Depends} ${Recommends} 
${Suggests} ${Enhances} ${Conflicts} ${Replaces} ${Breaks}\n' -W | \
+        grep ":any" | cut -f1 | sort -u)
+    if [ -n "$bad_dep_pkgs" ]; then
+        cat <<- MSG
+       dpkg: error: Some installed packages have multiarch dependencies that
+       the old dpkg won't parse. You should get rid of them (or downgrade
+       them to versions without those dependencies) before proceeding with
+       dpkg's downgrade.
+
+       List of affected packages:
+
+       $bad_dep_pkgs
+       MSG
+        exit 1
+    fi
+
+    dep_fields='Depends|Recommends|Suggests|Enhances|Conflicts|Replaces|Breaks'
+    if grep -qE "^($dep_fields):.*:any" $admindir/available; then
+       cat <<- MSG
+       dpkg: error: Some available packages have multiarch dependencies that
+       the old dpkg won't parse. You should clear this file before proceeding
+       with dpkg's downgrade, with:
+
+         # dpkg --clear-avail
+       MSG
+       exit 1
+    fi
+
+    echo "Downgrading the multiarch dpkg control files database ..."
+    ls $pkgadmindir | grep : | while read oldfile; do
+        # We first do a round of hardlinks to the new names, so that the db
+        # will never be unusable for either of the dpkg versions.
+        newfile=$(echo $oldfile | sed -e 's/:[^.]\+//')
+        ln -f "$pkgadmindir/$oldfile" "$pkgadmindir/$newfile"
+    done
+}
+
 case "$1" in
     upgrade)
         # Allow the downgrade only if no package is using the
@@ -66,6 +126,10 @@ case "$1" in
         if dpkg --compare-versions "$2" lt 1.16.1~; then
             ensure_no_triggers_noawait
         fi
+        # Downgrade the multiarch db to a “monoarch” db layout
+        if dpkg --compare-versions "$2" lt 1.16.2~; then
+            downgrade_multiarch_infodb
+        fi
         ;;
 
     remove|failed-upgrade|deconfigure)

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to