From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 11E41138359 for ; Thu, 19 Nov 2020 15:29:26 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id B1DE2E0828; Thu, 19 Nov 2020 15:29:23 +0000 (UTC) Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [IPv6:2a00:1450:4864:20::52e]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 67DD4E07B3 for ; Thu, 19 Nov 2020 15:29:23 +0000 (UTC) Received: by mail-ed1-x52e.google.com with SMTP id y4so6248279edy.5 for ; Thu, 19 Nov 2020 07:29:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gentoo-org.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=9xEZOP2KcCoWbxi6gLycKpFZb8Ic7YRFr2rm7TbKDuA=; b=YJfY/RDTu0alhQXvjkpa7R9gl2szwxB5cUUpJsByKFy2TqR+b+eNbC8r4S156D8Rzq J1FJKijHPftau09hv4aRMmbyuYO4F9+97TWbOcg1EL9npvfSHS5fFTo3kjeomo669Sz1 2IMJczTmx02y5Ec7QksULFzSLYpQeTDxvkyS5u8RqMSdkLZ1vbF4M+9/0Y8/++yrZXic SQSrx0KJelk512cUrTu10EMhfKwX9koY3hmthr2svul0KberO74kjQr6wV48XSJDdkxX A0xTDhNFFR5uVvv6K083ARh1DUvtGyGZFIUXaQgS1dW0FQF7JQJg4nFptR2/cK8OLSe9 QQ8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=9xEZOP2KcCoWbxi6gLycKpFZb8Ic7YRFr2rm7TbKDuA=; b=GWo5LmjXivACRzVxbskJ9u8FBbsjrIUMxFU/FU/CRt2u8d/msslIoR0Vam1l/OgLN0 iLop17RnZnNACqfz+PeiWpoO8JyjoXpX+/JVNY6ax4ndQw/4U383M7YI7MvjKIC5pemY w160PshbfgFaxCsS916rLYtCQhprp5aoGeP003rbMrSTojub3GDQomiUR0nX40O5tQcH G74IFpxU0cGaL/2Oze+Z/wOn38Px6uX0ksvfWoqge7zFgMkjBhW2kuQGz6eMwsHz8RkF 8XB3luaPhxnEk+S6B1UF2vhkvVHoBVI4Wd/WI2HUC86k+y5tBq0vr27IETR9PehxETon 1GBg== X-Gm-Message-State: AOAM530IO/wOKe870uA6HvqYOJLuV8qi0rbgm6ASrrGoAd6gDgVSEZRz F4bBC0KHnq67Oakzq6//ZLv8ixsPvKYu6laFhHOFoOCrtOeT/Ff5 X-Google-Smtp-Source: ABdhPJwRbLyCnvrZ0nbsxl28XjKtc+rPuud+D7viDwE88xZ28c0LVG/ZkRjKqwbxYy2coFV8SUxKP0/5ar7tbH1jzGE= X-Received: by 2002:a50:a410:: with SMTP id u16mr513054edb.274.1605799761657; Thu, 19 Nov 2020 07:29:21 -0800 (PST) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-dev@lists.gentoo.org Reply-to: gentoo-dev@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply MIME-Version: 1.0 References: <20201119103150.22841-1-ulm@gentoo.org> In-Reply-To: From: Alec Warner Date: Thu, 19 Nov 2020 07:29:10 -0800 Message-ID: Subject: Re: [gentoo-dev] [PATCH 1/2] eapi8-dosym.eclass: New eclass. To: Gentoo Dev Cc: =?UTF-8?Q?Ulrich_M=C3=BCller?= Content-Type: multipart/alternative; boundary="00000000000060031105b47764cc" X-Archives-Salt: d1bfdab2-6eb5-4d14-a051-ab5d51c0e3b0 X-Archives-Hash: 506ae91caf07bf844a5b5c129c200991 --00000000000060031105b47764cc Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Thu, Nov 19, 2020 at 7:28 AM Alec Warner wrote: > > > On Thu, Nov 19, 2020 at 2:32 AM Ulrich M=C3=BCller 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 " will expand the (apparent) path of >> relative to the (apparent) path of the directory containing . >> 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 or . 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=C3=BCller >> --- >> 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 >> +# @AUTHOR: >> +# Ulrich M=C3=BCller >> +# @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=3D${EAPI:-0} not supported" ;; >> +esac >> + >> +# @FUNCTION: _dosym8_canonicalize >> +# @USAGE: >> +# @INTERNAL >> +# @DESCRIPTION: >> +# Transparent bash-only replacement for GNU "realpath -m -s". >> +# Resolve references to "/./", "/../" and remove extra "/" characters >> +# from , 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=3D/ >> + >> + path=3D( $1 ) >> + [[ $1 =3D=3D /* ]] && slash=3D/ >> + >> + while true; do >> + # Find first instance of non-".." path component followe= d >> by "..", >> + # or as a special case, "/.." at the beginning of the >> path. >> + # Also drop empty and "." path components as we go along= . >> + prev=3D >> + for i in ${!path[@]}; do >> + if [[ -z ${path[i]} || ${path[i]} =3D=3D . ]]; t= hen >> + unset "path[i]" >> + elif [[ ${path[i]} !=3D .. ]]; then >> + prev=3D${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=3D"${slash}${path[*]}" >> + echo "${out:-.}" >> +} >> + >> +# @FUNCTION: dosym8 >> +# @USAGE: [-r] >> +# @DESCRIPTION: >> +# Create a symbolic link , pointing to . If the >> +# directory containing the new link does not exist, create it. >> +# >> +# If called with option -r, expand relative to the apparent >> +# path of the directory containing . 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=3Dt; shift ;; >> + esac >> + >> + [[ $# -eq 2 ]] || die "${FUNCNAME}: bad number of arguments" >> + >> + local target=3D$1 link=3D$2 >> + >> + if [[ ${option_r} ]]; then >> + local linkdir comp >> + >> + # Expansion makes sense only for an absolute target path >> + [[ ${target} =3D=3D /* ]] \ >> + || die "${FUNCNAME}: -r specified but no absolut= e >> target path" >> + >> + target=3D$(_dosym8_canonicalize "${target}") >> + linkdir=3D$(_dosym8_canonicalize "/${link#/}") >> + linkdir=3D${linkdir%/*} # poor man's dirname(1) >> + linkdir=3D${linkdir:-/} # always keep the initial "/" >> + >> + local ifs_save=3D${IFS-$' \t\n'} IFS=3D/ >> + for comp in ${linkdir}; do >> + if [[ ${target%%/*} =3D=3D "${comp}" ]]; then >> + target=3D${target#"${comp}"} >> + target=3D${target#/} >> + else >> + target=3D..${target:+/}${target} >> + fi >> + done >> + IFS=3D${ifs_save} >> + target=3D${target:-.} >> + fi >> + >> + dosym "${target}" "${link}" >> +} >> -- >> 2.29.2 >> >> >> --00000000000060031105b47764cc Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


=
On Thu, Nov 19, 2020 at 7:28 AM Alec = Warner <antarus@gentoo.org>= wrote:


On Thu, Nov 19, 2020 at 2:32 AM Ulrich M=C3= =BCller <ulm@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 look= s at
the specified apparent paths, without touching any actual files in ED
or EROOT.

Signed-off-by: Ulrich M=C3=BCller <ulm@gentoo.org>
---
=C2=A0eclass/eapi8-dosym.eclass | 108 +++++++++++++++++++++++++++++++++++++= +
=C2=A01 file changed, 108 insertions(+)
=C2=A0create 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 <pms@gen= too.org>
+# @AUTHOR:
+# Ulrich M=C3=BCller <ulm@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
+=C2=A0 =C2=A0 =C2=A0 =C2=A05|6|7) ;;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0*) die "${ECLASS}: EAPI=3D${EAPI:-0} not s= upported" ;;
+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 fu= nction (particularly around edge cases.)
I see eclass/tests exist= s, could we add a couple for this?

<= /div>
hah, and you added them in the second patch, sorry I didn't r= ead ahead! :)

-A
=C2=A0
=C2=A0
+_dosym8_canonicalize() {

in dosym8() y= ou save and restore IFS, but you don't here, is there a reason for that= ?
=C2=A0
+=C2=A0 =C2=A0 =C2=A0 =C2=A0local path slash i prev out IFS=3D/
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0path=3D( $1 )
+=C2=A0 =C2=A0 =C2=A0 =C2=A0[[ $1 =3D=3D /* ]] && slash=3D/
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0while true; do
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Find first instan= ce of non-".." path component followed by "..",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# or as a special c= ase, "/.." at the beginning of the path.
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Also drop empty a= nd "." path components as we go along.
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0prev=3D
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for i in ${!path[@]= }; do
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0if [[ -z ${path[i]} || ${path[i]} =3D=3D . ]]; then
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0unset "path[i]"
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0elif [[ ${path[i]} !=3D .. ]]; then
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0prev=3D${i}
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0elif [[ ${prev} || ${slash} ]]; then
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Found, remove path components and r= eiterate
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0[[ ${prev} ]] && unset "= path[prev]"
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0unset "path[i]"
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0continue 2
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0fi
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0done
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# No (further) inst= ance found, so we're done
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break
+=C2=A0 =C2=A0 =C2=A0 =C2=A0done
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0out=3D"${slash}${path[*]}"
+=C2=A0 =C2=A0 =C2=A0 =C2=A0echo "${out:-.}"
+}
+
+# @FUNCTION: dosym8
+# @USAGE: [-r] <target> <link>
+# @DESCRIPTION:
+# Create a symbolic link <link>, pointing to <target>.=C2=A0 I= f 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>.=C2=A0 For example, "= dosym8 -r
+# /bin/foo /usr/bin/foo" will create a link named "../../bin/foo= ".
+dosym8() {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0local option_r
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0case $1 in
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-r) option_r=3Dt; s= hift ;;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0esac
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0[[ $# -eq 2 ]] || die "${FUNCNAME}: bad nu= mber of arguments"
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0local target=3D$1 link=3D$2
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if [[ ${option_r} ]]; then
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0local linkdir comp<= br> +
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Expansion makes s= ense only for an absolute target path
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0[[ ${target} =3D=3D= /* ]] \
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0|| die "${FUNCNAME}: -r specified but no absolute target pat= h"
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target=3D$(_dosym8_= canonicalize "${target}")
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0linkdir=3D$(_dosym8= _canonicalize "/${link#/}")
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0linkdir=3D${linkdir= %/*}=C2=A0 =C2=A0# poor man's dirname(1)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0linkdir=3D${linkdir= :-/}=C2=A0 =C2=A0# always keep the initial "/"
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0local ifs_save=3D${= IFS-$' \t\n'} IFS=3D/
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for comp in ${linkd= ir}; do
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0if [[ ${target%%/*} =3D=3D "${comp}" ]]; then
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target=3D${target#"${comp}"= }
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target=3D${target#/}
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0else
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target=3D..${target:+/}${target}
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0fi
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0done
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0IFS=3D${ifs_save} +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target=3D${target:-= .}
+=C2=A0 =C2=A0 =C2=A0 =C2=A0fi
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0dosym "${target}" "${link}"=
+}
--
2.29.2


--00000000000060031105b47764cc--