diffcore: fix iteration order of identical files during rename detection
commitca4e3ca029def86b7b29451d4ba77ef76574949e
authorSZEDER Gábor <szeder@ira.uka.de>
Wed, 30 Mar 2016 08:35:07 +0000 (30 10:35 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 30 Mar 2016 20:46:04 +0000 (30 13:46 -0700)
treefd786af948557ed06142807e3f48d7a9ddc8d598
parent765428699a5381f113d19974720bc91b5bfeaf1d
diffcore: fix iteration order of identical files during rename detection

If the two paths 'dir/A/file' and 'dir/B/file' have identical content
and the parent directory is renamed, e.g. 'git mv dir other-dir', then
diffcore reports the following exact renames:

    renamed:    dir/B/file -> other-dir/A/file
    renamed:    dir/A/file -> other-dir/B/file

While technically not wrong, this is confusing not only for the user,
but also for git commands that make decisions based on rename
information, e.g. 'git log --follow other-dir/A/file' follows
'dir/B/file' past the rename.

This behavior is a side effect of commit v2.0.0-rc4~8^2~14
(diffcore-rename.c: simplify finding exact renames, 2013-11-14): the
hashmap storing sources returns entries from the same bucket, i.e.
sources matching the current destination, in LIFO order.  Thus the
iteration first examines 'other-dir/A/file' and 'dir/B/file' and, upon
finding identical content and basename, reports an exact rename.

Other hashmap users are apparently happy with the current iteration
order over the entries of a bucket.  Changing the iteration order
would risk upsetting other hashmap users and would increase the memory
footprint of each bucket by a pointer to the tail element.

Fill the hashmap with source entries in reverse order to restore the
original exact rename detection behavior.

Reported-by: Bill Okara <billokara@gmail.com>
Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diffcore-rename.c
t/t4001-diff-rename.sh