Code

test-lib: unset GIT_NOTES_REF to stop it from influencing tests
[git.git] / builtin-grep.c
index 229555d52d93c5a8eba5e7cd923fd05f0fe3e5f7..da854fa94f5cc159ea93156ba4c87973ee15cae9 100644 (file)
@@ -14,6 +14,7 @@
 #include "userdiff.h"
 #include "grep.h"
 #include "quote.h"
+#include "dir.h"
 
 static char const * const grep_usage[] = {
        "git grep [options] [-e] <pattern> [<rev>...] [[--] path...]",
@@ -181,8 +182,6 @@ static int grep_file(struct grep_opt *opt, const char *filename)
                        error("'%s': %s", filename, strerror(errno));
                return 0;
        }
-       if (!st.st_size)
-               return 0; /* empty file -- no grep hit */
        if (!S_ISREG(st.st_mode))
                return 0;
        sz = xsize_t(st.st_size);
@@ -197,6 +196,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
                return 0;
        }
        close(i);
+       data[sz] = 0;
        if (opt->relative && opt->prefix_length)
                filename = quote_path_relative(filename, -1, &buf, opt->prefix);
        i = grep_buffer(opt, filename, data, sz);
@@ -222,7 +222,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
                 * are identical, even if worktree file has been modified, so use
                 * cache version instead
                 */
-               if (cached || (ce->ce_flags & CE_VALID)) {
+               if (cached || (ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) {
                        if (ce_stage(ce))
                                continue;
                        hit |= grep_sha1(opt, ce->sha1, ce->name, 0);
@@ -320,6 +320,21 @@ static int grep_object(struct grep_opt *opt, const char **paths,
        die("unable to grep from object of type %s", typename(obj->type));
 }
 
+static int grep_directory(struct grep_opt *opt, const char **paths)
+{
+       struct dir_struct dir;
+       int i, hit = 0;
+
+       memset(&dir, 0, sizeof(dir));
+       setup_standard_excludes(&dir);
+
+       fill_directory(&dir, paths);
+       for (i = 0; i < dir.nr; i++)
+               hit |= grep_file(opt, dir.entries[i]->name);
+       free_grep_patterns(opt);
+       return hit;
+}
+
 static int context_callback(const struct option *opt, const char *arg,
                            int unset)
 {
@@ -418,6 +433,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        struct option options[] = {
                OPT_BOOLEAN(0, "cached", &cached,
                        "search in index instead of in the work tree"),
+               OPT_BOOLEAN(0, "index", &use_index,
+                       "--no-index finds in contents not managed by git"),
                OPT_GROUP(""),
                OPT_BOOLEAN('v', "invert-match", &opt.invert,
                        "show non-matching lines"),
@@ -591,6 +608,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                paths[1] = NULL;
        }
 
+       if (!use_index) {
+               if (cached)
+                       die("--cached cannot be used with --no-index.");
+               if (list.nr)
+                       die("--no-index cannot be used with revs.");
+               return !grep_directory(&opt, paths);
+       }
+
        if (!list.nr) {
                if (!cached)
                        setup_work_tree();