diff --git a/.tsan-suppressions b/.tsan-suppressions index 5ba86d68459e61..d84883bd90f9a6 100644 --- a/.tsan-suppressions +++ b/.tsan-suppressions @@ -7,7 +7,6 @@ # A static variable is written to racily, but we always write the same value, so # in practice it (hopefully!) doesn't matter. race:^want_color$ -race:^transfer_debug$ # A boolean value, which tells whether the replace_map has been initialized or # not, is read racily with an update. As this variable is written to only once, diff --git a/Documentation/RelNotes/2.55.0.adoc b/Documentation/RelNotes/2.55.0.adoc index 37f7a610a29b09..ecc76177e84e7d 100644 --- a/Documentation/RelNotes/2.55.0.adoc +++ b/Documentation/RelNotes/2.55.0.adoc @@ -73,6 +73,9 @@ UI, Workflows & Features * "git rev-list" (and "git log" family of commands) learned a new "--max-count-oldest" that picks oldest N commits in the range instead of the usual newest. + * Various AsciiDoc markup fixes in 'git config' documentation and + related files to ensure lists and formatting are rendered correctly. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -208,6 +211,16 @@ Performance, Internal Implementation, Development Support etc. delta cache instead of immediately freeing them, letting the existing cache limit policy decide eviction. + * `git ls-files --modified` and `git ls-files --deleted` have been + optimized to filter with pathspec before calling lstat() when there is + only a single pathspec item, avoiding unnecessary filesystem access + for entries that will not be shown. + + * The UNUSED macro in 'compat/posix.h' has been updated to use a + newly introduced GIT_CLANG_PREREQ macro for compiler version + checks, and the existing GIT_GNUC_PREREQ macro has been modernized + to use explicit major/minor comparisons rather than bit-shifting. + Fixes since v2.54 ----------------- @@ -389,6 +402,24 @@ Fixes since v2.54 (e.g., a clean/smudge filter) fails to start. (merge 061a68e443 mm/subprocess-handshake-fix later to maint). + * The TSAN race in transfer_debug() within transport-helper.c has been + resolved by initializing the debug flag early in + bidirectional_transfer_loop() before spawning worker threads, allowing + the removal of a TSAN suppression. + (merge 85704eda18 ps/transport-helper-tsan-fix later to maint). + + * 'git describe' has been taught to pass the 'refs/tags/' prefix down to + the ref iterator when '--all' is not requested, avoiding unnecessary + iteration over non-tag refs. + (merge 55088ac8a4 td/describe-tag-iteration later to maint). + + * compute_reachable_generation_numbers() in commit-graph used a 32-bit + integer to accumulate parent generations, which is OK for generation + number v1 (topological levels), but with generation number v2 + (adjusted committer timestamps), it truncated timestamps beyond + 2106. Fixed by widening the accumulator to timestamp_t. + (merge fbcc5408fc en/commit-graph-timestamp-fix later to maint). + * Other code cleanup, docfix, build fix, etc. (merge 80f4b802e9 ja/doc-difftool-synopsis-style later to maint). (merge b96490241e jc/doc-timestamps-in-stat later to maint). @@ -414,3 +445,4 @@ Fixes since v2.54 (merge d1b72b29e9 am/doc-tech-hash-typofix later to maint). (merge 014c454799 ak/typofixes later to maint). (merge 522ea8ef7d js/osxkeychain-build-wo-rust later to maint). + (merge e8f12e0e95 jc/t1400-fifo-cleanup later to maint). diff --git a/Documentation/config.adoc b/Documentation/config.adoc index a80e7db46d9697..15b1a4d5934758 100644 --- a/Documentation/config.adoc +++ b/Documentation/config.adoc @@ -276,13 +276,15 @@ boolean:: When a variable is said to take a boolean value, many synonyms are accepted for 'true' and 'false'; these are all case-insensitive. - ++ +-- true;; Boolean true literals are `yes`, `on`, `true`, and `1`. Also, a variable defined without `= ` is taken as true. false;; Boolean false literals are `no`, `off`, `false`, `0` and the empty string. +-- + When converting a value to its canonical form using the `--type=bool` type specifier, 'git config' will ensure that the output is "true" or diff --git a/Documentation/config/promisor.adoc b/Documentation/config/promisor.adoc index b0fa43b8393a53..39af63dcb87a32 100644 --- a/Documentation/config/promisor.adoc +++ b/Documentation/config/promisor.adoc @@ -63,11 +63,13 @@ If one of these field names (e.g., "token") is being checked for an advertised promisor remote (e.g., "foo"), three conditions must be met for the check of this specific field to pass: + +-- 1. The corresponding local configuration (e.g., `remote.foo.token`) must be set. 2. The server must advertise the "token" field for remote "foo". 3. The value of the locally configured `remote.foo.token` must exactly match the value advertised by the server for the "token" field. +-- + If any of these conditions is not met for any field name listed in `promisor.checkFields`, the advertised remote "foo" is rejected. diff --git a/Documentation/config/safe.adoc b/Documentation/config/safe.adoc index 5b1690aebe8f58..99fbfc06188c52 100644 --- a/Documentation/config/safe.adoc +++ b/Documentation/config/safe.adoc @@ -2,12 +2,14 @@ safe.bareRepository:: Specifies which bare repositories Git will work with. The currently supported values are: + +-- * `all`: Git works with all bare repositories. This is the default in Git 2.x. * `explicit`: Git only works with bare repositories specified via the top-level `--git-dir` command-line option, or the `GIT_DIR` environment variable (see linkgit:git[1]). This will be the default in Git 3.0. +-- + If you do not use bare repositories in your workflow, then it may be beneficial to set `safe.bareRepository` to `explicit` in your global diff --git a/Documentation/config/sideband.adoc b/Documentation/config/sideband.adoc index ff007aeb738a3d..f5b159e15fd834 100644 --- a/Documentation/config/sideband.adoc +++ b/Documentation/config/sideband.adoc @@ -9,7 +9,7 @@ sideband.allowControlCharacters:: `color`:: Allow ANSI color sequences, line feeds and horizontal tabs, but mask all other control characters. This is the default. - `cursor:`: + `cursor`:: Allow control sequences that move the cursor. This is disabled by default. `erase`:: diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc index 00545b20542c60..57af010ade5b5b 100644 --- a/Documentation/git-config.adoc +++ b/Documentation/git-config.adoc @@ -119,10 +119,10 @@ OPTIONS Append a comment at the end of new or modified lines. + If __ begins with one or more whitespaces followed -by "#", it is used as-is. If it begins with "#", a space is -prepended before it is used. Otherwise, a string " # " (a +by `#`, it is used as-is. If it begins with `#`, a space is +prepended before it is used. Otherwise, a string `" # "` (a space followed by a hash followed by a space) is prepended -to it. And the resulting string is placed immediately after +to it. The resulting string is placed immediately after the value defined for the variable. The __ must not contain linefeed characters (no multi-line comments are permitted). @@ -221,6 +221,7 @@ Use `--no-value` to unset __. + Valid ``'s include: + +-- - 'bool': canonicalize values `true`, `yes`, `on`, and positive numbers as "true", and values `false`, `no`, `off` and `0` as "false". @@ -239,6 +240,7 @@ Valid ``'s include: escape sequence. When setting a value, a sanity-check is performed to ensure that the given value is canonicalize-able as an ANSI color, but it is written as-is. +-- + If the command is in `list` mode, then the `--type ` argument will apply to each listed config value. If the value does not successfully parse in that diff --git a/builtin/describe.c b/builtin/describe.c index faaf44cec57364..a94dad998cddd7 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -752,6 +752,9 @@ int cmd_describe(int argc, return ret; } + if (!all) + for_each_ref_opts.prefix = "refs/tags/"; + hashmap_init(&names, commit_name_neq, NULL, 0); refs_for_each_ref_ext(get_main_ref_store(the_repository), get_name, NULL, &for_each_ref_opts); diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 12d5d828ff581a..99e98fc187accb 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -453,6 +453,17 @@ static void show_files(struct repository *repo, struct dir_struct *dir) continue; if (ce_skip_worktree(ce)) continue; + /* + * match_pathspec() is linear in pathspec.nr, so prefilter only + * the single-pathspec case. Only entries shown by show_ce() + * satisfy --error-unmatch. + */ + if (pathspec.nr == 1 && + !match_pathspec(repo->index, &pathspec, fullname.buf, + fullname.len, max_prefix_len, NULL, + S_ISDIR(ce->ce_mode) || + S_ISGITLINK(ce->ce_mode))) + continue; stat_err = lstat(fullname.buf, &st); if (stat_err && (errno != ENOENT && errno != ENOTDIR)) error_errno("cannot lstat '%s'", fullname.buf); diff --git a/commit-graph.c b/commit-graph.c index 0820cf5fb83cbe..801471a09802d9 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -1669,7 +1669,7 @@ static void compute_reachable_generation_numbers( struct commit *current = list->item; struct commit_list *parent; int all_parents_computed = 1; - uint32_t max_gen = 0; + timestamp_t max_gen = 0; for (parent = current->parents; parent; parent = parent->next) { repo_parse_commit(info->r, parent->item); diff --git a/compat/posix.h b/compat/posix.h index faaae1b6555d1b..2f01564b0d8a60 100644 --- a/compat/posix.h +++ b/compat/posix.h @@ -4,22 +4,33 @@ #define _FILE_OFFSET_BITS 64 /* - * Derived from Linux "Features Test Macro" header - * Convenience macros to test the versions of gcc (or - * a compatible compiler). + * Convenience macros to test the versions of GCC (or a compatible compiler). * Use them like this: * #if GIT_GNUC_PREREQ (2,8) - * ... code requiring gcc 2.8 or later ... + * ... code requiring GCC 2.8 or later ... * #endif * + * Note that Clang and other compilers define __GNUC__ for compatibility; use + * GIT_CLANG_PREREQ() to check for specific Clang versions. + * * This macro of course is not part of POSIX, but we need it for the UNUSED * macro which is used by some of our POSIX compatibility wrappers. -*/ + */ #if defined(__GNUC__) && defined(__GNUC_MINOR__) # define GIT_GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) + ((__GNUC__ > (maj)) || \ + (__GNUC__ == (maj) && __GNUC_MINOR__ >= (min))) +#else +# define GIT_GNUC_PREREQ(maj, min) 0 +#endif + +/* Similar for Clang. */ +#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_major__) +# define GIT_CLANG_PREREQ(maj, min) \ + ((__clang_major__ > (maj)) || \ + (__clang_major__ == (maj) && __clang_minor__ >= (min))) #else - #define GIT_GNUC_PREREQ(maj, min) 0 +# define GIT_CLANG_PREREQ(maj, min) 0 #endif /* @@ -35,14 +46,14 @@ * When a parameter may be used or unused, depending on conditional * compilation, consider using MAYBE_UNUSED instead. */ -#if GIT_GNUC_PREREQ(4, 5) -#define UNUSED __attribute__((unused)) \ - __attribute__((deprecated ("parameter declared as UNUSED"))) +#if GIT_GNUC_PREREQ(4, 5) || GIT_CLANG_PREREQ(2, 9) +# define UNUSED __attribute__((unused)) \ + __attribute__((deprecated("parameter declared as UNUSED"))) #elif defined(__GNUC__) -#define UNUSED __attribute__((unused)) \ +# define UNUSED __attribute__((unused)) \ __attribute__((deprecated)) #else -#define UNUSED +# define UNUSED #endif #ifdef __MINGW64__ diff --git a/t/meson.build b/t/meson.build index c5832fee053561..3219264fe7d497 100644 --- a/t/meson.build +++ b/t/meson.build @@ -1141,6 +1141,7 @@ benchmarks = [ 'perf/p1500-graph-walks.sh', 'perf/p1501-rev-parse-oneline.sh', 'perf/p2000-sparse-operations.sh', + 'perf/p3010-ls-files.sh', 'perf/p3400-rebase.sh', 'perf/p3404-rebase-interactive.sh', 'perf/p4000-diff-algorithms.sh', diff --git a/t/perf/p3010-ls-files.sh b/t/perf/p3010-ls-files.sh new file mode 100755 index 00000000000000..ae14449432453b --- /dev/null +++ b/t/perf/p3010-ls-files.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +test_description='Tests ls-files worktree performance' + +. ./perf-lib.sh + +test_perf_large_repo +test_checkout_worktree + +test_expect_success 'select a zero-prefix pathspec' ' + tracked_file=$(git ls-files | sed -n 1p) && + test -n "$tracked_file" && + pathspec="?${tracked_file#?}" && + test_export pathspec +' + +test_perf 'ls-files --deleted with pathspec' ' + git -c core.fsmonitor=false ls-files --deleted \ + -- "$pathspec" >/dev/null +' + +test_perf 'ls-files --deleted with all-matching pathspec' ' + git -c core.fsmonitor=false ls-files --deleted -- "*" >/dev/null +' + +test_perf 'ls-files --modified with pathspec' ' + git -c core.fsmonitor=false ls-files --modified \ + -- "$pathspec" >/dev/null +' + +test_done diff --git a/t/perf/p6100-describe.sh b/t/perf/p6100-describe.sh index 069f91ce493a70..b1c61529bb7bf8 100755 --- a/t/perf/p6100-describe.sh +++ b/t/perf/p6100-describe.sh @@ -27,4 +27,16 @@ test_perf 'describe HEAD with one tag' ' git describe --match=new HEAD ' +test_expect_success 'set up many unrelated refs' ' + ref_count=10000 && + git tag -m tip tip HEAD && + test_seq -f "create refs/heads/describe-perf/%05d HEAD" $ref_count | + git update-ref --stdin && + git pack-refs --all +' + +test_perf 'describe exact tag with many unrelated refs' ' + git describe --exact-match HEAD +' + test_done diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index 1015f335e31611..f059d63e38055f 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -1624,6 +1624,7 @@ test_expect_success 'transaction cannot restart ongoing transaction' ' ' test_expect_success PIPE 'transaction flushes status updates' ' + test_when_finished "rm -f in out" && mkfifo in out && (git update-ref --stdin out &) && diff --git a/t/t3010-ls-files-killed-modified.sh b/t/t3010-ls-files-killed-modified.sh index 7af4532cd1dfd0..6e38e10219e28e 100755 --- a/t/t3010-ls-files-killed-modified.sh +++ b/t/t3010-ls-files-killed-modified.sh @@ -124,4 +124,22 @@ test_expect_success 'validate git ls-files -m output.' ' test_cmp .expected .output ' +test_expect_success 'worktree modes honor wildcard pathspecs' ' + cat >.expected <<-\EOF && + path2/file2 + path3/file3 + EOF + git ls-files --deleted -- "path?/file?" >.output && + test_cmp .expected .output && + + cat >.expected <<-\EOF && + path7 + path8 + EOF + git ls-files --modified --error-unmatch -- "path[78]" >.output && + test_cmp .expected .output && + + test_must_fail git ls-files --modified --error-unmatch -- path10 +' + test_done diff --git a/t/t5328-commit-graph-64bit-time.sh b/t/t5328-commit-graph-64bit-time.sh index d8891e6a922463..bc651b69deeea4 100755 --- a/t/t5328-commit-graph-64bit-time.sh +++ b/t/t5328-commit-graph-64bit-time.sh @@ -74,6 +74,15 @@ test_expect_success 'single commit with generation data exceeding UINT32_MAX' ' git -C repo-uint32-max commit-graph verify ' +test_expect_success 'descendant of commit with date exceeding UINT32_MAX' ' + git init repo-uint32-max-descendant && + test_commit -C repo-uint32-max-descendant \ + --date "@4294967300 +0000" future-parent && + test_commit -C repo-uint32-max-descendant present-day-child && + git -C repo-uint32-max-descendant commit-graph write --reachable && + git -C repo-uint32-max-descendant commit-graph verify +' + test_expect_success PERL_TEST_HELPERS 'reader notices out-of-bounds generation overflow' ' graph=.git/objects/info/commit-graph && test_when_finished "rm -rf $graph" && diff --git a/transport-helper.c b/transport-helper.c index 0fa0eb2d72b2a6..80f90eb7bace6f 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -1361,24 +1361,18 @@ int transport_helper_init(struct transport *transport, const char *name) /* This should be enough to hold debugging message. */ #define PBUFFERSIZE 8192 +static int transfer_debug_enabled = -1; + /* Print bidirectional transfer loop debug message. */ __attribute__((format (printf, 1, 2))) static void transfer_debug(const char *fmt, ...) { - /* - * NEEDSWORK: This function is sometimes used from multiple threads, and - * we end up using debug_enabled racily. That "should not matter" since - * we always write the same value, but it's still wrong. This function - * is listed in .tsan-suppressions for the time being. - */ - va_list args; char msgbuf[PBUFFERSIZE]; - static int debug_enabled = -1; - if (debug_enabled < 0) - debug_enabled = getenv("GIT_TRANSLOOP_DEBUG") ? 1 : 0; - if (!debug_enabled) + if (transfer_debug_enabled < 0) + BUG("somebody forgot to check GIT_TRANSLOOP_DEBUG!"); + if (!transfer_debug_enabled) return; va_start(args, fmt); @@ -1648,6 +1642,9 @@ int bidirectional_transfer_loop(int input, int output) { struct bidirectional_transfer_state state; + if (transfer_debug_enabled < 0) + transfer_debug_enabled = getenv("GIT_TRANSLOOP_DEBUG") ? 1 : 0; + /* Fill the state fields. */ state.ptg.src = input; state.ptg.dest = 1;