Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Builtin "git grep" |
| 3 | * |
| 4 | * Copyright (c) 2006 Junio C Hamano |
| 5 | */ |
| 6 | #include "cache.h" |
| 7 | #include "blob.h" |
| 8 | #include "tree.h" |
| 9 | #include "commit.h" |
| 10 | #include "tag.h" |
Junio C Hamano | 1362671 | 2006-05-01 15:58:29 -0700 | [diff] [blame] | 11 | #include "tree-walk.h" |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 12 | #include "builtin.h" |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 13 | #include "parse-options.h" |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 14 | #include "string-list.h" |
| 15 | #include "run-command.h" |
René Scharfe | 60ecac9 | 2009-07-02 00:07:24 +0200 | [diff] [blame] | 16 | #include "userdiff.h" |
Junio C Hamano | 83b5d2f | 2006-09-17 16:02:52 -0700 | [diff] [blame] | 17 | #include "grep.h" |
Clemens Buchacher | 493b7a0 | 2009-09-05 14:31:17 +0200 | [diff] [blame] | 18 | #include "quote.h" |
Junio C Hamano | 59332d1 | 2010-02-06 10:40:08 -0800 | [diff] [blame] | 19 | #include "dir.h" |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 20 | |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 21 | static char const * const grep_usage[] = { |
Štěpán Němec | 62b4698 | 2010-10-08 19:31:15 +0200 | [diff] [blame] | 22 | "git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]", |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 23 | NULL |
| 24 | }; |
| 25 | |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 26 | static int use_threads = 1; |
| 27 | |
| 28 | #ifndef NO_PTHREADS |
| 29 | #define THREADS 8 |
| 30 | static pthread_t threads[THREADS]; |
| 31 | |
| 32 | static void *load_sha1(const unsigned char *sha1, unsigned long *size, |
| 33 | const char *name); |
| 34 | static void *load_file(const char *filename, size_t *sz); |
| 35 | |
| 36 | enum work_type {WORK_SHA1, WORK_FILE}; |
| 37 | |
| 38 | /* We use one producer thread and THREADS consumer |
| 39 | * threads. The producer adds struct work_items to 'todo' and the |
| 40 | * consumers pick work items from the same array. |
| 41 | */ |
Jonathan Nieder | 9cba13c | 2011-03-16 02:08:34 -0500 | [diff] [blame] | 42 | struct work_item { |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 43 | enum work_type type; |
| 44 | char *name; |
| 45 | |
| 46 | /* if type == WORK_SHA1, then 'identifier' is a SHA1, |
| 47 | * otherwise type == WORK_FILE, and 'identifier' is a NUL |
| 48 | * terminated filename. |
| 49 | */ |
| 50 | void *identifier; |
| 51 | char done; |
| 52 | struct strbuf out; |
| 53 | }; |
| 54 | |
| 55 | /* In the range [todo_done, todo_start) in 'todo' we have work_items |
| 56 | * that have been or are processed by a consumer thread. We haven't |
| 57 | * written the result for these to stdout yet. |
| 58 | * |
| 59 | * The work_items in [todo_start, todo_end) are waiting to be picked |
| 60 | * up by a consumer thread. |
| 61 | * |
| 62 | * The ranges are modulo TODO_SIZE. |
| 63 | */ |
| 64 | #define TODO_SIZE 128 |
| 65 | static struct work_item todo[TODO_SIZE]; |
| 66 | static int todo_start; |
| 67 | static int todo_end; |
| 68 | static int todo_done; |
| 69 | |
| 70 | /* Has all work items been added? */ |
| 71 | static int all_work_added; |
| 72 | |
| 73 | /* This lock protects all the variables above. */ |
| 74 | static pthread_mutex_t grep_mutex; |
| 75 | |
Junio C Hamano | 1487a12 | 2011-10-26 11:45:15 -0700 | [diff] [blame] | 76 | static inline void grep_lock(void) |
| 77 | { |
| 78 | if (use_threads) |
| 79 | pthread_mutex_lock(&grep_mutex); |
| 80 | } |
| 81 | |
| 82 | static inline void grep_unlock(void) |
| 83 | { |
| 84 | if (use_threads) |
| 85 | pthread_mutex_unlock(&grep_mutex); |
| 86 | } |
| 87 | |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 88 | /* Used to serialize calls to read_sha1_file. */ |
| 89 | static pthread_mutex_t read_sha1_mutex; |
| 90 | |
Junio C Hamano | 1487a12 | 2011-10-26 11:45:15 -0700 | [diff] [blame] | 91 | static inline void read_sha1_lock(void) |
| 92 | { |
| 93 | if (use_threads) |
| 94 | pthread_mutex_lock(&read_sha1_mutex); |
| 95 | } |
| 96 | |
| 97 | static inline void read_sha1_unlock(void) |
| 98 | { |
| 99 | if (use_threads) |
| 100 | pthread_mutex_unlock(&read_sha1_mutex); |
| 101 | } |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 102 | |
| 103 | /* Signalled when a new work_item is added to todo. */ |
| 104 | static pthread_cond_t cond_add; |
| 105 | |
| 106 | /* Signalled when the result from one work_item is written to |
| 107 | * stdout. |
| 108 | */ |
| 109 | static pthread_cond_t cond_write; |
| 110 | |
| 111 | /* Signalled when we are finished with everything. */ |
| 112 | static pthread_cond_t cond_result; |
| 113 | |
René Scharfe | 08303c3 | 2011-06-05 17:24:15 +0200 | [diff] [blame] | 114 | static int skip_first_line; |
René Scharfe | 431d6e7 | 2010-03-15 17:21:10 +0100 | [diff] [blame] | 115 | |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 116 | static void add_work(enum work_type type, char *name, void *id) |
| 117 | { |
| 118 | grep_lock(); |
| 119 | |
| 120 | while ((todo_end+1) % ARRAY_SIZE(todo) == todo_done) { |
| 121 | pthread_cond_wait(&cond_write, &grep_mutex); |
| 122 | } |
| 123 | |
| 124 | todo[todo_end].type = type; |
| 125 | todo[todo_end].name = name; |
| 126 | todo[todo_end].identifier = id; |
| 127 | todo[todo_end].done = 0; |
| 128 | strbuf_reset(&todo[todo_end].out); |
| 129 | todo_end = (todo_end + 1) % ARRAY_SIZE(todo); |
| 130 | |
| 131 | pthread_cond_signal(&cond_add); |
| 132 | grep_unlock(); |
| 133 | } |
| 134 | |
| 135 | static struct work_item *get_work(void) |
| 136 | { |
| 137 | struct work_item *ret; |
| 138 | |
| 139 | grep_lock(); |
| 140 | while (todo_start == todo_end && !all_work_added) { |
| 141 | pthread_cond_wait(&cond_add, &grep_mutex); |
| 142 | } |
| 143 | |
| 144 | if (todo_start == todo_end && all_work_added) { |
| 145 | ret = NULL; |
| 146 | } else { |
| 147 | ret = &todo[todo_start]; |
| 148 | todo_start = (todo_start + 1) % ARRAY_SIZE(todo); |
| 149 | } |
| 150 | grep_unlock(); |
| 151 | return ret; |
| 152 | } |
| 153 | |
| 154 | static void grep_sha1_async(struct grep_opt *opt, char *name, |
| 155 | const unsigned char *sha1) |
| 156 | { |
| 157 | unsigned char *s; |
| 158 | s = xmalloc(20); |
| 159 | memcpy(s, sha1, 20); |
| 160 | add_work(WORK_SHA1, name, s); |
| 161 | } |
| 162 | |
| 163 | static void grep_file_async(struct grep_opt *opt, char *name, |
| 164 | const char *filename) |
| 165 | { |
| 166 | add_work(WORK_FILE, name, xstrdup(filename)); |
| 167 | } |
| 168 | |
| 169 | static void work_done(struct work_item *w) |
| 170 | { |
| 171 | int old_done; |
| 172 | |
| 173 | grep_lock(); |
| 174 | w->done = 1; |
| 175 | old_done = todo_done; |
| 176 | for(; todo[todo_done].done && todo_done != todo_start; |
| 177 | todo_done = (todo_done+1) % ARRAY_SIZE(todo)) { |
| 178 | w = &todo[todo_done]; |
René Scharfe | 431d6e7 | 2010-03-15 17:21:10 +0100 | [diff] [blame] | 179 | if (w->out.len) { |
René Scharfe | 08303c3 | 2011-06-05 17:24:15 +0200 | [diff] [blame] | 180 | const char *p = w->out.buf; |
| 181 | size_t len = w->out.len; |
| 182 | |
| 183 | /* Skip the leading hunk mark of the first file. */ |
| 184 | if (skip_first_line) { |
| 185 | while (len) { |
| 186 | len--; |
| 187 | if (*p++ == '\n') |
| 188 | break; |
| 189 | } |
| 190 | skip_first_line = 0; |
| 191 | } |
| 192 | |
| 193 | write_or_die(1, p, len); |
René Scharfe | 431d6e7 | 2010-03-15 17:21:10 +0100 | [diff] [blame] | 194 | } |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 195 | free(w->name); |
| 196 | free(w->identifier); |
| 197 | } |
| 198 | |
| 199 | if (old_done != todo_done) |
| 200 | pthread_cond_signal(&cond_write); |
| 201 | |
| 202 | if (all_work_added && todo_done == todo_end) |
| 203 | pthread_cond_signal(&cond_result); |
| 204 | |
| 205 | grep_unlock(); |
| 206 | } |
| 207 | |
| 208 | static void *run(void *arg) |
| 209 | { |
| 210 | int hit = 0; |
| 211 | struct grep_opt *opt = arg; |
| 212 | |
| 213 | while (1) { |
| 214 | struct work_item *w = get_work(); |
| 215 | if (!w) |
| 216 | break; |
| 217 | |
| 218 | opt->output_priv = w; |
| 219 | if (w->type == WORK_SHA1) { |
| 220 | unsigned long sz; |
| 221 | void* data = load_sha1(w->identifier, &sz, w->name); |
| 222 | |
| 223 | if (data) { |
| 224 | hit |= grep_buffer(opt, w->name, data, sz); |
| 225 | free(data); |
| 226 | } |
| 227 | } else if (w->type == WORK_FILE) { |
| 228 | size_t sz; |
| 229 | void* data = load_file(w->identifier, &sz); |
| 230 | if (data) { |
| 231 | hit |= grep_buffer(opt, w->name, data, sz); |
| 232 | free(data); |
| 233 | } |
| 234 | } else { |
| 235 | assert(0); |
| 236 | } |
| 237 | |
| 238 | work_done(w); |
| 239 | } |
Dan McGee | bfac23d | 2010-01-30 09:42:58 -0600 | [diff] [blame] | 240 | free_grep_patterns(arg); |
| 241 | free(arg); |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 242 | |
| 243 | return (void*) (intptr_t) hit; |
| 244 | } |
| 245 | |
| 246 | static void strbuf_out(struct grep_opt *opt, const void *buf, size_t size) |
| 247 | { |
| 248 | struct work_item *w = opt->output_priv; |
| 249 | strbuf_add(&w->out, buf, size); |
| 250 | } |
| 251 | |
| 252 | static void start_threads(struct grep_opt *opt) |
| 253 | { |
| 254 | int i; |
| 255 | |
| 256 | pthread_mutex_init(&grep_mutex, NULL); |
| 257 | pthread_mutex_init(&read_sha1_mutex, NULL); |
Thomas Rast | 0579f91 | 2011-12-12 22:16:07 +0100 | [diff] [blame] | 258 | pthread_mutex_init(&grep_attr_mutex, NULL); |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 259 | pthread_cond_init(&cond_add, NULL); |
| 260 | pthread_cond_init(&cond_write, NULL); |
| 261 | pthread_cond_init(&cond_result, NULL); |
| 262 | |
| 263 | for (i = 0; i < ARRAY_SIZE(todo); i++) { |
| 264 | strbuf_init(&todo[i].out, 0); |
| 265 | } |
| 266 | |
| 267 | for (i = 0; i < ARRAY_SIZE(threads); i++) { |
| 268 | int err; |
| 269 | struct grep_opt *o = grep_opt_dup(opt); |
| 270 | o->output = strbuf_out; |
| 271 | compile_grep_patterns(o); |
| 272 | err = pthread_create(&threads[i], NULL, run, o); |
| 273 | |
| 274 | if (err) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 275 | die(_("grep: failed to create thread: %s"), |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 276 | strerror(err)); |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | static int wait_all(void) |
| 281 | { |
| 282 | int hit = 0; |
| 283 | int i; |
| 284 | |
| 285 | grep_lock(); |
| 286 | all_work_added = 1; |
| 287 | |
| 288 | /* Wait until all work is done. */ |
| 289 | while (todo_done != todo_end) |
| 290 | pthread_cond_wait(&cond_result, &grep_mutex); |
| 291 | |
| 292 | /* Wake up all the consumer threads so they can see that there |
| 293 | * is no more work to do. |
| 294 | */ |
| 295 | pthread_cond_broadcast(&cond_add); |
| 296 | grep_unlock(); |
| 297 | |
| 298 | for (i = 0; i < ARRAY_SIZE(threads); i++) { |
| 299 | void *h; |
| 300 | pthread_join(threads[i], &h); |
| 301 | hit |= (int) (intptr_t) h; |
| 302 | } |
| 303 | |
| 304 | pthread_mutex_destroy(&grep_mutex); |
| 305 | pthread_mutex_destroy(&read_sha1_mutex); |
Thomas Rast | 0579f91 | 2011-12-12 22:16:07 +0100 | [diff] [blame] | 306 | pthread_mutex_destroy(&grep_attr_mutex); |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 307 | pthread_cond_destroy(&cond_add); |
| 308 | pthread_cond_destroy(&cond_write); |
| 309 | pthread_cond_destroy(&cond_result); |
| 310 | |
| 311 | return hit; |
| 312 | } |
| 313 | #else /* !NO_PTHREADS */ |
| 314 | #define read_sha1_lock() |
| 315 | #define read_sha1_unlock() |
| 316 | |
| 317 | static int wait_all(void) |
| 318 | { |
| 319 | return 0; |
| 320 | } |
| 321 | #endif |
| 322 | |
René Scharfe | 7e8f59d | 2009-03-07 13:32:32 +0100 | [diff] [blame] | 323 | static int grep_config(const char *var, const char *value, void *cb) |
| 324 | { |
| 325 | struct grep_opt *opt = cb; |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 326 | char *color = NULL; |
René Scharfe | 7e8f59d | 2009-03-07 13:32:32 +0100 | [diff] [blame] | 327 | |
René Scharfe | 60ecac9 | 2009-07-02 00:07:24 +0200 | [diff] [blame] | 328 | switch (userdiff_config(var, value)) { |
| 329 | case 0: break; |
| 330 | case -1: return -1; |
| 331 | default: return 0; |
| 332 | } |
| 333 | |
Joe Ratterman | b22520a | 2011-03-30 14:31:05 -0500 | [diff] [blame] | 334 | if (!strcmp(var, "grep.extendedregexp")) { |
| 335 | if (git_config_bool(var, value)) |
| 336 | opt->regflags |= REG_EXTENDED; |
| 337 | else |
| 338 | opt->regflags &= ~REG_EXTENDED; |
| 339 | return 0; |
| 340 | } |
| 341 | |
| 342 | if (!strcmp(var, "grep.linenumber")) { |
| 343 | opt->linenum = git_config_bool(var, value); |
| 344 | return 0; |
| 345 | } |
| 346 | |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 347 | if (!strcmp(var, "color.grep")) |
Jeff King | e269eb7 | 2011-08-17 22:03:48 -0700 | [diff] [blame] | 348 | opt->color = git_config_colorbool(var, value); |
Mark Lodato | 00588bb | 2010-03-07 11:52:47 -0500 | [diff] [blame] | 349 | else if (!strcmp(var, "color.grep.context")) |
| 350 | color = opt->color_context; |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 351 | else if (!strcmp(var, "color.grep.filename")) |
| 352 | color = opt->color_filename; |
Mark Lodato | 00588bb | 2010-03-07 11:52:47 -0500 | [diff] [blame] | 353 | else if (!strcmp(var, "color.grep.function")) |
| 354 | color = opt->color_function; |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 355 | else if (!strcmp(var, "color.grep.linenumber")) |
| 356 | color = opt->color_lineno; |
| 357 | else if (!strcmp(var, "color.grep.match")) |
| 358 | color = opt->color_match; |
Mark Lodato | 00588bb | 2010-03-07 11:52:47 -0500 | [diff] [blame] | 359 | else if (!strcmp(var, "color.grep.selected")) |
| 360 | color = opt->color_selected; |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 361 | else if (!strcmp(var, "color.grep.separator")) |
| 362 | color = opt->color_sep; |
| 363 | else |
| 364 | return git_color_default_config(var, value, cb); |
| 365 | if (color) { |
René Scharfe | 7e8f59d | 2009-03-07 13:32:32 +0100 | [diff] [blame] | 366 | if (!value) |
| 367 | return config_error_nonbool(var); |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 368 | color_parse(value, var, color); |
René Scharfe | 7e8f59d | 2009-03-07 13:32:32 +0100 | [diff] [blame] | 369 | } |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 370 | return 0; |
René Scharfe | 7e8f59d | 2009-03-07 13:32:32 +0100 | [diff] [blame] | 371 | } |
| 372 | |
Junio C Hamano | 5f02d31 | 2010-02-15 18:34:28 -0800 | [diff] [blame] | 373 | static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size) |
| 374 | { |
| 375 | void *data; |
| 376 | |
Junio C Hamano | 7641613 | 2011-10-26 12:15:51 -0700 | [diff] [blame] | 377 | read_sha1_lock(); |
| 378 | data = read_sha1_file(sha1, type, size); |
| 379 | read_sha1_unlock(); |
Junio C Hamano | 5f02d31 | 2010-02-15 18:34:28 -0800 | [diff] [blame] | 380 | return data; |
| 381 | } |
| 382 | |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 383 | static void *load_sha1(const unsigned char *sha1, unsigned long *size, |
| 384 | const char *name) |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 385 | { |
Nicolas Pitre | 21666f1 | 2007-02-26 14:55:59 -0500 | [diff] [blame] | 386 | enum object_type type; |
Junio C Hamano | 5f02d31 | 2010-02-15 18:34:28 -0800 | [diff] [blame] | 387 | void *data = lock_and_read_sha1_file(sha1, &type, size); |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 388 | |
| 389 | if (!data) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 390 | error(_("'%s': unable to read %s"), name, sha1_to_hex(sha1)); |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 391 | |
| 392 | return data; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 393 | } |
| 394 | |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 395 | static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, |
| 396 | const char *filename, int tree_name_len) |
| 397 | { |
| 398 | struct strbuf pathbuf = STRBUF_INIT; |
| 399 | char *name; |
| 400 | |
| 401 | if (opt->relative && opt->prefix_length) { |
| 402 | quote_path_relative(filename + tree_name_len, -1, &pathbuf, |
| 403 | opt->prefix); |
| 404 | strbuf_insert(&pathbuf, 0, filename, tree_name_len); |
| 405 | } else { |
| 406 | strbuf_addstr(&pathbuf, filename); |
| 407 | } |
| 408 | |
| 409 | name = strbuf_detach(&pathbuf, NULL); |
| 410 | |
| 411 | #ifndef NO_PTHREADS |
| 412 | if (use_threads) { |
| 413 | grep_sha1_async(opt, name, sha1); |
| 414 | return 0; |
| 415 | } else |
| 416 | #endif |
| 417 | { |
| 418 | int hit; |
| 419 | unsigned long sz; |
| 420 | void *data = load_sha1(sha1, &sz, name); |
| 421 | if (!data) |
| 422 | hit = 0; |
| 423 | else |
| 424 | hit = grep_buffer(opt, name, data, sz); |
| 425 | |
| 426 | free(data); |
| 427 | free(name); |
| 428 | return hit; |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | static void *load_file(const char *filename, size_t *sz) |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 433 | { |
| 434 | struct stat st; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 435 | char *data; |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 436 | int i; |
Shawn O. Pearce | dc49cd7 | 2007-03-06 20:44:37 -0500 | [diff] [blame] | 437 | |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 438 | if (lstat(filename, &st) < 0) { |
| 439 | err_ret: |
| 440 | if (errno != ENOENT) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 441 | error(_("'%s': %s"), filename, strerror(errno)); |
Stephen Boyd | 1e4cd68 | 2011-04-03 00:06:54 -0700 | [diff] [blame] | 442 | return NULL; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 443 | } |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 444 | if (!S_ISREG(st.st_mode)) |
Stephen Boyd | 1e4cd68 | 2011-04-03 00:06:54 -0700 | [diff] [blame] | 445 | return NULL; |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 446 | *sz = xsize_t(st.st_size); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 447 | i = open(filename, O_RDONLY); |
| 448 | if (i < 0) |
| 449 | goto err_ret; |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 450 | data = xmalloc(*sz + 1); |
| 451 | if (st.st_size != read_in_full(i, data, *sz)) { |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 452 | error(_("'%s': short read %s"), filename, strerror(errno)); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 453 | close(i); |
| 454 | free(data); |
Stephen Boyd | 1e4cd68 | 2011-04-03 00:06:54 -0700 | [diff] [blame] | 455 | return NULL; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 456 | } |
| 457 | close(i); |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 458 | data[*sz] = 0; |
| 459 | return data; |
| 460 | } |
| 461 | |
| 462 | static int grep_file(struct grep_opt *opt, const char *filename) |
| 463 | { |
| 464 | struct strbuf buf = STRBUF_INIT; |
| 465 | char *name; |
| 466 | |
Junio C Hamano | 0d042fe | 2006-08-11 00:44:42 -0700 | [diff] [blame] | 467 | if (opt->relative && opt->prefix_length) |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 468 | quote_path_relative(filename, -1, &buf, opt->prefix); |
| 469 | else |
| 470 | strbuf_addstr(&buf, filename); |
| 471 | name = strbuf_detach(&buf, NULL); |
| 472 | |
| 473 | #ifndef NO_PTHREADS |
| 474 | if (use_threads) { |
| 475 | grep_file_async(opt, name, filename); |
| 476 | return 0; |
| 477 | } else |
| 478 | #endif |
| 479 | { |
| 480 | int hit; |
| 481 | size_t sz; |
| 482 | void *data = load_file(filename, &sz); |
| 483 | if (!data) |
| 484 | hit = 0; |
| 485 | else |
| 486 | hit = grep_buffer(opt, name, data, sz); |
| 487 | |
| 488 | free(data); |
| 489 | free(name); |
| 490 | return hit; |
| 491 | } |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 492 | } |
| 493 | |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 494 | static void append_path(struct grep_opt *opt, const void *data, size_t len) |
| 495 | { |
| 496 | struct string_list *path_list = opt->output_priv; |
| 497 | |
| 498 | if (len == 1 && *(const char *)data == '\0') |
| 499 | return; |
Julian Phillips | 0c72cea | 2010-06-26 00:41:39 +0100 | [diff] [blame] | 500 | string_list_append(path_list, xstrndup(data, len)); |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 501 | } |
| 502 | |
| 503 | static void run_pager(struct grep_opt *opt, const char *prefix) |
| 504 | { |
| 505 | struct string_list *path_list = opt->output_priv; |
| 506 | const char **argv = xmalloc(sizeof(const char *) * (path_list->nr + 1)); |
| 507 | int i, status; |
| 508 | |
| 509 | for (i = 0; i < path_list->nr; i++) |
| 510 | argv[i] = path_list->items[i].string; |
| 511 | argv[path_list->nr] = NULL; |
| 512 | |
| 513 | if (prefix && chdir(prefix)) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 514 | die(_("Failed to chdir: %s"), prefix); |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 515 | status = run_command_v_opt(argv, RUN_USING_SHELL); |
| 516 | if (status) |
| 517 | exit(status); |
| 518 | free(argv); |
| 519 | } |
| 520 | |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 521 | static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int cached) |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 522 | { |
| 523 | int hit = 0; |
| 524 | int nr; |
| 525 | read_cache(); |
| 526 | |
| 527 | for (nr = 0; nr < active_nr; nr++) { |
| 528 | struct cache_entry *ce = active_cache[nr]; |
Linus Torvalds | 7a51ed6 | 2008-01-14 16:03:17 -0800 | [diff] [blame] | 529 | if (!S_ISREG(ce->ce_mode)) |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 530 | continue; |
Nguyễn Thái Ngọc Duy | 2ed2437 | 2010-12-15 22:02:52 +0700 | [diff] [blame] | 531 | if (!match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL)) |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 532 | continue; |
Nguyễn Thái Ngọc Duy | 57d4346 | 2008-12-27 15:21:03 +0700 | [diff] [blame] | 533 | /* |
| 534 | * If CE_VALID is on, we assume worktree file and its cache entry |
| 535 | * are identical, even if worktree file has been modified, so use |
| 536 | * cache version instead |
| 537 | */ |
Nguyễn Thái Ngọc Duy | b4d1690 | 2009-08-20 20:46:58 +0700 | [diff] [blame] | 538 | if (cached || (ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) { |
Junio C Hamano | 36f2587 | 2006-11-26 12:47:52 -0800 | [diff] [blame] | 539 | if (ce_stage(ce)) |
| 540 | continue; |
Junio C Hamano | 0d042fe | 2006-08-11 00:44:42 -0700 | [diff] [blame] | 541 | hit |= grep_sha1(opt, ce->sha1, ce->name, 0); |
Junio C Hamano | 36f2587 | 2006-11-26 12:47:52 -0800 | [diff] [blame] | 542 | } |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 543 | else |
| 544 | hit |= grep_file(opt, ce->name); |
Junio C Hamano | 36f2587 | 2006-11-26 12:47:52 -0800 | [diff] [blame] | 545 | if (ce_stage(ce)) { |
| 546 | do { |
| 547 | nr++; |
| 548 | } while (nr < active_nr && |
| 549 | !strcmp(ce->name, active_cache[nr]->name)); |
| 550 | nr--; /* compensate for loop control */ |
| 551 | } |
Junio C Hamano | c8610a2 | 2010-01-25 15:37:23 -0800 | [diff] [blame] | 552 | if (hit && opt->status_only) |
| 553 | break; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 554 | } |
| 555 | return hit; |
| 556 | } |
| 557 | |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 558 | static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 559 | struct tree_desc *tree, struct strbuf *base, int tn_len) |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 560 | { |
Nguyễn Thái Ngọc Duy | d688cf0 | 2011-10-24 17:36:10 +1100 | [diff] [blame] | 561 | int hit = 0; |
| 562 | enum interesting match = entry_not_interesting; |
Linus Torvalds | 4c068a9 | 2006-05-30 09:45:45 -0700 | [diff] [blame] | 563 | struct name_entry entry; |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 564 | int old_baselen = base->len; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 565 | |
Linus Torvalds | 4c068a9 | 2006-05-30 09:45:45 -0700 | [diff] [blame] | 566 | while (tree_entry(tree, &entry)) { |
Nguyễn Thái Ngọc Duy | 0de1633 | 2011-10-24 17:36:09 +1100 | [diff] [blame] | 567 | int te_len = tree_entry_len(&entry); |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 568 | |
Nguyễn Thái Ngọc Duy | d688cf0 | 2011-10-24 17:36:10 +1100 | [diff] [blame] | 569 | if (match != all_entries_interesting) { |
Nguyễn Thái Ngọc Duy | 97d0b74 | 2011-03-25 16:34:20 +0700 | [diff] [blame] | 570 | match = tree_entry_interesting(&entry, base, tn_len, pathspec); |
Nguyễn Thái Ngọc Duy | d688cf0 | 2011-10-24 17:36:10 +1100 | [diff] [blame] | 571 | if (match == all_entries_not_interesting) |
Nguyễn Thái Ngọc Duy | 97d0b74 | 2011-03-25 16:34:20 +0700 | [diff] [blame] | 572 | break; |
Nguyễn Thái Ngọc Duy | d688cf0 | 2011-10-24 17:36:10 +1100 | [diff] [blame] | 573 | if (match == entry_not_interesting) |
Nguyễn Thái Ngọc Duy | 1376e50 | 2010-12-17 19:45:33 +0700 | [diff] [blame] | 574 | continue; |
| 575 | } |
| 576 | |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 577 | strbuf_add(base, entry.path, te_len); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 578 | |
Nguyễn Thái Ngọc Duy | 1376e50 | 2010-12-17 19:45:33 +0700 | [diff] [blame] | 579 | if (S_ISREG(entry.mode)) { |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 580 | hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len); |
| 581 | } |
Linus Torvalds | 4c068a9 | 2006-05-30 09:45:45 -0700 | [diff] [blame] | 582 | else if (S_ISDIR(entry.mode)) { |
Nicolas Pitre | 21666f1 | 2007-02-26 14:55:59 -0500 | [diff] [blame] | 583 | enum object_type type; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 584 | struct tree_desc sub; |
| 585 | void *data; |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 586 | unsigned long size; |
| 587 | |
Junio C Hamano | 5f02d31 | 2010-02-15 18:34:28 -0800 | [diff] [blame] | 588 | data = lock_and_read_sha1_file(entry.sha1, &type, &size); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 589 | if (!data) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 590 | die(_("unable to read tree (%s)"), |
Linus Torvalds | 4c068a9 | 2006-05-30 09:45:45 -0700 | [diff] [blame] | 591 | sha1_to_hex(entry.sha1)); |
Nguyễn Thái Ngọc Duy | 1376e50 | 2010-12-17 19:45:33 +0700 | [diff] [blame] | 592 | |
| 593 | strbuf_addch(base, '/'); |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 594 | init_tree_desc(&sub, data, size); |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 595 | hit |= grep_tree(opt, pathspec, &sub, base, tn_len); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 596 | free(data); |
| 597 | } |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 598 | strbuf_setlen(base, old_baselen); |
| 599 | |
Junio C Hamano | c8610a2 | 2010-01-25 15:37:23 -0800 | [diff] [blame] | 600 | if (hit && opt->status_only) |
| 601 | break; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 602 | } |
| 603 | return hit; |
| 604 | } |
| 605 | |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 606 | static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 607 | struct object *obj, const char *name) |
| 608 | { |
Linus Torvalds | 1974632 | 2006-07-11 20:45:31 -0700 | [diff] [blame] | 609 | if (obj->type == OBJ_BLOB) |
Junio C Hamano | 0d042fe | 2006-08-11 00:44:42 -0700 | [diff] [blame] | 610 | return grep_sha1(opt, obj->sha1, name, 0); |
Linus Torvalds | 1974632 | 2006-07-11 20:45:31 -0700 | [diff] [blame] | 611 | if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) { |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 612 | struct tree_desc tree; |
| 613 | void *data; |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 614 | unsigned long size; |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 615 | struct strbuf base; |
| 616 | int hit, len; |
| 617 | |
Nicolas Morey-Chaisemartin | 8cb5775 | 2011-08-30 15:45:38 +0200 | [diff] [blame] | 618 | read_sha1_lock(); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 619 | data = read_object_with_reference(obj->sha1, tree_type, |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 620 | &size, NULL); |
Nicolas Morey-Chaisemartin | 8cb5775 | 2011-08-30 15:45:38 +0200 | [diff] [blame] | 621 | read_sha1_unlock(); |
| 622 | |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 623 | if (!data) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 624 | die(_("unable to read tree (%s)"), sha1_to_hex(obj->sha1)); |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 625 | |
| 626 | len = name ? strlen(name) : 0; |
| 627 | strbuf_init(&base, PATH_MAX + len + 1); |
| 628 | if (len) { |
| 629 | strbuf_add(&base, name, len); |
| 630 | strbuf_addch(&base, ':'); |
| 631 | } |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 632 | init_tree_desc(&tree, data, size); |
Nguyễn Thái Ngọc Duy | e5e062b | 2010-12-17 19:44:25 +0700 | [diff] [blame] | 633 | hit = grep_tree(opt, pathspec, &tree, &base, base.len); |
| 634 | strbuf_release(&base); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 635 | free(data); |
| 636 | return hit; |
| 637 | } |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 638 | die(_("unable to grep from object of type %s"), typename(obj->type)); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 639 | } |
| 640 | |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 641 | static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, |
Jonathan Nieder | 30d00c3 | 2010-06-12 11:31:18 -0500 | [diff] [blame] | 642 | const struct object_array *list) |
| 643 | { |
| 644 | unsigned int i; |
| 645 | int hit = 0; |
| 646 | const unsigned int nr = list->nr; |
| 647 | |
| 648 | for (i = 0; i < nr; i++) { |
| 649 | struct object *real_obj; |
| 650 | real_obj = deref_tag(list->objects[i].item, NULL, 0); |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 651 | if (grep_object(opt, pathspec, real_obj, list->objects[i].name)) { |
Jonathan Nieder | 30d00c3 | 2010-06-12 11:31:18 -0500 | [diff] [blame] | 652 | hit = 1; |
| 653 | if (opt->status_only) |
| 654 | break; |
| 655 | } |
| 656 | } |
| 657 | return hit; |
| 658 | } |
| 659 | |
Junio C Hamano | dbfae86 | 2011-10-04 18:40:41 -0700 | [diff] [blame] | 660 | static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec, |
| 661 | int exc_std) |
Junio C Hamano | 59332d1 | 2010-02-06 10:40:08 -0800 | [diff] [blame] | 662 | { |
| 663 | struct dir_struct dir; |
| 664 | int i, hit = 0; |
| 665 | |
| 666 | memset(&dir, 0, sizeof(dir)); |
Junio C Hamano | 0a93fb8 | 2011-09-27 13:43:12 -0700 | [diff] [blame] | 667 | if (exc_std) |
| 668 | setup_standard_excludes(&dir); |
Junio C Hamano | 59332d1 | 2010-02-06 10:40:08 -0800 | [diff] [blame] | 669 | |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 670 | fill_directory(&dir, pathspec->raw); |
Junio C Hamano | 59332d1 | 2010-02-06 10:40:08 -0800 | [diff] [blame] | 671 | for (i = 0; i < dir.nr; i++) { |
Junio C Hamano | 9d8b831 | 2011-02-16 14:39:00 -0800 | [diff] [blame] | 672 | const char *name = dir.entries[i]->name; |
| 673 | int namelen = strlen(name); |
| 674 | if (!match_pathspec_depth(pathspec, name, namelen, 0, NULL)) |
| 675 | continue; |
Junio C Hamano | 59332d1 | 2010-02-06 10:40:08 -0800 | [diff] [blame] | 676 | hit |= grep_file(opt, dir.entries[i]->name); |
| 677 | if (hit && opt->status_only) |
| 678 | break; |
| 679 | } |
Junio C Hamano | 59332d1 | 2010-02-06 10:40:08 -0800 | [diff] [blame] | 680 | return hit; |
| 681 | } |
| 682 | |
René Scharfe | ff3c7f9 | 2009-05-21 00:05:22 +0200 | [diff] [blame] | 683 | static int context_callback(const struct option *opt, const char *arg, |
| 684 | int unset) |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 685 | { |
| 686 | struct grep_opt *grep_opt = opt->value; |
| 687 | int value; |
| 688 | const char *endp; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 689 | |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 690 | if (unset) { |
| 691 | grep_opt->pre_context = grep_opt->post_context = 0; |
| 692 | return 0; |
| 693 | } |
| 694 | value = strtol(arg, (char **)&endp, 10); |
| 695 | if (*endp) { |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 696 | return error(_("switch `%c' expects a numerical value"), |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 697 | opt->short_name); |
| 698 | } |
| 699 | grep_opt->pre_context = grep_opt->post_context = value; |
| 700 | return 0; |
| 701 | } |
| 702 | |
René Scharfe | ff3c7f9 | 2009-05-21 00:05:22 +0200 | [diff] [blame] | 703 | static int file_callback(const struct option *opt, const char *arg, int unset) |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 704 | { |
| 705 | struct grep_opt *grep_opt = opt->value; |
René Scharfe | c41dd2f | 2011-03-19 19:33:15 +0100 | [diff] [blame] | 706 | int from_stdin = !strcmp(arg, "-"); |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 707 | FILE *patterns; |
| 708 | int lno = 0; |
Matt Kraai | cfe370c | 2009-10-16 07:13:25 -0700 | [diff] [blame] | 709 | struct strbuf sb = STRBUF_INIT; |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 710 | |
René Scharfe | c41dd2f | 2011-03-19 19:33:15 +0100 | [diff] [blame] | 711 | patterns = from_stdin ? stdin : fopen(arg, "r"); |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 712 | if (!patterns) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 713 | die_errno(_("cannot open '%s'"), arg); |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 714 | while (strbuf_getline(&sb, patterns, '\n') == 0) { |
René Scharfe | ed40a09 | 2010-05-22 23:43:43 +0200 | [diff] [blame] | 715 | char *s; |
| 716 | size_t len; |
| 717 | |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 718 | /* ignore empty line like grep does */ |
| 719 | if (sb.len == 0) |
| 720 | continue; |
René Scharfe | ed40a09 | 2010-05-22 23:43:43 +0200 | [diff] [blame] | 721 | |
| 722 | s = strbuf_detach(&sb, &len); |
| 723 | append_grep_pat(grep_opt, s, len, arg, ++lno, GREP_PATTERN); |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 724 | } |
René Scharfe | c41dd2f | 2011-03-19 19:33:15 +0100 | [diff] [blame] | 725 | if (!from_stdin) |
| 726 | fclose(patterns); |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 727 | strbuf_release(&sb); |
| 728 | return 0; |
| 729 | } |
| 730 | |
René Scharfe | ff3c7f9 | 2009-05-21 00:05:22 +0200 | [diff] [blame] | 731 | static int not_callback(const struct option *opt, const char *arg, int unset) |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 732 | { |
| 733 | struct grep_opt *grep_opt = opt->value; |
| 734 | append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT); |
| 735 | return 0; |
| 736 | } |
| 737 | |
René Scharfe | ff3c7f9 | 2009-05-21 00:05:22 +0200 | [diff] [blame] | 738 | static int and_callback(const struct option *opt, const char *arg, int unset) |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 739 | { |
| 740 | struct grep_opt *grep_opt = opt->value; |
| 741 | append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND); |
| 742 | return 0; |
| 743 | } |
| 744 | |
René Scharfe | ff3c7f9 | 2009-05-21 00:05:22 +0200 | [diff] [blame] | 745 | static int open_callback(const struct option *opt, const char *arg, int unset) |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 746 | { |
| 747 | struct grep_opt *grep_opt = opt->value; |
| 748 | append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN); |
| 749 | return 0; |
| 750 | } |
| 751 | |
René Scharfe | ff3c7f9 | 2009-05-21 00:05:22 +0200 | [diff] [blame] | 752 | static int close_callback(const struct option *opt, const char *arg, int unset) |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 753 | { |
| 754 | struct grep_opt *grep_opt = opt->value; |
| 755 | append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN); |
| 756 | return 0; |
| 757 | } |
| 758 | |
René Scharfe | ff3c7f9 | 2009-05-21 00:05:22 +0200 | [diff] [blame] | 759 | static int pattern_callback(const struct option *opt, const char *arg, |
| 760 | int unset) |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 761 | { |
| 762 | struct grep_opt *grep_opt = opt->value; |
| 763 | append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN); |
| 764 | return 0; |
| 765 | } |
| 766 | |
René Scharfe | ff3c7f9 | 2009-05-21 00:05:22 +0200 | [diff] [blame] | 767 | static int help_callback(const struct option *opt, const char *arg, int unset) |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 768 | { |
| 769 | return -1; |
| 770 | } |
Junio C Hamano | 088b084 | 2006-07-04 02:44:48 -0700 | [diff] [blame] | 771 | |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 772 | int cmd_grep(int argc, const char **argv, const char *prefix) |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 773 | { |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 774 | int hit = 0; |
Junio C Hamano | 0a93fb8 | 2011-09-27 13:43:12 -0700 | [diff] [blame] | 775 | int cached = 0, untracked = 0, opt_exclude = -1; |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 776 | int seen_dashdash = 0; |
Junio C Hamano | bbc09c2 | 2010-01-12 19:06:41 -0800 | [diff] [blame] | 777 | int external_grep_allowed__ignored; |
Johannes Schindelin | 0af88c1 | 2010-06-12 11:39:46 -0500 | [diff] [blame] | 778 | const char *show_in_pager = NULL, *default_pager = "dummy"; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 779 | struct grep_opt opt; |
Thiago Farina | 3cd4745 | 2010-08-28 23:04:17 -0300 | [diff] [blame] | 780 | struct object_array list = OBJECT_ARRAY_INIT; |
Junio C Hamano | 1362671 | 2006-05-01 15:58:29 -0700 | [diff] [blame] | 781 | const char **paths = NULL; |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 782 | struct pathspec pathspec; |
Thiago Farina | 183113a | 2010-07-04 16:46:19 -0300 | [diff] [blame] | 783 | struct string_list path_list = STRING_LIST_INIT_NODUP; |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 784 | int i; |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 785 | int dummy; |
Nguyễn Thái Ngọc Duy | ff38d1a | 2010-08-05 22:06:39 -0500 | [diff] [blame] | 786 | int use_index = 1; |
Junio C Hamano | cca2c17 | 2011-05-09 18:48:36 -0700 | [diff] [blame] | 787 | enum { |
| 788 | pattern_type_unspecified = 0, |
| 789 | pattern_type_bre, |
| 790 | pattern_type_ere, |
| 791 | pattern_type_fixed, |
| 792 | pattern_type_pcre, |
| 793 | }; |
| 794 | int pattern_type = pattern_type_unspecified; |
| 795 | |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 796 | struct option options[] = { |
| 797 | OPT_BOOLEAN(0, "cached", &cached, |
| 798 | "search in index instead of in the work tree"), |
Bert Wesarg | ac1d33d | 2011-09-15 20:26:02 +0200 | [diff] [blame] | 799 | { OPTION_BOOLEAN, 0, "index", &use_index, NULL, |
| 800 | "finds in contents not managed by git", |
| 801 | PARSE_OPT_NOARG | PARSE_OPT_NEGHELP }, |
Junio C Hamano | 0a93fb8 | 2011-09-27 13:43:12 -0700 | [diff] [blame] | 802 | OPT_BOOLEAN(0, "untracked", &untracked, |
| 803 | "search in both tracked and untracked files"), |
| 804 | OPT_SET_INT(0, "exclude-standard", &opt_exclude, |
| 805 | "search also in ignored files", 1), |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 806 | OPT_GROUP(""), |
| 807 | OPT_BOOLEAN('v', "invert-match", &opt.invert, |
| 808 | "show non-matching lines"), |
Brian Collins | 5183bf6 | 2009-11-06 01:22:35 -0800 | [diff] [blame] | 809 | OPT_BOOLEAN('i', "ignore-case", &opt.ignore_case, |
| 810 | "case insensitive matching"), |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 811 | OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp, |
| 812 | "match patterns only at word boundaries"), |
| 813 | OPT_SET_INT('a', "text", &opt.binary, |
| 814 | "process binary files as text", GREP_BINARY_TEXT), |
| 815 | OPT_SET_INT('I', NULL, &opt.binary, |
| 816 | "don't match patterns in binary files", |
| 817 | GREP_BINARY_NOMATCH), |
Michał Kiedrowicz | a91f453 | 2009-07-22 19:52:15 +0200 | [diff] [blame] | 818 | { OPTION_INTEGER, 0, "max-depth", &opt.max_depth, "depth", |
| 819 | "descend at most <depth> levels", PARSE_OPT_NONEG, |
| 820 | NULL, 1 }, |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 821 | OPT_GROUP(""), |
Junio C Hamano | cca2c17 | 2011-05-09 18:48:36 -0700 | [diff] [blame] | 822 | OPT_SET_INT('E', "extended-regexp", &pattern_type, |
| 823 | "use extended POSIX regular expressions", |
| 824 | pattern_type_ere), |
| 825 | OPT_SET_INT('G', "basic-regexp", &pattern_type, |
| 826 | "use basic POSIX regular expressions (default)", |
| 827 | pattern_type_bre), |
| 828 | OPT_SET_INT('F', "fixed-strings", &pattern_type, |
| 829 | "interpret patterns as fixed strings", |
| 830 | pattern_type_fixed), |
| 831 | OPT_SET_INT('P', "perl-regexp", &pattern_type, |
| 832 | "use Perl-compatible regular expressions", |
| 833 | pattern_type_pcre), |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 834 | OPT_GROUP(""), |
Joe Ratterman | 7d6cb10 | 2011-03-28 13:11:55 -0500 | [diff] [blame] | 835 | OPT_BOOLEAN('n', "line-number", &opt.linenum, "show line numbers"), |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 836 | OPT_NEGBIT('h', NULL, &opt.pathname, "don't show filenames", 1), |
| 837 | OPT_BIT('H', NULL, &opt.pathname, "show filenames", 1), |
| 838 | OPT_NEGBIT(0, "full-name", &opt.relative, |
| 839 | "show filenames relative to top directory", 1), |
| 840 | OPT_BOOLEAN('l', "files-with-matches", &opt.name_only, |
| 841 | "show only filenames instead of matching lines"), |
| 842 | OPT_BOOLEAN(0, "name-only", &opt.name_only, |
| 843 | "synonym for --files-with-matches"), |
| 844 | OPT_BOOLEAN('L', "files-without-match", |
| 845 | &opt.unmatch_name_only, |
| 846 | "show only the names of files without match"), |
| 847 | OPT_BOOLEAN('z', "null", &opt.null_following_name, |
| 848 | "print NUL after filenames"), |
| 849 | OPT_BOOLEAN('c', "count", &opt.count, |
| 850 | "show the number of matches instead of matching lines"), |
Mark Lodato | 73e9da0 | 2010-02-16 23:55:58 -0500 | [diff] [blame] | 851 | OPT__COLOR(&opt.color, "highlight matches"), |
René Scharfe | a8f0e76 | 2011-06-05 17:24:25 +0200 | [diff] [blame] | 852 | OPT_BOOLEAN(0, "break", &opt.file_break, |
| 853 | "print empty line between matches from different files"), |
René Scharfe | 1d84f72 | 2011-06-05 17:24:36 +0200 | [diff] [blame] | 854 | OPT_BOOLEAN(0, "heading", &opt.heading, |
| 855 | "show filename only once above matches from same file"), |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 856 | OPT_GROUP(""), |
René Scharfe | 317f63c | 2011-08-01 19:22:52 +0200 | [diff] [blame] | 857 | OPT_CALLBACK('C', "context", &opt, "n", |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 858 | "show <n> context lines before and after matches", |
| 859 | context_callback), |
René Scharfe | 317f63c | 2011-08-01 19:22:52 +0200 | [diff] [blame] | 860 | OPT_INTEGER('B', "before-context", &opt.pre_context, |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 861 | "show <n> context lines before matches"), |
René Scharfe | 317f63c | 2011-08-01 19:22:52 +0200 | [diff] [blame] | 862 | OPT_INTEGER('A', "after-context", &opt.post_context, |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 863 | "show <n> context lines after matches"), |
| 864 | OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM", |
| 865 | context_callback), |
René Scharfe | 2944e4e | 2009-07-02 00:06:34 +0200 | [diff] [blame] | 866 | OPT_BOOLEAN('p', "show-function", &opt.funcname, |
| 867 | "show a line with the function name before matches"), |
René Scharfe | 317f63c | 2011-08-01 19:22:52 +0200 | [diff] [blame] | 868 | OPT_BOOLEAN('W', "function-context", &opt.funcbody, |
René Scharfe | ba8ea74 | 2011-08-01 19:20:53 +0200 | [diff] [blame] | 869 | "show the surrounding function"), |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 870 | OPT_GROUP(""), |
| 871 | OPT_CALLBACK('f', NULL, &opt, "file", |
| 872 | "read patterns from file", file_callback), |
| 873 | { OPTION_CALLBACK, 'e', NULL, &opt, "pattern", |
| 874 | "match <pattern>", PARSE_OPT_NONEG, pattern_callback }, |
| 875 | { OPTION_CALLBACK, 0, "and", &opt, NULL, |
| 876 | "combine patterns specified with -e", |
| 877 | PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback }, |
| 878 | OPT_BOOLEAN(0, "or", &dummy, ""), |
| 879 | { OPTION_CALLBACK, 0, "not", &opt, NULL, "", |
| 880 | PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback }, |
| 881 | { OPTION_CALLBACK, '(', NULL, &opt, NULL, "", |
| 882 | PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH, |
| 883 | open_callback }, |
| 884 | { OPTION_CALLBACK, ')', NULL, &opt, NULL, "", |
| 885 | PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH, |
| 886 | close_callback }, |
René Scharfe | d52ee6e | 2010-11-08 19:06:54 +0100 | [diff] [blame] | 887 | OPT__QUIET(&opt.status_only, |
| 888 | "indicate hit with exit status without output"), |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 889 | OPT_BOOLEAN(0, "all-match", &opt.all_match, |
| 890 | "show only matches from files that match all patterns"), |
| 891 | OPT_GROUP(""), |
Johannes Schindelin | 0af88c1 | 2010-06-12 11:39:46 -0500 | [diff] [blame] | 892 | { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager, |
| 893 | "pager", "show matching files in the pager", |
| 894 | PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager }, |
Junio C Hamano | bbc09c2 | 2010-01-12 19:06:41 -0800 | [diff] [blame] | 895 | OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed__ignored, |
| 896 | "allow calling of grep(1) (ignored by this build)"), |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 897 | { OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage", |
| 898 | PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback }, |
| 899 | OPT_END() |
| 900 | }; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 901 | |
Jonathan Nieder | 9c855c3 | 2009-11-09 09:04:42 -0600 | [diff] [blame] | 902 | /* |
| 903 | * 'git grep -h', unlike 'git grep -h <pattern>', is a request |
| 904 | * to show usage information and exit. |
| 905 | */ |
| 906 | if (argc == 2 && !strcmp(argv[1], "-h")) |
| 907 | usage_with_options(grep_usage, options); |
| 908 | |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 909 | memset(&opt, 0, sizeof(opt)); |
Clemens Buchacher | 493b7a0 | 2009-09-05 14:31:17 +0200 | [diff] [blame] | 910 | opt.prefix = prefix; |
Junio C Hamano | 0d042fe | 2006-08-11 00:44:42 -0700 | [diff] [blame] | 911 | opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0; |
| 912 | opt.relative = 1; |
Linus Torvalds | 7977f0e | 2006-09-14 10:45:12 -0700 | [diff] [blame] | 913 | opt.pathname = 1; |
Junio C Hamano | f9b9faf | 2006-05-02 15:40:49 -0700 | [diff] [blame] | 914 | opt.pattern_tail = &opt.pattern_list; |
Junio C Hamano | 80235ba | 2010-01-17 20:09:06 -0800 | [diff] [blame] | 915 | opt.header_tail = &opt.header_list; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 916 | opt.regflags = REG_NEWLINE; |
Michał Kiedrowicz | a91f453 | 2009-07-22 19:52:15 +0200 | [diff] [blame] | 917 | opt.max_depth = -1; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 918 | |
Mark Lodato | 00588bb | 2010-03-07 11:52:47 -0500 | [diff] [blame] | 919 | strcpy(opt.color_context, ""); |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 920 | strcpy(opt.color_filename, ""); |
Mark Lodato | 00588bb | 2010-03-07 11:52:47 -0500 | [diff] [blame] | 921 | strcpy(opt.color_function, ""); |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 922 | strcpy(opt.color_lineno, ""); |
Mark Lodato | 758df17 | 2010-03-07 11:52:45 -0500 | [diff] [blame] | 923 | strcpy(opt.color_match, GIT_COLOR_BOLD_RED); |
Mark Lodato | 00588bb | 2010-03-07 11:52:47 -0500 | [diff] [blame] | 924 | strcpy(opt.color_selected, ""); |
Mark Lodato | 55f638b | 2010-03-07 11:52:46 -0500 | [diff] [blame] | 925 | strcpy(opt.color_sep, GIT_COLOR_CYAN); |
René Scharfe | 7e8f59d | 2009-03-07 13:32:32 +0100 | [diff] [blame] | 926 | opt.color = -1; |
| 927 | git_config(grep_config, &opt); |
René Scharfe | 7e8f59d | 2009-03-07 13:32:32 +0100 | [diff] [blame] | 928 | |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 929 | /* |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 930 | * If there is no -- then the paths must exist in the working |
| 931 | * tree. If there is no explicit pattern specified with -e or |
| 932 | * -f, we take the first unrecognized non option to be the |
| 933 | * pattern, but then what follows it must be zero or more |
| 934 | * valid refs up to the -- (if exists), and then existing |
| 935 | * paths. If there is an explicit pattern, then the first |
Pavel Roskin | 82e5a82 | 2006-07-10 01:50:18 -0400 | [diff] [blame] | 936 | * unrecognized non option is the beginning of the refs list |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 937 | * that continues up to the -- (if exists), and then paths. |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 938 | */ |
Stephen Boyd | 3778292 | 2009-05-23 11:53:12 -0700 | [diff] [blame] | 939 | argc = parse_options(argc, argv, prefix, options, grep_usage, |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 940 | PARSE_OPT_KEEP_DASHDASH | |
| 941 | PARSE_OPT_STOP_AT_NON_OPTION | |
| 942 | PARSE_OPT_NO_INTERNAL_HELP); |
Junio C Hamano | cca2c17 | 2011-05-09 18:48:36 -0700 | [diff] [blame] | 943 | switch (pattern_type) { |
| 944 | case pattern_type_fixed: |
| 945 | opt.fixed = 1; |
| 946 | opt.pcre = 0; |
| 947 | break; |
| 948 | case pattern_type_bre: |
| 949 | opt.fixed = 0; |
| 950 | opt.pcre = 0; |
| 951 | opt.regflags &= ~REG_EXTENDED; |
| 952 | break; |
| 953 | case pattern_type_ere: |
| 954 | opt.fixed = 0; |
| 955 | opt.pcre = 0; |
| 956 | opt.regflags |= REG_EXTENDED; |
| 957 | break; |
| 958 | case pattern_type_pcre: |
| 959 | opt.fixed = 0; |
| 960 | opt.pcre = 1; |
| 961 | break; |
| 962 | default: |
| 963 | break; /* nothing */ |
| 964 | } |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 965 | |
Nguyễn Thái Ngọc Duy | ff38d1a | 2010-08-05 22:06:39 -0500 | [diff] [blame] | 966 | if (use_index && !startup_info->have_repository) |
Junio C Hamano | 59332d1 | 2010-02-06 10:40:08 -0800 | [diff] [blame] | 967 | /* die the same way as if we did it at the beginning */ |
| 968 | setup_git_directory(); |
| 969 | |
Jeff King | 1123c67 | 2010-02-06 23:44:15 -0500 | [diff] [blame] | 970 | /* |
| 971 | * skip a -- separator; we know it cannot be |
| 972 | * separating revisions from pathnames if |
| 973 | * we haven't even had any patterns yet |
| 974 | */ |
| 975 | if (argc > 0 && !opt.pattern_list && !strcmp(argv[0], "--")) { |
| 976 | argv++; |
| 977 | argc--; |
| 978 | } |
| 979 | |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 980 | /* First unrecognized non-option token */ |
| 981 | if (argc > 0 && !opt.pattern_list) { |
| 982 | append_grep_pattern(&opt, argv[0], "command line", 0, |
| 983 | GREP_PATTERN); |
| 984 | argv++; |
| 985 | argc--; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 986 | } |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 987 | |
Johannes Schindelin | 0af88c1 | 2010-06-12 11:39:46 -0500 | [diff] [blame] | 988 | if (show_in_pager == default_pager) |
| 989 | show_in_pager = git_pager(1); |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 990 | if (show_in_pager) { |
Nazri Ramliy | e7b082a | 2010-07-02 21:55:06 -0500 | [diff] [blame] | 991 | opt.color = 0; |
Johannes Schindelin | 0af88c1 | 2010-06-12 11:39:46 -0500 | [diff] [blame] | 992 | opt.name_only = 1; |
| 993 | opt.null_following_name = 1; |
| 994 | opt.output_priv = &path_list; |
| 995 | opt.output = append_path; |
Julian Phillips | 0c72cea | 2010-06-26 00:41:39 +0100 | [diff] [blame] | 996 | string_list_append(&path_list, show_in_pager); |
Johannes Schindelin | 0af88c1 | 2010-06-12 11:39:46 -0500 | [diff] [blame] | 997 | use_threads = 0; |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 998 | } |
| 999 | |
Junio C Hamano | f9b9faf | 2006-05-02 15:40:49 -0700 | [diff] [blame] | 1000 | if (!opt.pattern_list) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 1001 | die(_("no pattern given.")); |
Brian Collins | 5183bf6 | 2009-11-06 01:22:35 -0800 | [diff] [blame] | 1002 | if (!opt.fixed && opt.ignore_case) |
| 1003 | opt.regflags |= REG_ICASE; |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 1004 | |
Junio C Hamano | 83b5d2f | 2006-09-17 16:02:52 -0700 | [diff] [blame] | 1005 | compile_grep_patterns(&opt); |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 1006 | |
| 1007 | /* Check revs and then paths */ |
René Scharfe | 3e230fa | 2009-05-07 21:46:48 +0200 | [diff] [blame] | 1008 | for (i = 0; i < argc; i++) { |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 1009 | const char *arg = argv[i]; |
Junio C Hamano | 1362671 | 2006-05-01 15:58:29 -0700 | [diff] [blame] | 1010 | unsigned char sha1[20]; |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 1011 | /* Is it a rev? */ |
| 1012 | if (!get_sha1(arg, sha1)) { |
| 1013 | struct object *object = parse_object(sha1); |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 1014 | if (!object) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 1015 | die(_("bad object %s"), arg); |
Linus Torvalds | 1f1e895 | 2006-06-19 17:42:35 -0700 | [diff] [blame] | 1016 | add_object_array(object, arg, &list); |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 1017 | continue; |
| 1018 | } |
| 1019 | if (!strcmp(arg, "--")) { |
| 1020 | i++; |
| 1021 | seen_dashdash = 1; |
| 1022 | } |
| 1023 | break; |
Junio C Hamano | 1362671 | 2006-05-01 15:58:29 -0700 | [diff] [blame] | 1024 | } |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 1025 | |
Thomas Rast | 53b8d93 | 2011-12-12 22:16:08 +0100 | [diff] [blame^] | 1026 | #ifndef NO_PTHREADS |
| 1027 | if (list.nr || cached || online_cpus() == 1) |
| 1028 | use_threads = 0; |
| 1029 | #else |
| 1030 | use_threads = 0; |
| 1031 | #endif |
| 1032 | |
| 1033 | opt.use_threads = use_threads; |
| 1034 | |
| 1035 | #ifndef NO_PTHREADS |
| 1036 | if (use_threads) { |
| 1037 | if (opt.pre_context || opt.post_context || opt.file_break || |
| 1038 | opt.funcbody) |
| 1039 | skip_first_line = 1; |
| 1040 | start_threads(&opt); |
| 1041 | } |
| 1042 | #endif |
| 1043 | |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 1044 | /* The rest are paths */ |
| 1045 | if (!seen_dashdash) { |
| 1046 | int j; |
Junio C Hamano | c39c4f4 | 2006-05-09 18:15:21 -0700 | [diff] [blame] | 1047 | for (j = i; j < argc; j++) |
Junio C Hamano | 5acd64e | 2006-05-08 23:55:47 -0700 | [diff] [blame] | 1048 | verify_filename(prefix, argv[j]); |
| 1049 | } |
| 1050 | |
Junio C Hamano | 7c5f3cc | 2011-05-09 21:34:04 -0700 | [diff] [blame] | 1051 | paths = get_pathspec(prefix, argv + i); |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 1052 | init_pathspec(&pathspec, paths); |
Nguyễn Thái Ngọc Duy | 1376e50 | 2010-12-17 19:45:33 +0700 | [diff] [blame] | 1053 | pathspec.max_depth = opt.max_depth; |
| 1054 | pathspec.recursive = 1; |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 1055 | |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 1056 | if (show_in_pager && (cached || list.nr)) |
Ævar Arnfjörð Bjarmason | e4fe4ba | 2011-02-22 23:41:56 +0000 | [diff] [blame] | 1057 | die(_("--open-files-in-pager only works on the worktree")); |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 1058 | |
| 1059 | if (show_in_pager && opt.pattern_list && !opt.pattern_list->next) { |
| 1060 | const char *pager = path_list.items[0].string; |
| 1061 | int len = strlen(pager); |
| 1062 | |
| 1063 | if (len > 4 && is_dir_sep(pager[len - 5])) |
| 1064 | pager += len - 4; |
| 1065 | |
| 1066 | if (!strcmp("less", pager) || !strcmp("vi", pager)) { |
| 1067 | struct strbuf buf = STRBUF_INIT; |
| 1068 | strbuf_addf(&buf, "+/%s%s", |
| 1069 | strcmp("less", pager) ? "" : "*", |
| 1070 | opt.pattern_list->pattern); |
Julian Phillips | 0c72cea | 2010-06-26 00:41:39 +0100 | [diff] [blame] | 1071 | string_list_append(&path_list, buf.buf); |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 1072 | strbuf_detach(&buf, NULL); |
| 1073 | } |
| 1074 | } |
| 1075 | |
| 1076 | if (!show_in_pager) |
| 1077 | setup_pager(); |
| 1078 | |
Junio C Hamano | 0a93fb8 | 2011-09-27 13:43:12 -0700 | [diff] [blame] | 1079 | if (!use_index && (untracked || cached)) |
Junio C Hamano | dbfae86 | 2011-10-04 18:40:41 -0700 | [diff] [blame] | 1080 | die(_("--cached or --untracked cannot be used with --no-index.")); |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 1081 | |
Junio C Hamano | 0a93fb8 | 2011-09-27 13:43:12 -0700 | [diff] [blame] | 1082 | if (!use_index || untracked) { |
Junio C Hamano | 0a93fb8 | 2011-09-27 13:43:12 -0700 | [diff] [blame] | 1083 | int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude; |
Junio C Hamano | 59332d1 | 2010-02-06 10:40:08 -0800 | [diff] [blame] | 1084 | if (list.nr) |
Junio C Hamano | dbfae86 | 2011-10-04 18:40:41 -0700 | [diff] [blame] | 1085 | die(_("--no-index or --untracked cannot be used with revs.")); |
| 1086 | hit = grep_directory(&opt, &pathspec, use_exclude); |
| 1087 | } else if (0 <= opt_exclude) { |
Junio C Hamano | 9fddaf7 | 2011-10-15 20:26:52 -0700 | [diff] [blame] | 1088 | die(_("--[no-]exclude-standard cannot be used for tracked contents.")); |
Johannes Schindelin | 685359c | 2010-06-12 11:32:11 -0500 | [diff] [blame] | 1089 | } else if (!list.nr) { |
Nguyễn Thái Ngọc Duy | 6577f54 | 2008-08-28 20:04:30 +0700 | [diff] [blame] | 1090 | if (!cached) |
| 1091 | setup_work_tree(); |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 1092 | |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 1093 | hit = grep_cache(&opt, &pathspec, cached); |
Johannes Schindelin | 685359c | 2010-06-12 11:32:11 -0500 | [diff] [blame] | 1094 | } else { |
| 1095 | if (cached) |
Ævar Arnfjörð Bjarmason | 2fc5f9f | 2011-02-22 23:41:55 +0000 | [diff] [blame] | 1096 | die(_("both --cached and trees are given.")); |
Nguyễn Thái Ngọc Duy | f34bbc1 | 2010-12-15 22:02:51 +0700 | [diff] [blame] | 1097 | hit = grep_objects(&opt, &pathspec, &list); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 1098 | } |
Fredrik Kuivinen | 5b594f4 | 2010-01-25 23:51:39 +0100 | [diff] [blame] | 1099 | |
| 1100 | if (use_threads) |
| 1101 | hit |= wait_all(); |
Johannes Schindelin | 678e484 | 2010-06-12 11:36:51 -0500 | [diff] [blame] | 1102 | if (hit && show_in_pager) |
| 1103 | run_pager(&opt, prefix); |
Junio C Hamano | b48fb5b | 2006-09-27 16:27:10 -0700 | [diff] [blame] | 1104 | free_grep_patterns(&opt); |
Junio C Hamano | 5010cb5 | 2006-04-30 23:28:15 -0700 | [diff] [blame] | 1105 | return !hit; |
| 1106 | } |