diff --git a/Documentation/config/diff.adoc b/Documentation/config/diff.adoc index 1135a62a0ad3de..2dadcf7a1da348 100644 --- a/Documentation/config/diff.adoc +++ b/Documentation/config/diff.adoc @@ -6,7 +6,9 @@ contents in the work tree match the contents in the index. This option defaults to `true`. Note that this affects only `git diff` Porcelain, and not lower level - `diff` commands such as `git diff-files`. + `diff` commands such as `git diff-files`. If + `--no-optional-locks` is set (see linkgit:git[1] for + details), the index file is not updated. `diff.dirstat`:: ifdef::git-diff[] diff --git a/Documentation/git-describe.adoc b/Documentation/git-describe.adoc index 08ff715709ccd1..97b4c6560786f3 100644 --- a/Documentation/git-describe.adoc +++ b/Documentation/git-describe.adoc @@ -198,6 +198,18 @@ selected and output. Here fewest commits different is defined as the number of commits which would be shown by `git log tag..input` will be the smallest number of commits possible. +BACKGROUND REFRESH +------------------ + +By default, `git describe --dirty` will automatically refresh the index, +similar to the background refresh functionality of +linkgit:git-status[1]. Writing out the updated index is an optimization +that isn't strictly necessary. When `describe` is run in the background, +the lock held during the write may conflict with other simultaneous +processes, causing them to fail. Scripts running `describe` in the +background should consider using `git --no-optional-locks status` (see +linkgit:git[1] for details). + BUGS ---- diff --git a/Documentation/git.adoc b/Documentation/git.adoc index 743b7b00e4d751..754880b86720cb 100644 --- a/Documentation/git.adoc +++ b/Documentation/git.adoc @@ -189,7 +189,9 @@ If you just want to run git as if it was started in `` then use --no-optional-locks:: Do not perform optional operations that require locks. This is - equivalent to setting the `GIT_OPTIONAL_LOCKS` to `0`. + equivalent to setting the `GIT_OPTIONAL_LOCKS` to `0`. This + functionality is implemented for `git status`, `git describe`, + and `git diff`. --no-advice:: Disable all advice hints from being printed. diff --git a/builtin/describe.c b/builtin/describe.c index e2e73f3d757cab..d4fea55352d927 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -704,7 +704,6 @@ int cmd_describe(int argc, } else if (dirty) { struct lock_file index_lock = LOCK_INIT; struct rev_info revs; - int fd; setup_work_tree(); prepare_repo_settings(the_repository); @@ -712,10 +711,13 @@ int cmd_describe(int argc, repo_read_index(the_repository); refresh_index(the_repository->index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL); - fd = repo_hold_locked_index(the_repository, - &index_lock, 0); - if (0 <= fd) - repo_update_index_if_able(the_repository, &index_lock); + if (use_optional_locks()) { + int fd = repo_hold_locked_index(the_repository, + &index_lock, 0); + if (0 <= fd) + repo_update_index_if_able(the_repository, + &index_lock); + } repo_init_revisions(the_repository, &revs, prefix); diff --git a/builtin/diff.c b/builtin/diff.c index a4fffee42c6c8c..5469e58bf5dddc 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -9,6 +9,7 @@ #include "builtin.h" #include "config.h" +#include "environment.h" #include "ewah/ewok.h" #include "lockfile.h" #include "color.h" @@ -239,6 +240,9 @@ static void refresh_index_quietly(void) struct lock_file lock_file = LOCK_INIT; int fd; + if (!use_optional_locks()) + return; + fd = repo_hold_locked_index(the_repository, &lock_file, 0); if (fd < 0) return; diff --git a/t/meson.build b/t/meson.build index a59da26be3f471..10d7cace3c6a2c 100644 --- a/t/meson.build +++ b/t/meson.build @@ -500,6 +500,7 @@ integration_tests = [ 't4067-diff-partial-clone.sh', 't4068-diff-symmetric-merge-base.sh', 't4069-remerge-diff.sh', + 't4070-diff-auto-refresh-index.sh', 't4100-apply-stat.sh', 't4101-apply-nonl.sh', 't4102-apply-rename.sh', diff --git a/t/t4070-diff-auto-refresh-index.sh b/t/t4070-diff-auto-refresh-index.sh new file mode 100755 index 00000000000000..9e38f1d3206625 --- /dev/null +++ b/t/t4070-diff-auto-refresh-index.sh @@ -0,0 +1,46 @@ +#!/bin/sh +# +# Copyright (c) 2025 Benjamin Woodruff +# + +test_description='diff.autoRefreshIndex config option' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-diff.sh + +test_expect_success 'index is updated when autoRefreshIndex is true' ' + >tracked && + git add tracked && + + # stat() must change (but not file contents) to trigger an index update + test_set_magic_mtime tracked && + + # check the mtime of .git/index does not change without autoRefreshIndex + test_set_magic_mtime .git/index && + git config diff.autoRefreshIndex false && + git diff && + test_is_magic_mtime .git/index && + + # but it does change when autoRefreshIndex is true (the default) + git config diff.autoRefreshIndex true && + git diff && + ! test_is_magic_mtime .git/index +' + +test_expect_success '--no-optional-locks overrides autoRefreshIndex' ' + >tracked && + git add tracked && + test_set_magic_mtime tracked && + + # `--no-optional-locks` overrides `autoRefreshIndex` + test_set_magic_mtime .git/index && + git config diff.autoRefreshIndex true && + git --no-optional-locks diff && + + # sanity check that without `--no-optional-locks` it still updates + test_is_magic_mtime .git/index && + git diff && + ! test_is_magic_mtime .git/index +' + +test_done diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 76843a61691cb5..ae7b6901ed62c2 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -749,4 +749,12 @@ test_expect_success 'do not be fooled by invalid describe format ' ' test_must_fail git cat-file -t "refs/tags/super-invalid/./../...../ ~^:/?*[////\\\\\\&}/busted.lock-42-g"$(cat out) ' +test_expect_success '--no-optional-locks prevents index update' ' + test_set_magic_mtime .git/index && + git --no-optional-locks describe --dirty && + test_is_magic_mtime .git/index && + git describe --dirty && + ! test_is_magic_mtime .git/index +' + test_done