Skip to content

Commit

Permalink
main (ble/util/readlink): work around non-standard or missing "readlink"
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Jul 28, 2022
1 parent e5501a3 commit d785f5d
Showing 1 changed file with 107 additions and 32 deletions.
139 changes: 107 additions & 32 deletions ble.pp
Expand Up @@ -131,11 +131,17 @@ function ble/restore-bash-options {
_ble_init_original_IFS=$IFS
IFS=$' \t\n'

_ble_bash_loaded_in_function=0
[[ ${FUNCNAME+set} ]] && _ble_bash_loaded_in_function=1

#------------------------------------------------------------------------------
# check environment

function ble/util/print { builtin printf '%s\n' "$1"; }

# will be overwritten by src/util.sh
function ble/util/assign { builtin eval "$1=\$(builtin eval -- \"\${@:2}\")"; }

# ble/bin

## 関数 ble/bin/.default-utility-path commands...
Expand Down Expand Up @@ -165,11 +171,11 @@ function ble/bin/.freeze-utility-path {
}

if ((_ble_bash>=40000)); then
function ble/bin#has { type "$@" &>/dev/null; }
function ble/bin#has { type -t "$@" &>/dev/null; }
else
function ble/bin#has {
local cmd
for cmd; do type "$cmd" || return 1; done &>/dev/null
for cmd; do type -t "$cmd" || return 1; done &>/dev/null
return 0
}
fi
Expand Down Expand Up @@ -241,43 +247,112 @@ function ble/bin/awk.use-solaris-xpg4 {
}

#------------------------------------------------------------------------------
# readlink -f (Originally taken from akinomyoga/mshex.git)

_ble_bash_loaded_in_function=0
[[ ${FUNCNAME+set} ]] && _ble_bash_loaded_in_function=1
## @fn ble/util/readlink path
## @var[out] ret

# will be overwritten by ble-core.sh
function ble/util/assign {
builtin eval "$1=\$(builtin eval \"\${@:2}\")"
}
if ((_ble_bash>=40000)); then
_ble_util_readlink_visited_init='local -A visited=()'
function ble/util/readlink/.visited {
[[ ${visited[$1]+set} ]] && return 0
visited[$1]=1
return 1
}
else
_ble_util_readlink_visited_init="local -a visited=()"
function ble/util/readlink/.visited {
local key
for key in "${visited[@]}"; do
[[ $1 == "$key" ]] && return 0
done
visited=("$1" "${visited[@]}")
return 1
}
fi

# readlink -f (taken from akinomyoga/mshex.git)
function ble/util/readlink {
ret=
## @fn ble/util/readlink/.readlink path
## @var[out] link
function ble/util/readlink/.readlink {
local path=$1
case "$OSTYPE" in
(cygwin|msys|linux-gnu)
# 少なくとも cygwin, GNU/Linux では readlink -f が使える
ble/util/assign ret 'PATH=/bin:/usr/bin readlink -f "$path"' ;;
(darwin*|*)
# Mac OSX には readlink -f がない。
local PWD=$PWD OLDPWD=$OLDPWD
while [[ -h $path ]]; do
local link; ble/util/assign link 'PATH=/bin:/usr/bin readlink "$path" 2>/dev/null || true'
[[ $link ]] || break

if [[ $link = /* || $path != */* ]]; then
# * $link ~ 絶対パス の時
# * $link ~ 相対パス かつ ( $path が現在のディレクトリにある ) の時
path=$link
else
local dir=${path%/*}
path=${dir%/}/$link
fi
done
ret=$path ;;
if ble/bin#has ble/bin/readlink; then
ble/util/assign link 'ble/bin/readlink -- "$path"'
[[ $link ]]
elif ble/bin#has ble/bin/ls; then
ble/util/assign link 'ble/bin/ls -ld -- "$path"' &&
[[ $link == *" $path -> "?* ]] &&
link=${link#*" $path -> "}
else
false
fi
} 2>/dev/null
## @fn ble/util/readlink/.resolve-physical-directory
## @var[in,out] path
function ble/util/readlink/.resolve-physical-directory {
[[ $path == */?* ]] || return 0
local PWD=$PWD OLDPWD=$OLDPWD CDPATH=
builtin cd -L . &&
local pwd=$PWD &&
builtin cd -P "${path%/*}/" &&
path=${PWD%/}/${path##*/}
builtin cd -L "$pwd"
return 0
}
function ble/util/readlink/.resolve-loop {
local path=$ret
builtin eval -- "$_ble_util_readlink_visited_init"
while [[ -h $path ]]; do
local link
ble/util/readlink/.visited "$path" && break
ble/util/readlink/.readlink "$path" || break
if [[ $link == /* || $path != */* ]]; then
path=$link
else
# 相対パス ../ は物理ディレクトリ構造に従って遡る。
ble/util/readlink/.resolve-physical-directory
path=${path%/}/$link
fi
while [[ $path == ?*/ ]]; do path=${path%/}; done
done
ret=$path
}
function ble/util/readlink/.resolve {
# 初回呼び出し時に実装を選択
_ble_util_readlink_type=

# より効率的な実装が可能な場合は ble/util/readlink/.resolve を独自定義。
case $OSTYPE in
(cygwin | msys | linux-gnu)
# これらのシステムの標準 readlink では readlink -f が使える。
#
# Note: 例えば NixOS では標準の readlink を使おうとすると問題が起こるらしい
# ので、見えている readlink を使う。見えている readlink が非標準の時は -f
# が使えるか分からないので readlink -f による実装は有効化しない。
#
local readlink
ble/util/assign readlink 'type -P readlink'
case $readlink in
(/bin/readlink | /usr/bin/readlink)
_ble_util_readlink_type=readlink-f
builtin eval "function ble/util/readlink/.resolve { ble/util/assign ret '$readlink -f -- \"\$ret\"'; }" ;;
esac ;;
esac

if [[ ! $_ble_util_readlink_type ]]; then
_ble_util_readlink_type=loop
ble/bin/.freeze-utility-path readlink ls
function ble/util/readlink/.resolve { ble/util/readlink/.resolve-loop; }
fi

ble/util/readlink/.resolve
}
function ble/util/readlink {
ret=$1
if [[ -h $ret ]]; then ble/util/readlink/.resolve; fi
}

#---------------------------------------

function ble/base/.create-user-directory {
local var=$1 dir=$2
if [[ ! -d $dir ]]; then
Expand Down

0 comments on commit d785f5d

Please sign in to comment.