Gentoo Archives: gentoo-dev

From: Alec Warner <antarus@g.o>
To: Gentoo Dev <gentoo-dev@l.g.o>
Cc: "Ulrich Müller" <ulm@g.o>
Subject: Re: [gentoo-dev] [PATCH 1/2] eapi8-dosym.eclass: New eclass.
Date: Thu, 19 Nov 2020 15:29:26
Message-Id: CAAr7Pr9kYtO+Mx8xZBr3jKiQFbofmCPvjHa=OOhLvkND9h27Zw@mail.gmail.com
In Reply to: Re: [gentoo-dev] [PATCH 1/2] eapi8-dosym.eclass: New eclass. by Alec Warner
1 On Thu, Nov 19, 2020 at 7:28 AM Alec Warner <antarus@g.o> wrote:
2
3 >
4 >
5 > On Thu, Nov 19, 2020 at 2:32 AM Ulrich Müller <ulm@g.o> wrote:
6 >
7 >> This implements the dosym command proposed for EAPI 8 (called dosym8
8 >> because we cannot use the same name as the package-manager builtin).
9 >>
10 >> "dosym -r <target> <link>" will expand the (apparent) path of <target>
11 >> relative to the (apparent) path of the directory containing <link>.
12 >> The main aim of this is to allow for an absolute path to be specified
13 >> as the link target, and the function will count path components and
14 >> convert it into a relative path.
15 >>
16 >> Since we're inside ED at this point but the image will finally be
17 >> installed in EROOT, we don't try to resolve any pre-existing symlinks
18 >> in <target> or <link>. In other words, path expansion only looks at
19 >> the specified apparent paths, without touching any actual files in ED
20 >> or EROOT.
21 >>
22 >> Signed-off-by: Ulrich Müller <ulm@g.o>
23 >> ---
24 >> eclass/eapi8-dosym.eclass | 108 ++++++++++++++++++++++++++++++++++++++
25 >> 1 file changed, 108 insertions(+)
26 >> create mode 100644 eclass/eapi8-dosym.eclass
27 >>
28 >> diff --git a/eclass/eapi8-dosym.eclass b/eclass/eapi8-dosym.eclass
29 >> new file mode 100644
30 >> index 000000000000..52f0ffe3e62b
31 >> --- /dev/null
32 >> +++ b/eclass/eapi8-dosym.eclass
33 >> @@ -0,0 +1,108 @@
34 >> +# Copyright 2020 Gentoo Authors
35 >> +# Distributed under the terms of the GNU General Public License v2
36 >> +
37 >> +# @ECLASS: eapi8-dosym.eclass
38 >> +# @MAINTAINER:
39 >> +# PMS team <pms@g.o>
40 >> +# @AUTHOR:
41 >> +# Ulrich Müller <ulm@g.o>
42 >> +# @SUPPORTED_EAPIS: 5 6 7
43 >> +# @BLURB: Testing implementation of EAPI 8 dosym -r option
44 >> +# @DESCRIPTION:
45 >> +# A stand-alone implementation of the dosym command aimed for EAPI 8.
46 >> +# Intended to be used for wider testing of the proposed option and to
47 >> +# allow ebuilds to switch to the new model early, with minimal change
48 >> +# needed for actual EAPI 8.
49 >> +#
50 >> +# https://bugs.gentoo.org/708360
51 >> +
52 >> +case ${EAPI} in
53 >> + 5|6|7) ;;
54 >> + *) die "${ECLASS}: EAPI=${EAPI:-0} not supported" ;;
55 >> +esac
56 >> +
57 >> +# @FUNCTION: _dosym8_canonicalize
58 >> +# @USAGE: <path>
59 >> +# @INTERNAL
60 >> +# @DESCRIPTION:
61 >> +# Transparent bash-only replacement for GNU "realpath -m -s".
62 >> +# Resolve references to "/./", "/../" and remove extra "/" characters
63 >> +# from <path>, without touching any actual file.
64 >>
65 >
66 > Take this as a nit, but do we have any way to test this function
67 > (particularly around edge cases.)
68 > I see eclass/tests exists, could we add a couple for this?
69 >
70
71 hah, and you added them in the second patch, sorry I didn't read ahead! :)
72
73 -A
74
75
76 >
77 >
78 >> +_dosym8_canonicalize() {
79 >>
80 >
81 > in dosym8() you save and restore IFS, but you don't here, is there a
82 > reason for that?
83 >
84 >
85 >> + local path slash i prev out IFS=/
86 >> +
87 >> + path=( $1 )
88 >> + [[ $1 == /* ]] && slash=/
89 >> +
90 >> + while true; do
91 >> + # Find first instance of non-".." path component followed
92 >> by "..",
93 >> + # or as a special case, "/.." at the beginning of the
94 >> path.
95 >> + # Also drop empty and "." path components as we go along.
96 >> + prev=
97 >> + for i in ${!path[@]}; do
98 >> + if [[ -z ${path[i]} || ${path[i]} == . ]]; then
99 >> + unset "path[i]"
100 >> + elif [[ ${path[i]} != .. ]]; then
101 >> + prev=${i}
102 >> + elif [[ ${prev} || ${slash} ]]; then
103 >> + # Found, remove path components and
104 >> reiterate
105 >> + [[ ${prev} ]] && unset "path[prev]"
106 >> + unset "path[i]"
107 >> + continue 2
108 >> + fi
109 >> + done
110 >> + # No (further) instance found, so we're done
111 >> + break
112 >> + done
113 >> +
114 >> + out="${slash}${path[*]}"
115 >> + echo "${out:-.}"
116 >> +}
117 >> +
118 >> +# @FUNCTION: dosym8
119 >> +# @USAGE: [-r] <target> <link>
120 >> +# @DESCRIPTION:
121 >> +# Create a symbolic link <link>, pointing to <target>. If the
122 >> +# directory containing the new link does not exist, create it.
123 >> +#
124 >> +# If called with option -r, expand <target> relative to the apparent
125 >> +# path of the directory containing <link>. For example, "dosym8 -r
126 >> +# /bin/foo /usr/bin/foo" will create a link named "../../bin/foo".
127 >> +dosym8() {
128 >> + local option_r
129 >> +
130 >> + case $1 in
131 >> + -r) option_r=t; shift ;;
132 >> + esac
133 >> +
134 >> + [[ $# -eq 2 ]] || die "${FUNCNAME}: bad number of arguments"
135 >> +
136 >> + local target=$1 link=$2
137 >> +
138 >> + if [[ ${option_r} ]]; then
139 >> + local linkdir comp
140 >> +
141 >> + # Expansion makes sense only for an absolute target path
142 >> + [[ ${target} == /* ]] \
143 >> + || die "${FUNCNAME}: -r specified but no absolute
144 >> target path"
145 >> +
146 >> + target=$(_dosym8_canonicalize "${target}")
147 >> + linkdir=$(_dosym8_canonicalize "/${link#/}")
148 >> + linkdir=${linkdir%/*} # poor man's dirname(1)
149 >> + linkdir=${linkdir:-/} # always keep the initial "/"
150 >> +
151 >> + local ifs_save=${IFS-$' \t\n'} IFS=/
152 >> + for comp in ${linkdir}; do
153 >> + if [[ ${target%%/*} == "${comp}" ]]; then
154 >> + target=${target#"${comp}"}
155 >> + target=${target#/}
156 >> + else
157 >> + target=..${target:+/}${target}
158 >> + fi
159 >> + done
160 >> + IFS=${ifs_save}
161 >> + target=${target:-.}
162 >> + fi
163 >> +
164 >> + dosym "${target}" "${link}"
165 >> +}
166 >> --
167 >> 2.29.2
168 >>
169 >>
170 >>