On 03/08/14 15:31, Andrew Gregory wrote:
> Original-work-by: Allan McRae <[email protected]>
> Signed-off-by: Andrew Gregory <[email protected]>
> ---
> 

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:-@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"
>  
> 

Reply via email to