summaryrefslogtreecommitdiff
path: root/builtin
AgeCommit message (Collapse)Author
2024-04-19Sync with 2.41.1Johannes Schindelin
* maint-2.41: (38 commits) Git 2.41.1 Git 2.40.2 Git 2.39.4 fsck: warn about symlink pointing inside a gitdir core.hooksPath: add some protection while cloning init.templateDir: consider this config setting protected clone: prevent hooks from running during a clone Add a helper function to compare file contents init: refactor the template directory discovery into its own function find_hook(): refactor the `STRIP_EXTENSION` logic clone: when symbolic links collide with directories, keep the latter entry: report more colliding paths t5510: verify that D/F confusion cannot lead to an RCE submodule: require the submodule path to contain directories only clone_submodule: avoid using `access()` on directories submodules: submodule paths must not contain symlinks clone: prevent clashing git dirs when cloning submodule in parallel t7423: add tests for symlinked submodule directories has_dir_name(): do not get confused by characters < '/' docs: document security issues around untrusted .git dirs ...
2024-04-19Sync with 2.40.2Johannes Schindelin
* maint-2.40: (39 commits) Git 2.40.2 Git 2.39.4 fsck: warn about symlink pointing inside a gitdir core.hooksPath: add some protection while cloning init.templateDir: consider this config setting protected clone: prevent hooks from running during a clone Add a helper function to compare file contents init: refactor the template directory discovery into its own function find_hook(): refactor the `STRIP_EXTENSION` logic clone: when symbolic links collide with directories, keep the latter entry: report more colliding paths t5510: verify that D/F confusion cannot lead to an RCE submodule: require the submodule path to contain directories only clone_submodule: avoid using `access()` on directories submodules: submodule paths must not contain symlinks clone: prevent clashing git dirs when cloning submodule in parallel t7423: add tests for symlinked submodule directories has_dir_name(): do not get confused by characters < '/' docs: document security issues around untrusted .git dirs upload-pack: disable lazy-fetching by default ...
2024-04-19Sync with 2.39.4Johannes Schindelin
* maint-2.39: (38 commits) Git 2.39.4 fsck: warn about symlink pointing inside a gitdir core.hooksPath: add some protection while cloning init.templateDir: consider this config setting protected clone: prevent hooks from running during a clone Add a helper function to compare file contents init: refactor the template directory discovery into its own function find_hook(): refactor the `STRIP_EXTENSION` logic clone: when symbolic links collide with directories, keep the latter entry: report more colliding paths t5510: verify that D/F confusion cannot lead to an RCE submodule: require the submodule path to contain directories only clone_submodule: avoid using `access()` on directories submodules: submodule paths must not contain symlinks clone: prevent clashing git dirs when cloning submodule in parallel t7423: add tests for symlinked submodule directories has_dir_name(): do not get confused by characters < '/' docs: document security issues around untrusted .git dirs upload-pack: disable lazy-fetching by default fetch/clone: detect dubious ownership of local repositories ...
2024-04-19Merge branch 'ownership-checks-in-local-clones'Johannes Schindelin
This topic addresses two CVEs: - CVE-2024-32020: Local clones may end up hardlinking files into the target repository's object database when source and target repository reside on the same disk. If the source repository is owned by a different user, then those hardlinked files may be rewritten at any point in time by the untrusted user. - CVE-2024-32021: When cloning a local source repository that contains symlinks via the filesystem, Git may create hardlinks to arbitrary user-readable files on the same filesystem as the target repository in the objects/ directory. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-19clone: prevent hooks from running during a cloneJohannes Schindelin
Critical security issues typically combine relatively common vulnerabilities such as case confusion in file paths with other weaknesses in order to raise the severity of the attack. One such weakness that has haunted the Git project in many a submodule-related CVE is that any hooks that are found are executed during a clone operation. Examples are the `post-checkout` and `fsmonitor` hooks. However, Git's design calls for hooks to be disabled by default, as only disabled example hooks are copied over from the templates in `<prefix>/share/git-core/templates/`. As a defense-in-depth measure, let's prevent those hooks from running. Obviously, administrators can choose to drop enabled hooks into the template directory, though, _and_ it is also possible to override `core.hooksPath`, in which case the new check needs to be disabled. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-17init: refactor the template directory discovery into its own functionJohannes Schindelin
We will need to call this function from `hook.c` to be able to prevent hooks from running that were written as part of a `clone` but did not originate from the template directory. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-17submodule: require the submodule path to contain directories onlyJohannes Schindelin
Submodules are stored in subdirectories of their superproject. When these subdirectories have been replaced with symlinks by a malicious actor, all kinds of mayhem can be caused. This _should_ not be possible, but many CVEs in the past showed that _when_ possible, it allows attackers to slip in code that gets executed during, say, a `git clone --recursive` operation. Let's add some defense-in-depth to disallow submodule paths to have anything except directories in them. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-17clone_submodule: avoid using `access()` on directoriesJohannes Schindelin
In 0060fd1511b (clone --recurse-submodules: prevent name squatting on Windows, 2019-09-12), I introduced code to verify that a git dir either does not exist, or is at least empty, to fend off attacks where an inadvertently (and likely maliciously) pre-populated git dir would be used while cloning submodules recursively. The logic used `access(<path>, X_OK)` to verify that a directory exists before calling `is_empty_dir()` on it. That is a curious way to check for a directory's existence and might well fail for unwanted reasons. Even the original author (it was I ;-) ) struggles to explain why this function was used rather than `stat()`. This code was _almost_ copypastad in the previous commit, but that `access()` call was caught during review. Let's use `stat()` instead also in the code that was almost copied verbatim. Let's not use `lstat()` because in the unlikely event that somebody snuck a symbolic link in, pointing to a crafted directory, we want to verify that that directory is empty. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-17submodules: submodule paths must not contain symlinksJohannes Schindelin
When creating a submodule path, we must be careful not to follow symbolic links. Otherwise we may follow a symbolic link pointing to a gitdir (which are valid symbolic links!) e.g. while cloning. On case-insensitive filesystems, however, we blindly replace a directory that has been created as part of the `clone` operation with a symlink when the path to the latter differs only in case from the former's path. Let's simply avoid this situation by expecting not ever having to overwrite any existing file/directory/symlink upon cloning. That way, we won't even replace a directory that we just created. This addresses CVE-2024-32002. Reported-by: Filip Hejsek <filip.hejsek@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-17clone: prevent clashing git dirs when cloning submodule in parallelFilip Hejsek
While it is expected to have several git dirs within the `.git/modules/` tree, it is important that they do not interfere with each other. For example, if one submodule was called "captain" and another submodule "captain/hooks", their respective git dirs would clash, as they would be located in `.git/modules/captain/` and `.git/modules/captain/hooks/`, respectively, i.e. the latter's files could clash with the actual Git hooks of the former. To prevent these clashes, and in particular to prevent hooks from being written and then executed as part of a recursive clone, we introduced checks as part of the fix for CVE-2019-1387 in a8dee3ca61 (Disallow dubiously-nested submodule git directories, 2019-10-01). It is currently possible to bypass the check for clashing submodule git dirs in two ways: 1. parallel cloning 2. checkout --recurse-submodules Let's check not only before, but also after parallel cloning (and before checking out the submodule), that the git dir is not clashing with another one, otherwise fail. This addresses the parallel cloning issue. As to the parallel checkout issue: It requires quite a few manual steps to create clashing git dirs because Git itself would refuse to initialize the inner one, as demonstrated by the test case. Nevertheless, let's teach the recursive checkout (namely, the `submodule_move_head()` function that is used by the recursive checkout) to be careful to verify that it does not use a clashing git dir, and if it does, disable it (by deleting the `HEAD` file so that subsequent Git calls won't recognize it as a git dir anymore). Note: The parallel cloning test case contains a `cat err` that proved to be highly useful when analyzing the racy nature of the operation (the operation can fail with three different error messages, depending on timing), and was left on purpose to ease future debugging should the need arise. Signed-off-by: Filip Hejsek <filip.hejsek@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-17upload-pack: disable lazy-fetching by defaultJeff King
The upload-pack command tries to avoid trusting the repository in which it's run (e.g., by not running any hooks and not using any config that contains arbitrary commands). But if the server side of a fetch or a clone is a partial clone, then either upload-pack or its child pack-objects may run a lazy "git fetch" under the hood. And it is very easy to convince fetch to run arbitrary commands. The "server" side can be a local repository owned by someone else, who would be able to configure commands that are run during a clone with the current user's permissions. This issue has been designated CVE-2024-32004. The fix in this commit's parent helps in this scenario, as well as in related scenarios using SSH to clone, where the untrusted .git directory is owned by a different user id. But if you received one as a zip file, on a USB stick, etc, it may be owned by your user but still untrusted. This has been designated CVE-2024-32465. To mitigate the issue more completely, let's disable lazy fetching entirely during `upload-pack`. While fetching from a partial repository should be relatively rare, it is certainly not an unreasonable workflow. And thus we need to provide an escape hatch. This commit works by respecting a GIT_NO_LAZY_FETCH environment variable (to skip the lazy-fetch), and setting it in upload-pack, but only when the user has not already done so (which gives us the escape hatch). The name of the variable is specifically chosen to match what has already been added in 'master' via e6d5479e7a (git: extend --no-lazy-fetch to work across subprocesses, 2024-02-27). Since we're building this fix as a backport for older versions, we could cherry-pick that patch and its earlier steps. However, we don't really need the niceties (like a "--no-lazy-fetch" option) that it offers. By using the same name, everything should just work when the two are eventually merged, but here are a few notes: - the blocking of the fetch in e6d5479e7a is incomplete! It sets fetch_if_missing to 0 when we setup the repository variable, but that isn't enough. pack-objects in particular will call prefetch_to_pack() even if that variable is 0. This patch by contrast checks the environment variable at the lowest level before we call the lazy fetch, where we can be sure to catch all code paths. Possibly the setting of fetch_if_missing from e6d5479e7a can be reverted, but it may be useful to have. For example, some code may want to use that flag to change behavior before it gets to the point of trying to start the fetch. At any rate, that's all outside the scope of this patch. - there's documentation for GIT_NO_LAZY_FETCH in e6d5479e7a. We can live without that here, because for the most part the user shouldn't need to set it themselves. The exception is if they do want to override upload-pack's default, and that requires a separate documentation section (which is added here) - it would be nice to use the NO_LAZY_FETCH_ENVIRONMENT macro added by e6d5479e7a, but those definitions have moved from cache.h to environment.h between 2.39.3 and master. I just used the raw string literals, and we can replace them with the macro once this topic is merged to master. At least with respect to CVE-2024-32004, this does render this commit's parent commit somewhat redundant. However, it is worth retaining that commit as defense in depth, and because it may help other issues (e.g., symlink/hardlink TOCTOU races, where zip files are not really an interesting attack vector). The tests in t0411 still pass, but now we have _two_ mechanisms ensuring that the evil command is not run. Let's beef up the existing ones to check that they failed for the expected reason, that we refused to run upload-pack at all with an alternate user id. And add two new ones for the same-user case that both the restriction and its escape hatch. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-17builtin/clone: refuse local clones of unsafe repositoriesPatrick Steinhardt
When performing a local clone of a repository we end up either copying or hardlinking the source repository into the target repository. This is significantly more performant than if we were to use git-upload-pack(1) and git-fetch-pack(1) to create the new repository and preserves both disk space and compute time. Unfortunately though, performing such a local clone of a repository that is not owned by the current user is inherently unsafe: - It is possible that source files get swapped out underneath us while we are copying or hardlinking them. While we do perform some checks here to assert that we hardlinked the expected file, they cannot reliably thwart time-of-check-time-of-use (TOCTOU) style races. It is thus possible for an adversary to make us copy or hardlink unexpected files into the target directory. Ideally, we would address this by starting to use openat(3P), fstatat(3P) and friends. Due to platform compatibility with Windows we cannot easily do that though. Furthermore, the scope of these fixes would likely be quite broad and thus not fit for an embargoed security release. - Even if we handled TOCTOU-style races perfectly, hardlinking files owned by a different user into the target repository is not a good idea in general. It is possible for an adversary to rewrite those files to contain whatever data they want even after the clone has completed. Address these issues by completely refusing local clones of a repository that is not owned by the current user. This reuses our existing infra we have in place via `ensure_valid_ownership()` and thus allows a user to override the safety guard by adding the source repository path to the "safe.directory" configuration. This addresses CVE-2024-32020. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-17builtin/clone: abort when hardlinked source and target file differPatrick Steinhardt
When performing local clones with hardlinks we refuse to copy source files which are symlinks as a mitigation for CVE-2022-39253. This check can be raced by an adversary though by changing the file to a symlink after we have checked it. Fix the issue by checking whether the hardlinked destination file matches the source file and abort in case it doesn't. This addresses CVE-2024-32021. Reported-by: Apple Product Security <product-security@apple.com> Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2024-04-17builtin/clone: stop resolving symlinks when copying filesPatrick Steinhardt
When a user performs a local clone without `--no-local`, then we end up copying the source repository into the target repository directly. To optimize this even further, we try to hardlink files into place instead of copying data over, which helps both disk usage and speed. There is an important edge case in this context though, namely when we try to hardlink symlinks from the source repository into the target repository. Depending on both platform and filesystem the resulting behaviour here can be different: - On macOS and NetBSD, calling link(3P) with a symlink target creates a hardlink to the file pointed to by the symlink. - On Linux, calling link(3P) instead creates a hardlink to the symlink itself. To unify this behaviour, 36596fd2df (clone: better handle symlinked files at .git/objects/, 2019-07-10) introduced logic to resolve symlinks before we try to link(3P) files. Consequently, the new behaviour was to always create a hard link to the target of the symlink on all platforms. Eventually though, we figured out that following symlinks like this can cause havoc when performing a local clone of a malicious repository, which resulted in CVE-2022-39253. This issue was fixed via 6f054f9fb3 (builtin/clone.c: disallow `--local` clones with symlinks, 2022-07-28), by refusing symlinks in the source repository. But even though we now shouldn't ever link symlinks anymore, the code that resolves symlinks still exists. In the best case the code does not end up doing anything because there are no symlinks anymore. In the worst case though this can be abused by an adversary that rewrites the source file after it has been checked not to be a symlink such that it actually is a symlink when we call link(3P). Thus, it is still possible to recreate CVE-2022-39253 due to this time-of-check-time-of-use bug. Remove the call to `realpath()`. This doesn't yet address the actual vulnerability, which will be handled in a subsequent commit. Reported-by: Apple Product Security <product-security@apple.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2023-11-02Merge branch 'jc/commit-new-underscore-index-fix' into maint-2.42Junio C Hamano
Message fix. * jc/commit-new-underscore-index-fix: commit: do not use cryptic "new_index" in end-user facing messages
2023-11-02Merge branch 'ni/die-message-fix-for-git-add' into maint-2.42Junio C Hamano
Message updates. * ni/die-message-fix-for-git-add: builtin/add.c: clean up die() messages
2023-11-02Merge branch 'sn/cat-file-doc-update' into maint-2.42Junio C Hamano
"git cat-file" documentation updates. * sn/cat-file-doc-update: doc/cat-file: make synopsis and description less confusing
2023-11-02Merge branch 'ob/am-msgfix' into maint-2.42Junio C Hamano
The parameters to generate an error message have been corrected. * ob/am-msgfix: am: fix error message in parse_opt_show_current_patch()
2023-11-02Merge branch 'rs/name-rev-use-opt-hidden-bool' into maint-2.42Junio C Hamano
Simplify use of parse-options API a bit. * rs/name-rev-use-opt-hidden-bool: name-rev: use OPT_HIDDEN_BOOL for --peel-tag
2023-11-02Merge branch 'rs/grep-parseopt-simplify' into maint-2.42Junio C Hamano
Simplify use of parse-options API a bit. * rs/grep-parseopt-simplify: grep: use OPT_INTEGER_F for --max-depth
2023-11-02Merge branch 'bc/more-git-var' into maint-2.42Junio C Hamano
Fix-up for a topic that already has graduated. * bc/more-git-var: var: avoid a segmentation fault when `HOME` is unset
2023-11-02Merge branch 'jc/mv-d-to-d-error-message-fix' into maint-2.42Junio C Hamano
Typofix in an error message. * jc/mv-d-to-d-error-message-fix: mv: fix error for moving directory to another
2023-11-02Merge branch 'ja/worktree-orphan' into maint-2.42Junio C Hamano
Typofix in an error message. * ja/worktree-orphan: builtin/worktree.c: fix typo in "forgot fetch" msg
2023-11-02Merge branch 'js/systemd-timers-wsl-fix' into maint-2.42Junio C Hamano
Update "git maintainance" timers' implementation based on systemd timers to work with WSL. * js/systemd-timers-wsl-fix: maintenance(systemd): support the Windows Subsystem for Linux
2023-11-02Merge branch 'rs/grep-no-no-or' into maint-2.42Junio C Hamano
"git grep -e A --no-or -e B" is accepted, even though the negation of "or" did not mean anything, which has been tightened. * rs/grep-no-no-or: grep: reject --no-or
2023-11-02Merge branch 'jk/diff-result-code-cleanup' into maint-2.42Junio C Hamano
"git diff --no-such-option" and other corner cases around the exit status of the "diff" command has been corrected. * jk/diff-result-code-cleanup: diff: drop useless "status" parameter from diff_result_code() diff: drop useless return values in git-diff helpers diff: drop useless return from run_diff_{files,index} functions diff: die when failing to read index in git-diff builtin diff: show usage for unknown builtin_diff_files() options diff-files: avoid negative exit value diff: spell DIFF_INDEX_CACHED out when calling run_diff_index()
2023-11-02Merge branch 'ts/unpacklimit-config-fix' into maint-2.42Junio C Hamano
transfer.unpackLimit ought to be used as a fallback, but overrode fetch.unpackLimit and receive.unpackLimit instead. * ts/unpacklimit-config-fix: transfer.unpackLimit: fetch/receive.unpackLimit takes precedence
2023-10-17commit: do not use cryptic "new_index" in end-user facing messagesJunio C Hamano
These error messages say "new_index" as if that spelling has some significance to the end users (e.g. the file "$GIT_DIR/new_index" has some issues), but that is not the case at all. The i18n folks were made to include the word literally in the translated messages, which was not a good idea at all. Spell it "new index", as we are just telling the users that we failed to create a new index file. The term is expected to be translated to the end-users' languages, not left as if it were a literal file name. This dates all the way back to the first re-implemenation of "git commit" command in C (the scripted version did not have such wording in its error messages), in f5bbc322 (Port git commit to C., 2007-11-08). Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-10-17builtin/add.c: clean up die() messagesNaomi Ibe
As described in the CodingGuidelines document, a single line message given to die() and its friends should not capitalize its first word, and should not add full-stop at the end. Signed-off-by: Naomi Ibe <naomi.ibeh69@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-10-09doc/cat-file: make synopsis and description less confusingŠtěpán Němec
The DESCRIPTION's "first form" is actually the 1st, 2nd, 3rd and 5th form in SYNOPSIS, the "second form" is the 4th one. Interestingly, this state of affairs was introduced in 97fe7250753b (cat-file docs: fix SYNOPSIS and "-h" output, 2021-12-28) with the claim of "Now the two will match again." ("the two" being DESCRIPTION and SYNOPSIS)... The description also suffers from other correctness and clarity issues, e.g., the "first form" paragraph discusses -p, -s and -t, but leaves out -e, which is included in the corresponding SYNOPSIS section; the second paragraph mentions <format>, which doesn't occur in SYNOPSIS at all, and of the three batch options, really only describes the behavior of --batch-check. Also the mention of "drivers" seems an implementation detail not adding much clarity in a short summary (and isn't expanded upon in the rest of the man page, either). Rather than trying to maintain one-to-one (or N-to-M) correspondence between the DESCRIPTION and SYNOPSIS forms, creating duplication and providing opportunities for error, shorten the former into a concise summary describing the two general modes of operation: batch and non-batch, leaving details to the subsequent manual sections. While here, fix a grammar error in the description of -e and make the following further minor improvements: NAME: shorten ("content or type and size" isn't the whole story; say "details" and leave the actual details to later sections) SYNOPSIS and --help: move the (--textconv | --filters) form before --batch, closer to the other non-batch forms Signed-off-by: Štěpán Němec <stepnem@smrk.net> Acked-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-09-21am: fix error message in parse_opt_show_current_patch()Oswald Buddenhagen
The argument order was incorrect. This was introduced by 246cac8505 (i18n: turn even more messages into "cannot be used together" ones, 2022-01-05). Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-09-11maintenance(systemd): support the Windows Subsystem for LinuxJohannes Schindelin
When running in the Windows Subsystem for Linux (WSL), it is usually necessary to use the Git Credential Manager for authentication when performing the background fetches. This requires interoperability between the Windows Subsystem for Linux and the Windows host to work, which uses so-called vsocks, i.e. sockets intended for communcations between virtual machines and the host they are running on. However, when Git is configured to run background maintenance via `systemd`, the address families available to those maintenance processes are restricted, and did not include `AF_VSOCK`. This leads to problems e.g. when a background fetch tries to access github.com: systemd[437]: Starting Optimize Git repositories data... git[747387]: WSL (747387) ERROR: UtilBindVsockAnyPort:285: socket failed 97 git[747381]: fatal: could not read Username for 'https://github.com': No such device or address git[747381]: error: failed to prefetch remotes git[747381]: error: task 'prefetch' failed systemd[437]: git-maintenance@hourly.service: Main process exited, code=exited, status=1/FAILURE systemd[437]: git-maintenance@hourly.service: Failed with result 'exit-code'. systemd[437]: Failed to start Optimize Git repositories data. Address this (pun intended) by adding the `AF_VSOCK` address family to the allow list. This fixes https://github.com/microsoft/git/issues/604. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-09-07grep: reject --no-orRené Scharfe
Since 3e230fa1b2 (grep: use parseopt, 2009-05-07) git grep has been accepting the option --no-or. It does the same as --or: nothing. That's confusing and unintended. Forbid negating --or. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-09-05var: avoid a segmentation fault when `HOME` is unsetJohannes Schindelin
The code introduced in 576a37fccbf (var: add attributes files locations, 2023-06-27) paid careful attention to use `xstrdup()` for pointers known never to be `NULL`, and `xstrdup_or_null()` otherwise. One spot was missed, though: `git_attr_global_file()` can return `NULL`, when the `HOME` variable is not set (and neither `XDG_CONFIG_HOME`), a scenario not too uncommon in certain server scenarios. Fix this, and add a test case to avoid future regressions. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Acked-by: brian m. carlson <bk2204@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-09-05grep: use OPT_INTEGER_F for --max-depthRené Scharfe
a91f453f64 (grep: Add --max-depth option., 2009-07-22) added the option --max-depth, defining it using a positional struct option initializer of type OPTION_INTEGER. It also sets defval to 1 for some reason, but that value would only be used if the flag PARSE_OPT_OPTARG was given. Use the macro OPT_INTEGER_F instead to standardize the definition and specify only the necessary values. This also normalizes argh to N_("n") as a side-effect, which is OK. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-09-05name-rev: use OPT_HIDDEN_BOOL for --peel-tagRené Scharfe
adfc1857bd (describe: fix --contains when a tag is given as input, 2013-07-18) added the option --peel-tag, defining it using a positional struct option initializer and a comment indicating that it's intended to be a hidden OPT_BOOL. 4741edd549 (Remove deprecated OPTION_BOOLEAN for parsing arguments, 2013-08-03) added the macro OPT_HIDDEN_BOOL, which allows to express this more succinctly. Use it. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-22transfer.unpackLimit: fetch/receive.unpackLimit takes precedenceJunio C Hamano
The transfer.unpackLimit configuration variable is documented to be used only as a fallback value when the more operation-specific fetch.unpackLimit and receive.unpackLimit variables are not set, but the implementation had the precedence reversed. Apparently this was broken since the transfer.unpackLimit was introduced in e28714c5 (Consolidate {receive,fetch}.unpackLimit, 2007-01-24). Often when documentation and code have diverged for so long, we prefer to change the documentation instead, to avoid disrupting users. But doing so would make these weirdly unlike most other "specific overrides general" config options. And the fact that the bug has existed for so long without anyone noticing implies to me that nobody really tries to mix and match them much. Signed-off-by: Taylor Santiago <taylorsantiago@google.com> [jc: rewrote the log message, added tests, covered receive-pack as well] Helped-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-21diff: drop useless "status" parameter from diff_result_code()Jeff King
Many programs use diff_result_code() to get a user-visible program exit code from a diff result (e.g., checking opts.found_changes if --exit-code was requested). This function also takes a "status" parameter, which seems at first glance that it could be used to propagate an error encountered when computing the diff. But it doesn't work that way: - negative values are passed through as-is, but are not appropriate as program exit codes - when --exit-code or --check is in effect, we _ignore_ the passed-in status completely. So a failed diff which did not have a chance to set opts.found_changes would erroneously report "success, no changes" instead of propagating the error. After recent cleanups, neither of these bugs is possible to trigger, as every caller just passes in "0". So rather than fixing them, we can simply drop the useless parameter instead. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-21diff: drop useless return values in git-diff helpersJeff King
Since git-diff has many diff modes, it dispatches to many helpers to perform each one. But every helper simply returns "0", as it exits directly if there are serious errors (and options like --exit-code are handled afterwards). So let's get rid of these useless return values, which makes the code flow more clear. There's very little chance that we'd later want to propagate errors instead of dying immediately. These are all static-local helpers for the git-diff program implementing its various modes. More "lib-ified" code would directly call the underlying functions. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-21diff: drop useless return from run_diff_{files,index} functionsJeff King
Neither of these functions ever returns a value other than zero. Instead, they expect unrecoverable errors to exit immediately, and things like "--exit-code" are stored inside the diff_options struct to be handled later via diff_result_code(). Some callers do check the return values, but many don't bother. Let's drop the useless return values, which are misleading callers about how the functions work. This could be seen as a step in the wrong direction, as we might want to eventually "lib-ify" these to more cleanly return errors up the stack, in which case we'd have to add the return values back in. But there are some benefits to doing this now: 1. In the current code, somebody could accidentally add a "return -1" to one of the functions, which would be erroneously ignored by many callers. By removing the return code, the compiler can notice the mismatch and force the developer to decide what to do. Obviously the other option here is that we could start consistently checking the error code in every caller. But it would be dead code, and we wouldn't get any compile-time help in catching new cases. 2. It communicates the situation to callers, who may want to choose a different function. These functions are really thin wrappers for doing git-diff-files and git-diff-index within the process. But callers who care about recovering from an error here are probably better off using the underlying library functions, many of which do return errors. If somebody eventually wants to teach these functions to propagate errors, they'll have to switch back to returning a value, effectively reverting this patch. But at least then they will be starting with a level playing field: they know that they will need to inspect each caller to see how it should handle the error. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-21diff: die when failing to read index in git-diff builtinJeff King
When the git-diff program fails to read the index in its diff-files or diff-index helper functions, it propagates the error up the stack. This eventually lands in diff_result_code(), which does not handle it well (as discussed in the previous patch). Since the only sensible thing here is to exit with an error code (and what we were expecting the propagated error code to cause), let's just do that directly. There's no test here, as I'm not even sure this case can be triggered. The index-reading functions tend to die() themselves when encountering any errors, and the return value is just the number of entries in the file (and so always 0 or positive). But let's err on the conservative side and keep checking the return value. It may be worth digging into as a separate topic (though index-reading is low-level enough that we probably want to eventually teach it to propagate errors anyway for lib-ification purposes, at which point this code would already be doing the right thing). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-21diff: show usage for unknown builtin_diff_files() optionsJeff King
The git-diff command has many modes (comparing worktree to index, index to HEAD, individual blobs, etc). As a result, it dispatches to many helper functions and cannot completely parse its options until we're in those helper functions. Most of them, when seeing an unknown option, exit immediately by calling usage(). But builtin_diff_files(), which is the default if no revision or blob arguments are given, instead prints an error() and returns -1. One obvious shortcoming here is that the user doesn't get to see the usual usage message. But there's a much more important bug: the -1 return is fed to diff_result_code(), which is not ready to handle it. By default, it passes the code along as an exit code. We try to avoid negative exit codes because they get converted to unsigned values, but it should at least consistently show up as non-zero (i.e., a failure). But much worse is that when --exit-code is in effect, diff_result_code() will _ignore_ the status passed in by the caller, and instead only report on whether the diff found changes. It didn't, of course, because we never ran the diff, and the program unexpectedly exits with success! We can fix this bug by just calling usage(), like the other helpers do. Another option would of course be to teach diff_result_code() to handle this value. But as we'll see in the next few patches, it can be cleaned up even further. Let's just fix this bug directly to start with. Reported-by: Romain Chossart <romainchossart@gmail.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-21diff-files: avoid negative exit valueJeff King
If loading the index fails, we print an error and then return "-1" from the function. But since this is a builtin, we end up with exit(-1), which produces odd results since program exit codes are unsigned. Because of integer conversion, it usually becomes 255, which is at least still an error, but values above 128 are usually interpreted as signal death. Since we know the program is exiting immediately, we can just replace the error return with a die(). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-21diff: spell DIFF_INDEX_CACHED out when calling run_diff_index()Junio C Hamano
Many callers of run_diff_index() passed literal "1" for the option flag word, which should better be spelled out as DIFF_INDEX_CACHED for readablity. Everybody else passes "0" that can stay as-is. The other bit in the option flag word is DIFF_INDEX_MERGE_BASE, but curiously there is only one caller that can pass it, which is "git diff-index --merge-base" itself---no internal callers uses the feature. A bit tricky call to the function is in builtin/submodule--helper.c where the .cached member in a private struct is set/reset as a plain Boolean flag, which happens to be "1" and happens to match the value of DIFF_INDEX_CACHED. Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-19fsck: use enum object_type for fsck_walk callbackJeff King
We switched the function interface for fsck callbacks in a1aad71601 (fsck.h: use "enum object_type" instead of "int", 2021-03-28). However, we accidentally flipped the type back to "int" as part of 0b4e9013f1 (fsck: mark unused parameters in various fsck callbacks, 2023-07-03). The mistake happened because that commit was written before a1aad71601 and rebased forward, and I screwed up while resolving the conflict. Curiously, the compiler does not warn about this mismatch, at least not when using gcc and clang on Linux (nor in any of our CI environments). Based on 28abf260a5 (builtin/fsck.c: don't conflate "int" and "enum" in callback, 2021-06-01), I'd guess that this would cause the AIX xlc compiler to complain. I noticed because clang-18's UBSan now identifies mis-matched function calls at runtime, and does complain of this case when running the test suite. I'm not entirely clear on whether this mismatch is a problem in practice. Compilers are certainly free to make enums smaller than "int" if they don't need the bits, but I suspect that they have to promote back to int for function calls (though I didn't dig in the standard, and I won't be surprised if I'm simply wrong and the real-world impact would depend on the ABI). Regardless, switching it back to enum is obviously the right thing to do here; the switch to "int" was simply a mistake. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-15Merge branch 'st/mv-lstat-fix'Junio C Hamano
Correct use of lstat() that assumed a failing call would not clobber the statbuf. * st/mv-lstat-fix: mv: handle lstat() failure correctly
2023-08-15Merge branch 'ds/maintenance-on-windows-fix'Junio C Hamano
Windows updates. * ds/maintenance-on-windows-fix: git maintenance: avoid console window in scheduled tasks on Windows win32: add a helper to run `git.exe` without a foreground window
2023-08-13builtin/worktree.c: fix typo in "forgot fetch" msgJacob Abel
Replace misspelled word "overide" with correctly spelled "override". Reported-By: Teng Long <dyroneteng@gmail.com> Signed-off-by: Jacob Abel <jacobabel@nullpo.dev> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-11mv: fix error for moving directory to anotherJunio C Hamano
If both directories D1 and D2 already exists, and further there is a filesystem entity D2/D1, "git mv D1 D2" would fail, and we get an error message that says: "cannot move directory over file, source=D1, destination=D2/D1" regardless of the type of existing "D2/D1". If it is a file, the message is correct, but if it is a directory, it is not (we could make the D2/D1 directory a union of its original contents and what was in D1/, but that is not what we do). The code that decies to issue the error message only checks for existence of "D2/D1" and does not care what kind of thing sits at the path. Rephrase the message to say "destination already exists, source=D1, destination=D2/D1" that would be suitable for any kind of thing being in the way. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-08-09git maintenance: avoid console window in scheduled tasks on WindowsJohannes Schindelin
We just introduced a helper to avoid showing a console window when the scheduled task runs `git.exe`. Let's actually use it. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>