Move git_sort(), a stable sort, into into libgit.a

The `qsort()` function is not guaranteed to be stable, i.e. it does not promise to maintain the order of items it is told to consider equal. In contrast, the `git_sort()` function we carry in `compat/qsort.c` _is_ stable, by virtue of implementing a merge sort algorithm. In preparation for using a stable sort in Git's rename detection, move the stable sort into `libgit.a` so that it is compiled in unconditionally, and rename it to `git_stable_qsort()`. Note: this also makes the hack obsolete that was introduced in fe21c6b285d (mingw: reencode environment variables on the fly (UTF-16 <-> UTF-8), 2018-10-30), where we included `compat/qsort.c` directly in `compat/mingw.c` to use the stable sort. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Sep 30, 2019 at 10:21 UTC 97fff6101220b66bc293239ab2cf29fc3624072b
4 files changed +13 -15
Makefile
+1 -1
@@ -983,6 +983,7 @@ LIB_OBJS += shallow.o
983 LIB_OBJS += sideband.o
984 LIB_OBJS += sigchain.o
985 LIB_OBJS += split-index.o
986 +LIB_OBJS += stable-qsort.o
987 LIB_OBJS += strbuf.o
988 LIB_OBJS += streaming.o
989 LIB_OBJS += string-list.o
@@ -1714,7 +1715,6 @@ ifdef NO_GETPAGESIZE
1715 endif
1716 ifdef INTERNAL_QSORT
1717 COMPAT_CFLAGS += -DINTERNAL_QSORT
1717 - COMPAT_OBJS += compat/qsort.o
1718 endif
1719 ifdef HAVE_ISO_QSORT_S
1720 COMPAT_CFLAGS += -DHAVE_ISO_QSORT_S
compat/mingw.c
+3 -8
@@ -1229,11 +1229,6 @@ static int wenvcmp(const void *a, const void *b)
1229 return _wcsnicmp(p, q, p_len);
1230 }
1231
1232 -/* We need a stable sort to convert the environment between UTF-16 <-> UTF-8 */
1233 -#ifndef INTERNAL_QSORT
1234 -#include "qsort.c"
1235 -#endif
1236 -
1232 /*
1233 * Build an environment block combining the inherited environment
1234 * merged with the given list of settings.
@@ -1272,8 +1267,8 @@ static wchar_t *make_environment_block(char **deltaenv)
1267
1268 /*
1269 * If there is a deltaenv, let's accumulate all keys into `array`,
1275 - * sort them using the stable git_qsort() and then copy, skipping
1276 - * duplicate keys
1270 + * sort them using the stable git_stable_qsort() and then copy,
1271 + * skipping duplicate keys
1272 */
1273 for (p = wenv; p && *p; ) {
1274 ALLOC_GROW(array, nr + 1, alloc);
@@ -1296,7 +1291,7 @@ static wchar_t *make_environment_block(char **deltaenv)
1291 p += wlen + 1;
1292 }
1293
1299 - git_qsort(array, nr, sizeof(*array), wenvcmp);
1294 + git_stable_qsort(array, nr, sizeof(*array), wenvcmp);
1295 ALLOC_ARRAY(result, size + delta_size);
1296
1297 for (p = result, i = 0; i < nr; i++) {
git-compat-util.h
+6 -3
@@ -1094,10 +1094,10 @@ static inline int strtol_i(char const *s, int base, int *result)
1094 return 0;
1095 }
1096
1097 +void git_stable_qsort(void *base, size_t nmemb, size_t size,
1098 + int(*compar)(const void *, const void *));
1099 #ifdef INTERNAL_QSORT
1098 -void git_qsort(void *base, size_t nmemb, size_t size,
1099 - int(*compar)(const void *, const void *));
1100 -#define qsort git_qsort
1100 +#define qsort git_stable_qsort
1101 #endif
1102
1103 #define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
@@ -1108,6 +1108,9 @@ static inline void sane_qsort(void *base, size_t nmemb, size_t size,
1108 qsort(base, nmemb, size, compar);
1109 }
1110
1111 +#define STABLE_QSORT(base, n, compar) \
1112 + git_stable_qsort((base), (n), sizeof(*(base)), compar)
1113 +
1114 #ifndef HAVE_ISO_QSORT_S
1115 int git_qsort_s(void *base, size_t nmemb, size_t size,
1116 int (*compar)(const void *, const void *, void *), void *ctx);
stable-qsort.c renamed
+3 -3
@@ -1,4 +1,4 @@
1 -#include "../git-compat-util.h"
1 +#include "git-compat-util.h"
2
3 /*
4 * 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,
44 memcpy(b, t, (n - n2) * s);
45 }
46
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 *))
49 {
50 const size_t size = st_mult(n, s);
51 char buf[1024];