Merge branch 'sb/grep-die-on-unreadable-index'
authorJunio C Hamano <gitster@pobox.com>
Wed, 30 May 2018 12:51:26 +0000 (21:51 +0900)
committerJunio C Hamano <gitster@pobox.com>
Wed, 30 May 2018 12:51:26 +0000 (21:51 +0900)
Error behaviour of "git grep" when it cannot read the index was
inconsistent with other commands that uses the index, which has
been corrected to error out early.

* sb/grep-die-on-unreadable-index:
grep: handle corrupt index files early

1  2 
builtin/grep.c
diff --combined builtin/grep.c
index 6e7bc76785ace33f80251edfcc4feac8ad19d7c5,567565b2d2dc5cf9a4d5c971588e6c2c398883a9..69f0743619f3134df44c94912dfd1e1c43f5fdc5
@@@ -22,7 -22,6 +22,7 @@@
  #include "pathspec.h"
  #include "submodule.h"
  #include "submodule-config.h"
 +#include "object-store.h"
  
  static char const * const grep_usage[] = {
        N_("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"),
@@@ -93,7 -92,8 +93,7 @@@ static pthread_cond_t cond_result
  
  static int skip_first_line;
  
 -static void add_work(struct grep_opt *opt, enum grep_source_type type,
 -                   const char *name, const char *path, const void *id)
 +static void add_work(struct grep_opt *opt, const struct grep_source *gs)
  {
        grep_lock();
  
                pthread_cond_wait(&cond_write, &grep_mutex);
        }
  
 -      grep_source_init(&todo[todo_end].source, type, name, path, id);
 +      todo[todo_end].source = *gs;
        if (opt->binary != GREP_BINARY_TEXT)
                grep_source_load_driver(&todo[todo_end].source);
        todo[todo_end].done = 0;
@@@ -307,7 -307,7 +307,7 @@@ static void *lock_and_read_oid_file(con
        void *data;
  
        grep_read_lock();
 -      data = read_sha1_file(oid->hash, type, size);
 +      data = read_object_file(oid, type, size);
        grep_read_unlock();
        return data;
  }
@@@ -317,7 -317,6 +317,7 @@@ static int grep_oid(struct grep_opt *op
                     const char *path)
  {
        struct strbuf pathbuf = STRBUF_INIT;
 +      struct grep_source gs;
  
        if (opt->relative && opt->prefix_length) {
                quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf);
                strbuf_addstr(&pathbuf, filename);
        }
  
 +      grep_source_init(&gs, GREP_SOURCE_OID, pathbuf.buf, path, oid);
 +      strbuf_release(&pathbuf);
 +
  #ifndef NO_PTHREADS
        if (num_threads) {
 -              add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid);
 -              strbuf_release(&pathbuf);
 +              /*
 +               * add_work() copies gs and thus assumes ownership of
 +               * its fields, so do not call grep_source_clear()
 +               */
 +              add_work(opt, &gs);
                return 0;
        } else
  #endif
        {
 -              struct grep_source gs;
                int hit;
  
 -              grep_source_init(&gs, GREP_SOURCE_OID, pathbuf.buf, path, oid);
 -              strbuf_release(&pathbuf);
                hit = grep_source(opt, &gs);
  
                grep_source_clear(&gs);
  static int grep_file(struct grep_opt *opt, const char *filename)
  {
        struct strbuf buf = STRBUF_INIT;
 +      struct grep_source gs;
  
        if (opt->relative && opt->prefix_length)
                quote_path_relative(filename, opt->prefix, &buf);
        else
                strbuf_addstr(&buf, filename);
  
 +      grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename, filename);
 +      strbuf_release(&buf);
 +
  #ifndef NO_PTHREADS
        if (num_threads) {
 -              add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename);
 -              strbuf_release(&buf);
 +              /*
 +               * add_work() copies gs and thus assumes ownership of
 +               * its fields, so do not call grep_source_clear()
 +               */
 +              add_work(opt, &gs);
                return 0;
        } else
  #endif
        {
 -              struct grep_source gs;
                int hit;
  
 -              grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename, filename);
 -              strbuf_release(&buf);
                hit = grep_source(opt, &gs);
  
                grep_source_clear(&gs);
@@@ -440,7 -432,7 +440,7 @@@ static int grep_submodule(struct grep_o
         * object.
         */
        grep_read_lock();
 -      add_to_alternates_memory(submodule.objectdir);
 +      add_to_alternates_memory(submodule.objects->objectdir);
        grep_read_unlock();
  
        if (oid) {
                object = parse_object_or_die(oid, oid_to_hex(oid));
  
                grep_read_lock();
 -              data = read_object_with_reference(object->oid.hash, tree_type,
 +              data = read_object_with_reference(&object->oid, tree_type,
                                                  &size, NULL);
                grep_read_unlock();
  
@@@ -488,7 -480,8 +488,8 @@@ static int grep_cache(struct grep_opt *
                strbuf_addstr(&name, repo->submodule_prefix);
        }
  
-       repo_read_index(repo);
+       if (repo_read_index(repo) < 0)
+               die("index file corrupt");
  
        for (nr = 0; nr < repo->index->cache_nr; nr++) {
                const struct cache_entry *ce = repo->index->cache[nr];
@@@ -602,7 -595,8 +603,7 @@@ static int grep_tree(struct grep_opt *o
  }
  
  static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
 -                     struct object *obj, const char *name, const char *path,
 -                     struct repository *repo)
 +                     struct object *obj, const char *name, const char *path)
  {
        if (obj->type == OBJ_BLOB)
                return grep_oid(opt, &obj->oid, name, 0, path);
                int hit, len;
  
                grep_read_lock();
 -              data = read_object_with_reference(obj->oid.hash, tree_type,
 +              data = read_object_with_reference(&obj->oid, tree_type,
                                                  &size, NULL);
                grep_read_unlock();
  
                }
                init_tree_desc(&tree, data, size);
                hit = grep_tree(opt, pathspec, &tree, &base, base.len,
 -                              obj->type == OBJ_COMMIT, repo);
 +                              obj->type == OBJ_COMMIT, the_repository);
                strbuf_release(&base);
                free(data);
                return hit;
        }
 -      die(_("unable to grep from object of type %s"), typename(obj->type));
 +      die(_("unable to grep from object of type %s"), type_name(obj->type));
  }
  
  static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
 -                      struct repository *repo,
                        const struct object_array *list)
  {
        unsigned int i;
  
                /* load the gitmodules file for this rev */
                if (recurse_submodules) {
 -                      submodule_free();
 +                      submodule_free(the_repository);
                        gitmodules_config_oid(&real_obj->oid);
                }
 -              if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path,
 -                              repo)) {
 +              if (grep_object(opt, pathspec, real_obj, list->objects[i].name,
 +                              list->objects[i].path)) {
                        hit = 1;
                        if (opt->status_only)
                                break;
@@@ -838,9 -833,8 +839,9 @@@ int cmd_grep(int argc, const char **arg
                OPT_BOOL('L', "files-without-match",
                        &opt.unmatch_name_only,
                        N_("show only the names of files without match")),
 -              OPT_BOOL('z', "null", &opt.null_following_name,
 -                      N_("print NUL after filenames")),
 +              OPT_BOOL_F('z', "null", &opt.null_following_name,
 +                         N_("print NUL after filenames"),
 +                         PARSE_OPT_NOCOMPLETE),
                OPT_BOOL('c', "count", &opt.count,
                        N_("show the number of matches instead of matching lines")),
                OPT__COLOR(&opt.color, N_("highlight matches")),
                OPT_GROUP(""),
                { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
                        N_("pager"), N_("show matching files in the pager"),
 -                      PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },
 -              OPT_BOOL(0, "ext-grep", &external_grep_allowed__ignored,
 -                       N_("allow calling of grep(1) (ignored by this build)")),
 +                      PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE,
 +                      NULL, (intptr_t)default_pager },
 +              OPT_BOOL_F(0, "ext-grep", &external_grep_allowed__ignored,
 +                         N_("allow calling of grep(1) (ignored by this build)"),
 +                         PARSE_OPT_NOCOMPLETE),
                OPT_END()
        };
  
                       prefix, argv + i);
        pathspec.max_depth = opt.max_depth;
        pathspec.recursive = 1;
 +      pathspec.recurse_submodules = !!recurse_submodules;
  
  #ifndef NO_PTHREADS
        if (list.nr || cached || show_in_pager)
                if (cached)
                        die(_("both --cached and trees are given."));
  
 -              hit = grep_objects(&opt, &pathspec, the_repository, &list);
 +              hit = grep_objects(&opt, &pathspec, &list);
        }
  
        if (num_threads)