Fix more inconsistent behaviour with symlinks in paths.

Both redo and minimal/do were doing slightly weird things with
symlinked directories, especially when combined with "..".  For
example, if x is a link to ., then x/x/x/x/../y should resolve to
"../y", which is quite non-obvious.

Added some tests to make sure this stays fixed.
This commit is contained in:
Avery Pennarun 2018-12-17 15:58:06 +00:00
commit 686c381109
13 changed files with 121 additions and 8 deletions

2
t/.gitignore vendored
View file

@ -3,5 +3,7 @@
/shellfail
/shelltest.warned
/shelltest.failed
/shlink
/stress.log
/symlink path
/flush-cache

5
t/105-sympath/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
/*.dyn
/src
/x
/y

31
t/105-sympath/all.do Normal file
View file

@ -0,0 +1,31 @@
redo-ifchange ../flush-cache
rm -f src
: >src
for iter in 10 20; do
rm -rf y
rm -f x *.dyn static
mkdir y
: >y/static
ln -s . y/x
../flush-cache
(
cd y/x/x/x/x/x
IFS=$(printf '\n')
redo-ifchange static x/x/x/static $PWD/static \
$(/bin/pwd)/static /etc/passwd
redo-ifchange $PWD/../static 2>/dev/null && exit 35
redo-ifchange 1.dyn x/x/x/2.dyn $PWD/3.dyn \
$PWD/../4.dyn $(/bin/pwd)/5.dyn
)
[ -e y/1.dyn ] || exit $((iter + 1))
[ -e y/2.dyn ] || exit $((iter + 2))
[ -e y/3.dyn ] || exit $((iter + 3))
[ -e 4.dyn ] || exit $((iter + 4))
[ -e y/5.dyn ] || exit $((iter + 5))
# Second iteration won't work in minimal/do since it only ever
# builds things once.
. ../skip-if-minimal-do.sh
done

2
t/105-sympath/clean.do Normal file
View file

@ -0,0 +1,2 @@
rm -rf y
rm -f src x *.dyn *~ .*~

View file

@ -0,0 +1,2 @@
redo-ifchange src
echo dynamic >$3

View file

@ -2,6 +2,6 @@
sed 's/\.do$//' |
xargs redo
rm -f broken shellfile shellfail shelltest.warned shelltest.failed \
*~ .*~ stress.log flush-cache
rm -f broken shellfile shellfail shelltest.warned shelltest.failed shlink \
*~ .*~ stress.log flush-cache 'symlink path'
rm -rf 'space home dir'

View file

@ -474,6 +474,12 @@ set x y z
x=$(printf "a%-5sc" "b")
[ "$x" = "ab c" ] || warn 119
# Make sure cd supports -L and -P options properly
rm -f shlink
ln -s . shlink
(cd -L shlink/shlink/shlink/../shlink) || fail 120
(cd -P shlink/shlink/shlink/../shlink) && fail 121
[ -e shelltest.failed ] && exit 41
[ -e shelltest.warned ] && exit 42
exit 40