Просмотр исходного кода

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.

[hertzog@debian.org:
 - Detect arch qualified dependencies in status and available files. ]
Guillem Jover лет назад: 15
Родитель
Сommit
bcba64dde3
2 измененных файлов с 84 добавлено и 1 удалено
  1. 20 1
      debian/dpkg.postrm
  2. 64 0
      debian/dpkg.prerm

+ 20 - 1
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)
 	;;
 
 

+ 64 - 0
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)