commit: dfa50503f76f3e70bac50f959a9c7248e6ea880d Author: Ulrich Müller <ulm <AT> gentoo <DOT> org> AuthorDate: Mon Nov 23 09:06:49 2020 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Mon May 24 05:55:41 2021 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=dfa50503
dosym: Implement -r option for EAPI 8. "dosym -r <target> <link>" will expand the (apparent) path of <target> relative to the (apparent) path of the directory containing <link>. The main aim of this is to allow for an absolute path to be specified as the link target, and the function will count path components and convert it into a relative path. Since we're inside ED at this point but the image will finally be installed in EROOT, we don't try to resolve any pre-existing symlinks in <target> or <link>. In other words, path expansion only looks at the specified apparent paths, without touching any actual files in ED or EROOT. Bug: https://bugs.gentoo.org/708360 Signed-off-by: Ulrich Müller <ulm <AT> gentoo.org> Signed-off-by: Michał Górny <mgorny <AT> gentoo.org> Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> bin/eapi.sh | 4 +++ bin/ebuild-helpers/dosym | 67 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/bin/eapi.sh b/bin/eapi.sh index 80bade87e..362cc07c0 100644 --- a/bin/eapi.sh +++ b/bin/eapi.sh @@ -266,6 +266,10 @@ ___eapi_has_DESTTREE_INSDESTTREE() { [[ ${1-${EAPI-0}} =~ ^(0|1|2|3|4|4-python|4-slot-abi|5|5-progress|6)$ ]] } +___eapi_has_dosym_r() { + [[ ! ${1-${EAPI-0}} =~ ^(0|1|2|3|4|4-python|4-slot-abi|5|5-progress|6|7)$ ]] +} + ___eapi_usev_has_second_arg() { [[ ! ${1-${EAPI-0}} =~ ^(0|1|2|3|4|4-python|4-slot-abi|5|5-progress|6|7)$ ]] } diff --git a/bin/ebuild-helpers/dosym b/bin/ebuild-helpers/dosym index abd4da4f0..69d38956f 100755 --- a/bin/ebuild-helpers/dosym +++ b/bin/ebuild-helpers/dosym @@ -4,6 +4,12 @@ source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1 +option_r= +if [[ ___eapi_has_dosym_r && $1 == -r ]]; then + option_r=t + shift +fi + if [[ $# -ne 2 ]] ; then __helpers_die "${0##*/}: two arguments needed" exit 1 @@ -18,9 +24,68 @@ if [[ ${2} == */ ]] || [[ -d ${ED%/}/${2#/} && ! -L ${ED%/}/${2#/} ]] ; then __helpers_die "${0##*/}: dosym target omits basename: '${2}'" fi +target=$1 + +if [[ ${option_r} ]]; then + # Transparent bash-only replacement for GNU "realpath -m -s". + # Resolve references to "/./", "/../" and remove extra "/" characters + # from <path>, without touching any actual file. + dosym_canonicalize() { + local path slash i prev out IFS=/ + + path=( $1 ) + [[ $1 == /* ]] && slash=/ + + while true; do + # Find first instance of non-".." path component followed by "..", + # or as a special case, "/.." at the beginning of the path. + # Also drop empty and "." path components as we go along. + prev= + for i in ${!path[@]}; do + if [[ -z ${path[i]} || ${path[i]} == . ]]; then + unset "path[i]" + elif [[ ${path[i]} != .. ]]; then + prev=${i} + elif [[ ${prev} || ${slash} ]]; then + # Found, remove path components and reiterate + [[ ${prev} ]] && unset "path[prev]" + unset "path[i]" + continue 2 + fi + done + # No (further) instance found, so we're done + break + done + + out="${slash}${path[*]}" + echo "${out:-.}" + } + + # Expansion makes sense only for an absolute target path + [[ ${target} == /* ]] || __helpers_die \ + "${0##*/}: -r specified but no absolute target path: '${target}'" + + target=$(dosym_canonicalize "${target}") + linkdir=$(dosym_canonicalize "/${2#/}") + linkdir=${linkdir%/*} # poor man's dirname(1) + linkdir=${linkdir:-/} # always keep the initial "/" + + IFS=/ + for comp in ${linkdir}; do + if [[ ${target%%/*} == "${comp}" ]]; then + target=${target#"${comp}"} + target=${target#/} + else + target=..${target:+/}${target} + fi + done + unset IFS + target=${target:-.} +fi + destdir=${2%/*} [[ ! -d ${ED%/}/${destdir#/} ]] && dodir "${destdir}" -ln -snf "${1}" "${ED%/}/${2#/}" +ln -snf "${target}" "${ED%/}/${2#/}" ret=$? [[ $ret -ne 0 ]] && __helpers_die "${0##*/} failed"
