Skip to content

Commit 8174627

Browse files
sgngitster
authored andcommitted
diff-lib: ignore paths that are outside $cwd if --relative asked
For diff family commands, we can tell them to exclude changes outside of some directories if --relative is requested. In diff_unmerge(), NULL will be returned if the requested path is outside of the interesting directories, thus we'll run into NULL pointer dereference in run_diff_files when trying to dereference its return value. Checking for return value of diff_unmerge before dereferencing is not sufficient, though. Since, diff engine will try to work on such pathspec later. Let's not run diff on those unintesting entries, instead. As a side effect, by skipping like that, we can save some CPU cycles. Reported-by: Thomas De Zeeuw <[email protected]> Tested-by: Carlo Arenas <[email protected]> Signed-off-by: Đoàn Trần Công Danh <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 94f6e3e commit 8174627

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

diff-lib.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
116116
if (!ce_path_match(istate, ce, &revs->prune_data, NULL))
117117
continue;
118118

119+
if (revs->diffopt.prefix &&
120+
strncmp(ce->name, revs->diffopt.prefix, revs->diffopt.prefix_length))
121+
continue;
122+
119123
if (ce_stage(ce)) {
120124
struct combine_diff_path *dpath;
121125
struct diff_filepair *pair;

t/t4045-diff-relative.sh

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,57 @@ check_diff_relative_option subdir file2 true --no-relative --relative
162162
check_diff_relative_option . file2 false --no-relative --relative=subdir
163163
check_diff_relative_option . file2 true --no-relative --relative=subdir
164164

165+
test_expect_success 'setup diff --relative unmerged' '
166+
test_commit zero file0 &&
167+
test_commit base subdir/file0 &&
168+
git switch -c br1 &&
169+
test_commit one file0 &&
170+
test_commit sub1 subdir/file0 &&
171+
git switch -c br2 base &&
172+
test_commit two file0 &&
173+
git switch -c br3 &&
174+
test_commit sub3 subdir/file0
175+
'
176+
177+
test_expect_success 'diff --relative without change in subdir' '
178+
git switch br2 &&
179+
test_when_finished "git merge --abort" &&
180+
test_must_fail git merge one &&
181+
git -C subdir diff --relative >out &&
182+
test_must_be_empty out &&
183+
git -C subdir diff --relative --name-only >out &&
184+
test_must_be_empty out
185+
'
186+
187+
test_expect_success 'diff --relative --name-only with change in subdir' '
188+
git switch br3 &&
189+
test_when_finished "git merge --abort" &&
190+
test_must_fail git merge sub1 &&
191+
test_write_lines file0 file0 >expected &&
192+
git -C subdir diff --relative --name-only >out &&
193+
test_cmp expected out
194+
'
195+
196+
test_expect_failure 'diff --relative with change in subdir' '
197+
git switch br3 &&
198+
br1_blob=$(git rev-parse --short --verify br1:subdir/file0) &&
199+
br3_blob=$(git rev-parse --short --verify br3:subdir/file0) &&
200+
test_when_finished "git merge --abort" &&
201+
test_must_fail git merge br1 &&
202+
cat >expected <<-EOF &&
203+
diff --cc file0
204+
index $br3_blob,$br1_blob..0000000
205+
--- a/file0
206+
+++ b/file0
207+
@@@ -1,1 -1,1 +1,5 @@@
208+
++<<<<<<< HEAD
209+
+sub3
210+
++=======
211+
+ sub1
212+
++>>>>>>> br1
213+
EOF
214+
git -C subdir diff --relative >out &&
215+
test_cmp expected out
216+
'
217+
165218
test_done

0 commit comments

Comments
 (0)