[pacman-dev] [PATCH] [WIP] Extend database upgrade script to handle alpm db version 9

Andrew Gregory andrew.gregory.8 at gmail.com
Sun Aug 3 01:31:40 EDT 2014


Original-work-by: Allan McRae <allan at archlinux.org>
Signed-off-by: Andrew Gregory <andrew.gregory.8 at gmail.com>
---

Changes:
* set alternate root with PACROOT environment variable
* filter results through grep and sort to remove empty lines and duplicates
* add parent directories (duplicates filtered out by sort)
* verify that the resolved directory is inside our root
* replace longer symlinks first
* handle conflict between resolved directory and existing filelist entry

 scripts/pacman-db-upgrade.sh.in | 92 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 82 insertions(+), 10 deletions(-)

diff --git a/scripts/pacman-db-upgrade.sh.in b/scripts/pacman-db-upgrade.sh.in
index b0b0ac8..7ea4077 100644
--- a/scripts/pacman-db-upgrade.sh.in
+++ b/scripts/pacman-db-upgrade.sh.in
@@ -25,9 +25,17 @@ export TEXTDOMAINDIR='@localedir@'
 
 declare -r myver='@PACKAGE_VERSION@'
 
+resolve_dir() {
+	local d="$(cd "$1"; pwd -P)"
+	[[ $d == */ ]] || d+=/
+	printf "%s" "$d"
+}
+
 eval $(awk '/DBPath/ {print $1$2$3}' @sysconfdir@/pacman.conf)
 dbroot="${DBPath:- at localstatedir@/lib/pacman/}"
 
+pacroot="$(resolve_dir "${PACROOT:-/}")"
+
 USE_COLOR='y'
 
 m4_include(library/output_format.sh)
@@ -112,18 +120,82 @@ fi
 # do not let pacman run while we do this
 touch "$lockfile"
 
-# pacman-3.4 to 3.5 upgrade - merge depends into desc
-if [[ $(find "$dbroot"/local -name depends) ]]; then
-	msg "$(gettext "Pre-3.5 database format detected - upgrading...")"
-	for i in "$dbroot"/local/*; do
-		if [[ -f "$i"/depends ]]; then
-			cat "$i"/depends >> "$i"/desc
-			rm "$i"/depends
-		fi
-	done
-	msg "$(gettext "Done.")"
+if [[ -f "${dbroot}"/local/.alpm_db_version ]]; then
+	db_version=$(cat "${dbroot}"/local/.alpm_db_version)
 fi
 
+if [[ -z "$db_version" ]]; then
+	# pacman-3.4 to 3.5 upgrade - merge depends into desc
+	if [[ $(find "$dbroot"/local -name depends) ]]; then
+		msg "$(gettext "Pre-3.5 database format detected - upgrading...")"
+		for i in "$dbroot"/local/*; do
+			if [[ -f "$i"/depends ]]; then
+				cat "$i"/depends >> "$i"/desc
+				rm "$i"/depends
+			fi
+		done
+		msg "$(gettext "Done.")"
+	fi
+
+	# pacman 4.1 to 4.2 upgrade - remove directory symlink support
+	dirlist=()
+
+	unset GREP_OPTIONS
+	while IFS= read -r dir; do
+		dirlist+=("${pacroot}${dir%/}")
+	done < <(grep -h '/$' "$dbroot"/local/*/files | sort -ru)
+
+	mapfile -t dirlist < <(find "${dirlist[@]}" -maxdepth 0 -type l)
+
+	if [[ ${#dirlist[@]} != 0 ]]; then
+		msg "$(gettext "Pre-4.2 database format detected - upgrading...")"
+		for dir in "${dirlist[@]}"; do
+			realdir="$(resolve_dir "$(cd $dir; pwd -P)")"
+
+			# verify realdir is inside root
+			if [[ ${realdir:0:${#pacroot}} != $pacroot ]]; then
+				warning "$(gettext "symlink '%s' points outside pacman root, manual repair required")" "$dir"
+				continue
+			fi
+
+			# convert to an appropriate form for the replacement
+			olddir="${dir:${#pacroot}}/"
+			newdir="${realdir:${#pacroot}}"
+
+			# construct the parents of the new directory
+			parents=""
+			parent="$(dirname "$newdir")"
+			while [[ $parent != "." ]]; do
+				parents+="$parent/\n"
+				parent="$(dirname "$parent")"
+			done
+
+			for f in "$dbroot"/local/*/files; do
+				awk -v "olddir=$olddir" -v "newdir=$newdir" -v "parents=$parents" '
+					BEGIN {
+						i = length(olddir) + 1
+						file = substr(newdir, 0, length(newdir) - 1)
+					}
+					{
+						if ($0 == olddir) {
+							printf("%s", parents)
+							printf("%s\n", newdir)
+						} else if ($0 == file) {
+							# skip
+						} else if (index($0, olddir) == 1) {
+							printf("%s%s\n", newdir, substr($0, i))
+						} else {
+							print
+						}
+					}' "$f" | grep . | LC_ALL=C sort -u > "$f.tmp"
+				mv "$f.tmp" "$f"
+			done
+		done
+	fi
+fi
+
+echo "9" > "$dbroot"/local/.alpm_db_version
+
 # remove the lock file
 rm -f "$lockfile"
 
-- 
2.0.2


More information about the pacman-dev mailing list