Make relative_path match full dir and not just a prefix
Before this change, relative_path "/A/B/C" "/A/B/CD" would return "" instead of the correct "../CD".
This commit is contained in:
parent
0b91140ea8
commit
b164d03594
2 changed files with 53 additions and 53 deletions
|
@ -11,11 +11,16 @@ import pytest
|
||||||
("/A/B/C", "/A/B/C", ""),
|
("/A/B/C", "/A/B/C", ""),
|
||||||
("/A/B/C", "/A/B/C/D", "D"),
|
("/A/B/C", "/A/B/C/D", "D"),
|
||||||
("/A/B/C", "/A/B/C/D/E", "D/E"),
|
("/A/B/C", "/A/B/C/D/E", "D/E"),
|
||||||
|
("/A/B/C", "/A/B/CD", "../CD"),
|
||||||
|
("/A/B/C", "/A/BB/C", "../../BB/C"),
|
||||||
("/A/B/C", "/A/B/D", "../D"),
|
("/A/B/C", "/A/B/D", "../D"),
|
||||||
("/A/B/C", "/A/B/D/E", "../D/E"),
|
("/A/B/C", "/A/B/D/E", "../D/E"),
|
||||||
("/A/B/C", "/A/D", "../../D"),
|
("/A/B/C", "/A/D", "../../D"),
|
||||||
("/A/B/C", "/A/D/E", "../../D/E"),
|
("/A/B/C", "/A/D/E", "../../D/E"),
|
||||||
("/A/B/C", "/D/E/F", "../../../D/E/F"),
|
("/A/B/C", "/D/E/F", "../../../D/E/F"),
|
||||||
|
("/", "/A/B/C", "A/B/C"),
|
||||||
|
("/A/B/C", "/", "../../.."),
|
||||||
|
("/A/B B/C", "/A/C C/D", "../../C C/D"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_relative_path(runner, paths, base, full_path, expected):
|
def test_relative_path(runner, paths, base, full_path, expected):
|
||||||
|
|
101
yadm
101
yadm
|
@ -759,16 +759,13 @@ function alt_linking() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ln_relative() {
|
function ln_relative() {
|
||||||
local full_source full_target target_dir
|
local source="$1"
|
||||||
local full_source="$1"
|
local target="$2"
|
||||||
local full_target="$2"
|
|
||||||
local target_dir="${full_target%/*}"
|
|
||||||
if [ "$target_dir" == "" ]; then
|
|
||||||
target_dir="/"
|
|
||||||
fi
|
|
||||||
local rel_source
|
local rel_source
|
||||||
rel_source=$(relative_path "$target_dir" "$full_source")
|
rel_source=$(relative_path "$(builtin_dirname "$target")" "$source")
|
||||||
ln -nfs "$rel_source" "$full_target"
|
|
||||||
|
ln -nfs "$rel_source" "$target"
|
||||||
alt_linked+=("$rel_source")
|
alt_linked+=("$rel_source")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2011,61 +2008,59 @@ function parse_encrypt() {
|
||||||
function builtin_dirname() {
|
function builtin_dirname() {
|
||||||
# dirname is not builtin, and universally available, this is a built-in
|
# dirname is not builtin, and universally available, this is a built-in
|
||||||
# replacement using parameter expansion
|
# replacement using parameter expansion
|
||||||
path="$1"
|
local path="$1"
|
||||||
dname="${path%/*}"
|
while [ "${path: -1}" = "/" ]; do
|
||||||
if ! [[ "$path" =~ / ]]; then
|
path="${path%/}"
|
||||||
echo "."
|
done
|
||||||
elif [ "$dname" = "" ]; then
|
|
||||||
echo "/"
|
local dir_name="${path%/*}"
|
||||||
else
|
while [ "${dir_name: -1}" = "/" ]; do
|
||||||
echo "$dname"
|
dir_name="${dir_name%/}"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$path" = "$dir_name" ]; then
|
||||||
|
dir_name="."
|
||||||
|
elif [ -z "$dir_name" ]; then
|
||||||
|
dir_name="/"
|
||||||
fi
|
fi
|
||||||
|
echo "$dir_name"
|
||||||
}
|
}
|
||||||
|
|
||||||
function relative_path() {
|
function relative_path() {
|
||||||
# Output a path to $2/full, relative to $1/base
|
# Output a path to $2/full, relative to $1/base
|
||||||
#
|
#
|
||||||
# This fucntion created with ideas from
|
# This function created with ideas from
|
||||||
# https://stackoverflow.com/questions/2564634
|
# https://stackoverflow.com/questions/2564634
|
||||||
base="$1"
|
local base="$1"
|
||||||
full="$2"
|
if [ "${base:0:1}" != "/" ]; then
|
||||||
|
base="$PWD/$base"
|
||||||
|
fi
|
||||||
|
|
||||||
common_part="$base"
|
local full="$2"
|
||||||
result=""
|
if [ "${full:0:1}" != "/" ]; then
|
||||||
|
full="$PWD/$full"
|
||||||
|
fi
|
||||||
|
|
||||||
count=0
|
local common_part="$base"
|
||||||
while [ "${full#"$common_part"}" == "${full}" ]; do
|
local result=""
|
||||||
[ "$count" = "500" ] && return # this is a failsafe
|
|
||||||
# no match, means that candidate common part is not correct
|
while [ "$common_part" != "$full" ]; do
|
||||||
# go up one level (reduce common part)
|
if [ "$common_part" = "/" ]; then
|
||||||
common_part="$(builtin_dirname "$common_part")"
|
# No common part found. Append / if result is set to make the final
|
||||||
# and record that we went back, with correct / handling
|
# result correct.
|
||||||
if [[ -z $result ]]; then
|
result="${result:+$result/}"
|
||||||
result=".."
|
break
|
||||||
else
|
elif [ "${full#"$common_part"/}" != "$full" ]; then
|
||||||
result="../$result"
|
common_part="$common_part/"
|
||||||
fi
|
result="${result:+$result/}"
|
||||||
count=$((count+1))
|
break
|
||||||
|
fi
|
||||||
|
# Move to parent directory and update result
|
||||||
|
common_part=$(builtin_dirname "$common_part")
|
||||||
|
result="..${result:+/$result}"
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ $common_part == "/" ]]; then
|
echo "$result${full#"$common_part"}"
|
||||||
# special case for root (no common path)
|
|
||||||
result="$result/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# since we now have identified the common part,
|
|
||||||
# compute the non-common part
|
|
||||||
forward_part="${full#"$common_part"}"
|
|
||||||
|
|
||||||
# and now stick all parts together
|
|
||||||
if [[ -n $result ]] && [[ -n $forward_part ]]; then
|
|
||||||
result="$result$forward_part"
|
|
||||||
elif [[ -n $forward_part ]]; then
|
|
||||||
# extra slash removal
|
|
||||||
result="${forward_part:1}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$result"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ****** Auto Functions ******
|
# ****** Auto Functions ******
|
||||||
|
|
Loading…
Reference in a new issue