Skip to content

Commit

Permalink
rm: do not complain about d/f conflicts during deletion
Browse files Browse the repository at this point in the history
If we used to have an index entry "d/f", but "d" has been
replaced by a non-directory entry, the user may still want
to run "git rm" to delete the stale index entry. They could
use "git rm --cached" to just touch the index, but "git rm"
should also work: we explicitly try to handle the case that
the file has already been removed from the working tree.

However, because unlinking "d/f" in this case will not yield
ENOENT, but rather ENOTDIR, we do not notice that the file
is already gone. Instead, we report it as an error.

The simple solution is to treat ENOTDIR in this case exactly
like ENOENT; all we want to know is whether the file is
already gone, and if a leading path is no longer a
directory, then by definition the sub-path is gone.

Reported-by: jpinheiro <7jpinheiro@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Apr 4, 2013
1 parent 9b924ee commit 9a6728d
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
2 changes: 1 addition & 1 deletion builtin/rm.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ static int check_local_mod(unsigned char *head, int index_only)
ce = active_cache[pos];

if (lstat(ce->name, &st) < 0) {
if (errno != ENOENT)
if (errno != ENOENT && errno != ENOTDIR)
warning("'%s': %s", ce->name, strerror(errno));
/* It already vanished from the working tree */
continue;
Expand Down
2 changes: 1 addition & 1 deletion dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1603,7 +1603,7 @@ int remove_path(const char *name)
{
char *slash;

if (unlink(name) && errno != ENOENT)
if (unlink(name) && errno != ENOENT && errno != ENOTDIR)
return -1;

slash = strrchr(name, '/');
Expand Down
25 changes: 25 additions & 0 deletions t/t3600-rm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -622,4 +622,29 @@ test_expect_success 'rm of a populated nested submodule with a nested .git direc
rm -rf submod
'

test_expect_success 'rm of d/f when d has become a non-directory' '
rm -rf d &&
mkdir d &&
>d/f &&
git add d &&
rm -rf d &&
>d &&
git rm d/f &&
test_must_fail git rev-parse --verify :d/f &&
test_path_is_file d
'

test_expect_success SYMLINKS 'rm of d/f when d has become a dangling symlink' '
rm -rf d &&
mkdir d &&
>d/f &&
git add d &&
rm -rf d &&
ln -s nonexistent d &&
git rm d/f &&
test_must_fail git rev-parse --verify :d/f &&
test -h d &&
test_path_is_missing d
'

test_done

0 comments on commit 9a6728d

Please sign in to comment.