Skip to content

Commit 3ba3113

Browse files
committed
diff: implement --no-optional-locks
When used with `autoRefreshIndex`, `git diff` may update the index in the background for similar performance reasons to `git-status`. This commit implements the `--no-optional-locks` option for `git diff`, which allows scripts to bypass this behavior. Signed-off-by: Benjamin Woodruff <benjamin.woodruff@vercel.com>
1 parent 46c90ba commit 3ba3113

File tree

5 files changed

+56
-2
lines changed

5 files changed

+56
-2
lines changed

Diff for: Documentation/config/diff.adoc

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
contents in the work tree match the contents in the
77
index. This option defaults to `true`. Note that this
88
affects only `git diff` Porcelain, and not lower level
9-
`diff` commands such as `git diff-files`.
9+
`diff` commands such as `git diff-files`. If
10+
`--no-optional-locks` is set (see linkgit:git[1] for
11+
details), the index file is not updated.
1012

1113
`diff.dirstat`::
1214
ifdef::git-diff[]

Diff for: Documentation/git.adoc

+2-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ If you just want to run git as if it was started in `<path>` then use
190190
--no-optional-locks::
191191
Do not perform optional operations that require locks. This is
192192
equivalent to setting the `GIT_OPTIONAL_LOCKS` to `0`. This
193-
functionality is implemented for `git status` and `git describe`.
193+
functionality is implemented for `git status`, `git describe`,
194+
and `git diff`.
194195

195196
--no-advice::
196197
Disable all advice hints from being printed.

Diff for: builtin/diff.c

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "builtin.h"
1111
#include "config.h"
12+
#include "environment.h"
1213
#include "ewah/ewok.h"
1314
#include "lockfile.h"
1415
#include "color.h"
@@ -239,6 +240,9 @@ static void refresh_index_quietly(void)
239240
struct lock_file lock_file = LOCK_INIT;
240241
int fd;
241242

243+
if (!use_optional_locks())
244+
return;
245+
242246
fd = repo_hold_locked_index(the_repository, &lock_file, 0);
243247
if (fd < 0)
244248
return;

Diff for: t/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ integration_tests = [
500500
't4067-diff-partial-clone.sh',
501501
't4068-diff-symmetric-merge-base.sh',
502502
't4069-remerge-diff.sh',
503+
't4070-diff-auto-refresh-index.sh',
503504
't4100-apply-stat.sh',
504505
't4101-apply-nonl.sh',
505506
't4102-apply-rename.sh',

Diff for: t/t4070-diff-auto-refresh-index.sh

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2025 Benjamin Woodruff
4+
#
5+
6+
test_description='diff.autoRefreshIndex config option'
7+
8+
. ./test-lib.sh
9+
. "$TEST_DIRECTORY"/lib-diff.sh
10+
11+
test_expect_success 'index is updated when autoRefreshIndex is true' '
12+
>tracked &&
13+
git add tracked &&
14+
15+
# stat() must change (but not file contents) to trigger an index update
16+
test_set_magic_mtime tracked &&
17+
18+
# check the mtime of .git/index does not change without autoRefreshIndex
19+
test_set_magic_mtime .git/index &&
20+
git config diff.autoRefreshIndex false &&
21+
git diff &&
22+
test_is_magic_mtime .git/index &&
23+
24+
# but it does change when autoRefreshIndex is true (the default)
25+
git config diff.autoRefreshIndex true &&
26+
git diff &&
27+
! test_is_magic_mtime .git/index
28+
'
29+
30+
test_expect_success '--no-optional-locks overrides autoRefreshIndex' '
31+
>tracked &&
32+
git add tracked &&
33+
test_set_magic_mtime tracked &&
34+
35+
# `--no-optional-locks` overrides `autoRefreshIndex`
36+
test_set_magic_mtime .git/index &&
37+
git config diff.autoRefreshIndex true &&
38+
git --no-optional-locks diff &&
39+
40+
# sanity check that without `--no-optional-locks` it still updates
41+
test_is_magic_mtime .git/index &&
42+
git diff &&
43+
! test_is_magic_mtime .git/index
44+
'
45+
46+
test_done

0 commit comments

Comments
 (0)