Skip to content

Commit 36c5109

Browse files
committed
Merge branch 'th/diff-no-index-fixes' into maint
"git diff --no-index" did not correctly handle relative paths and did not correctly give exit codes when run under "--quiet" option. * th/diff-no-index-fixes: diff-no-index: exit(1) if 'diff --quiet <repo file> <external file>' finds changes diff: handle relative paths in no-index
2 parents 4ac01b0 + 304970d commit 36c5109

File tree

5 files changed

+112
-24
lines changed

5 files changed

+112
-24
lines changed

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ extern void verify_filename(const char *prefix,
413413
const char *name,
414414
int diagnose_misspelt_rev);
415415
extern void verify_non_filename(const char *prefix, const char *name);
416+
extern int path_inside_repo(const char *prefix, const char *path);
416417

417418
#define INIT_DB_QUIET 0x0001
418419

diff-no-index.c

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -151,23 +151,6 @@ static int queue_diff(struct diff_options *o,
151151
}
152152
}
153153

154-
static int path_outside_repo(const char *path)
155-
{
156-
const char *work_tree;
157-
size_t len;
158-
159-
if (!is_absolute_path(path))
160-
return 0;
161-
work_tree = get_git_work_tree();
162-
if (!work_tree)
163-
return 1;
164-
len = strlen(work_tree);
165-
if (strncmp(path, work_tree, len) ||
166-
(path[len] != '\0' && path[len] != '/'))
167-
return 1;
168-
return 0;
169-
}
170-
171154
void diff_no_index(struct rev_info *revs,
172155
int argc, const char **argv,
173156
int nongit, const char *prefix)
@@ -197,8 +180,8 @@ void diff_no_index(struct rev_info *revs,
197180
* a colourful "diff" replacement.
198181
*/
199182
if ((argc != i + 2) ||
200-
(!path_outside_repo(argv[i]) &&
201-
!path_outside_repo(argv[i+1])))
183+
(path_inside_repo(prefix, argv[i]) &&
184+
path_inside_repo(prefix, argv[i+1])))
202185
return;
203186
}
204187
if (argc != i + 2)
@@ -268,5 +251,5 @@ void diff_no_index(struct rev_info *revs,
268251
* The return code for --no-index imitates diff(1):
269252
* 0 = no changes, 1 = changes, else error
270253
*/
271-
exit(revs->diffopt.found_changes);
254+
exit(diff_result_code(&revs->diffopt, 0));
272255
}

setup.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
static int inside_git_dir = -1;
55
static int inside_work_tree = -1;
66

7-
char *prefix_path(const char *prefix, int len, const char *path)
7+
static char *prefix_path_gently(const char *prefix, int len, const char *path)
88
{
99
const char *orig = path;
1010
char *sanitized;
@@ -31,7 +31,8 @@ char *prefix_path(const char *prefix, int len, const char *path)
3131
if (strncmp(sanitized, work_tree, len) ||
3232
(len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) {
3333
error_out:
34-
die("'%s' is outside repository", orig);
34+
free(sanitized);
35+
return NULL;
3536
}
3637
if (sanitized[len] == '/')
3738
len++;
@@ -40,6 +41,25 @@ char *prefix_path(const char *prefix, int len, const char *path)
4041
return sanitized;
4142
}
4243

44+
char *prefix_path(const char *prefix, int len, const char *path)
45+
{
46+
char *r = prefix_path_gently(prefix, len, path);
47+
if (!r)
48+
die("'%s' is outside repository", path);
49+
return r;
50+
}
51+
52+
int path_inside_repo(const char *prefix, const char *path)
53+
{
54+
int len = prefix ? strlen(prefix) : 0;
55+
char *r = prefix_path_gently(prefix, len, path);
56+
if (r) {
57+
free(r);
58+
return 1;
59+
}
60+
return 0;
61+
}
62+
4363
int check_filename(const char *prefix, const char *arg)
4464
{
4565
const char *name;

t/t4035-diff-quiet.sh

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,22 @@ test_expect_success 'setup' '
1010
git commit -m first &&
1111
echo 2 >b &&
1212
git add . &&
13-
git commit -a -m second
13+
git commit -a -m second &&
14+
mkdir -p test-outside/repo && (
15+
cd test-outside/repo &&
16+
git init &&
17+
echo "1 1" >a &&
18+
git add . &&
19+
git commit -m 1
20+
) &&
21+
mkdir -p test-outside/non/git && (
22+
cd test-outside/non/git &&
23+
echo "1 1" >a &&
24+
echo "1 1" >matching-file &&
25+
echo "1 1 " >trailing-space &&
26+
echo "1 1" >extra-space &&
27+
echo "2" >never-match
28+
)
1429
'
1530

1631
test_expect_success 'git diff-tree HEAD^ HEAD' '
@@ -77,4 +92,60 @@ test_expect_success 'git diff-index --cached HEAD' '
7792
}
7893
'
7994

95+
test_expect_success 'git diff, one file outside repo' '
96+
(
97+
cd test-outside/repo &&
98+
test_expect_code 0 git diff --quiet a ../non/git/matching-file &&
99+
test_expect_code 1 git diff --quiet a ../non/git/extra-space
100+
)
101+
'
102+
103+
test_expect_success 'git diff, both files outside repo' '
104+
(
105+
GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/test-outside" &&
106+
export GIT_CEILING_DIRECTORIES &&
107+
cd test-outside/non/git &&
108+
test_expect_code 0 git diff --quiet a matching-file &&
109+
test_expect_code 1 git diff --quiet a extra-space
110+
)
111+
'
112+
113+
test_expect_success 'git diff --ignore-space-at-eol, one file outside repo' '
114+
(
115+
cd test-outside/repo &&
116+
test_expect_code 0 git diff --quiet --ignore-space-at-eol a ../non/git/trailing-space &&
117+
test_expect_code 1 git diff --quiet --ignore-space-at-eol a ../non/git/extra-space
118+
)
119+
'
120+
121+
test_expect_success 'git diff --ignore-space-at-eol, both files outside repo' '
122+
(
123+
GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/test-outside" &&
124+
export GIT_CEILING_DIRECTORIES &&
125+
cd test-outside/non/git &&
126+
test_expect_code 0 git diff --quiet --ignore-space-at-eol a trailing-space &&
127+
test_expect_code 1 git diff --quiet --ignore-space-at-eol a extra-space
128+
)
129+
'
130+
131+
test_expect_success 'git diff --ignore-all-space, one file outside repo' '
132+
(
133+
cd test-outside/repo &&
134+
test_expect_code 0 git diff --quiet --ignore-all-space a ../non/git/trailing-space &&
135+
test_expect_code 0 git diff --quiet --ignore-all-space a ../non/git/extra-space &&
136+
test_expect_code 1 git diff --quiet --ignore-all-space a ../non/git/never-match
137+
)
138+
'
139+
140+
test_expect_success 'git diff --ignore-all-space, both files outside repo' '
141+
(
142+
GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/test-outside" &&
143+
export GIT_CEILING_DIRECTORIES &&
144+
cd test-outside/non/git &&
145+
test_expect_code 0 git diff --quiet --ignore-all-space a trailing-space &&
146+
test_expect_code 0 git diff --quiet --ignore-all-space a extra-space &&
147+
test_expect_code 1 git diff --quiet --ignore-all-space a never-match
148+
)
149+
'
150+
80151
test_done

t/t4053-diff-no-index.sh

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,25 @@ test_expect_success 'setup' '
88
mkdir a &&
99
mkdir b &&
1010
echo 1 >a/1 &&
11-
echo 2 >a/2
11+
echo 2 >a/2 &&
12+
git init repo &&
13+
echo 1 >repo/a &&
14+
mkdir -p non/git &&
15+
echo 1 >non/git/a &&
16+
echo 1 >non/git/b
1217
'
1318

1419
test_expect_success 'git diff --no-index directories' '
1520
git diff --no-index a b >cnt
1621
test $? = 1 && test_line_count = 14 cnt
1722
'
1823

24+
test_expect_success 'git diff --no-index relative path outside repo' '
25+
(
26+
cd repo &&
27+
test_expect_code 0 git diff --no-index a ../non/git/a &&
28+
test_expect_code 0 git diff --no-index ../non/git/a ../non/git/b
29+
)
30+
'
31+
1932
test_done

0 commit comments

Comments
 (0)