Original-work-by: Allan McRae <[email protected]>
Signed-off-by: Andrew Gregory <[email protected]>
---

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

Reply via email to