summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 929e37d)
raw | patch | inline | side by side (parent: 929e37d)
author | Clemens Buchacher <drizzd@aon.at> | |
Sat, 5 Sep 2009 12:31:17 +0000 (14:31 +0200) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Mon, 7 Sep 2009 22:03:04 +0000 (15:03 -0700) |
"git grep" would barf at relative paths pointing outside the current
working directory (or subdirectories thereof). Use quote_path_relative(),
which can handle such cases just fine.
[jc: added tests.]
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
working directory (or subdirectories thereof). Use quote_path_relative(),
which can handle such cases just fine.
[jc: added tests.]
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-grep.c | patch | blob | history | |
grep.h | patch | blob | history | |
t/t7002-grep.sh | patch | blob | history |
diff --git a/builtin-grep.c b/builtin-grep.c
index da2f4fe1b85099fdce09d74062d4c700b3403fa3..eda2c884870abde5f9d943259916de45d9425a6c 100644 (file)
--- a/builtin-grep.c
+++ b/builtin-grep.c
#include "tree-walk.h"
#include "builtin.h"
#include "grep.h"
+#include "quote.h"
#ifndef NO_EXTERNAL_GREP
#ifdef __unix__
@@ -114,8 +115,8 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char
unsigned long size;
char *data;
enum object_type type;
- char *to_free = NULL;
int hit;
+ struct strbuf pathbuf = STRBUF_INIT;
data = read_sha1_file(sha1, &type, &size);
if (!data) {
@@ -123,26 +124,13 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char
return 0;
}
if (opt->relative && opt->prefix_length) {
- static char name_buf[PATH_MAX];
- char *cp;
- int name_len = strlen(name) - opt->prefix_length + 1;
-
- if (!tree_name_len)
- name += opt->prefix_length;
- else {
- if (ARRAY_SIZE(name_buf) <= name_len)
- cp = to_free = xmalloc(name_len);
- else
- cp = name_buf;
- memcpy(cp, name, tree_name_len);
- strcpy(cp + tree_name_len,
- name + tree_name_len + opt->prefix_length);
- name = cp;
- }
+ quote_path_relative(name + tree_name_len, -1, &pathbuf, opt->prefix);
+ strbuf_insert(&pathbuf, 0, name, tree_name_len);
+ name = pathbuf.buf;
}
hit = grep_buffer(opt, name, data, size);
+ strbuf_release(&pathbuf);
free(data);
- free(to_free);
return hit;
}
int i;
char *data;
size_t sz;
+ struct strbuf buf = STRBUF_INIT;
if (lstat(filename, &st) < 0) {
err_ret:
}
close(i);
if (opt->relative && opt->prefix_length)
- filename += opt->prefix_length;
+ filename = quote_path_relative(filename, -1, &buf, opt->prefix);
i = grep_buffer(opt, filename, data, sz);
+ strbuf_release(&buf);
free(data);
return i;
}
int i;
memset(&opt, 0, sizeof(opt));
+ opt.prefix = prefix;
opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
opt.relative = 1;
opt.pathname = 1;
verify_filename(prefix, argv[j]);
}
- if (i < argc) {
+ if (i < argc)
paths = get_pathspec(prefix, argv + i);
- if (opt.prefix_length && opt.relative) {
- /* Make sure we do not get outside of paths */
- for (i = 0; paths[i]; i++)
- if (strncmp(prefix, paths[i], opt.prefix_length))
- die("git grep: cannot generate relative filenames containing '..'");
- }
- }
else if (prefix) {
paths = xcalloc(2, sizeof(const char *));
paths[0] = prefix;
index a67005de62d1442e7ba6a8dc27320225a0d55819..5b767c931c0fec250d4dff74f6ef72c0abea16af 100644 (file)
--- a/grep.h
+++ b/grep.h
struct grep_pat *pattern_list;
struct grep_pat **pattern_tail;
struct grep_expr *pattern_expression;
+ const char *prefix;
int prefix_length;
regex_t regexp;
unsigned linenum:1;
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index 7868af8f1896e621b98a2ae9b71492a68a96e584..fe87834fbeb22dfe21fabbbfb56f7c73558de2b2 100755 (executable)
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
git checkout t/t
'
+test_expect_success 'grep from a subdirectory to search wider area (1)' '
+ mkdir -p s &&
+ (
+ cd s && git grep "x x x" ..
+ )
+'
+
+test_expect_success 'grep from a subdirectory to search wider area (2)' '
+ mkdir -p s &&
+ (
+ cd s || exit 1
+ ( git grep xxyyzz .. >out ; echo $? >status )
+ ! test -s out &&
+ test 1 = $(cat status)
+ )
+'
+
test_done