Skip to content

Commit

Permalink
feat(_comp_abspath): handle ".."
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Aug 23, 2024
1 parent e1a70c6 commit d599dcf
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 10 deletions.
23 changes: 15 additions & 8 deletions bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -2181,15 +2181,22 @@ _comp_compgen_fstypes()
_comp_abspath()
{
REPLY=$1
case $REPLY in
/*) ;;
../*) REPLY=$PWD/${REPLY:3} ;;
*) REPLY=$PWD/$REPLY ;;
esac
while [[ $REPLY == */./* ]]; do
REPLY=${REPLY//\/.\//\/}
done
[[ $REPLY == /* ]] || REPLY=$PWD/$REPLY
REPLY=${REPLY//+(\/)/\/}
while true; do
# Process "." and "..". To avoid reducing "/../../ => /", we convert
# "/*/../" one by one. "/.." at the beginning is ignored. Then, /*/../
# in the middle is processed. Finally, /*/.. at the end is removed.
case $REPLY in
*/./*) REPLY=${REPLY//\/.\//\/} ;;
*/.) REPLY=${REPLY%/.} ;;
/..?(/*)) REPLY=${REPLY#/..} ;;
*/+([^/])/../*) REPLY=${REPLY/\/+([^\/])\/..\//\/} ;;
*/+([^/])/..) REPLY=${REPLY%/+([^/])/..} ;;
*) break ;;
esac
done
[[ $REPLY ]] || REPLY=/
}

# Get real command.
Expand Down
130 changes: 128 additions & 2 deletions test/t/unit/test_unit_abspath.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def test_relative(self, bash, functions):
)
assert output.strip().endswith("/shared/foo/bar")

def test_cwd(self, bash, functions):
def test_cwd1(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester ./foo/./bar",
Expand All @@ -55,7 +55,34 @@ def test_cwd(self, bash, functions):
)
assert output.strip().endswith("/shared/foo/bar")

def test_parent(self, bash, functions):
def test_cwd2(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /.",
want_output=True,
want_newline=False,
)
assert output.strip() == "/"

def test_cwd3(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /foo/.",
want_output=True,
want_newline=False,
)
assert output.strip() == "/foo"

def test_cwd4(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /././.",
want_output=True,
want_newline=False,
)
assert output.strip() == "/"

def test_parent1(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester ../shared/foo/bar",
Expand All @@ -65,3 +92,102 @@ def test_parent(self, bash, functions):
assert output.strip().endswith(
"/shared/foo/bar"
) and not output.strip().endswith("../shared/foo/bar")

def test_parent2(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /foo/..",
want_output=True,
want_newline=False,
)
assert output.strip() == "/"

def test_parent3(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /..",
want_output=True,
want_newline=False,
)
assert output.strip() == "/"

def test_parent4(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /../foo/bar",
want_output=True,
want_newline=False,
)
assert output.strip() == "/foo/bar"

def test_parent5(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /../../foo/bar",
want_output=True,
want_newline=False,
)
assert output.strip() == "/foo/bar"

def test_parent6(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /foo/../bar",
want_output=True,
want_newline=False,
)
assert output.strip() == "/bar"

def test_parent7(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /foo/../../bar",
want_output=True,
want_newline=False,
)
assert output.strip() == "/bar"

def test_parent8(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /dir1/dir2/dir3/../dir4/../../foo",
want_output=True,
want_newline=False,
)
assert output.strip() == "/dir1/foo"

def test_parent9(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester //dir1/dir2///../foo",
want_output=True,
want_newline=False,
)
assert output.strip() == "/dir1/foo"

def test_parent10(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /dir1/dir2/dir3/..",
want_output=True,
want_newline=False,
)
assert output.strip() == "/dir1/dir2"

def test_parent11(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /dir1/dir2/dir3/../..",
want_output=True,
want_newline=False,
)
assert output.strip() == "/dir1"

def test_parent12(self, bash, functions):
output = assert_bash_exec(
bash,
"__tester /dir1/dir2/dir3/../../../..",
want_output=True,
want_newline=False,
)
assert output.strip() == "/"

0 comments on commit d599dcf

Please sign in to comment.