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? > +_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 > > >