* [PATCH] diffcore: fix iteration order of identical files during rename detection
@ 2016-03-30 8:35 SZEDER Gábor
2016-03-30 20:51 ` Junio C Hamano
0 siblings, 1 reply; 2+ messages in thread
From: SZEDER Gábor @ 2016-03-30 8:35 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Karsten Blees, Bill Okara, SZEDER Gábor
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>
---
Resend of the patch, with a slightly updated commit message, included
in
http://thread.gmane.org/gmane.comp.version-control.git/287281/focus=287570
Being embedded with scissors in an email without Junio among the
recipients on the day the first -rc was tagged... no wonder it flew
below the radar.
diffcore-rename.c | 6 ++++--
t/t4001-diff-rename.sh | 11 +++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 3b3c1ed535e7..7f03eb5a0404 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -340,9 +340,11 @@ static int find_exact_renames(struct diff_options *options)
int i, renames = 0;
struct hashmap file_table;
- /* Add all sources to the hash table */
+ /* Add all sources to the hash table in reverse order, because
+ * later on they will be retrieved in LIFO order.
+ */
hashmap_init(&file_table, NULL, rename_src_nr);
- for (i = 0; i < rename_src_nr; i++)
+ for (i = rename_src_nr-1; i >= 0; i--)
insert_file_table(&file_table, i, rename_src[i].p->one);
/* Walk the destinations and find best source match */
diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh
index 2f327b749588..ed90c6c6f984 100755
--- a/t/t4001-diff-rename.sh
+++ b/t/t4001-diff-rename.sh
@@ -77,6 +77,17 @@ test_expect_success 'favour same basenames even with minor differences' '
git show HEAD:path1 | sed "s/15/16/" > subdir/path1 &&
git status | test_i18ngrep "renamed: .*path1 -> subdir/path1"'
+test_expect_success 'two files with same basename and same content' '
+ git reset --hard &&
+ mkdir -p dir/A dir/B &&
+ cp path1 dir/A/file &&
+ cp path1 dir/B/file &&
+ git add dir &&
+ git commit -m 2 &&
+ git mv dir other-dir &&
+ git status | test_i18ngrep "renamed: .*dir/A/file -> other-dir/A/file"
+'
+
test_expect_success 'setup for many rename source candidates' '
git reset --hard &&
for i in 0 1 2 3 4 5 6 7 8 9;
--
2.8.0.46.gb821760
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] diffcore: fix iteration order of identical files during rename detection
2016-03-30 8:35 [PATCH] diffcore: fix iteration order of identical files during rename detection SZEDER Gábor
@ 2016-03-30 20:51 ` Junio C Hamano
0 siblings, 0 replies; 2+ messages in thread
From: Junio C Hamano @ 2016-03-30 20:51 UTC (permalink / raw)
To: SZEDER Gábor; +Cc: git, Karsten Blees, Bill Okara
SZEDER Gábor <szeder@ira.uka.de> writes:
> Fill the hashmap with source entries in reverse order to restore the
> original exact rename detection behavior.
Thanks for digging out and fixing this unintended regression that
happened long time ago. Will queue.
>
> Reported-by: Bill Okara <billokara@gmail.com>
> Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
> ---
>
> Resend of the patch, with a slightly updated commit message, included
> in
>
> http://thread.gmane.org/gmane.comp.version-control.git/287281/focus=287570
>
> Being embedded with scissors in an email without Junio among the
> recipients on the day the first -rc was tagged... no wonder it flew
> below the radar.
>
> diffcore-rename.c | 6 ++++--
> t/t4001-diff-rename.sh | 11 +++++++++++
> 2 files changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/diffcore-rename.c b/diffcore-rename.c
> index 3b3c1ed535e7..7f03eb5a0404 100644
> --- a/diffcore-rename.c
> +++ b/diffcore-rename.c
> @@ -340,9 +340,11 @@ static int find_exact_renames(struct diff_options *options)
> int i, renames = 0;
> struct hashmap file_table;
>
> - /* Add all sources to the hash table */
> + /* Add all sources to the hash table in reverse order, because
> + * later on they will be retrieved in LIFO order.
> + */
> hashmap_init(&file_table, NULL, rename_src_nr);
> - for (i = 0; i < rename_src_nr; i++)
> + for (i = rename_src_nr-1; i >= 0; i--)
> insert_file_table(&file_table, i, rename_src[i].p->one);
>
> /* Walk the destinations and find best source match */
> diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh
> index 2f327b749588..ed90c6c6f984 100755
> --- a/t/t4001-diff-rename.sh
> +++ b/t/t4001-diff-rename.sh
> @@ -77,6 +77,17 @@ test_expect_success 'favour same basenames even with minor differences' '
> git show HEAD:path1 | sed "s/15/16/" > subdir/path1 &&
> git status | test_i18ngrep "renamed: .*path1 -> subdir/path1"'
>
> +test_expect_success 'two files with same basename and same content' '
> + git reset --hard &&
> + mkdir -p dir/A dir/B &&
> + cp path1 dir/A/file &&
> + cp path1 dir/B/file &&
> + git add dir &&
> + git commit -m 2 &&
> + git mv dir other-dir &&
> + git status | test_i18ngrep "renamed: .*dir/A/file -> other-dir/A/file"
> +'
> +
> test_expect_success 'setup for many rename source candidates' '
> git reset --hard &&
> for i in 0 1 2 3 4 5 6 7 8 9;
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-03-30 20:51 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-30 8:35 [PATCH] diffcore: fix iteration order of identical files during rename detection SZEDER Gábor
2016-03-30 20:51 ` Junio C Hamano
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).