Skip to content

Commit 016da89

Browse files
committed
Merge branch 'js/diff-rename-force-stable-sort' into jch
The rename detection logic sorts a list of rename source candidates by similarity to pick the best candidate, which means that a tie between sources with the same similarity is broken by the original location in the original canidate list (which is sorted by path). Force the sorting by similarity done with a stable sort, which is not promised by system supplied qsort(3), to ensure consistent results across platforms. * js/diff-rename-force-stable-sort: diffcore_rename(): use a stable sort Move git_sort(), a stable sort, into into libgit.a
2 parents 2f61aea + 2049b8d commit 016da89

File tree

5 files changed

+14
-16
lines changed

5 files changed

+14
-16
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,7 @@ LIB_OBJS += shallow.o
981981
LIB_OBJS += sideband.o
982982
LIB_OBJS += sigchain.o
983983
LIB_OBJS += split-index.o
984+
LIB_OBJS += stable-qsort.o
984985
LIB_OBJS += strbuf.o
985986
LIB_OBJS += streaming.o
986987
LIB_OBJS += string-list.o
@@ -1726,7 +1727,6 @@ ifdef NO_GETPAGESIZE
17261727
endif
17271728
ifdef INTERNAL_QSORT
17281729
COMPAT_CFLAGS += -DINTERNAL_QSORT
1729-
COMPAT_OBJS += compat/qsort.o
17301730
endif
17311731
ifdef HAVE_ISO_QSORT_S
17321732
COMPAT_CFLAGS += -DHAVE_ISO_QSORT_S

compat/mingw.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,11 +1236,6 @@ static int wenvcmp(const void *a, const void *b)
12361236
return _wcsnicmp(p, q, p_len);
12371237
}
12381238

1239-
/* We need a stable sort to convert the environment between UTF-16 <-> UTF-8 */
1240-
#ifndef INTERNAL_QSORT
1241-
#include "qsort.c"
1242-
#endif
1243-
12441239
/*
12451240
* Build an environment block combining the inherited environment
12461241
* merged with the given list of settings.
@@ -1279,8 +1274,8 @@ static wchar_t *make_environment_block(char **deltaenv)
12791274

12801275
/*
12811276
* If there is a deltaenv, let's accumulate all keys into `array`,
1282-
* sort them using the stable git_qsort() and then copy, skipping
1283-
* duplicate keys
1277+
* sort them using the stable git_stable_qsort() and then copy,
1278+
* skipping duplicate keys
12841279
*/
12851280
for (p = wenv; p && *p; ) {
12861281
ALLOC_GROW(array, nr + 1, alloc);
@@ -1303,7 +1298,7 @@ static wchar_t *make_environment_block(char **deltaenv)
13031298
p += wlen + 1;
13041299
}
13051300

1306-
git_qsort(array, nr, sizeof(*array), wenvcmp);
1301+
git_stable_qsort(array, nr, sizeof(*array), wenvcmp);
13071302
ALLOC_ARRAY(result, size + delta_size);
13081303

13091304
for (p = result, i = 0; i < nr; i++) {

diffcore-rename.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ void diffcore_rename(struct diff_options *options)
584584
stop_progress(&progress);
585585

586586
/* cost matrix sorted by most to least similar pair */
587-
QSORT(mx, dst_cnt * NUM_CANDIDATE_PER_DST, score_compare);
587+
STABLE_QSORT(mx, dst_cnt * NUM_CANDIDATE_PER_DST, score_compare);
588588

589589
rename_count += find_renames(mx, dst_cnt, minimum_score, 0);
590590
if (detect_rename == DIFF_DETECT_COPY)

git-compat-util.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,10 +1092,10 @@ static inline int strtol_i(char const *s, int base, int *result)
10921092
return 0;
10931093
}
10941094

1095+
void git_stable_qsort(void *base, size_t nmemb, size_t size,
1096+
int(*compar)(const void *, const void *));
10951097
#ifdef INTERNAL_QSORT
1096-
void git_qsort(void *base, size_t nmemb, size_t size,
1097-
int(*compar)(const void *, const void *));
1098-
#define qsort git_qsort
1098+
#define qsort git_stable_qsort
10991099
#endif
11001100

11011101
#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
@@ -1106,6 +1106,9 @@ static inline void sane_qsort(void *base, size_t nmemb, size_t size,
11061106
qsort(base, nmemb, size, compar);
11071107
}
11081108

1109+
#define STABLE_QSORT(base, n, compar) \
1110+
git_stable_qsort((base), (n), sizeof(*(base)), compar)
1111+
11091112
#ifndef HAVE_ISO_QSORT_S
11101113
int git_qsort_s(void *base, size_t nmemb, size_t size,
11111114
int (*compar)(const void *, const void *, void *), void *ctx);

compat/qsort.c renamed to stable-qsort.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "../git-compat-util.h"
1+
#include "git-compat-util.h"
22

33
/*
44
* A merge sort implementation, simplified from the qsort implementation
@@ -44,8 +44,8 @@ static void msort_with_tmp(void *b, size_t n, size_t s,
4444
memcpy(b, t, (n - n2) * s);
4545
}
4646

47-
void git_qsort(void *b, size_t n, size_t s,
48-
int (*cmp)(const void *, const void *))
47+
void git_stable_qsort(void *b, size_t n, size_t s,
48+
int (*cmp)(const void *, const void *))
4949
{
5050
const size_t size = st_mult(n, s);
5151
char buf[1024];

0 commit comments

Comments
 (0)