checkout: don't follow symlinks when removing entries
commitfab78a0c3defddff87ea5aa7dd32c5e444c43f1f
authorMatheus Tavares <matheus.bernardino@usp.br>
Thu, 18 Mar 2021 18:43:47 +0000 (18 15:43 -0300)
committerJunio C Hamano <gitster@pobox.com>
Thu, 18 Mar 2021 19:58:10 +0000 (18 12:58 -0700)
treed18015c917149b5b89c61f96d5857d60dfa7ef14
parent462b4e8dfd688b8964da77daf17b64da5bdc54ad
checkout: don't follow symlinks when removing entries

At 1d718a5108 ("do not overwrite untracked symlinks", 2011-02-20),
symlink.c:check_leading_path() started returning different codes for
FL_ENOENT and FL_SYMLINK. But one of its callers, unlink_entry(), was
not adjusted for this change, so it started to follow symlinks on the
leading path of to-be-removed entries. Fix that and add a regression
test.

Note that since 1d718a5108 check_leading_path() no longer differentiates
the case where it found a symlink in the path's leading components from
the cases where it found a regular file or failed to lstat() the
component. So, a side effect of this current patch is that
unlink_entry() now returns early in all of these three cases. And
because we no longer try to unlink such paths, we also don't get the
warning from remove_or_warn().

For the regular file and symlink cases, it's questionable whether the
warning was useful in the first place: unlink_entry() removes tracked
paths that should no longer be present in the state we are checking out
to. If the path had its leading dir replaced by another file, it means
that the basename already doesn't exist, so there is no need for a
warning. Sure, we are leaving a regular file or symlink behind at the
path's dirname, but this file is either untracked now (so again, no
need to warn), or it will be replaced by a tracked file during the next
phase of this checkout operation.

As for failing to lstat() one of the leading components, the basename
might still exist only we cannot unlink it (e.g. due to the lack of the
required permissions). Since the user expect it to be removed
(especially with checkout's --no-overlay option), add back the warning
in this more relevant case.

Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
cache.h
entry.c
symlinks.c
t/t2021-checkout-overwrite.sh
unpack-trees.c