Add function relative_path

This function will create a path relative to another, without the use of
an external program like dirname.
This commit is contained in:
Tim Byrne 2019-11-17 12:58:49 -06:00
parent f8d6d2b0e4
commit 98392b9a9c
No known key found for this signature in database
GPG Key ID: 14DB4FC2465A4B12
2 changed files with 91 additions and 0 deletions

View File

@ -0,0 +1,31 @@
"""Unit tests: relative_path"""
import pytest
@pytest.mark.parametrize(
'base,full_path,expected',
[
("/A/B/C", "/A", "../.."),
("/A/B/C", "/A/B", ".."),
("/A/B/C", "/A/B/C", ""),
("/A/B/C", "/A/B/C/D", "D"),
("/A/B/C", "/A/B/C/D/E", "D/E"),
("/A/B/C", "/A/B/D", "../D"),
("/A/B/C", "/A/B/D/E", "../D/E"),
("/A/B/C", "/A/D", "../../D"),
("/A/B/C", "/A/D/E", "../../D/E"),
("/A/B/C", "/D/E/F", "../../../D/E/F"),
],
)
def test_relative_path(runner, paths, base, full_path, expected):
"""Test translate_to_relative"""
script = f"""
YADM_TEST=1 source {paths.pgm}
relative_path "{base}" "{full_path}"
"""
run = runner(command=['bash'], inp=script)
assert run.success
assert run.err == ''
assert run.out.strip() == expected

60
yadm
View File

@ -1592,6 +1592,66 @@ function parse_encrypt() {
}
function builtin_dirname() {
# dirname is not builtin, and universally available, this is a built-in
# replacement using parameter expansion
path="$1"
dname="${path%/*}"
if ! [[ "$path" =~ / ]]; then
echo "."
elif [ "$dname" = "" ]; then
echo "/"
else
echo "$dname"
fi
}
function relative_path() {
# Output a path to $2/full, relative to $1/base
#
# This fucntion created with ideas from
# https://stackoverflow.com/questions/2564634
base="$1"
full="$2"
common_part="$base"
result=""
count=0
while [ "${full#$common_part}" == "${full}" ]; do
[ "$count" = "500" ] && return # this is a failsafe
# no match, means that candidate common part is not correct
# go up one level (reduce common part)
common_part="$(builtin_dirname "$common_part")"
# and record that we went back, with correct / handling
if [[ -z $result ]]; then
result=".."
else
result="../$result"
fi
count=$((count+1))
done
if [[ $common_part == "/" ]]; then
# 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 ******
function auto_alt() {