From 14d7583beb020a4b3c388f8b7ea580cf2a156ff8 Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Tue, 15 Jul 2025 15:00:56 +0100 Subject: [PATCH 01/14] config: remove unneeded struct field As well as receiving the config key and value, config callbacks also receive a "struct key_value_info" containing information about the source of the key-value pair. Accessing the "path" field of this struct from a callback passed to repo_config() results in a use-after-free. This happens because repo_config() first populates a configset by calling config_with_options() and then iterates over the configset with the callback passed by the caller. When the configset is constructed it takes a shallow copy of the "struct key_value_info" for each config setting. This leads to the use-after-free as the "path" member is freed before config_with_options() returns. We could fix this by interning the "path" field as we do for the "filename" field but the "path" field is not actually needed. It is populated with a copy of the "path" field from "struct config_source". That field was added in d14d42440d8 (config: disallow relative include paths from blobs, 2014-02-19) to distinguish between relative include directives in files and those in blobs. However, since 1b8132d99d8 (i18n: config: unfold error messages marked for translation, 2016-07-28) we can differentiate these by looking at the "origin_type" field in "struct key_value_info". So let's remove the "path" members from "struct config_source" and "struct key_value_info" and instead use a combination of the "filename" and "origin_type" fields to determine the absolute path of relative includes. Signed-off-by: Phillip Wood Signed-off-by: Junio C Hamano --- config.c | 28 +++++++++++++--------------- config.h | 2 -- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/config.c b/config.c index b18b5617fcd05d..85883afb6c58bb 100644 --- a/config.c +++ b/config.c @@ -56,7 +56,6 @@ struct config_source { } u; enum config_origin_type origin_type; const char *name; - const char *path; enum config_error_action default_error_action; int linenr; int eof; @@ -173,14 +172,14 @@ static int handle_path_include(const struct key_value_info *kvi, if (!is_absolute_path(path)) { char *slash; - if (!kvi || !kvi->path) { + if (!kvi || kvi->origin_type != CONFIG_ORIGIN_FILE) { ret = error(_("relative config includes must come from files")); goto cleanup; } - slash = find_last_dir_sep(kvi->path); + slash = find_last_dir_sep(kvi->filename); if (slash) - strbuf_add(&buf, kvi->path, slash - kvi->path + 1); + strbuf_add(&buf, kvi->filename, slash - kvi->filename + 1); strbuf_addstr(&buf, path); path = buf.buf; } @@ -224,11 +223,11 @@ static int prepare_include_condition_pattern(const struct key_value_info *kvi, if (pat->buf[0] == '.' && is_dir_sep(pat->buf[1])) { const char *slash; - if (!kvi || !kvi->path) + if (!kvi || kvi->origin_type != CONFIG_ORIGIN_FILE) return error(_("relative config include " "conditionals must come from files")); - strbuf_realpath(&path, kvi->path, 1); + strbuf_realpath(&path, kvi->filename, 1); slash = find_last_dir_sep(path.buf); if (!slash) BUG("how is this possible?"); @@ -633,7 +632,6 @@ void kvi_from_param(struct key_value_info *out) out->linenr = -1; out->origin_type = CONFIG_ORIGIN_CMDLINE; out->scope = CONFIG_SCOPE_COMMAND; - out->path = NULL; } int git_config_parse_parameter(const char *text, @@ -1036,7 +1034,6 @@ static void kvi_from_source(struct config_source *cs, out->origin_type = cs->origin_type; out->linenr = cs->linenr; out->scope = scope; - out->path = cs->path; } static int git_parse_source(struct config_source *cs, config_fn_t fn, @@ -1855,17 +1852,19 @@ static int do_config_from(struct config_source *top, config_fn_t fn, static int do_config_from_file(config_fn_t fn, const enum config_origin_type origin_type, - const char *name, const char *path, FILE *f, - void *data, enum config_scope scope, + const char *name, FILE *f, void *data, + enum config_scope scope, const struct config_options *opts) { struct config_source top = CONFIG_SOURCE_INIT; int ret; + if (origin_type == CONFIG_ORIGIN_FILE && (!name || !*name)) + BUG("missing filename for CONFIG_ORIGIN_FILE"); + top.u.file = f; top.origin_type = origin_type; top.name = name; - top.path = path; top.default_error_action = CONFIG_ERROR_DIE; top.do_fgetc = config_file_fgetc; top.do_ungetc = config_file_ungetc; @@ -1880,8 +1879,8 @@ static int do_config_from_file(config_fn_t fn, static int git_config_from_stdin(config_fn_t fn, void *data, enum config_scope scope) { - return do_config_from_file(fn, CONFIG_ORIGIN_STDIN, "", NULL, stdin, - data, scope, NULL); + return do_config_from_file(fn, CONFIG_ORIGIN_STDIN, "", stdin, data, + scope, NULL); } int git_config_from_file_with_options(config_fn_t fn, const char *filename, @@ -1896,7 +1895,7 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename, f = fopen_or_warn(filename, "r"); if (f) { ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename, - filename, f, data, scope, opts); + f, data, scope, opts); fclose(f); } return ret; @@ -1921,7 +1920,6 @@ int git_config_from_mem(config_fn_t fn, top.u.buf.pos = 0; top.origin_type = origin_type; top.name = name; - top.path = NULL; top.default_error_action = CONFIG_ERROR_ERROR; top.do_fgetc = config_buf_fgetc; top.do_ungetc = config_buf_ungetc; diff --git a/config.h b/config.h index 29a027748375f1..cbb0f4fddcddec 100644 --- a/config.h +++ b/config.h @@ -122,14 +122,12 @@ struct key_value_info { int linenr; enum config_origin_type origin_type; enum config_scope scope; - const char *path; }; #define KVI_INIT { \ .filename = NULL, \ .linenr = -1, \ .origin_type = CONFIG_ORIGIN_UNKNOWN, \ .scope = CONFIG_SCOPE_UNKNOWN, \ - .path = NULL, \ } /* Captures additional information that a config callback can use. */ From d79f8c6865862c9a48c095493735923800bcf34b Mon Sep 17 00:00:00 2001 From: Kyle Lippincott Date: Tue, 15 Jul 2025 18:57:54 +0000 Subject: [PATCH 02/14] test-lib: respect GIT_TEST_INSTALLED when querying default hash $GIT_TEST_INSTALLED can be set to use an "installed" git instead of the one from $GIT_BUILD_DIR. This is used by my company's internal test infrastructure, and not using $GIT_TEST_INSTALLED when querying the default hash meant that the tests were failing because the hash was effectively set to the empty string (since git didn't execute). In the two places we attempt to detect/execute git itself prior to overriding everything and putting it in $PATH, use identical logic for identifying the git binary to execute. This also has the effect of including the $X suffix when querying the default hash, but that's not strictly necessary. You don't need to specify .exe when running a binary on Windows, just when testing whether it exists or not. Signed-off-by: Kyle Lippincott Signed-off-by: Junio C Hamano --- t/test-lib.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/t/test-lib.sh b/t/test-lib.sh index 315543f2933a09..d8e0e035520e2a 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -134,7 +134,8 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME ################################################################ # It appears that people try to run tests without building... -"${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" >/dev/null +GIT_BINARY="${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" +"$GIT_BINARY" >/dev/null if test $? != 1 then if test -n "$GIT_TEST_INSTALLED" @@ -536,7 +537,7 @@ export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME export GIT_COMMITTER_DATE GIT_AUTHOR_DATE export EDITOR -GIT_TEST_BUILTIN_HASH=$("$GIT_BUILD_DIR/git" version --build-options | sed -ne 's/^default-hash: //p') +GIT_TEST_BUILTIN_HASH=$("$GIT_BINARY" version --build-options | sed -ne 's/^default-hash: //p') GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}" export GIT_DEFAULT_HASH GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}" From f1b85243034a690691d34af0576e6d3cb1a08743 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 15 Jul 2025 21:12:26 +0200 Subject: [PATCH 03/14] bswap.h: add support for __BYTE_ORDER__ The __BYTE_ORDER__ define is provided by gcc (since ~v4.6), clang (since ~v3.2) and icc (since ~16.0.3). The __BYTE_ORDER and BYTE_ORDER macros are libc specific and are not available on all supported platforms such as mingw. Add support for the __BYTE_ORDER__ macro as a fallback. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Junio C Hamano --- compat/bswap.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compat/bswap.h b/compat/bswap.h index b34054f2bd7284..0a457542dd76ab 100644 --- a/compat/bswap.h +++ b/compat/bswap.h @@ -116,6 +116,12 @@ static inline uint64_t git_bswap64(uint64_t x) # define GIT_LITTLE_ENDIAN LITTLE_ENDIAN # define GIT_BIG_ENDIAN BIG_ENDIAN +#elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) + +# define GIT_BYTE_ORDER __BYTE_ORDER__ +# define GIT_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +# define GIT_BIG_ENDIAN __ORDER_BIG_ENDIAN__ + #else # define GIT_BIG_ENDIAN 4321 From 30dea7ddf7a10d11818e754deba8120cef8446ca Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 15 Jul 2025 21:12:27 +0200 Subject: [PATCH 04/14] bswap.h: define GIT_LITTLE_ENDIAN on msvc as little endian The Microsoft Visual C++ (MSVC) compiler (as of Visual Studio 2022 version 17.13.6) does not define __BYTE_ORDER__ and its C-library does not define __BYTE_ORDER. The compiler is supported only on arm64 and x86 which are all little endian. Define GIT_BYTE_ORDER on msvc as little endian to avoid further checks. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Junio C Hamano --- compat/bswap.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compat/bswap.h b/compat/bswap.h index 0a457542dd76ab..fd604d9f7b74b0 100644 --- a/compat/bswap.h +++ b/compat/bswap.h @@ -81,6 +81,10 @@ static inline uint64_t git_bswap64(uint64_t x) #define bswap32(x) _byteswap_ulong(x) #define bswap64(x) _byteswap_uint64(x) +#define GIT_LITTLE_ENDIAN 1234 +#define GIT_BIG_ENDIAN 4321 +#define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN + #endif #if defined(bswap32) @@ -122,7 +126,7 @@ static inline uint64_t git_bswap64(uint64_t x) # define GIT_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ # define GIT_BIG_ENDIAN __ORDER_BIG_ENDIAN__ -#else +#elif !defined(GIT_BYTE_ORDER) # define GIT_BIG_ENDIAN 4321 # define GIT_LITTLE_ENDIAN 1234 From 4544cd19e429975882e20fa89dab7e73956f26e4 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 15 Jul 2025 21:12:28 +0200 Subject: [PATCH 05/14] bswap.h: always overwrite ntohl/ ntohll macros The ntohl and htonl macros are redefined because the provided macros were not always optimal. Sometimes it was a function call, sometimes it was a macro which did the shifting. Using the 'bswap' opcode on x86 provides probably better performance than performing the shifting. These macros are only overwritten on x86 if the "optimized" version is available. The ntohll and htonll macros are not available on every platform (at least glibc does not provide them) which means they need to be defined once the endianness of the system is determined. In order to get a more symmetrical setup, redfine the macros once the endianness of the system has been determined. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Junio C Hamano --- compat/bswap.h | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/compat/bswap.h b/compat/bswap.h index fd604d9f7b74b0..aeef304f671f50 100644 --- a/compat/bswap.h +++ b/compat/bswap.h @@ -87,27 +87,6 @@ static inline uint64_t git_bswap64(uint64_t x) #endif -#if defined(bswap32) - -#undef ntohl -#undef htonl -#define ntohl(x) bswap32(x) -#define htonl(x) bswap32(x) - -#endif - -#if defined(bswap64) - -#undef ntohll -#undef htonll -#define ntohll(x) bswap64(x) -#define htonll(x) bswap64(x) - -#else - -#undef ntohll -#undef htonll - #if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) # define GIT_BYTE_ORDER __BYTE_ORDER @@ -145,14 +124,33 @@ static inline uint64_t git_bswap64(uint64_t x) #endif +#undef ntohl +#undef htonl +#undef ntohll +#undef htonll + #if GIT_BYTE_ORDER == GIT_BIG_ENDIAN -# define ntohll(n) (n) -# define htonll(n) (n) +# define ntohl(x) (x) +# define htonl(x) (x) +# define ntohll(x) (x) +# define htonll(x) (x) #else -# define ntohll(n) default_bswap64(n) -# define htonll(n) default_bswap64(n) -#endif +# if defined(bswap32) +# define ntohl(x) bswap32(x) +# define htonl(x) bswap32(x) +# else +# define ntohl(x) default_swab32(x) +# define htonl(x) default_swab32(x) +# endif + +# if defined(bswap64) +# define ntohll(x) bswap64(x) +# define htonll(x) bswap64(x) +# else +# define ntohll(x) default_bswap64(x) +# define htonll(x) default_bswap64(x) +# endif #endif static inline uint16_t get_be16(const void *ptr) From 0132f114efe90fb5f0baf61dbda8a1a33eace929 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 15 Jul 2025 21:12:29 +0200 Subject: [PATCH 06/14] bswap.h: remove optimized x86 version of bswap32/64 On x86 the bswap32/64 macro is implemented based on the x86 opcode which performs the required shifting in just one opcode. The other CPUs fallback to the generic shifting as implemented by default_swab32() and default_bswap64() if needed. I've been looking at how good a compiler is at recognizing the default shift and emitting an optimized operation: - x86, arm64 msvc v19.20 default_swab32() optimized default_bswap64() shifts _byteswap_uint64() optimized - x86, arm64 msvc v19.37 default_swab32() optimized default_bswap64() optimized _byteswap_uint64() optimized - arm64, gcc-4.9.4: optimized - x86-64, gcc-4.4.7: shifts - x86-64, gcc-4.5.3: optimized - x86-64, clang-3.0: optimized Given that gcc-4.5 and clang-3.0 are fairly old, any recent compiler should recognize the shift. Remove the optimized x86 version and rely on the compiler. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Junio C Hamano --- compat/bswap.h | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/compat/bswap.h b/compat/bswap.h index aeef304f671f50..ed00f6d1d53f3e 100644 --- a/compat/bswap.h +++ b/compat/bswap.h @@ -35,46 +35,7 @@ static inline uint64_t default_bswap64(uint64_t val) #undef bswap32 #undef bswap64 -#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) - -#define bswap32 git_bswap32 -static inline uint32_t git_bswap32(uint32_t x) -{ - uint32_t result; - if (__builtin_constant_p(x)) - result = default_swab32(x); - else - __asm__("bswap %0" : "=r" (result) : "0" (x)); - return result; -} - -#define bswap64 git_bswap64 -#if defined(__x86_64__) -static inline uint64_t git_bswap64(uint64_t x) -{ - uint64_t result; - if (__builtin_constant_p(x)) - result = default_bswap64(x); - else - __asm__("bswap %q0" : "=r" (result) : "0" (x)); - return result; -} -#else -static inline uint64_t git_bswap64(uint64_t x) -{ - union { uint64_t i64; uint32_t i32[2]; } tmp, result; - if (__builtin_constant_p(x)) - result.i64 = default_bswap64(x); - else { - tmp.i64 = x; - result.i32[0] = git_bswap32(tmp.i32[1]); - result.i32[1] = git_bswap32(tmp.i32[0]); - } - return result.i64; -} -#endif - -#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64)) +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64)) #include From f4ac32c03af5ac53964a05c4de435da53a59615c Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 15 Jul 2025 21:12:30 +0200 Subject: [PATCH 07/14] bswap.h: provide a built-in based version of bswap32/64 if possible The compiler is in general able to recognize the endian shift and replace it with an optimized opcode if possible. On certain architectures such as RiscV or MIPS the situation can get complicated. They don't provide an optimized opcode and masking the "higher" bits may required loading a constant which needs shifting. This causes the compiler to emit a lot of instructions for the operation. The provided builtin directive on these architecture calls a function which does the operation instead of emitting the code for operation. Bring back the change from commit 6547d1c9 (bswap.h: add support for built-in bswap functions, 2025-04-23). The bswap32/64 macro can now be defined unconditionally so it won't regress on big endian architectures. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Junio C Hamano --- compat/bswap.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compat/bswap.h b/compat/bswap.h index ed00f6d1d53f3e..28635ebc690e35 100644 --- a/compat/bswap.h +++ b/compat/bswap.h @@ -32,6 +32,14 @@ static inline uint64_t default_bswap64(uint64_t val) ((val & (uint64_t)0xff00000000000000ULL) >> 56)); } +/* + * __has_builtin is available since Clang 10 and GCC 10. + * Below is a fallback for older compilers. + */ +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + #undef bswap32 #undef bswap64 @@ -46,6 +54,11 @@ static inline uint64_t default_bswap64(uint64_t val) #define GIT_BIG_ENDIAN 4321 #define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN +#elif __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64) + +#define bswap32(x) __builtin_bswap32((x)) +#define bswap64(x) __builtin_bswap64((x)) + #endif #if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) From 586919c3b2b76f11d22e2ce571cb95b8e4bfbd2a Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Wed, 16 Jul 2025 00:32:38 +0100 Subject: [PATCH 08/14] meson: fix installation when -Dlibexexdir is set commit 837f637cf5 ("meson.build: correct setting of GIT_EXEC_PATH", 2025-05-19) corrected the GIT_EXEC_PATH build setting, but then forgot to update the installation path for the library executables. This causes a regression when attempting to execute commands, after installing to a non-standard location (reported here[1]): $ meson -Dprefix=/tmp/git -Dlibexecdir=libexec-different build $ meson install $ /tmp/git/bin/git --exec-path /tmp/git/libexec-different $ /tmp/git/bin/git daemon git: 'daemon' is not a git command. See 'git --help' In order to fix the issue, use the 'git_exec_path' variable (calculated while processing -Dlibexecdir) as the 'install_dir' field during the installation of the library executables. [1]: <66fd343a-1351-4350-83eb-c797e47b7693@gmail.com> Reported-by: irecca.kun@gmail.com Signed-off-by: Ramsay Jones Signed-off-by: Junio C Hamano --- meson.build | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/meson.build b/meson.build index 596f5ac7110ebf..4aae6da05e81a6 100644 --- a/meson.build +++ b/meson.build @@ -1744,7 +1744,7 @@ git_builtin = executable('git', sources: builtin_sources + 'git.c', dependencies: [libgit_commonmain], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) bin_wrappers += git_builtin @@ -1752,35 +1752,35 @@ test_dependencies += executable('git-daemon', sources: 'daemon.c', dependencies: [libgit_commonmain], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) test_dependencies += executable('git-sh-i18n--envsubst', sources: 'sh-i18n--envsubst.c', dependencies: [libgit_commonmain], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) bin_wrappers += executable('git-shell', sources: 'shell.c', dependencies: [libgit_commonmain], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) test_dependencies += executable('git-http-backend', sources: 'http-backend.c', dependencies: [libgit_commonmain], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) bin_wrappers += executable('scalar', sources: 'scalar.c', dependencies: [libgit_commonmain], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) if curl.found() @@ -1796,14 +1796,14 @@ if curl.found() sources: 'remote-curl.c', dependencies: [libgit_curl], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) test_dependencies += executable('git-http-fetch', sources: 'http-fetch.c', dependencies: [libgit_curl], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) if expat.found() @@ -1811,7 +1811,7 @@ if curl.found() sources: 'http-push.c', dependencies: [libgit_curl], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) endif @@ -1822,7 +1822,7 @@ if curl.found() ) install_symlink(alias + executable_suffix, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, pointing_to: 'git-remote-http', ) endforeach @@ -1832,7 +1832,7 @@ test_dependencies += executable('git-imap-send', sources: 'imap-send.c', dependencies: [ use_curl_for_imap_send ? libgit_curl : libgit_commonmain ], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) foreach alias : [ 'git-receive-pack', 'git-upload-archive', 'git-upload-pack' ] @@ -1842,7 +1842,7 @@ foreach alias : [ 'git-receive-pack', 'git-upload-archive', 'git-upload-pack' ] ) install_symlink(alias + executable_suffix, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, pointing_to: 'git', ) endforeach @@ -1856,9 +1856,9 @@ foreach symlink : [ 'scalar', ] if meson.version().version_compare('>=1.3.0') - pointing_to = fs.relative_to(get_option('libexecdir') / 'git-core' / symlink, get_option('bindir')) + pointing_to = fs.relative_to(git_exec_path / symlink, get_option('bindir')) else - pointing_to = '../libexec/git-core' / symlink + pointing_to = '..' / git_exec_path / symlink endif install_symlink(symlink, @@ -1898,7 +1898,7 @@ foreach script : scripts_sh meson.project_build_root() / 'GIT-BUILD-OPTIONS', ], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) endforeach @@ -1931,7 +1931,7 @@ if perl_features_enabled input: perl_header_template, output: 'GIT-PERL-HEADER', configuration: { - 'GITEXECDIR_REL': get_option('libexecdir') / 'git-core', + 'GITEXECDIR_REL': git_exec_path, 'PERLLIBDIR_REL': perllibdir, 'LOCALEDIR_REL': get_option('datadir') / 'locale', 'INSTLIBDIR': perllibdir, @@ -1955,7 +1955,7 @@ if perl_features_enabled output: fs.stem(script), command: generate_perl_command, install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, depends: [git_version_file], ) test_dependencies += generated_script @@ -1964,9 +1964,9 @@ if perl_features_enabled bin_wrappers += generated_script if meson.version().version_compare('>=1.3.0') - pointing_to = fs.relative_to(get_option('libexecdir') / 'git-core' / fs.stem(script), get_option('bindir')) + pointing_to = fs.relative_to(git_exec_path / fs.stem(script), get_option('bindir')) else - pointing_to = '../libexec/git-core' / fs.stem(script) + pointing_to = '..' / git_exec_path / fs.stem(script) endif install_symlink(fs.stem(script), @@ -1996,7 +1996,7 @@ if python.found() '@OUTPUT@', ], install: true, - install_dir: get_option('libexecdir') / 'git-core', + install_dir: git_exec_path, ) test_dependencies += generated_python endforeach @@ -2030,7 +2030,7 @@ mergetools = [ ] foreach mergetool : mergetools - install_data(mergetool, install_dir: get_option('libexecdir') / 'git-core' / 'mergetools') + install_data(mergetool, install_dir: git_exec_path / 'mergetools') endforeach if intl.found() From 056dbe861272bfe0bd1ce642820f7d38c5313ae4 Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Wed, 16 Jul 2025 00:32:39 +0100 Subject: [PATCH 09/14] po/meson.build: add missing 'ga' language code Commit bf5ce434db ("l10n: Add full Irish translation (ga.po)", 2025-05-16) added a new translation to git. In a make build, new 'po' files (ga.po in this case) are added to the build automatically using a wildcard pattern. In a meson build you have to add the language code ('ga') to a list explicitly to have it included in the build. In order to include the new translation in the meson build, add the 'ga' language code to the list of translations in the 'po/meson.build' file. Signed-off-by: Ramsay Jones Signed-off-by: Junio C Hamano --- po/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/po/meson.build b/po/meson.build index d7154b6395b2bf..de3b4e2c387a7c 100644 --- a/po/meson.build +++ b/po/meson.build @@ -8,6 +8,7 @@ translations = i18n.gettext('git', 'el', 'es', 'fr', + 'ga', 'id', 'is', 'it', From 1f0fed312a40620b9f33f712d180a3c649e91e27 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Wed, 16 Jul 2025 00:25:23 +0000 Subject: [PATCH 10/14] SubmittingPatches: allow non-real name contributions Our submission guidelines require people to use their real name, but this is not always suitable for various reasons. For people who are transgender or non-binary and are transitioning or who think they might want to transition, it can be a major obstacle and cause major discomfort to require the use of their real name. This is made worse by the fact that Git provides no way to change names built into history, so the use of a deadname is forever. Our code of conduct states that we "pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community," and changing this policy is one way we can improve things for contributors. In addition, there are some developers who are so widely known pseudonymously that they have a Wikipedia page with their handle and no real name. It would seem silly to reject patches from people who are known and respected in their open-source community just because they don't wish to share a real name. There are also other good reasons why people might operate pseudonymously: because they or their family members are well known and they wish to protect their privacy, because of current or past harassment or retaliation or fear of that happening in the future, or because of concerns about unwanted attention from government officials or other authority figures. As much as possible, we want to welcome contributions from anyone who is willing to participate positively in our community without having them worry about their safety or privacy. In all of these cases, we should allow people to proceed using a preferred name or pseudonymously if, in their best judgment, that's the right thing to do. State that it is common to use a real name but explicitly mention that contributors who are not comfortable doing so or prefer to operate pseudonymously or under a preferred name can proceed otherwise, provided the name is distinctive, identifying, and not misleading. For instance, using U+2060 (WORD JOINER) as one's ID would likely be distinctive but not identifying, since most people would have trouble reading it due to its zero-width nature. We prohibit identities which are misleading, since our goal is to create a community which works together with a common goal, and misleading or deceiving others is not conducive to good community or compatible with our code of conduct, nor is it compatible with making a legal assertion about the provenance of one's code. Explicitly prohibit anonymous contributions to ensure that we have some line of provenance to a known (if pseudonymous) author who might be able to respond to questions about it. Explain that this is the reason we have this policy to help contributors understand the rationale better. Use "some form of your real name" since some current contributors use shortened forms of their name or use initials, which have always been considered acceptable. This helps guide people who would be fine using their real name but have misconfigured `user.name` thinking it is intended to be a username or is used for authentication (despite our documentation to the contrary), but also allows for a variety of circumstances where the contributor would feel more comfortable not doing so. Note that this policy is the same as that of the Linux kernel[0] and the CNCF[1], as well as many smaller projects. The Linux kernel patch was Acked-by one of the Linux Foundation's lawyers, Michael Dolan, so it appears these changes have had legal review. Additionally, retain the section header ID for ease of linking across versions. [0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d4563201f33a022fc0353033d9dfeb1606a88330 [1] https://github.com/cncf/foundation/blob/659fd32c86dc/dco-guidelines.md Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- Documentation/SubmittingPatches | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 958e3cc3d54741..86ca7f6a78a9b6 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -408,8 +408,15 @@ your patch differs from project to project, so it may be different from that of the project you are accustomed to. [[real-name]] -Also notice that a real name is used in the `Signed-off-by` trailer. Please -don't hide your real name. +Please use a known identity in the `Signed-off-by` trailer, since we cannot +accept anonymous contributions. It is common, but not required, to use some form +of your real name. We realize that some contributors are not comfortable doing +so or prefer to contribute under a pseudonym or preferred name and we can accept +your patch either way, as long as the name and email you use are distinctive, +identifying, and not misleading. + +The goal of this policy is to allow us to have sufficient information to contact +you if questions arise about your contribution. [[commit-trailers]] If you like, you can put extra trailers at the end: From bfa405ea36b1d3dd9bb3999a6a5590c15af13fae Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Wed, 16 Jul 2025 10:38:28 +0100 Subject: [PATCH 11/14] CodingGuidelines: allow the use of bool We have had a test balloon for C99's bool type since 8277dbe987 (git-compat-util: convert skip_{prefix,suffix}{,_mem} to bool, 2023-12-16). As we've had it over 18 months without any complaints let's declare it a success. Signed-off-by: Phillip Wood Signed-off-by: Junio C Hamano --- Documentation/CodingGuidelines | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index c1046abfb7d10b..d787bb21eaf19f 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -298,6 +298,9 @@ For C programs: . since late 2021 with 44ba10d6, we have had variables declared in the for loop "for (int i = 0; i < 10; i++)". + . since late 2023 with 8277dbe987 we have been using the bool type + from . + New C99 features that we cannot use yet: . %z and %zu as a printf() argument for a size_t (the %z being for From f3ba426e3539b2d585944f9d6425dbc13b7d0d28 Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Wed, 16 Jul 2025 10:38:29 +0100 Subject: [PATCH 12/14] git-compat-util: convert string predicates to return bool Since 8277dbe987 (git-compat-util: convert skip_{prefix,suffix}{,_mem} to bool, 2023-12-16) a number of our string predicates have been returning bool instead of int. Now that we've declared that experiment a success, let's convert the return type of the case-independent skip_iprefix() and skip_iprefix_mem() functions to match the return type of their case-dependent equivalents. Returning bool instead of int makes it clear that these functions are predicates. Signed-off-by: Phillip Wood Signed-off-by: Junio C Hamano --- git-compat-util.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/git-compat-util.h b/git-compat-util.h index 4678e21c4cb80b..50ca9dc547fe1a 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -895,16 +895,16 @@ static inline size_t xsize_t(off_t len) * is done via tolower(), so it is strictly ASCII (no multi-byte characters or * locale-specific conversions). */ -static inline int skip_iprefix(const char *str, const char *prefix, +static inline bool skip_iprefix(const char *str, const char *prefix, const char **out) { do { if (!*prefix) { *out = str; - return 1; + return true; } } while (tolower(*str++) == tolower(*prefix++)); - return 0; + return false; } /* @@ -912,7 +912,7 @@ static inline int skip_iprefix(const char *str, const char *prefix, * comparison is done via tolower(), so it is strictly ASCII (no multi-byte * characters or locale-specific conversions). */ -static inline int skip_iprefix_mem(const char *buf, size_t len, +static inline bool skip_iprefix_mem(const char *buf, size_t len, const char *prefix, const char **out, size_t *outlen) { @@ -920,10 +920,10 @@ static inline int skip_iprefix_mem(const char *buf, size_t len, if (!*prefix) { *out = buf; *outlen = len; - return 1; + return true; } } while (len-- > 0 && tolower(*buf++) == tolower(*prefix++)); - return 0; + return false; } static inline int strtoul_ui(char const *s, int base, unsigned int *result) From f006e0323ee4b407bee3e0ff241d9d3f7a03b66a Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Wed, 16 Jul 2025 10:38:30 +0100 Subject: [PATCH 13/14] strbuf: convert predicates to return bool Now that the string predicates defined in git-compat-util.h all return bool let's convert the return type of the string predicates in strbuf.{c,h} to match them. Signed-off-by: Phillip Wood Signed-off-by: Junio C Hamano --- strbuf.c | 28 ++++++++++++++-------------- strbuf.h | 12 ++++++------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/strbuf.c b/strbuf.c index f30fdc6984310e..6c3851a7f84d72 100644 --- a/strbuf.c +++ b/strbuf.c @@ -8,55 +8,55 @@ #include "utf8.h" #include "date.h" -int starts_with(const char *str, const char *prefix) +bool starts_with(const char *str, const char *prefix) { for (; ; str++, prefix++) if (!*prefix) - return 1; + return true; else if (*str != *prefix) - return 0; + return false; } -int istarts_with(const char *str, const char *prefix) +bool istarts_with(const char *str, const char *prefix) { for (; ; str++, prefix++) if (!*prefix) - return 1; + return true; else if (tolower(*str) != tolower(*prefix)) - return 0; + return false; } -int starts_with_mem(const char *str, size_t len, const char *prefix) +bool starts_with_mem(const char *str, size_t len, const char *prefix) { const char *end = str + len; for (; ; str++, prefix++) { if (!*prefix) - return 1; + return true; else if (str == end || *str != *prefix) - return 0; + return false; } } -int skip_to_optional_arg_default(const char *str, const char *prefix, +bool skip_to_optional_arg_default(const char *str, const char *prefix, const char **arg, const char *def) { const char *p; if (!skip_prefix(str, prefix, &p)) - return 0; + return false; if (!*p) { if (arg) *arg = def; - return 1; + return true; } if (*p != '=') - return 0; + return false; if (arg) *arg = p + 1; - return 1; + return true; } /* diff --git a/strbuf.h b/strbuf.h index 6362777c0a017d..a580ac6084b7f1 100644 --- a/strbuf.h +++ b/strbuf.h @@ -660,9 +660,9 @@ char *xstrvfmt(const char *fmt, va_list ap); __attribute__((format (printf, 1, 2))) char *xstrfmt(const char *fmt, ...); -int starts_with(const char *str, const char *prefix); -int istarts_with(const char *str, const char *prefix); -int starts_with_mem(const char *str, size_t len, const char *prefix); +bool starts_with(const char *str, const char *prefix); +bool istarts_with(const char *str, const char *prefix); +bool starts_with_mem(const char *str, size_t len, const char *prefix); /* * If the string "str" is the same as the string in "prefix", then the "arg" @@ -678,16 +678,16 @@ int starts_with_mem(const char *str, size_t len, const char *prefix); * can be used instead of !strcmp(arg, "--key") and then * skip_prefix(arg, "--key=", &arg) to parse such an option. */ -int skip_to_optional_arg_default(const char *str, const char *prefix, +bool skip_to_optional_arg_default(const char *str, const char *prefix, const char **arg, const char *def); -static inline int skip_to_optional_arg(const char *str, const char *prefix, +static inline bool skip_to_optional_arg(const char *str, const char *prefix, const char **arg) { return skip_to_optional_arg_default(str, prefix, arg, ""); } -static inline int ends_with(const char *str, const char *suffix) +static inline bool ends_with(const char *str, const char *suffix) { size_t len; return strip_suffix(str, suffix, &len); From e4ef0485fd78fcb05866ea78df35796b904e4a8e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 24 Jul 2025 16:03:41 -0700 Subject: [PATCH 14/14] The fourteenth batch Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.51.0.adoc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/RelNotes/2.51.0.adoc b/Documentation/RelNotes/2.51.0.adoc index ed968c5342db2c..1a874e6b466488 100644 --- a/Documentation/RelNotes/2.51.0.adoc +++ b/Documentation/RelNotes/2.51.0.adoc @@ -97,6 +97,12 @@ Performance, Internal Implementation, Development Support etc. * Flipping the default hash function to SHA-256 at Git 3.0 boundary is planned. + * Declare weather-balloon we raised for "bool" type 18 months ago a + success and officially allow using the type in our codebase. + + * GIT_TEST_INSTALLED was not honored in the recent topic related to + SHA256 hashes, which has been corrected. + Fixes since v2.50 ----------------- @@ -208,6 +214,17 @@ including security updates, are included in this release. ourselves. (merge 9d3b33125f ps/sane-ctype-workaround later to maint). + * Clean-up compat/bswap.h mess. + (merge f4ac32c03a ss/compat-bswap-revamp later to maint). + + * Meson-based build did not handle libexecdir setting correctly, + which has been corrected. + (merge 056dbe8612 rj/meson-libexecdir-fix later to maint). + + * Document that we do not require "real" name when signing your + patches off. + (merge 1f0fed312a bc/contribution-under-non-real-names later to maint). + * Other code cleanup, docfix, build fix, etc. (merge b257adb571 lo/my-first-ow-doc-update later to maint). (merge 8b34b6a220 ly/sequencer-update-squash-is-fixup-only later to maint). @@ -233,3 +250,4 @@ including security updates, are included in this release. (merge ad7780b38f ps/doc-pack-refs-auto-with-files-backend-fix later to maint). (merge f4fa8a3687 rh/doc-glob-pathspec-fix later to maint). (merge b27be108c8 ja/doc-git-log-markup later to maint). + (merge 14d7583beb pw/config-kvi-remove-path later to maint).