| Age | Commit message (Collapse) | Author | Files | Lines |
|
* convert commands and options to synopsis style
* use _<placeholder>_ for arguments
* small style fixes
Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
* convert commands to synopsis style
* use _<placeholder>_ for arguments
* fix conditional text to sentence limits
Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Commit 85127bcdea ("backfill: assume --sparse when sparse-checkout is
enabled") intended for 'git backfill' to consult the repository
configuration when the user does not pass '--sparse' or
'--no-sparse' on the command line. It added the sentinel check:
if (ctx->sparse < 0)
ctx->sparse = cfg->apply_sparse_checkout;
However, the ctx->sparse field is initialized to 0 instead of -1,
so this guard never triggers. Consequently, the repository config
(core.sparseCheckout) is never checked, and the command always
performs a full backfill even when sparse-checkout is enabled.
Fix this by initializing ctx->sparse to -1, ensuring the existing
fallback logic correctly reads the repository configuration when
no explicit flags are provided.
Add a test to verify that 'git backfill' automatically respects
sparse-checkout settings when no flags are passed.
Signed-off-by: Trieu Huynh <vikingtc4@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
There's a typo in the comment, making it hard to understand. And the
macro itself is indented with spaces rather than tab.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Upstream adds 18 new translatable messages.
* 'master' of https://github.com/git/git: (41 commits)
A bit more on top of 2.54-rc0
...
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
|
|
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The way dash 0.5.13 handles non-ASCII contents in here-doc
is buggy and breaks our existing tests, which unfortunately
have been rewritten to avoid triggering the bug.
* ps/dash-buggy-0.5.13-workaround:
t9300: work around partial read bug in Dash v0.5.13
t: work around multibyte bug in quoted heredocs with Dash v0.5.13
|
|
Build instruction for recently added writev() compatibility wrapper
has been also added to cmake.
* js/cmake-needs-writev-compat-too:
cmake: use writev(3p) wrapper as needed
|
|
MinGW build updates.
* js/mingw-use-strftime-directly-in-ucrt-build:
mingw: use strftime() directly in UCRT builds
|
|
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Test clean-up.
* th/t8003-unhide-git-failures:
t8003: modernise style
t8003: avoid suppressing git's exit code
|
|
"git replay" (experimental) learns, in addition to "pick" and
"replay", a new operating mode "revert".
* sa/replay-revert:
replay: add --revert mode to reverse commit changes
sequencer: extract revert message formatting into shared function
|
|
Reduce the reference to the_repository in the worktree subsystem.
* pw/worktree-reduce-the-repository:
worktree: reject NULL worktree in get_worktree_git_dir()
worktree add: stop reading ".git/HEAD"
worktree: remove "the_repository" from is_current_worktree()
|
|
Code clean-up around the recent "hooks defined in config" topic.
* ar/config-hook-cleanups:
hook: reject unknown hook names in git-hook(1)
hook: show disabled hooks in "git hook list"
hook: show config scope in git hook list
hook: introduce hook_config_cache_entry for per-hook data
t1800: add test to verify hook execution ordering
hook: make consistent use of friendly-name in docs
hook: replace hook_list_clear() -> string_list_clear_func()
hook: detect & emit two more bugs
hook: rename cb_data_free/alloc -> hook_data_free/alloc
hook: fix minor style issues
builtin/receive-pack: properly init receive_hook strbuf
hook: move unsorted_string_list_remove() to string-list.[ch]
|
|
`git backfill` learned to accept revision and pathspec arguments.
* ds/backfill-revs:
t5620: test backfill's unknown argument handling
path-walk: support wildcard pathspecs for blob filtering
backfill: work with prefix pathspecs
backfill: accept revision arguments
t5620: prepare branched repo for revision tests
revision: include object-name.h
|
|
Doc updates.
* mf/format-patch-commit-list-format-doc:
format-patch: removing unconditional wrapping
docs: fix --commit-list-format related entries
|
|
Improve the recently introduced `git format-patch
--commit-list-format` (formerly `--cover-letter-format`) option,
including a new "modern" preset and better CLI ergonomics.
* mf/format-patch-commit-list-format:
format-patch: --commit-list-format without prefix
format-patch: add preset for --commit-list-format
format-patch: wrap generate_commit_list_cover()
format.commitListFormat: strip meaning from empty
docs/pretty-formats: add %(count) and %(total)
format-patch: rename --cover-letter-format option
format-patch: refactor generate_commit_list_cover
pretty.c: better die message %(count) and %(total)
|
|
"git format-patch --cover-letter" learns to use a simpler format
instead of the traditional shortlog format to list its commits with
a new --cover-letter-format option and format.commitListFormat
configuration variable.
* mf/format-patch-cover-letter-format:
docs: add usage for the cover-letter fmt feature
format-patch: add commitListFormat config
format-patch: add ability to use alt cover format
format-patch: move cover letter summary generation
pretty.c: add %(count) and %(total) placeholders
|
|
The `mingw_strftime()` wrapper exists to work around msvcrt.dll's
incomplete `strftime()` implementation by dynamically loading the
version from ucrtbase.dll at runtime via `LoadLibrary()` +
`GetProcAddress()`. When the binary is already linked against UCRT
(i.e. when building in the UCRT64 environment), the linked-in
`strftime()` is the ucrtbase.dll version, making the dynamic loading
needless churn: It's calling the very same code.
Simply guard both the declaration and implementation so that the
unnecessary work-around is skipped in UCRT builds.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
This is a companion patch of 3b9b2c2a29a (compat/posix: introduce
writev(3p) wrapper, 2026-03-13) where support for using the `writev()`
wrapper was introduced in the `Makefile` and the Meson-based build, but
the CMake build still needs that treatment, too.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Document po/AGENTS.md-driven AI workflows (with an example prompt)
before the PO helper section, cross-reference git-po-helper, and
summarize quality checks plus optional agent integration in the PO
helper section.
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
|
|
Add a new "Reviewing po/XX.po" section to po/AGENTS.md that provides
comprehensive guidance for AI agents to review translation files.
Translation diffs lose context, especially for multi-line msgid and
msgstr entries. Some LLMs ignore context and cannot evaluate
translations accurately; others rely on scripts to search for context
in source files, making the review process time-consuming. To address
this, git-po-helper implements the compare subcommand, which extracts
new or modified translations with full context (complete msgid/msgstr
pairs), significantly improving review efficiency.
A limitation is that the extracted content lacks other
already-translated content for reference, which may affect terminology
consistency. This is mitigated by including a glossary in the PO file
header. git-po-helper-generated review files include the header entry
and glossary (if present) by default.
The review workflow leverages git-po-helper subcommands:
- git-po-helper compare: Extract new or changed entries between two
versions of a PO file into a valid PO file for review. Supports
multiple modes:
* Compare HEAD with the working tree (local changes)
* Compare a commit's parent with the commit (--commit)
* Compare a commit with the working tree (--since)
* Compare two arbitrary revisions (-r)
- git-po-helper msg-select: Split large review files into smaller
batches by entry index range for manageable review sessions. Supports
range formats like "-50" (first 50), "51-100", "101-" (to end).
Evaluation with the Qwen model:
git-po-helper agent-run review --commit 2000abefba --agent qwen
Benchmark results:
| Metric | Value |
|------------------|----------------------------------|
| Turns | 22 |
| Input tokens | 537263 |
| Output tokens | 4397 |
| API duration | 167.84 s |
| Review score | 96/100 |
| Total entries | 63 |
| With issues | 4 (1 critical, 2 major, 1 minor) |
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
|
|
Add a new "Translating po/XX.po" section to po/AGENTS.md with detailed
workflow and procedures for AI agents to translate language-specific PO
files. Users can invoke AI-assisted translation in coding tools with a
prompt such as:
"Translate the po/XX.po file by referring to @po/AGENTS.md"
Translation results serve as drafts; human contributors must review and
approve before submission.
To address the low translation efficiency of some LLMs, batch
translation replaces entry-by-entry translation. git-po-helper
implements a gettext JSON format for translation files, replacing PO
format during translation to enable batch processing.
Evaluation with the Qwen model:
git-po-helper agent-run --agent=qwen translate po/zh_CN.po
Test translation (127 entries, 50 per batch):
Initial state: 5998 translated, 91 fuzzy, 36 untranslated
Final state: 6125 translated, 0 fuzzy, 0 untranslated
Successfully translated: 127 entries (91 fuzzy + 36 untranslated)
Success rate: 100%
Benchmark results (3-run average):
AI agent using gettext tools:
| Metric | Value |
|------------------|--------------------------------|
| Avg. Num turns | 86 (176, 44, 40) |
| Avg. Exec. Time | 20m44s (39m56s, 14m38s, 7m38s) |
| Successful runs | 3/3 |
AI agent using git-po-helper (JSON batch flow):
| Metric | Value |
|------------------|--------------------------------|
| Avg. Num turns | 56 (68, 39, 63) |
| Avg. Exec. Time | 19m8s (28m55s, 9m1s, 19m28s) |
| Successful runs | 3/3 |
The git-po-helper flow reduces the number of turns (86 → 56) with
similar execution time; the bottleneck appears to be LLM processing
rather than network interaction.
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
|
|
Add a new section to po/AGENTS.md to provide clear instructions for
updating language-specific PO files. The improved documentation
significantly reduces both conversation turns and execution time.
Performance evaluation with the Qwen model:
# Before: instructions in po/README.md; the custom prompt
# references po/README.md during execution
git-po-helper agent-test --runs=5 --agent=qwen update-po \
--prompt="Update po/zh_CN.po according to po/README.md"
# After: instructions in po/AGENTS.md; the built-in prompt
# references po/AGENTS.md during execution
git-po-helper agent-test --runs=5 --agent=qwen update-po
Benchmark results (5-run average):
| Metric | Before | After | Improvement |
|-------------|---------|--------|-------------|
| Turns | 22 | 4 | -82% |
| Exec. time | 38s | 9s | -76% |
| Turn range | 17-39 | 3-9 | |
| Time range | 25s-68s | 7s-14s | |
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
|
|
Add a new documentation file po/AGENTS.md that provides agent-specific
instructions for generating or updating po/git.pot, separating them
from the general po/README.md. This separation allows for more targeted
optimization of AI agent workflows.
Performance evaluation with the Qwen model:
# Before: No agent-specific instructions; use po/README.md for
# reference.
git-po-helper agent-test --runs=5 --agent=qwen update-pot \
--prompt="Update po/git.pot according to po/README.md"
# Phase 1: add the instructions to po/README.md; the prompt
# references po/README.md during execution
git-po-helper agent-test --runs=5 --agent=qwen update-pot \
--prompt="Update po/git.pot according to po/README.md"
# Phase 2: add the instructions to po/AGENTS.md; use the built-in
# prompt that references po/AGENTS.md during execution
git-po-helper agent-test --runs=5 --agent=qwen update-pot
Benchmark results (5-run average):
Phase 1 - Optimizing po/README.md:
| Metric | Before | Phase 1 | Improvement |
|-------------|---------|---------|-------------|
| Turns | 17 | 5 | -71% |
| Exec. time | 34s | 14s | -59% |
| Turn range | 3-36 | 3-7 | |
| Time range | 10s-59s | 9s-19s | |
Phase 2 - Adding po/AGENTS.md (further optimization):
| Metric | Before | Phase 2 | Improvement |
|-------------|---------|---------|-------------|
| Turns | 17 | 3 | -82% |
| Exec. time | 34s | 8s | -76% |
| Turn range | 3-36 | 3-3 | |
| Time range | 10s-59s | 6s-9s | |
Separating agent-specific instructions into AGENTS.md provides:
- More focused and concise instructions for AI agents
- Cleaner README.md for human readers
- An additional 11% reduction in turns and 17% reduction in execution
time
- More consistent behavior (turn range reduced from 3-7 to 3-3)
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
|
|
To simplify the location filtering process for l10n contributors when
committing po/XX.po files, add filter attributes for selected PO
files to the repository. This ensures all contributors automatically
get the same filter configuration without manual setup in
.git/info/attributes.
The default filter (gettext-no-location) is applied to all .po files
except:
- Legacy, unmaintained PO files that still contain location comments.
Leaving the filter off avoids index vs working-tree discrepancies for
these files. The CI pipeline will report an error when future updates
touch these legacy files.
- Some PO files use a different filter that strips only line numbers
from location comments while keeping filenames.
Contributors still need to manually define the filter drivers via
git-config as documented in po/README.md.
Four PO files that use location filtering (po/ca.po, po/es.po, po/ga.po,
po/ru.po) were batch-modified so their on-disk format matches the filter
output (e.g. line wrapping), avoiding index vs working-tree mismatch.
Additionally, po/README.md has been reorganized: the material on
preparing location-less PO files for commit has been moved from
"Updating a XX.po file" to a separate "Preparing a XX.po file for
commit" section. This prevents AI agents from introducing unrelated
operations when updating PO files.
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
|
|
When executing t9300 with Dash v0.5.13.1 we can see that the test hangs
completely with the following (condensed) trace:
git fast-import
+ error=1
+ read output
+ cat input
+ echo checkpoint
+ echo progress checkpoint
+ test rogress checkpoint = progress checkpoint
+ test rogress checkpoint = UNEXPECTED
+ echo cruft: rogress checkpoint
cruft: rogress checkpoint
+ read output
+ test = progress checkpoint
+ test = UNEXPECTED
+ echo cruft:
cruft:
+ read output
Basically, what's happening here is that we spawn git-fast-import(1) and
wait for it to output a certain string, "progress checkpoint". Curiously
though, what we end up reading is "rogress checkpoint" -- so the first
byte of the expected string is missing.
Same as in the preceding commit, this seems to be a bug in Dash itself
that bisects to c5bf970 (expand: Add multi-byte support to pmatch,
2024-06-02). But other than in the preceding commit, this bug has
already been fixed upstream in 079059a (input: Fix heap-buffer-overflow
in preadbuffer on long lines, 2026-02-11), which is part of v0.5.13.2.
For now though, work around the bug by waiting for the expected output
in a different way. There is no good reason why one version should work
better than the other, but at least the new version doesn't exhibit the
bug. And, if you ask me, it's also slightly easier to read.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When executing our test suite with Dash v0.5.13.2 one can observe
several test failures that all have the same symptoms: we have a quoted
heredoc that contains multibyte characters, but the final data does not
match what we actually wanted to write. One such example is in t0300,
where we see the diffs like the following:
--- expect-stdout 2026-04-01 07:25:45.249919440 +0000
+++ stdout 2026-04-01 07:25:45.254919509 +0000
@@ -1,5 +1,5 @@
protocol=https
host=example.com
-path=perú.git
+path=perú.git
username=foo
password=bar
While seemingly the same, the data that we've written via the heredoc
contains some invisible bytes. The expected hex representation of the
string is:
7065 72c3 ba2e 6769 74 per...git
But what we actually get instead is this string:
7065 7285 02c3 ba02 852e 6769 74 per.......git
What's important to note here is that the multibyte character exists in
both versions. But in the broken version we see that the bytes are
wrapped in a sequence of "85 02" and "02 85". This is the CTLMBCHAR byte
sequence of Dash, which it uses internally to quote multibyte sequences.
As it turns out, this bug was introduced in c5bf970 (expand: Add
multi-byte support to pmatch, 2024-06-02), which adds multibyte support
to more contexts of Dash. One of these contexts seems to be in heredocs,
and Dash _does_ correctly unquote these multibyte sequences when using
an unquoted heredoc. But the bug seems to be that this unquoting does
not happen in quoted heredocs, and the bug still exists on the latest
"master" branch.
For now, work around the bug by using unquoted heredocs instead.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
In our codebase we have a couple of wrappers around mmap(3p) that allow
us to reimplement the syscall on platforms that don't have it natively,
like for example Windows. Other projects that embed the reftable library
may have a different infra though to hook up mmap wrappers, but these
are currently hard to integrate.
Provide the infrastructure to let projects easily define the mmap
interface with a custom struct and custom functions.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
We directly call gettimeofday(3p), which may not be available on some
platforms. Provide the infrastructure to let projects easily use their
own implementations of this function.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
While we have the reftable-specific `REFTABLE_UNUSED` header, we
accidentally introduced a new usage of the Git-specific `UNUSED` header
into the reftable library in 9051638519 (reftable: add code to
facilitate consistency checks, 2025-10-07).
Convert the site to use `REFTABLE_UNUSED`.
Ideally, we'd move the definition of `UNUSED` into "git-compat-util.h"
so that it becomes in accessible to the reftable library. But this is
unfortunately not easily possible as "compat/mingw-posix.h" requires
this macro, and this header is included by "compat/posix.h".
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Users of the reftable library are expected to provide their own function
callback in cases they want to sync(3p) data to disk via the reftable
write options. But if no such function was provided we end up calling
fsync(3p) directly, which may not even be available on some systems.
While dropping the explicit call to fsync(3p) would work, it would lead
to an unsafe default behaviour where a project may have forgotten to set
up the callback function, and that could lead to potential data loss. So
this is not a great solution.
Instead, drop the callback function and make it mandatory for the
project to define fsync(3p). In the case of Git, we can then easily
inject our custom implementation via the "reftable-system.h" header so
that we continue to use `fsync_component()`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
We're including a couple of standard headers like <stdint.h> in a bunch
of locations, which makes it hard for a project to plug in their own
logic for making required functionality available. For us this is for
example via "compat/posix.h", which already includes all of the system
headers relevant to us.
Introduce a new "reftable-system.h" header that allows projects to
provide their own headers. This new header is supposed to contain all
the project-specific bits to provide the POSIX-like environment, and some
additional supporting code. With this change, we thus have the following
split in our system-specific code:
- "reftable/reftable-system.h" is the project-specific header that
provides a POSIX-like environment. Every project is expected to
provide their own implementation.
- "reftable/system.h" contains the project-independent definition of
the interfaces that a project needs to implement. This file should
not be touched by a project.
- "reftable/system.c" contains the project-specific implementation of
the interfaces defined in "system.h". Again, every project is
expected to provide their own implementation.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
In show_one_reflog_ent(), we're fed a writable strbuf buffer, which we
parse into the various reflog components. We write a NUL over email_end
to tie off one of the fields, and thus email_end must be non-const.
But with a C23 implementation of libc, strchr() will now complain when
assigning the result to a non-const pointer from a const one. So we can
fix this by making the source pointer non-const.
But there's a catch. We derive that source pointer by parsing the line
with parse_oid_hex_algop(), which requires a const pointer for its
out-parameter. We can work around that by teaching it to use our
CONST_OUTPARAM() trick, just like skip_prefix().
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
In redact_sensitive_header(), a C23 implementation of libc will complain
that strstr() assigns the result from "const char *cookie" to "char
*semicolon".
Ultimately the memory is writable. We're fed a strbuf, generate a const
pointer "sensitive_header" within it using skip_iprefix(), and then
assign the result to "cookie". So we can solve this by dropping the
const from "cookie" and "sensitive_header".
However, this runs afoul of skip_iprefix(), which wants a "const char
**" for its out-parameter. We can solve that by teaching skip_iprefix()
the same "make sure out is at least as const as in" magic that we
recently taught to skip_prefix().
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
This is another case where we implicitly drop the "const" from a pointer
by feeding it to strstr() and assigning the result to a non-const
pointer. This is OK in practice, since the const pointer originally
comes from a writable source (a strbuf), but C23 libc implementations
have started to complain about it.
We do write to the output pointer, so it needs to remain non-const. We
can just switch the input pointer to also be non-const in this case. By
itself that would run into problems with calls to skip_prefix(), but
since that function has now been taught to match in/out constness
automatically, it just works without us doing anything further.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The "line" member of a packet_reader struct is marked as const. This
kind of makes sense, because it's not its own allocated buffer that
should be freed, and we often use const to indicate that. But it is
always writable, because it points into the non-const "buffer" member.
And we rely on this writability in places like send-pack and
receive-pack, where we parse incoming packet contents by writing NULs
over delimiters. This has traditionally worked because we implicitly
cast away the constness with strchr() like:
const char *head;
char *p;
head = reader->line;
p = strchr(head, ' ');
Since C23 libc provides a generic strchr() to detect this implicit
const removal, this now generate a compiler warning on some platforms
(like recent glibc).
We can fix it by marking "line" as non-const, as well as a few
intermediate variables (like "head" in the above example). Note that by
itself, switching to a non-const variable would cause problems with this
line in send-pack.c:
if (!skip_prefix(reader->line, "unpack ", &reader->line))
But due to our skip_prefix() magic introduced in the previous commit,
this compiles fine (both the in and out-parameters are non-const, so we
know it is safe).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The skip_prefix() function takes in a "const char *" string, and returns
via a "const char **" out-parameter that points somewhere in that
string. This is fine if you are operating on a const string, like:
const char *in = ...;
const char *out;
if (skip_prefix(in, "foo", &out))
...look at out...
It is also OK if "in" is not const but "out" is, as we add an implicit
const when we pass "in" to the function. But there's another case where
this is limiting. If we want both fields to be non-const, like:
char *in = ...;
char *out;
if (skip_prefix(in, "foo", &out))
*out = '\0';
it doesn't work. The compiler will complain about the type mismatch in
passing "&out" to a parameter which expects "const char **". So to make
this work, we have to do an explicit cast.
But such a cast is ugly, and also means that we run afoul of making this
mistake:
const char *in = ...;
char *out;
if (skip_prefix(in, "foo", (const char **)&out))
*out = '\0';
which causes us to write to the memory pointed by "in", which was const.
We can imagine these four cases as:
(1) const in, const out
(2) non-const in, const out
(3) non-const in, non-const out
(4) const in, non-const out
Cases (1) and (2) work now. We would like case (3) to work but it
doesn't. But we would like to catch case (4) as a compile error.
So ideally the rule is "the out-parameter must be at least as const as
the in-parameter". We can do this with some macro trickery. We wrap
skip_prefix() in a macro so that it has access to the real types of
in/out. And then we pass those parameters through another macro which:
1. Fails if the "at least as const" rule is not filled.
2. Casts to match the signature of the real skip_prefix().
There are a lot of ways to implement the "fails" part. You can use
__builtin_types_compatible_p() to check, and then either our
BUILD_ASSERT macros or _Static_assert to fail. But that requires some
conditional compilation based on compiler feature. That's probably OK
(the fallback would be to just cast without catching case 4). But we can
do better.
The macro I have here uses a ternary with a dead branch that tries to
assign "in" to "out", which should work everywhere and lets the compiler
catch the problem in the usual way. With an input like this:
int foo(const char *x, const char **y);
#define foo(in,out) foo((in), CONST_OUTPARAM((in), (out)))
void ok_const(const char *x, const char **y)
{
foo(x, y);
}
void ok_nonconst(char *x, char **y)
{
foo(x, y);
}
void ok_add_const(char *x, const char **y)
{
foo(x, y);
}
void bad_drop_const(const char *x, char **y)
{
foo(x, y);
}
gcc reports:
foo.c: In function ‘bad_drop_const’:
foo.c:2:35: error: assignment discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
2 | ((const char **)(0 ? ((*(out) = (in)),(out)) : (out)))
| ^
foo.c:4:31: note: in expansion of macro ‘CONST_OUTPARAM’
4 | #define foo(in,out) foo((in), CONST_OUTPARAM((in), (out)))
| ^~~~~~~~~~~~~~
foo.c:23:9: note: in expansion of macro ‘foo’
23 | foo(x, y);
| ^~~
It's a bit verbose, but I think makes it reasonably clear what's going
on. Using BUILD_ASSERT_OR_ZERO() ends up much worse. Using
_Static_assert you can be a bit more informative, but that's not
something we use at all yet in our code-base (it's an old gnu-ism later
standardized in C11).
Our generic macro only works for "const char **", which is something we
could improve by using typeof(in). But that introduces more portability
questions, and also some weird corner cases (e.g., around implicit void
conversion).
This patch just introduces the concept. We'll make use of it in future
patches.
Note that we rename skip_prefix() to skip_prefix_impl() here, to avoid
expanding the macro when defining the function. That's not strictly
necessary since we could just define the macro after defining the inline
function. But that would not be the case for a non-inline function (and
we will apply this technique to them later, and should be consistent).
It also gives us more freedom about where to define the macro. I did so
right above the definition here, which I think keeps the relevant bits
together.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The goal of this commit was to fix a const warning when compiling
with new versions of glibc, but ended up untangling a much deeper
problem.
The find_pseudo_merge() function does a bsearch() on the "commits"
pointer of a pseudo_merge_map. This pointer ultimately comes from memory
mapped from the on-disk bitmap file, and is thus not writable.
The "commits" array is correctly marked const, but the result from
bsearch() is returned directly as a non-const pseudo_merge_commit
struct. Since new versions of glibc annotate bsearch() in a way that
detects the implicit loss of const, the compiler now warns.
My first instinct was that we should be returning a const struct. That
requires apply_pseudo_merges_for_commit() to mark its local pointer as
const. But that doesn't work! If the offset field has the high-bit set,
we look it up in the extended table via nth_pseudo_merge_ext(). And that
function then feeds our const struct to read_pseudo_merge_commit_at(),
which writes into it by byte-swapping from the on-disk mmap.
But I think this points to a larger problem with find_pseudo_merge(). It
is not just that the return value is missing const, but it is missing
that byte-swapping! And we know that byte-swapping is needed here,
because the comparator we use for bsearch() also calls our
read_pseudo_merge_commit_at() helper.
So I think the interface is all wrong here. We should not be returning a
pointer to a struct which was cast from on-disk data. We should be
filling in a caller-provided struct using the bytes we found,
byte-swapping the values.
That of course raises the dual question: how did this ever work, and
does it work now? The answer to the first part is: this code does not
seem to be triggered in the test suite at all. If we insert a BUG("foo")
call into apply_pseudo_merges_for_commit(), it never triggers.
So I think there is something wrong or missing from the test setup, and
this bears further investigation. Sadly the answer to the second part
("does it work now") is still "no idea". I _think_ this takes us in a
positive direction, but my goal here is mainly to quiet the compiler
warning. Further bug-hunting on this experimental feature can be done
separately.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The find_last_dir_sep() function is implemented as an inline function
which takes in a "const char *" and returns a "char *" via strrchr().
That means that just like strrchr(), it quietly removes the const from
our pointer, which could lead to accidentally writing to the resulting
string.
But C23 versions of libc (including recent glibc) annotate strrchr()
such that the compiler can detect when const is implicitly lost, and it
now complains about the call in this inline function.
We can't just switch the return type of the function to "const char *",
though. Some callers really do want a non-const string to be returned
(and are OK because they are feeding a non-const string into the
function).
The most general solution is for us to annotate find_last_dir_sep() in
the same way that is done for strrchr(). But doing so relies on using
C23 generics, which we do not otherwise require.
Since this inline function is wrapping a single call to strrchr(), we
can take a shortcut. If we implement it as a macro, then the original
type information is still available to strrchr(), and it does the check
for us.
Note that this is just one implementation of find_last_dir_sep(). There
is an alternate implementation in compat/win32/path-utils.h. It doesn't
suffer from the same warning, as it does not use strrchr() and just
casts away const explicitly. That's not ideal, and eventually we may
want to conditionally teach it the same C23 generic trick that strrchr()
uses. But it has been that way forever, and our goal here is just
quieting new warnings, not improving const-checking.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
We do this:
char *equals = strchr(*e, '=');
which implicitly removes the constness from "*e" and cause the compiler
to complain. We never write to "equals", but later assign it to a
string_list util field, which is defined as non-const "void *".
We have to cast somewhere, but doing so at the assignment to util is the
least-bad place, since that is the source of the confusion. Sadly we are
still open to accidentally writing to the string via the util pointer,
but that is the cost of using void pointers, which lose all type
information.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When we do:
char *cp = strchr(argv[i], '=');
it implicitly removes the constness from argv[i]. We need "cp" to remain
writable (since we overwrite it with a NUL). In theory we should be able
to drop the const from argv[i], because it is a sub-pointer into our
duplicated pager_env variable.
But we get it from split_cmdline(), which uses the traditional "const
char **" type for argv. This is overly limiting, but changing it would
be awkward for all the other callers of split_cmdline().
Let's do an explicit cast with a note about why it is OK. This is enough
to silence compiler warnings about the implicit const problems.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
We implicitly drop the const from our "key" variable when we do:
char *p = strchr(key, ' ');
which causes compilation with some C23 versions of libc (notably recent
glibc) to complain.
We need "p" to remain writable, since we assign NUL over the space we
found. We can solve this by also making "key" writable. This works
because it comes from a strbuf, which is itself a writable string.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The "path" field of a "struct repo" (a custom http-push struct, not to
be confused with "struct repository) is a pointer into a const argv
string, and is never written to.
The compiler does not traditionally complain about assigning from a
const pointer because it happens via strchr(). But with some C23 libc
versions (notably recent glibc), it has started to do so. Let's mark the
field as const to silence the warnings.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
C23 versions of libc (like recent glibc) may provide generic versions of
strchr() that match constness between the input and return value. The
idea being that the compiler can detect when it implicitly converts a
const pointer into a non-const one (which then emits a warning).
There are a few cases here where the result pointer does not need to be
non-const at all, and we should mark it as such. That silences the
warning (and avoids any potential problems with trying to write via
those pointers).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When option '--onto' is passed to git-replay(1), the command will update
refs from the <revision-range> passed to the command. When using option
'--advance' or '--revert', the argument of that option is a ref that
will be updated.
To enable users to specify which ref to update, add option '--ref'. When
using option '--ref', the refs described above are left untouched and
instead the argument of this option is updated instead.
Because this introduces code paths in replay.c that jump to `out` before
init_basic_merge_options() is called on `merge_opt`, zero-initialize the
struct.
Signed-off-by: Toon Claes <toon@iotcl.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
gitcli(7) suggests to use stuck form. Change the documentation strings
to use this form.
While at it, reorder them to match the order in the docs.
Signed-off-by: Toon Claes <toon@iotcl.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The options '--onto', '--advance', '--revert', and '--ref-action' of
git-replay(1) are not negatable. Mark them as such using
PARSE_OPT_NONEG.
Signed-off-by: Toon Claes <toon@iotcl.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Signed-off-by: Todd Zullinger <tmz@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|