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

Allan McRae allan at archlinux.org
Sat Aug 9 23:16:50 EDT 2014


On 03/08/14 15:31, Andrew Gregory wrote:
> Original-work-by: Allan McRae <allan at archlinux.org>
> Signed-off-by: Andrew Gregory <andrew.gregory.8 at gmail.com>
> ---
> 

Big thanks for doing this!


> Changes:
> * set alternate root with PACROOT environment variable

As you have pointed out, that needs to be a -r/--root flag and not an
environmental 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"
> +}
> +

OK

>  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
>  

OK.

> +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
> +

OK

> +	# 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)
> +

OK

> +	mapfile -t dirlist < <(find "${dirlist[@]}" -maxdepth 0 -type l)
> +

OK

> +	if [[ ${#dirlist[@]} != 0 ]]; then

if (( ${#dirlist[@]} ))

> +		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

OK.

> +
> +			# convert to an appropriate form for the replacement
> +			olddir="${dir:${#pacroot}}/"
> +			newdir="${realdir:${#pacroot}}"
> +

OK

> +			# construct the parents of the new directory
> +			parents=""
> +			parent="$(dirname "$newdir")"

use bash:   parent=${newdir%/*}

> +			while [[ $parent != "." ]]; do

Should that be  != '/' ?

$ dirname /usr
/

Anyway, using the bash above this becomes
while [[ -n "$parent" ]]; do


> +				parents+="$parent/\n"
> +				parent="$(dirname "$parent")"
> +			done
> +

My awk is suboptimal...  So I'll comment my understanding as I go...

> +			for f in "$dbroot"/local/*/files; do
> +				awk -v "olddir=$olddir" -v "newdir=$newdir" -v "parents=$parents" '

"parents=${parents[@]}"

> +					BEGIN {
> +						i = length(olddir) + 1
> +						file = substr(newdir, 0, length(newdir) - 1)
> +					}
> +					{
> +						if ($0 == olddir) {
> +							printf("%s", parents)
> +							printf("%s\n", newdir)

OK (replacing old dir with newdir and its parents)

> +						} else if ($0 == file) {
> +							# skip

I do not understand what this bit is achieving!

> +						} else if (index($0, olddir) == 1) {
> +							printf("%s%s\n", newdir, substr($0, i))

OK ("moving" file in olddir to "newdir")

> +						} else {
> +							print

OK (not touching files outside of olddir)

> +						}
> +					}' "$f" | grep . | LC_ALL=C sort -u > "$f.tmp"

Why the grep?

> +				mv "$f.tmp" "$f"
> +			done
> +		done
> +	fi
> +fi
> +
> +echo "9" > "$dbroot"/local/.alpm_db_version
> +

OK

>  # remove the lock file
>  rm -f "$lockfile"
>  
> 


More information about the pacman-dev mailing list