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

Reply via email to