On Thu, Nov 19, 2020 at 7:28 AM Alec Warner <anta...@gentoo.org> wrote:
> > > On Thu, Nov 19, 2020 at 2:32 AM Ulrich Müller <u...@gentoo.org> wrote: > >> This implements the dosym command proposed for EAPI 8 (called dosym8 >> because we cannot use the same name as the package-manager builtin). >> >> "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. >> >> Signed-off-by: Ulrich Müller <u...@gentoo.org> >> --- >> eclass/eapi8-dosym.eclass | 108 ++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 108 insertions(+) >> create mode 100644 eclass/eapi8-dosym.eclass >> >> diff --git a/eclass/eapi8-dosym.eclass b/eclass/eapi8-dosym.eclass >> new file mode 100644 >> index 000000000000..52f0ffe3e62b >> --- /dev/null >> +++ b/eclass/eapi8-dosym.eclass >> @@ -0,0 +1,108 @@ >> +# Copyright 2020 Gentoo Authors >> +# Distributed under the terms of the GNU General Public License v2 >> + >> +# @ECLASS: eapi8-dosym.eclass >> +# @MAINTAINER: >> +# PMS team <p...@gentoo.org> >> +# @AUTHOR: >> +# Ulrich Müller <u...@gentoo.org> >> +# @SUPPORTED_EAPIS: 5 6 7 >> +# @BLURB: Testing implementation of EAPI 8 dosym -r option >> +# @DESCRIPTION: >> +# A stand-alone implementation of the dosym command aimed for EAPI 8. >> +# Intended to be used for wider testing of the proposed option and to >> +# allow ebuilds to switch to the new model early, with minimal change >> +# needed for actual EAPI 8. >> +# >> +# https://bugs.gentoo.org/708360 >> + >> +case ${EAPI} in >> + 5|6|7) ;; >> + *) die "${ECLASS}: EAPI=${EAPI:-0} not supported" ;; >> +esac >> + >> +# @FUNCTION: _dosym8_canonicalize >> +# @USAGE: <path> >> +# @INTERNAL >> +# @DESCRIPTION: >> +# Transparent bash-only replacement for GNU "realpath -m -s". >> +# Resolve references to "/./", "/../" and remove extra "/" characters >> +# from <path>, without touching any actual file. >> > > Take this as a nit, but do we have any way to test this function > (particularly around edge cases.) > I see eclass/tests exists, could we add a couple for this? > hah, and you added them in the second patch, sorry I didn't read ahead! :) -A > > >> +_dosym8_canonicalize() { >> > > in dosym8() you save and restore IFS, but you don't here, is there a > reason for that? > > >> + 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:-.}" >> +} >> + >> +# @FUNCTION: dosym8 >> +# @USAGE: [-r] <target> <link> >> +# @DESCRIPTION: >> +# Create a symbolic link <link>, pointing to <target>. If the >> +# directory containing the new link does not exist, create it. >> +# >> +# If called with option -r, expand <target> relative to the apparent >> +# path of the directory containing <link>. For example, "dosym8 -r >> +# /bin/foo /usr/bin/foo" will create a link named "../../bin/foo". >> +dosym8() { >> + local option_r >> + >> + case $1 in >> + -r) option_r=t; shift ;; >> + esac >> + >> + [[ $# -eq 2 ]] || die "${FUNCNAME}: bad number of arguments" >> + >> + local target=$1 link=$2 >> + >> + if [[ ${option_r} ]]; then >> + local linkdir comp >> + >> + # Expansion makes sense only for an absolute target path >> + [[ ${target} == /* ]] \ >> + || die "${FUNCNAME}: -r specified but no absolute >> target path" >> + >> + target=$(_dosym8_canonicalize "${target}") >> + linkdir=$(_dosym8_canonicalize "/${link#/}") >> + linkdir=${linkdir%/*} # poor man's dirname(1) >> + linkdir=${linkdir:-/} # always keep the initial "/" >> + >> + local ifs_save=${IFS-$' \t\n'} IFS=/ >> + for comp in ${linkdir}; do >> + if [[ ${target%%/*} == "${comp}" ]]; then >> + target=${target#"${comp}"} >> + target=${target#/} >> + else >> + target=..${target:+/}${target} >> + fi >> + done >> + IFS=${ifs_save} >> + target=${target:-.} >> + fi >> + >> + dosym "${target}" "${link}" >> +} >> -- >> 2.29.2 >> >> >>