From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Johannes Schindelin <johannes.schindelin@gmx.de>,
Junio C Hamano <gitster@pobox.com>,
Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH v2 1/2] Move git_sort(), a stable sort, into into libgit.a
Date: Mon, 30 Sep 2019 10:21:54 -0700 (PDT) [thread overview]
Message-ID: <8a99008a64eb1aa13aae8969e9c9963be898b31a.1569864113.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.352.v2.git.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
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>
---
Makefile | 2 +-
compat/mingw.c | 11 +++--------
git-compat-util.h | 9 ++++++---
compat/qsort.c => stable-qsort.c | 6 +++---
4 files changed, 13 insertions(+), 15 deletions(-)
rename compat/qsort.c => stable-qsort.c (89%)
diff --git a/Makefile b/Makefile
index f9255344ae..60c809e580 100644
--- a/Makefile
+++ b/Makefile
@@ -983,6 +983,7 @@ LIB_OBJS += shallow.o
LIB_OBJS += sideband.o
LIB_OBJS += sigchain.o
LIB_OBJS += split-index.o
+LIB_OBJS += stable-qsort.o
LIB_OBJS += strbuf.o
LIB_OBJS += streaming.o
LIB_OBJS += string-list.o
@@ -1714,7 +1715,6 @@ ifdef NO_GETPAGESIZE
endif
ifdef INTERNAL_QSORT
COMPAT_CFLAGS += -DINTERNAL_QSORT
- COMPAT_OBJS += compat/qsort.o
endif
ifdef HAVE_ISO_QSORT_S
COMPAT_CFLAGS += -DHAVE_ISO_QSORT_S
diff --git a/compat/mingw.c b/compat/mingw.c
index 738f0a826a..50af33b2b3 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1229,11 +1229,6 @@ static int wenvcmp(const void *a, const void *b)
return _wcsnicmp(p, q, p_len);
}
-/* We need a stable sort to convert the environment between UTF-16 <-> UTF-8 */
-#ifndef INTERNAL_QSORT
-#include "qsort.c"
-#endif
-
/*
* Build an environment block combining the inherited environment
* merged with the given list of settings.
@@ -1272,8 +1267,8 @@ static wchar_t *make_environment_block(char **deltaenv)
/*
* If there is a deltaenv, let's accumulate all keys into `array`,
- * sort them using the stable git_qsort() and then copy, skipping
- * duplicate keys
+ * sort them using the stable git_stable_qsort() and then copy,
+ * skipping duplicate keys
*/
for (p = wenv; p && *p; ) {
ALLOC_GROW(array, nr + 1, alloc);
@@ -1296,7 +1291,7 @@ static wchar_t *make_environment_block(char **deltaenv)
p += wlen + 1;
}
- git_qsort(array, nr, sizeof(*array), wenvcmp);
+ git_stable_qsort(array, nr, sizeof(*array), wenvcmp);
ALLOC_ARRAY(result, size + delta_size);
for (p = result, i = 0; i < nr; i++) {
diff --git a/git-compat-util.h b/git-compat-util.h
index 83be89de0a..7ec2c8fe31 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -1094,10 +1094,10 @@ static inline int strtol_i(char const *s, int base, int *result)
return 0;
}
+void git_stable_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *));
#ifdef INTERNAL_QSORT
-void git_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *));
-#define qsort git_qsort
+#define qsort git_stable_qsort
#endif
#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,
qsort(base, nmemb, size, compar);
}
+#define STABLE_QSORT(base, n, compar) \
+ git_stable_qsort((base), (n), sizeof(*(base)), compar)
+
#ifndef HAVE_ISO_QSORT_S
int git_qsort_s(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *, void *), void *ctx);
diff --git a/compat/qsort.c b/stable-qsort.c
similarity index 89%
rename from compat/qsort.c
rename to stable-qsort.c
index 7d071afb70..6cbaf39f7b 100644
--- a/compat/qsort.c
+++ b/stable-qsort.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
/*
* 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,
memcpy(b, t, (n - n2) * s);
}
-void git_qsort(void *b, size_t n, size_t s,
- int (*cmp)(const void *, const void *))
+void git_stable_qsort(void *b, size_t n, size_t s,
+ int (*cmp)(const void *, const void *))
{
const size_t size = st_mult(n, s);
char buf[1024];
--
gitgitgadget
next prev parent reply other threads:[~2019-09-30 21:04 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-25 8:35 [PATCH 0/2] Git's rename detection requires a stable sort Johannes Schindelin via GitGitGadget
2019-09-25 8:36 ` [PATCH 1/2] Move git_sort(), a stable sort, into into libgit.a Johannes Schindelin via GitGitGadget
2019-09-28 10:14 ` Junio C Hamano
2019-09-30 11:38 ` Johannes Schindelin
2019-09-25 8:36 ` [PATCH 2/2] diffcore_rename(): use a stable sort Johannes Schindelin via GitGitGadget
2019-09-30 17:21 ` [PATCH v2 0/2] Git's rename detection requires " Johannes Schindelin via GitGitGadget
2019-09-30 17:21 ` Johannes Schindelin via GitGitGadget [this message]
2019-09-30 17:21 ` [PATCH v2 2/2] diffcore_rename(): use " Johannes Schindelin via GitGitGadget
2019-10-02 5:47 ` [PATCH v2 0/2] Git's rename detection requires " Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8a99008a64eb1aa13aae8969e9c9963be898b31a.1569864113.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=johannes.schindelin@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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 NNTP newsgroup(s).