Original-work-by: Allan McRae <allan@archlinux.org> Signed-off-by: Andrew Gregory <andrew.gregory.8@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:-@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