stash: avoid feeding directories to update-index

When a file is removed from the cache, but there is a file of the same name present in the working directory, we would normally treat that file in the working directory as untracked. However, in the case of stash, doing that would prevent a simple 'git stash push', because the untracked file would be in the way of restoring the deleted file. git stash, however, blindly assumes that whatever is in the working directory for a deleted file is wanted and passes that path along to update-index. That causes problems when the working directory contains a directory with the same name as the deleted file. Add some code for this special case that will avoid passing directory names to update-index. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Sep 10, 2021 at 10:29 UTC 3d40e3723b1bc86d22136ff01b0787809a3267a4
2 files changed +15 -1
builtin/stash.c
+14
@@ -313,6 +313,17 @@ static int reset_head(void)
313 return run_command(&cp);
314 }
315
316 +static int is_path_a_directory(const char *path)
317 +{
318 + /*
319 + * This function differs from abspath.c:is_directory() in that
320 + * here we use lstat() instead of stat(); we do not want to
321 + * follow symbolic links here.
322 + */
323 + struct stat st;
324 + return (!lstat(path, &st) && S_ISDIR(st.st_mode));
325 +}
326 +
327 static void add_diff_to_buf(struct diff_queue_struct *q,
328 struct diff_options *options,
329 void *data)
@@ -320,6 +331,9 @@ static void add_diff_to_buf(struct diff_queue_struct *q,
331 int i;
332
333 for (i = 0; i < q->nr; i++) {
334 + if (is_path_a_directory(q->queue[i]->one->path))
335 + continue;
336 +
337 strbuf_addstr(data, q->queue[i]->one->path);
338
339 /* NUL-terminate: will be fed to update-index -z */
t/t3903-stash.sh
+1 -1
@@ -1307,7 +1307,7 @@ test_expect_success 'stash -c stash.useBuiltin=false warning ' '
1307 test_must_be_empty err
1308 '
1309
1310 -test_expect_failure 'git stash succeeds despite directory/file change' '
1310 +test_expect_success 'git stash succeeds despite directory/file change' '
1311 test_create_repo directory_file_switch_v1 &&
1312 (
1313 cd directory_file_switch_v1 &&