forked from gentoo/gentoo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]>
- Loading branch information
Showing
1 changed file
with
108 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <[email protected]> | ||
# @AUTHOR: | ||
# Ulrich Müller <[email protected]> | ||
# @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. | ||
_dosym8_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:-.}" | ||
} | ||
|
||
# @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}" | ||
} |