On Fri, Nov 24, 2017 at 2:59 PM, Elijah Newren <[email protected]> wrote:
> In commit ae352c7f3 (merge-recursive.c: fix case-changing merge bug,
> 2014-05-01), it was observed that removing files could be problematic on
> case insensitive file systems, because we could end up removing files
> that differed in case only rather than deleting the intended file --
> something that happened when files were renamed on one branch in a way
> that differed only in case. To avoid that problem, that commit added
> logic to avoid removing files other than the one intended, rejecting the
> removal if the files differed only in case.
>
> Unfortunately, the logic it used didn't fully implement that condition as
> stated above; instead it merely checked that a case-insensitive lookup of
> the file that was requested resulted in finding a file in the index at
> stage 0, not that the file found in the index actually differed in case.
> Alternatively, one could view the implementation as making an implicit
> assumption that the file we actually wanted to remove would never appear
> in the index with a stage of 0, and thus that if we found a file with our
> lookup, that it had to be a different file (but different in case only).
>
> The net result of this implementation is that it can ignore more requests
> than it should, leaving a file around in the working copy that should
> have been removed. Make sure that the file found in the index actually
> differs in case before silently ignoring the request to remove the file.
>
> ---
Missing sign-off.
> diff --git a/merge-recursive.c b/merge-recursive.c
> index b48b15a6f..100fb913f 100644
> --- a/merge-recursive.c
> +++ b/merge-recursive.c
> @@ -646,7 +646,7 @@ static int remove_file(struct merge_options *o, int clean,
> if (ignore_case) {
> struct cache_entry *ce;
> ce = cache_file_exists(path, strlen(path),
> ignore_case);
> - if (ce && ce_stage(ce) == 0)
> + if (ce && ce_stage(ce) == 0 && strcmp(path, ce->name))
> return 0;
> }
> if (remove_path(path))
> --
> 2.11.0