Skip to content

Commit e034d1b

Browse files
committed
Merge branch 'nd/grep-true-path'
"git grep -e pattern <tree>" asked the attribute system to read "<tree>:.gitattributes" file in the working tree, which was nonsense. * nd/grep-true-path: grep: stop looking at random places for .gitattributes
2 parents 58f3f98 + 55c6168 commit e034d1b

File tree

4 files changed

+51
-17
lines changed

4 files changed

+51
-17
lines changed

builtin/grep.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,15 @@ static pthread_cond_t cond_result;
8686
static int skip_first_line;
8787

8888
static void add_work(struct grep_opt *opt, enum grep_source_type type,
89-
const char *name, const void *id)
89+
const char *name, const char *path, const void *id)
9090
{
9191
grep_lock();
9292

9393
while ((todo_end+1) % ARRAY_SIZE(todo) == todo_done) {
9494
pthread_cond_wait(&cond_write, &grep_mutex);
9595
}
9696

97-
grep_source_init(&todo[todo_end].source, type, name, id);
97+
grep_source_init(&todo[todo_end].source, type, name, path, id);
9898
if (opt->binary != GREP_BINARY_TEXT)
9999
grep_source_load_driver(&todo[todo_end].source);
100100
todo[todo_end].done = 0;
@@ -280,7 +280,8 @@ static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type
280280
}
281281

282282
static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
283-
const char *filename, int tree_name_len)
283+
const char *filename, int tree_name_len,
284+
const char *path)
284285
{
285286
struct strbuf pathbuf = STRBUF_INIT;
286287

@@ -294,7 +295,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
294295

295296
#ifndef NO_PTHREADS
296297
if (use_threads) {
297-
add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, sha1);
298+
add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1);
298299
strbuf_release(&pathbuf);
299300
return 0;
300301
} else
@@ -303,7 +304,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
303304
struct grep_source gs;
304305
int hit;
305306

306-
grep_source_init(&gs, GREP_SOURCE_SHA1, pathbuf.buf, sha1);
307+
grep_source_init(&gs, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1);
307308
strbuf_release(&pathbuf);
308309
hit = grep_source(opt, &gs);
309310

@@ -323,7 +324,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
323324

324325
#ifndef NO_PTHREADS
325326
if (use_threads) {
326-
add_work(opt, GREP_SOURCE_FILE, buf.buf, filename);
327+
add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename);
327328
strbuf_release(&buf);
328329
return 0;
329330
} else
@@ -332,7 +333,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
332333
struct grep_source gs;
333334
int hit;
334335

335-
grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename);
336+
grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename, filename);
336337
strbuf_release(&buf);
337338
hit = grep_source(opt, &gs);
338339

@@ -388,7 +389,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
388389
if (cached || (ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) {
389390
if (ce_stage(ce))
390391
continue;
391-
hit |= grep_sha1(opt, ce->sha1, ce->name, 0);
392+
hit |= grep_sha1(opt, ce->sha1, ce->name, 0, ce->name);
392393
}
393394
else
394395
hit |= grep_file(opt, ce->name);
@@ -406,7 +407,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
406407
}
407408

408409
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
409-
struct tree_desc *tree, struct strbuf *base, int tn_len)
410+
struct tree_desc *tree, struct strbuf *base, int tn_len,
411+
int check_attr)
410412
{
411413
int hit = 0;
412414
enum interesting match = entry_not_interesting;
@@ -427,7 +429,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
427429
strbuf_add(base, entry.path, te_len);
428430

429431
if (S_ISREG(entry.mode)) {
430-
hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len);
432+
hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len,
433+
check_attr ? base->buf + tn_len : NULL);
431434
}
432435
else if (S_ISDIR(entry.mode)) {
433436
enum object_type type;
@@ -442,7 +445,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
442445

443446
strbuf_addch(base, '/');
444447
init_tree_desc(&sub, data, size);
445-
hit |= grep_tree(opt, pathspec, &sub, base, tn_len);
448+
hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
449+
check_attr);
446450
free(data);
447451
}
448452
strbuf_setlen(base, old_baselen);
@@ -457,7 +461,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
457461
struct object *obj, const char *name)
458462
{
459463
if (obj->type == OBJ_BLOB)
460-
return grep_sha1(opt, obj->sha1, name, 0);
464+
return grep_sha1(opt, obj->sha1, name, 0, NULL);
461465
if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) {
462466
struct tree_desc tree;
463467
void *data;
@@ -480,7 +484,8 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
480484
strbuf_addch(&base, ':');
481485
}
482486
init_tree_desc(&tree, data, size);
483-
hit = grep_tree(opt, pathspec, &tree, &base, base.len);
487+
hit = grep_tree(opt, pathspec, &tree, &base, base.len,
488+
obj->type == OBJ_COMMIT);
484489
strbuf_release(&base);
485490
free(data);
486491
return hit;

grep.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,7 @@ int grep_buffer(struct grep_opt *opt, char *buf, unsigned long size)
15501550
struct grep_source gs;
15511551
int r;
15521552

1553-
grep_source_init(&gs, GREP_SOURCE_BUF, NULL, NULL);
1553+
grep_source_init(&gs, GREP_SOURCE_BUF, NULL, NULL, NULL);
15541554
gs.buf = buf;
15551555
gs.size = size;
15561556

@@ -1561,10 +1561,12 @@ int grep_buffer(struct grep_opt *opt, char *buf, unsigned long size)
15611561
}
15621562

15631563
void grep_source_init(struct grep_source *gs, enum grep_source_type type,
1564-
const char *name, const void *identifier)
1564+
const char *name, const char *path,
1565+
const void *identifier)
15651566
{
15661567
gs->type = type;
15671568
gs->name = name ? xstrdup(name) : NULL;
1569+
gs->path = path ? xstrdup(path) : NULL;
15681570
gs->buf = NULL;
15691571
gs->size = 0;
15701572
gs->driver = NULL;
@@ -1586,6 +1588,8 @@ void grep_source_clear(struct grep_source *gs)
15861588
{
15871589
free(gs->name);
15881590
gs->name = NULL;
1591+
free(gs->path);
1592+
gs->path = NULL;
15891593
free(gs->identifier);
15901594
gs->identifier = NULL;
15911595
grep_source_clear_data(gs);
@@ -1678,7 +1682,8 @@ void grep_source_load_driver(struct grep_source *gs)
16781682
return;
16791683

16801684
grep_attr_lock();
1681-
gs->driver = userdiff_find_by_path(gs->name);
1685+
if (gs->path)
1686+
gs->driver = userdiff_find_by_path(gs->path);
16821687
if (!gs->driver)
16831688
gs->driver = userdiff_find_by_name("default");
16841689
grep_attr_unlock();

grep.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,13 @@ struct grep_source {
164164
char *buf;
165165
unsigned long size;
166166

167+
char *path; /* for attribute lookups */
167168
struct userdiff_driver *driver;
168169
};
169170

170171
void grep_source_init(struct grep_source *gs, enum grep_source_type type,
171-
const char *name, const void *identifier);
172+
const char *name, const char *path,
173+
const void *identifier);
172174
void grep_source_clear_data(struct grep_source *gs);
173175
void grep_source_clear(struct grep_source *gs);
174176
void grep_source_load_driver(struct grep_source *gs);

t/t7008-grep-binary.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,28 @@ test_expect_success 'grep respects binary diff attribute' '
111111
test_cmp expect actual
112112
'
113113

114+
test_expect_success 'grep --cached respects binary diff attribute' '
115+
git grep --cached text t >actual &&
116+
test_cmp expect actual
117+
'
118+
119+
test_expect_success 'grep --cached respects binary diff attribute (2)' '
120+
git add .gitattributes &&
121+
rm .gitattributes &&
122+
git grep --cached text t >actual &&
123+
test_when_finished "git rm --cached .gitattributes" &&
124+
test_when_finished "git checkout .gitattributes" &&
125+
test_cmp expect actual
126+
'
127+
128+
test_expect_success 'grep revision respects binary diff attribute' '
129+
git commit -m new &&
130+
echo "Binary file HEAD:t matches" >expect &&
131+
git grep text HEAD -- t >actual &&
132+
test_when_finished "git reset HEAD^" &&
133+
test_cmp expect actual
134+
'
135+
114136
test_expect_success 'grep respects not-binary diff attribute' '
115137
echo binQary | q_to_nul >b &&
116138
git add b &&

0 commit comments

Comments
 (0)