diff: handle relative paths in no-index
When diff-no-index is given a relative path to a file outside the repository, it aborts with error. However, if the file is given using an absolute path, the diff runs as expected. The two cases should be treated the same. Tests and commit message by Tim Henigan. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Tim Henigan <tim.henigan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Jun 21, 2012 at 14:09 UTC
546e0fd9e918b2ea3d9943124641d3b6af59a4fe
4 files changed
+39
-22
cache.h
+1
@@ -455,6 +455,7 @@ extern const char *prefix_filename(const char *prefix, int len, const char *path
455
extern int check_filename(const char *prefix, const char *name);
456
extern void verify_filename(const char *prefix, const char *name);
457
extern void verify_non_filename(const char *prefix, const char *name);
458
+extern int path_inside_repo(const char *prefix, const char *path);
459
460
#define INIT_DB_QUIET 0x0001
461
diff-no-index.c
+2
-19
@@ -151,23 +151,6 @@ static int queue_diff(struct diff_options *o,
151
}
152
}
153
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
-
154
void diff_no_index(struct rev_info *revs,
155
int argc, const char **argv,
156
int nongit, const char *prefix)
@@ -197,8 +180,8 @@ void diff_no_index(struct rev_info *revs,
180
* a colourful "diff" replacement.
181
*/
182
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])))
185
return;
186
}
187
if (argc != i + 2)
setup.c
+22
-2
@@ -4,7 +4,7 @@
4
static int inside_git_dir = -1;
5
static int inside_work_tree = -1;
6
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)
8
{
9
const char *orig = path;
10
char *sanitized;
@@ -31,7 +31,8 @@ char *prefix_path(const char *prefix, int len, const char *path)
31
if (strncmp(sanitized, work_tree, len) ||
32
(len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) {
33
error_out:
34
- die("'%s' is outside repository", orig);
34
+ free(sanitized);
35
+ return NULL;
36
}
37
if (sanitized[len] == '/')
38
len++;
@@ -40,6 +41,25 @@ char *prefix_path(const char *prefix, int len, const char *path)
41
return sanitized;
42
}
43
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
+
63
int check_filename(const char *prefix, const char *arg)
64
{
65
const char *name;
t/t4053-diff-no-index.sh
+14
-1
@@ -8,7 +8,12 @@ test_expect_success 'setup' '
8
mkdir a &&
9
mkdir b &&
10
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
17
'
18
19
test_expect_success 'git diff --no-index directories' '
@@ -16,4 +21,12 @@ test_expect_success 'git diff --no-index directories' '
21
test $? = 1 && test_line_count = 14 cnt
22
'
23
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
+
32
test_done