Merge branch 'bc/object-id' into bw/submodule-config-cleanup
authorJunio C Hamano <gitster@pobox.com>
Wed, 2 Aug 2017 21:34:28 +0000 (14:34 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 2 Aug 2017 21:34:28 +0000 (14:34 -0700)
* bc/object-id:
sha1_name: convert uses of 40 to GIT_SHA1_HEXSZ
sha1_name: convert GET_SHA1* flags to GET_OID*
sha1_name: convert get_sha1* to get_oid*
Convert remaining callers of get_sha1 to get_oid.
builtin/unpack-file: convert to struct object_id
bisect: convert bisect_checkout to struct object_id
builtin/update_ref: convert to struct object_id
sequencer: convert to struct object_id
remote: convert struct push_cas to struct object_id
submodule: convert submodule config lookup to use object_id
builtin/merge-tree: convert remaining caller of get_sha1 to object_id
builtin/fsck: convert remaining caller of get_sha1 to object_id
tag: convert gpg_verify_tag to use struct object_id
commit: convert lookup_commit_graft to struct object_id

13 files changed:
1  2 
builtin/grep.c
builtin/submodule--helper.c
cache.h
config.c
config.h
refs.c
remote.c
repository.c
revision.c
submodule-config.c
submodule-config.h
submodule.c
submodule.h
diff --combined builtin/grep.c
index cd0e51f3c04b1e6fc297a8806fa663d86ebc7734,9124450163ebf71eec82ee466b155fc2a749d93e..ac06d2d33c19edbe6bd857b7f6b24f0542013c23
@@@ -28,7 -28,13 +28,7 @@@ static char const * const grep_usage[] 
        NULL
  };
  
 -static const char *super_prefix;
  static int recurse_submodules;
 -static struct argv_array submodule_options = ARGV_ARRAY_INIT;
 -static const char *parent_basename;
 -
 -static int grep_submodule_launch(struct grep_opt *opt,
 -                               const struct grep_source *gs);
  
  #define GREP_NUM_THREADS_DEFAULT 8
  static int num_threads;
@@@ -180,7 -186,10 +180,7 @@@ static void *run(void *arg
                        break;
  
                opt->output_priv = w;
 -              if (w->source.type == GREP_SOURCE_SUBMODULE)
 -                      hit |= grep_submodule_launch(opt, &w->source);
 -              else
 -                      hit |= grep_source(opt, &w->source);
 +              hit |= grep_source(opt, &w->source);
                grep_source_clear_data(&w->source);
                work_done(w);
        }
@@@ -318,13 -327,21 +318,13 @@@ static int grep_oid(struct grep_opt *op
  {
        struct strbuf pathbuf = STRBUF_INIT;
  
 -      if (super_prefix) {
 -              strbuf_add(&pathbuf, filename, tree_name_len);
 -              strbuf_addstr(&pathbuf, super_prefix);
 -              strbuf_addstr(&pathbuf, filename + tree_name_len);
 +      if (opt->relative && opt->prefix_length) {
 +              quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf);
 +              strbuf_insert(&pathbuf, 0, filename, tree_name_len);
        } else {
                strbuf_addstr(&pathbuf, filename);
        }
  
 -      if (opt->relative && opt->prefix_length) {
 -              char *name = strbuf_detach(&pathbuf, NULL);
 -              quote_path_relative(name + tree_name_len, opt->prefix, &pathbuf);
 -              strbuf_insert(&pathbuf, 0, name, tree_name_len);
 -              free(name);
 -      }
 -
  #ifndef NO_PTHREADS
        if (num_threads) {
                add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid);
@@@ -349,10 -366,15 +349,10 @@@ static int grep_file(struct grep_opt *o
  {
        struct strbuf buf = STRBUF_INIT;
  
 -      if (super_prefix)
 -              strbuf_addstr(&buf, super_prefix);
 -      strbuf_addstr(&buf, filename);
 -
 -      if (opt->relative && opt->prefix_length) {
 -              char *name = strbuf_detach(&buf, NULL);
 -              quote_path_relative(name, opt->prefix, &buf);
 -              free(name);
 -      }
 +      if (opt->relative && opt->prefix_length)
 +              quote_path_relative(filename, opt->prefix, &buf);
 +      else
 +              strbuf_addstr(&buf, filename);
  
  #ifndef NO_PTHREADS
        if (num_threads) {
@@@ -399,89 -421,284 +399,89 @@@ static void run_pager(struct grep_opt *
                exit(status);
  }
  
 -static void compile_submodule_options(const struct grep_opt *opt,
 -                                    const char **argv,
 -                                    int cached, int untracked,
 -                                    int opt_exclude, int use_index,
 -                                    int pattern_type_arg)
 -{
 -      struct grep_pat *pattern;
 -
 -      if (recurse_submodules)
 -              argv_array_push(&submodule_options, "--recurse-submodules");
 -
 -      if (cached)
 -              argv_array_push(&submodule_options, "--cached");
 -      if (!use_index)
 -              argv_array_push(&submodule_options, "--no-index");
 -      if (untracked)
 -              argv_array_push(&submodule_options, "--untracked");
 -      if (opt_exclude > 0)
 -              argv_array_push(&submodule_options, "--exclude-standard");
 -
 -      if (opt->invert)
 -              argv_array_push(&submodule_options, "-v");
 -      if (opt->ignore_case)
 -              argv_array_push(&submodule_options, "-i");
 -      if (opt->word_regexp)
 -              argv_array_push(&submodule_options, "-w");
 -      switch (opt->binary) {
 -      case GREP_BINARY_NOMATCH:
 -              argv_array_push(&submodule_options, "-I");
 -              break;
 -      case GREP_BINARY_TEXT:
 -              argv_array_push(&submodule_options, "-a");
 -              break;
 -      default:
 -              break;
 -      }
 -      if (opt->allow_textconv)
 -              argv_array_push(&submodule_options, "--textconv");
 -      if (opt->max_depth != -1)
 -              argv_array_pushf(&submodule_options, "--max-depth=%d",
 -                               opt->max_depth);
 -      if (opt->linenum)
 -              argv_array_push(&submodule_options, "-n");
 -      if (!opt->pathname)
 -              argv_array_push(&submodule_options, "-h");
 -      if (!opt->relative)
 -              argv_array_push(&submodule_options, "--full-name");
 -      if (opt->name_only)
 -              argv_array_push(&submodule_options, "-l");
 -      if (opt->unmatch_name_only)
 -              argv_array_push(&submodule_options, "-L");
 -      if (opt->null_following_name)
 -              argv_array_push(&submodule_options, "-z");
 -      if (opt->count)
 -              argv_array_push(&submodule_options, "-c");
 -      if (opt->file_break)
 -              argv_array_push(&submodule_options, "--break");
 -      if (opt->heading)
 -              argv_array_push(&submodule_options, "--heading");
 -      if (opt->pre_context)
 -              argv_array_pushf(&submodule_options, "--before-context=%d",
 -                               opt->pre_context);
 -      if (opt->post_context)
 -              argv_array_pushf(&submodule_options, "--after-context=%d",
 -                               opt->post_context);
 -      if (opt->funcname)
 -              argv_array_push(&submodule_options, "-p");
 -      if (opt->funcbody)
 -              argv_array_push(&submodule_options, "-W");
 -      if (opt->all_match)
 -              argv_array_push(&submodule_options, "--all-match");
 -      if (opt->debug)
 -              argv_array_push(&submodule_options, "--debug");
 -      if (opt->status_only)
 -              argv_array_push(&submodule_options, "-q");
 -
 -      switch (pattern_type_arg) {
 -      case GREP_PATTERN_TYPE_BRE:
 -              argv_array_push(&submodule_options, "-G");
 -              break;
 -      case GREP_PATTERN_TYPE_ERE:
 -              argv_array_push(&submodule_options, "-E");
 -              break;
 -      case GREP_PATTERN_TYPE_FIXED:
 -              argv_array_push(&submodule_options, "-F");
 -              break;
 -      case GREP_PATTERN_TYPE_PCRE:
 -              argv_array_push(&submodule_options, "-P");
 -              break;
 -      case GREP_PATTERN_TYPE_UNSPECIFIED:
 -              break;
 -      default:
 -              die("BUG: Added a new grep pattern type without updating switch statement");
 -      }
 -
 -      for (pattern = opt->pattern_list; pattern != NULL;
 -           pattern = pattern->next) {
 -              switch (pattern->token) {
 -              case GREP_PATTERN:
 -                      argv_array_pushf(&submodule_options, "-e%s",
 -                                       pattern->pattern);
 -                      break;
 -              case GREP_AND:
 -              case GREP_OPEN_PAREN:
 -              case GREP_CLOSE_PAREN:
 -              case GREP_NOT:
 -              case GREP_OR:
 -                      argv_array_push(&submodule_options, pattern->pattern);
 -                      break;
 -              /* BODY and HEAD are not used by git-grep */
 -              case GREP_PATTERN_BODY:
 -              case GREP_PATTERN_HEAD:
 -                      break;
 -              }
 -      }
 -
 -      /*
 -       * Limit number of threads for child process to use.
 -       * This is to prevent potential fork-bomb behavior of git-grep as each
 -       * submodule process has its own thread pool.
 -       */
 -      argv_array_pushf(&submodule_options, "--threads=%d",
 -                       DIV_ROUND_UP(num_threads, 2));
 -
 -      /* Add Pathspecs */
 -      argv_array_push(&submodule_options, "--");
 -      for (; *argv; argv++)
 -              argv_array_push(&submodule_options, *argv);
 -}
 +static int grep_cache(struct grep_opt *opt, struct repository *repo,
 +                    const struct pathspec *pathspec, int cached);
 +static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 +                   struct tree_desc *tree, struct strbuf *base, int tn_len,
 +                   int check_attr, struct repository *repo);
  
 -/*
 - * Launch child process to grep contents of a submodule
 - */
 -static int grep_submodule_launch(struct grep_opt *opt,
 -                               const struct grep_source *gs)
 +static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
 +                        const struct pathspec *pathspec,
 +                        const struct object_id *oid,
 +                        const char *filename, const char *path)
  {
 -      struct child_process cp = CHILD_PROCESS_INIT;
 -      int status, i;
 -      const char *end_of_base;
 -      const char *name;
 -      struct strbuf child_output = STRBUF_INIT;
 -
 -      end_of_base = strchr(gs->name, ':');
 -      if (gs->identifier && end_of_base)
 -              name = end_of_base + 1;
 -      else
 -              name = gs->name;
 +      struct repository submodule;
 +      int hit;
  
 -      prepare_submodule_repo_env(&cp.env_array);
 -      argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT);
 +      if (!is_submodule_active(superproject, path))
 +              return 0;
  
 -      if (opt->relative && opt->prefix_length)
 -              argv_array_pushf(&cp.env_array, "%s=%s",
 -                               GIT_TOPLEVEL_PREFIX_ENVIRONMENT,
 -                               opt->prefix);
 +      if (repo_submodule_init(&submodule, superproject, path))
 +              return 0;
  
 -      /* Add super prefix */
 -      argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
 -                       super_prefix ? super_prefix : "",
 -                       name);
 -      argv_array_push(&cp.args, "grep");
 +      repo_read_gitmodules(&submodule);
  
        /*
 -       * Add basename of parent project
 -       * When performing grep on a tree object the filename is prefixed
 -       * with the object's name: 'tree-name:filename'.  In order to
 -       * provide uniformity of output we want to pass the name of the
 -       * parent project's object name to the submodule so the submodule can
 -       * prefix its output with the parent's name and not its own OID.
 +       * NEEDSWORK: This adds the submodule's object directory to the list of
 +       * alternates for the single in-memory object store.  This has some bad
 +       * consequences for memory (processed objects will never be freed) and
 +       * performance (this increases the number of pack files git has to pay
 +       * attention to, to the sum of the number of pack files in all the
 +       * repositories processed so far).  This can be removed once the object
 +       * store is no longer global and instead is a member of the repository
 +       * object.
         */
 -      if (gs->identifier && end_of_base)
 -              argv_array_pushf(&cp.args, "--parent-basename=%.*s",
 -                               (int) (end_of_base - gs->name),
 -                               gs->name);
 +      add_to_alternates_memory(submodule.objectdir);
  
 -      /* Add options */
 -      for (i = 0; i < submodule_options.argc; i++) {
 -              /*
 -               * If there is a tree identifier for the submodule, add the
 -               * rev after adding the submodule options but before the
 -               * pathspecs.  To do this we listen for the '--' and insert the
 -               * oid before pushing the '--' onto the child process argv
 -               * array.
 -               */
 -              if (gs->identifier &&
 -                  !strcmp("--", submodule_options.argv[i])) {
 -                      argv_array_push(&cp.args, oid_to_hex(gs->identifier));
 -              }
 +      if (oid) {
 +              struct object *object;
 +              struct tree_desc tree;
 +              void *data;
 +              unsigned long size;
 +              struct strbuf base = STRBUF_INIT;
  
 -              argv_array_push(&cp.args, submodule_options.argv[i]);
 -      }
 +              object = parse_object_or_die(oid, oid_to_hex(oid));
  
 -      cp.git_cmd = 1;
 -      cp.dir = gs->path;
 +              grep_read_lock();
 +              data = read_object_with_reference(object->oid.hash, tree_type,
 +                                                &size, NULL);
 +              grep_read_unlock();
  
 -      /*
 -       * Capture output to output buffer and check the return code from the
 -       * child process.  A '0' indicates a hit, a '1' indicates no hit and
 -       * anything else is an error.
 -       */
 -      status = capture_command(&cp, &child_output, 0);
 -      if (status && (status != 1)) {
 -              /* flush the buffer */
 -              write_or_die(1, child_output.buf, child_output.len);
 -              die("process for submodule '%s' failed with exit code: %d",
 -                  gs->name, status);
 -      }
 +              if (!data)
 +                      die(_("unable to read tree (%s)"), oid_to_hex(&object->oid));
  
 -      opt->output(opt, child_output.buf, child_output.len);
 -      strbuf_release(&child_output);
 -      /* invert the return code to make a hit equal to 1 */
 -      return !status;
 -}
 +              strbuf_addstr(&base, filename);
 +              strbuf_addch(&base, '/');
  
 -/*
 - * Prep grep structures for a submodule grep
 - * oid: the oid of the submodule or NULL if using the working tree
 - * filename: name of the submodule including tree name of parent
 - * path: location of the submodule
 - */
 -static int grep_submodule(struct grep_opt *opt, const struct object_id *oid,
 -                        const char *filename, const char *path)
 -{
 -      if (!is_submodule_active(the_repository, path))
 -              return 0;
 -      if (!is_submodule_populated_gently(path, NULL)) {
 -              /*
 -               * If searching history, check for the presence of the
 -               * submodule's gitdir before skipping the submodule.
 -               */
 -              if (oid) {
 -                      const struct submodule *sub =
 -                                      submodule_from_path(&null_oid, path);
 -                      if (sub)
 -                              path = git_path("modules/%s", sub->name);
 -
 -                      if (!(is_directory(path) && is_git_directory(path)))
 -                              return 0;
 -              } else {
 -                      return 0;
 -              }
 +              init_tree_desc(&tree, data, size);
 +              hit = grep_tree(opt, pathspec, &tree, &base, base.len,
 +                              object->type == OBJ_COMMIT, &submodule);
 +              strbuf_release(&base);
 +              free(data);
 +      } else {
 +              hit = grep_cache(opt, &submodule, pathspec, 1);
        }
  
 -#ifndef NO_PTHREADS
 -      if (num_threads) {
 -              add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, oid);
 -              return 0;
 -      } else
 -#endif
 -      {
 -              struct grep_source gs;
 -              int hit;
 -
 -              grep_source_init(&gs, GREP_SOURCE_SUBMODULE,
 -                               filename, path, oid);
 -              hit = grep_submodule_launch(opt, &gs);
 -
 -              grep_source_clear(&gs);
 -              return hit;
 -      }
 +      repo_clear(&submodule);
 +      return hit;
  }
  
 -static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
 -                    int cached)
 +static int grep_cache(struct grep_opt *opt, struct repository *repo,
 +                    const struct pathspec *pathspec, int cached)
  {
        int hit = 0;
        int nr;
        struct strbuf name = STRBUF_INIT;
        int name_base_len = 0;
 -      if (super_prefix) {
 -              name_base_len = strlen(super_prefix);
 -              strbuf_addstr(&name, super_prefix);
 +      if (repo->submodule_prefix) {
 +              name_base_len = strlen(repo->submodule_prefix);
 +              strbuf_addstr(&name, repo->submodule_prefix);
        }
  
 -      read_cache();
 +      repo_read_index(repo);
  
 -      for (nr = 0; nr < active_nr; nr++) {
 -              const struct cache_entry *ce = active_cache[nr];
 +      for (nr = 0; nr < repo->index->cache_nr; nr++) {
 +              const struct cache_entry *ce = repo->index->cache[nr];
                strbuf_setlen(&name, name_base_len);
                strbuf_addstr(&name, ce->name);
  
                            ce_skip_worktree(ce)) {
                                if (ce_stage(ce) || ce_intent_to_add(ce))
                                        continue;
 -                              hit |= grep_oid(opt, &ce->oid, ce->name,
 -                                               0, ce->name);
 +                              hit |= grep_oid(opt, &ce->oid, name.buf,
 +                                               0, name.buf);
                        } else {
 -                              hit |= grep_file(opt, ce->name);
 +                              hit |= grep_file(opt, name.buf);
                        }
                } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
                           submodule_path_match(pathspec, name.buf, NULL)) {
 -                      hit |= grep_submodule(opt, NULL, ce->name, ce->name);
 +                      hit |= grep_submodule(opt, repo, pathspec, NULL, ce->name, ce->name);
                } else {
                        continue;
                }
                if (ce_stage(ce)) {
                        do {
                                nr++;
 -                      } while (nr < active_nr &&
 -                               !strcmp(ce->name, active_cache[nr]->name));
 +                      } while (nr < repo->index->cache_nr &&
 +                               !strcmp(ce->name, repo->index->cache[nr]->name));
                        nr--; /* compensate for loop control */
                }
                if (hit && opt->status_only)
  
  static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                     struct tree_desc *tree, struct strbuf *base, int tn_len,
 -                   int check_attr)
 +                   int check_attr, struct repository *repo)
  {
        int hit = 0;
        enum interesting match = entry_not_interesting;
        int old_baselen = base->len;
        struct strbuf name = STRBUF_INIT;
        int name_base_len = 0;
 -      if (super_prefix) {
 -              strbuf_addstr(&name, super_prefix);
 +      if (repo->submodule_prefix) {
 +              strbuf_addstr(&name, repo->submodule_prefix);
                name_base_len = name.len;
        }
  
                        strbuf_addch(base, '/');
                        init_tree_desc(&sub, data, size);
                        hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
 -                                       check_attr);
 +                                       check_attr, repo);
                        free(data);
                } else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
 -                      hit |= grep_submodule(opt, entry.oid, base->buf,
 -                                            base->buf + tn_len);
 +                      hit |= grep_submodule(opt, repo, pathspec, entry.oid,
 +                                            base->buf, base->buf + tn_len);
                }
  
                strbuf_setlen(base, old_baselen);
  }
  
  static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
 -                     struct object *obj, const char *name, const char *path)
 +                     struct object *obj, const char *name, const char *path,
 +                     struct repository *repo)
  {
        if (obj->type == OBJ_BLOB)
                return grep_oid(opt, &obj->oid, name, 0, path);
                if (!data)
                        die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid));
  
 -              /* Use parent's name as base when recursing submodules */
 -              if (recurse_submodules && parent_basename)
 -                      name = parent_basename;
 -
                len = name ? strlen(name) : 0;
                strbuf_init(&base, PATH_MAX + len + 1);
                if (len) {
                }
                init_tree_desc(&tree, data, size);
                hit = grep_tree(opt, pathspec, &tree, &base, base.len,
 -                              obj->type == OBJ_COMMIT);
 +                              obj->type == OBJ_COMMIT, repo);
                strbuf_release(&base);
                free(data);
                return hit;
  }
  
  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();
-                       gitmodules_config_sha1(real_obj->oid.hash);
+                       gitmodules_config_oid(&real_obj->oid);
                }
 -              if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path)) {
 +              if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path,
 +                              repo)) {
                        hit = 1;
                        if (opt->status_only)
                                break;
@@@ -787,6 -1005,9 +787,6 @@@ int cmd_grep(int argc, const char **arg
                            N_("ignore files specified via '.gitignore'"), 1),
                OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
                         N_("recursively search in each submodule")),
 -              OPT_STRING(0, "parent-basename", &parent_basename,
 -                         N_("basename"),
 -                         N_("prepend parent project's basename to output")),
                OPT_GROUP(""),
                OPT_BOOL('v', "invert-match", &opt.invert,
                        N_("show non-matching lines")),
        init_grep_defaults();
        git_config(grep_cmd_config, NULL);
        grep_init(&opt, prefix);
 -      super_prefix = get_super_prefix();
  
        /*
         * If there is no -- then the paths must exist in the working
  
        if (!opt.pattern_list)
                die(_("no pattern given."));
 -      if (!opt.fixed && opt.ignore_case)
 -              opt.regflags |= REG_ICASE;
  
        /*
         * We have to find "--" in a separate pass, because its presence
                        break;
                }
  
-               if (get_sha1_with_context(arg, GET_SHA1_RECORD_PATH,
-                                         oid.hash, &oc)) {
+               if (get_oid_with_context(arg, GET_OID_RECORD_PATH,
+                                        &oid, &oc)) {
                        if (seen_dashdash)
                                die(_("unable to resolve revision: %s"), arg);
                        break;
  
        if (recurse_submodules) {
                gitmodules_config();
 -              compile_submodule_options(&opt, argv + i, cached, untracked,
 -                                        opt_exclude, use_index,
 -                                        pattern_type_arg);
        }
  
        if (show_in_pager && (cached || list.nr))
                if (!cached)
                        setup_work_tree();
  
 -              hit = grep_cache(&opt, &pathspec, cached);
 +              hit = grep_cache(&opt, the_repository, &pathspec, cached);
        } else {
                if (cached)
                        die(_("both --cached and trees are given."));
 -              hit = grep_objects(&opt, &pathspec, &list);
 +
 +              hit = grep_objects(&opt, &pathspec, the_repository, &list);
        }
  
        if (num_threads)
index 6d9600d4fbada7511bb6abf9df12737479ef87e8,af871f14e7b9d453c4d814ea3c7ff8e0a9f5e665..1e49ce580e3bb15fe80cbcda04183b7713c8540a
@@@ -350,7 -350,7 +350,7 @@@ static void init_submodule(const char *
        } else
                displaypath = xstrdup(path);
  
-       sub = submodule_from_path(null_sha1, path);
+       sub = submodule_from_path(&null_oid, path);
  
        if (!sub)
                die(_("No url found for submodule path '%s' in .gitmodules"),
@@@ -476,7 -476,7 +476,7 @@@ static int module_name(int argc, const 
                usage(_("git submodule--helper name <path>"));
  
        gitmodules_config();
-       sub = submodule_from_path(null_sha1, argv[1]);
+       sub = submodule_from_path(&null_oid, argv[1]);
  
        if (!sub)
                die(_("no submodule mapping found in .gitmodules for path '%s'"),
@@@ -795,7 -795,7 +795,7 @@@ static int prepare_to_clone_next_submod
                goto cleanup;
        }
  
-       sub = submodule_from_path(null_sha1, ce->name);
+       sub = submodule_from_path(&null_oid, ce->name);
  
        if (suc->recursive_prefix)
                displaypath = relative_path(suc->recursive_prefix,
@@@ -960,19 -960,10 +960,19 @@@ static int update_clone_task_finished(i
        return 0;
  }
  
 +static int gitmodules_update_clone_config(const char *var, const char *value,
 +                                        void *cb)
 +{
 +      int *max_jobs = cb;
 +      if (!strcmp(var, "submodule.fetchjobs"))
 +              *max_jobs = parse_submodule_fetchjobs(var, value);
 +      return 0;
 +}
 +
  static int update_clone(int argc, const char **argv, const char *prefix)
  {
        const char *update = NULL;
 -      int max_jobs = -1;
 +      int max_jobs = 1;
        struct string_list_item *item;
        struct pathspec pathspec;
        struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
        };
        suc.prefix = prefix;
  
 +      config_from_gitmodules(gitmodules_update_clone_config, &max_jobs);
 +      git_config(gitmodules_update_clone_config, &max_jobs);
 +
        argc = parse_options(argc, argv, prefix, module_update_clone_options,
                             git_submodule_helper_usage, 0);
  
        gitmodules_config();
        git_config(submodule_config, NULL);
  
 -      if (max_jobs < 0)
 -              max_jobs = parallel_submodules();
 -
        run_processes_parallel(max_jobs,
                               update_clone_get_next_task,
                               update_clone_start_failure,
@@@ -1069,7 -1060,7 +1069,7 @@@ static const char *remote_submodule_bra
        gitmodules_config();
        git_config(submodule_config, NULL);
  
-       sub = submodule_from_path(null_sha1, path);
+       sub = submodule_from_path(&null_oid, path);
        if (!sub)
                return NULL;
  
diff --combined cache.h
index c221434b2306e34b677927a1f0e25108f1f86e60,cfc3698ebacb8f4961356609e94c64c8306e98cd..88dacc16e415f90688acefd16e0a89f4aaa41d28
+++ b/cache.h
@@@ -417,6 -417,7 +417,6 @@@ static inline enum object_type object_t
  #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
  #define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
  #define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX"
 -#define GIT_TOPLEVEL_PREFIX_ENVIRONMENT "GIT_INTERNAL_TOPLEVEL_PREFIX"
  #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
  #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
  #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
  #define GITATTRIBUTES_FILE ".gitattributes"
  #define INFOATTRIBUTES_FILE "info/attributes"
  #define ATTRIBUTE_MACRO_PREFIX "[attr]"
 +#define GITMODULES_FILE ".gitmodules"
  #define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
  #define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
  #define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
@@@ -1283,38 -1283,37 +1283,37 @@@ struct object_context 
         */
        struct strbuf symlink_path;
        /*
-        * If GET_SHA1_RECORD_PATH is set, this will record path (if any)
+        * If GET_OID_RECORD_PATH is set, this will record path (if any)
         * found when resolving the name. The caller is responsible for
         * releasing the memory.
         */
        char *path;
  };
  
- #define GET_SHA1_QUIETLY           01
- #define GET_SHA1_COMMIT            02
- #define GET_SHA1_COMMITTISH        04
- #define GET_SHA1_TREE             010
- #define GET_SHA1_TREEISH          020
- #define GET_SHA1_BLOB             040
- #define GET_SHA1_FOLLOW_SYMLINKS 0100
- #define GET_SHA1_RECORD_PATH     0200
- #define GET_SHA1_ONLY_TO_DIE    04000
- #define GET_SHA1_DISAMBIGUATORS \
-       (GET_SHA1_COMMIT | GET_SHA1_COMMITTISH | \
-       GET_SHA1_TREE | GET_SHA1_TREEISH | \
-       GET_SHA1_BLOB)
- extern int get_sha1(const char *str, unsigned char *sha1);
- extern int get_sha1_commit(const char *str, unsigned char *sha1);
- extern int get_sha1_committish(const char *str, unsigned char *sha1);
- extern int get_sha1_tree(const char *str, unsigned char *sha1);
- extern int get_sha1_treeish(const char *str, unsigned char *sha1);
- extern int get_sha1_blob(const char *str, unsigned char *sha1);
- extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
- extern int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *oc);
+ #define GET_OID_QUIETLY           01
+ #define GET_OID_COMMIT            02
+ #define GET_OID_COMMITTISH        04
+ #define GET_OID_TREE             010
+ #define GET_OID_TREEISH          020
+ #define GET_OID_BLOB             040
+ #define GET_OID_FOLLOW_SYMLINKS 0100
+ #define GET_OID_RECORD_PATH     0200
+ #define GET_OID_ONLY_TO_DIE    04000
+ #define GET_OID_DISAMBIGUATORS \
+       (GET_OID_COMMIT | GET_OID_COMMITTISH | \
+       GET_OID_TREE | GET_OID_TREEISH | \
+       GET_OID_BLOB)
  
  extern int get_oid(const char *str, struct object_id *oid);
+ extern int get_oid_commit(const char *str, struct object_id *oid);
+ extern int get_oid_committish(const char *str, struct object_id *oid);
+ extern int get_oid_tree(const char *str, struct object_id *oid);
+ extern int get_oid_treeish(const char *str, struct object_id *oid);
+ extern int get_oid_blob(const char *str, struct object_id *oid);
+ extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
+ extern int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);
  
  typedef int each_abbrev_fn(const struct object_id *oid, void *);
  extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *);
diff --combined config.c
index 06645a3250cc1321f3722ffd427d04f3e5dcd3fe,014151d0321297098b39e8057ab7b1e10a535e6b..6f2b8abbdbb5c9900c7b23c21cc8fbac6887b0ad
+++ b/config.c
@@@ -1460,9 -1460,9 +1460,9 @@@ int git_config_from_mem(config_fn_t fn
        return do_config_from(&top, fn, data);
  }
  
- int git_config_from_blob_sha1(config_fn_t fn,
+ int git_config_from_blob_oid(config_fn_t fn,
                              const char *name,
-                             const unsigned char *sha1,
+                             const struct object_id *oid,
                              void *data)
  {
        enum object_type type;
        unsigned long size;
        int ret;
  
-       buf = read_sha1_file(sha1, &type, &size);
+       buf = read_sha1_file(oid->hash, &type, &size);
        if (!buf)
                return error("unable to load config blob object '%s'", name);
        if (type != OBJ_BLOB) {
@@@ -1488,11 -1488,11 +1488,11 @@@ static int git_config_from_blob_ref(con
                                    const char *name,
                                    void *data)
  {
-       unsigned char sha1[20];
+       struct object_id oid;
  
-       if (get_sha1(name, sha1) < 0)
+       if (get_oid(name, &oid) < 0)
                return error("unable to resolve config blob '%s'", name);
-       return git_config_from_blob_sha1(fn, name, sha1, data);
+       return git_config_from_blob_oid(fn, name, &oid, data);
  }
  
  const char *git_etc_gitconfig(void)
@@@ -1714,18 -1714,15 +1714,18 @@@ static int configset_add_value(struct c
        return 0;
  }
  
 -static int config_set_element_cmp(const struct config_set_element *e1,
 -                               const struct config_set_element *e2, const void *unused)
 +static int config_set_element_cmp(const void *unused_cmp_data,
 +                                const struct config_set_element *e1,
 +                                const struct config_set_element *e2,
 +                                const void *unused_keydata)
  {
        return strcmp(e1->key, e2->key);
  }
  
  void git_configset_init(struct config_set *cs)
  {
 -      hashmap_init(&cs->config_hash, (hashmap_cmp_fn)config_set_element_cmp, 0);
 +      hashmap_init(&cs->config_hash, (hashmap_cmp_fn)config_set_element_cmp,
 +                   NULL, 0);
        cs->hash_initialized = 1;
        cs->list.nr = 0;
        cs->list.alloc = 0;
@@@ -2053,23 -2050,6 +2053,23 @@@ int git_config_get_pathname(const char 
        return repo_config_get_pathname(the_repository, key, dest);
  }
  
 +/*
 + * Note: This function exists solely to maintain backward compatibility with
 + * 'fetch' and 'update_clone' storing configuration in '.gitmodules' and should
 + * NOT be used anywhere else.
 + *
 + * Runs the provided config function on the '.gitmodules' file found in the
 + * working directory.
 + */
 +void config_from_gitmodules(config_fn_t fn, void *data)
 +{
 +      if (the_repository->worktree) {
 +              char *file = repo_worktree_path(the_repository, GITMODULES_FILE);
 +              git_config_from_file(fn, file, data);
 +              free(file);
 +      }
 +}
 +
  int git_config_get_expiry(const char *key, const char **output)
  {
        int ret = git_config_get_string_const(key, output);
diff --combined config.h
index 6998e6645995a3302de0f42234c539d6685da008,827f2b0e4a652b008fd9e3f36cee4ae656836f4e..18b6f3f724bd823bf98f039e4699b0c2c5dc5393
+++ b/config.h
@@@ -39,8 -39,8 +39,8 @@@ extern int git_default_config(const cha
  extern int git_config_from_file(config_fn_t fn, const char *, void *);
  extern int git_config_from_mem(config_fn_t fn, const enum config_origin_type,
                                        const char *name, const char *buf, size_t len, void *data);
- extern int git_config_from_blob_sha1(config_fn_t fn, const char *name,
-                                    const unsigned char *sha1, void *data);
+ extern int git_config_from_blob_oid(config_fn_t fn, const char *name,
+                                   const struct object_id *oid, void *data);
  extern void git_config_push_parameter(const char *text);
  extern int git_config_from_parameters(config_fn_t fn, void *data);
  extern void read_early_config(config_fn_t cb, void *data);
@@@ -187,16 -187,6 +187,16 @@@ extern int repo_config_get_maybe_bool(s
  extern int repo_config_get_pathname(struct repository *repo,
                                    const char *key, const char **dest);
  
 +/*
 + * Note: This function exists solely to maintain backward compatibility with
 + * 'fetch' and 'update_clone' storing configuration in '.gitmodules' and should
 + * NOT be used anywhere else.
 + *
 + * Runs the provided config function on the '.gitmodules' file found in the
 + * working directory.
 + */
 +extern void config_from_gitmodules(config_fn_t fn, void *data);
 +
  extern int git_config_get_value(const char *key, const char **value);
  extern const struct string_list *git_config_get_value_multi(const char *key);
  extern void git_config_clear(void);
diff --combined refs.c
index ba22f4acefa262cc1029bcf8360edb21c0635953,e1de9251557d6e49d1ce846b1b31b080f0b320d6..4226f9ebf52717154f8d132fbaef42558776aecb
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -818,7 -818,7 +818,7 @@@ int read_ref_at(const char *refname, un
        for_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);
  
        if (!cb.reccnt) {
-               if (flags & GET_SHA1_QUIETLY)
+               if (flags & GET_OID_QUIETLY)
                        exit(128);
                else
                        die("Log for %s is empty.", refname);
@@@ -1525,8 -1525,7 +1525,8 @@@ struct ref_store_hash_entr
        char name[FLEX_ARRAY];
  };
  
 -static int ref_store_hash_cmp(const void *entry, const void *entry_or_key,
 +static int ref_store_hash_cmp(const void *unused_cmp_data,
 +                            const void *entry, const void *entry_or_key,
                              const void *keydata)
  {
        const struct ref_store_hash_entry *e1 = entry, *e2 = entry_or_key;
@@@ -1609,7 -1608,7 +1609,7 @@@ static void register_ref_store_map(stru
                                   const char *name)
  {
        if (!map->tablesize)
 -              hashmap_init(map, ref_store_hash_cmp, 0);
 +              hashmap_init(map, ref_store_hash_cmp, NULL, 0);
  
        if (hashmap_put(map, alloc_ref_store_hash_entry(name, refs)))
                die("BUG: %s ref_store '%s' initialized twice", type, name);
diff --combined remote.c
index 60d004392109f1e39f0bf34578e195cdf3af1639,2fb0895e4dd5212b158cc7d23a96c8a39f11ad0a..6a1be31bb168c86721364f19d39f227a639e48b8
+++ b/remote.c
@@@ -133,10 -133,7 +133,10 @@@ struct remotes_hash_key 
        int len;
  };
  
 -static int remotes_hash_cmp(const struct remote *a, const struct remote *b, const struct remotes_hash_key *key)
 +static int remotes_hash_cmp(const void *unused_cmp_data,
 +                          const struct remote *a,
 +                          const struct remote *b,
 +                          const struct remotes_hash_key *key)
  {
        if (key)
                return strncmp(a->name, key->str, key->len) || a->name[key->len];
  static inline void init_remotes_hash(void)
  {
        if (!remotes_hash.cmpfn)
 -              hashmap_init(&remotes_hash, (hashmap_cmp_fn)remotes_hash_cmp, 0);
 +              hashmap_init(&remotes_hash, (hashmap_cmp_fn)remotes_hash_cmp, NULL, 0);
  }
  
  static struct remote *make_remote(const char *name, int len)
@@@ -1081,7 -1078,7 +1081,7 @@@ static int try_explicit_object_name(con
                return 0;
        }
  
-       if (get_sha1(name, oid.hash))
+       if (get_oid(name, &oid))
                return -1;
  
        if (match) {
@@@ -2297,8 -2294,8 +2297,8 @@@ static int parse_push_cas_option(struc
        if (!*colon)
                entry->use_tracking = 1;
        else if (!colon[1])
-               hashclr(entry->expect);
-       else if (get_sha1(colon + 1, entry->expect))
+               oidclr(&entry->expect);
+       else if (get_oid(colon + 1, &entry->expect))
                return error("cannot parse expected object name '%s'", colon + 1);
        return 0;
  }
@@@ -2345,7 -2342,7 +2345,7 @@@ static void apply_cas(struct push_cas_o
                        continue;
                ref->expect_old_sha1 = 1;
                if (!entry->use_tracking)
-                       hashcpy(ref->old_oid_expect.hash, cas->entry[i].expect);
+                       oidcpy(&ref->old_oid_expect, &entry->expect);
                else if (remote_tracking(remote, ref->name, &ref->old_oid_expect))
                        oidclr(&ref->old_oid_expect);
                return;
diff --combined repository.c
index c0e0e0e7e76015e3f93b21528bff58286fab0fb2,1617467568c76e685d5f852c27ca16f26ed0494c..f107af7d763e848648ace5da0010be4df2e0d4dc
@@@ -4,9 -4,7 +4,9 @@@
  #include "submodule-config.h"
  
  /* The main repository */
 -static struct repository the_repo;
 +static struct repository the_repo = {
 +      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, 0, 0
 +};
  struct repository *the_repository = &the_repo;
  
  static char *git_path_from_env(const char *envvar, const char *git_dir,
@@@ -160,7 -158,7 +160,7 @@@ int repo_submodule_init(struct reposito
        struct strbuf worktree = STRBUF_INIT;
        int ret = 0;
  
-       sub = submodule_from_cache(superproject, null_sha1, path);
+       sub = submodule_from_cache(superproject, &null_oid, path);
        if (!sub) {
                ret = -1;
                goto out;
@@@ -237,6 -235,8 +237,6 @@@ int repo_read_index(struct repository *
  {
        if (!repo->index)
                repo->index = xcalloc(1, sizeof(*repo->index));
 -      else
 -              discard_index(repo->index);
  
        return read_index_from(repo->index, repo->index_file);
  }
diff --combined revision.c
index 6603af944486db6d5ec560dd9c655d24c31ce9e9,913ef8ce32ad8e6b747eb61bb79de68ffc8e9fc3..bfbf0514c20332d8c8d197081fb463a88053553d
@@@ -1303,7 -1303,7 +1303,7 @@@ static int add_parents_only(struct rev_
                flags ^= UNINTERESTING | BOTTOM;
                arg++;
        }
-       if (get_sha1_committish(arg, oid.hash))
+       if (get_oid_committish(arg, &oid))
                return 0;
        while (1) {
                it = get_reference(revs, arg, &oid, 0);
@@@ -1362,6 -1362,7 +1362,6 @@@ void init_revisions(struct rev_info *re
        init_grep_defaults();
        grep_init(&revs->grep_filter, prefix);
        revs->grep_filter.status_only = 1;
 -      revs->grep_filter.regflags = REG_NEWLINE;
  
        diff_setup(&revs->diffopt);
        if (prefix && !revs->diffopt.prefix) {
@@@ -1452,7 -1453,7 +1452,7 @@@ static int handle_dotdot_1(const char *
        unsigned int a_flags, b_flags;
        int symmetric = 0;
        unsigned int flags_exclude = flags ^ (UNINTERESTING | BOTTOM);
-       unsigned int oc_flags = GET_SHA1_COMMITTISH | GET_SHA1_RECORD_PATH;
+       unsigned int oc_flags = GET_OID_COMMITTISH | GET_OID_RECORD_PATH;
  
        a_name = arg;
        if (!*a_name)
        if (!*b_name)
                b_name = "HEAD";
  
-       if (get_sha1_with_context(a_name, oc_flags, a_oid.hash, a_oc) ||
-           get_sha1_with_context(b_name, oc_flags, b_oid.hash, b_oc))
+       if (get_oid_with_context(a_name, oc_flags, &a_oid, a_oc) ||
+           get_oid_with_context(b_name, oc_flags, &b_oid, b_oc))
                return -1;
  
        if (!cant_be_filename) {
@@@ -1548,7 -1549,7 +1548,7 @@@ int handle_revision_arg(const char *arg
        int local_flags;
        const char *arg = arg_;
        int cant_be_filename = revarg_opt & REVARG_CANNOT_BE_FILENAME;
-       unsigned get_sha1_flags = GET_SHA1_RECORD_PATH;
+       unsigned get_sha1_flags = GET_OID_RECORD_PATH;
  
        flags = flags & UNINTERESTING ? flags | BOTTOM : flags & ~BOTTOM;
  
        }
  
        if (revarg_opt & REVARG_COMMITTISH)
-               get_sha1_flags |= GET_SHA1_COMMITTISH;
+               get_sha1_flags |= GET_OID_COMMITTISH;
  
-       if (get_sha1_with_context(arg, get_sha1_flags, oid.hash, &oc))
+       if (get_oid_with_context(arg, get_sha1_flags, &oid, &oc))
                return revs->ignore_missing ? 0 : -1;
        if (!cant_be_filename)
                verify_non_filename(revs->prefix, arg);
@@@ -2021,6 -2022,7 +2021,6 @@@ static int handle_revision_opt(struct r
                revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_ERE;
        } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
                revs->grep_filter.ignore_case = 1;
 -              revs->grep_filter.regflags |= REG_ICASE;
                DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
        } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
                revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_FIXED;
@@@ -2319,7 -2321,7 +2319,7 @@@ int setup_revisions(int argc, const cha
                struct object_id oid;
                struct object *object;
                struct object_context oc;
-               if (get_sha1_with_context(revs->def, 0, oid.hash, &oc))
+               if (get_oid_with_context(revs->def, 0, &oid, &oc))
                        diagnose_missing_default(revs->def);
                object = get_reference(revs, revs->def, &oid, 0);
                add_pending_object_with_mode(revs, object, revs->def, oc.mode);
diff --combined submodule-config.c
index 70400f553aa91c102d55f7fbaa93e6c3aad42c8c,89de1d6a53db0c2222c008f98f2bb61bb9b25df7..0b429e9426529208c33cebfc5e16636449dfc6f1
@@@ -4,7 -4,6 +4,7 @@@
  #include "submodule-config.h"
  #include "submodule.h"
  #include "strbuf.h"
 +#include "parse-options.h"
  
  /*
   * submodule cache lookup structure
@@@ -34,19 -33,17 +34,19 @@@ enum lookup_type 
        lookup_path
  };
  
 -static int config_path_cmp(const struct submodule_entry *a,
 +static int config_path_cmp(const void *unused_cmp_data,
 +                         const struct submodule_entry *a,
                           const struct submodule_entry *b,
 -                         const void *unused)
 +                         const void *unused_keydata)
  {
        return strcmp(a->config->path, b->config->path) ||
               hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);
  }
  
 -static int config_name_cmp(const struct submodule_entry *a,
 +static int config_name_cmp(const void *unused_cmp_data,
 +                         const struct submodule_entry *a,
                           const struct submodule_entry *b,
 -                         const void *unused)
 +                         const void *unused_keydata)
  {
        return strcmp(a->config->name, b->config->name) ||
               hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);
@@@ -59,8 -56,8 +59,8 @@@ static struct submodule_cache *submodul
  
  static void submodule_cache_init(struct submodule_cache *cache)
  {
 -      hashmap_init(&cache->for_path, (hashmap_cmp_fn) config_path_cmp, 0);
 -      hashmap_init(&cache->for_name, (hashmap_cmp_fn) config_name_cmp, 0);
 +      hashmap_init(&cache->for_path, (hashmap_cmp_fn) config_path_cmp, NULL, 0);
 +      hashmap_init(&cache->for_name, (hashmap_cmp_fn) config_name_cmp, NULL, 0);
        cache->initialized = 1;
  }
  
@@@ -248,40 -245,11 +248,40 @@@ static int parse_fetch_recurse(const ch
        }
  }
  
 +int parse_submodule_fetchjobs(const char *var, const char *value)
 +{
 +      int fetchjobs = git_config_int(var, value);
 +      if (fetchjobs < 0)
 +              die(_("negative values not allowed for submodule.fetchjobs"));
 +      return fetchjobs;
 +}
 +
  int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
  {
        return parse_fetch_recurse(opt, arg, 1);
  }
  
 +int option_fetch_parse_recurse_submodules(const struct option *opt,
 +                                        const char *arg, int unset)
 +{
 +      int *v;
 +
 +      if (!opt->value)
 +              return -1;
 +
 +      v = opt->value;
 +
 +      if (unset) {
 +              *v = RECURSE_SUBMODULES_OFF;
 +      } else {
 +              if (arg)
 +                      *v = parse_fetch_recurse_submodules_arg(opt->long_name, arg);
 +              else
 +                      *v = RECURSE_SUBMODULES_ON;
 +      }
 +      return 0;
 +}
 +
  static int parse_update_recurse(const char *opt, const char *arg,
                                int die_on_error)
  {
@@@ -449,19 -417,19 +449,19 @@@ static int parse_config(const char *var
        return ret;
  }
  
- int gitmodule_sha1_from_commit(const unsigned char *treeish_name,
-                                     unsigned char *gitmodules_sha1,
+ int gitmodule_oid_from_commit(const struct object_id *treeish_name,
+                                     struct object_id *gitmodules_oid,
                                      struct strbuf *rev)
  {
        int ret = 0;
  
-       if (is_null_sha1(treeish_name)) {
-               hashclr(gitmodules_sha1);
+       if (is_null_oid(treeish_name)) {
+               oidclr(gitmodules_oid);
                return 1;
        }
  
-       strbuf_addf(rev, "%s:.gitmodules", sha1_to_hex(treeish_name));
-       if (get_sha1(rev->buf, gitmodules_sha1) >= 0)
+       strbuf_addf(rev, "%s:.gitmodules", oid_to_hex(treeish_name));
+       if (get_oid(rev->buf, gitmodules_oid) >= 0)
                ret = 1;
  
        return ret;
   * revisions.
   */
  static const struct submodule *config_from(struct submodule_cache *cache,
-               const unsigned char *treeish_name, const char *key,
+               const struct object_id *treeish_name, const char *key,
                enum lookup_type lookup_type)
  {
        struct strbuf rev = STRBUF_INIT;
        unsigned long config_size;
        char *config = NULL;
-       unsigned char sha1[20];
+       struct object_id oid;
        enum object_type type;
        const struct submodule *submodule = NULL;
        struct parse_config_parameter parameter;
                return entry->config;
        }
  
-       if (!gitmodule_sha1_from_commit(treeish_name, sha1, &rev))
+       if (!gitmodule_oid_from_commit(treeish_name, &oid, &rev))
                goto out;
  
        switch (lookup_type) {
        case lookup_name:
-               submodule = cache_lookup_name(cache, sha1, key);
+               submodule = cache_lookup_name(cache, oid.hash, key);
                break;
        case lookup_path:
-               submodule = cache_lookup_path(cache, sha1, key);
+               submodule = cache_lookup_path(cache, oid.hash, key);
                break;
        }
        if (submodule)
                goto out;
  
-       config = read_sha1_file(sha1, &type, &config_size);
+       config = read_sha1_file(oid.hash, &type, &config_size);
        if (!config || type != OBJ_BLOB)
                goto out;
  
        /* fill the submodule config into the cache */
        parameter.cache = cache;
-       parameter.treeish_name = treeish_name;
-       parameter.gitmodules_sha1 = sha1;
+       parameter.treeish_name = treeish_name->hash;
+       parameter.gitmodules_sha1 = oid.hash;
        parameter.overwrite = 0;
        git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
                        config, config_size, &parameter);
  
        switch (lookup_type) {
        case lookup_name:
-               return cache_lookup_name(cache, sha1, key);
+               return cache_lookup_name(cache, oid.hash, key);
        case lookup_path:
-               return cache_lookup_path(cache, sha1, key);
+               return cache_lookup_path(cache, oid.hash, key);
        default:
                return NULL;
        }
@@@ -572,14 -540,14 +572,14 @@@ int parse_submodule_config_option(cons
        return submodule_config_option(the_repository, var, value);
  }
  
- const struct submodule *submodule_from_name(const unsigned char *treeish_name,
+ const struct submodule *submodule_from_name(const struct object_id *treeish_name,
                const char *name)
  {
        submodule_cache_check_init(the_repository);
        return config_from(the_repository->submodule_cache, treeish_name, name, lookup_name);
  }
  
- const struct submodule *submodule_from_path(const unsigned char *treeish_name,
+ const struct submodule *submodule_from_path(const struct object_id *treeish_name,
                const char *path)
  {
        submodule_cache_check_init(the_repository);
  }
  
  const struct submodule *submodule_from_cache(struct repository *repo,
-                                            const unsigned char *treeish_name,
+                                            const struct object_id *treeish_name,
                                             const char *key)
  {
        submodule_cache_check_init(repo);
diff --combined submodule-config.h
index 995d404f88a1100fa5e39b6606f61a4e7a78d5dd,5f52e6567b7064bbf197f1ac8edcfde0154c9714..cccd34b929f5299fbba6f43c74daeb96773aebdf
@@@ -27,26 -27,22 +27,26 @@@ struct repository
  
  extern void submodule_cache_free(struct submodule_cache *cache);
  
 +extern int parse_submodule_fetchjobs(const char *var, const char *value);
  extern int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
 +struct option;
 +extern int option_fetch_parse_recurse_submodules(const struct option *opt,
 +                                               const char *arg, int unset);
  extern int parse_update_recurse_submodules_arg(const char *opt, const char *arg);
  extern int parse_push_recurse_submodules_arg(const char *opt, const char *arg);
  extern int parse_submodule_config_option(const char *var, const char *value);
  extern int submodule_config_option(struct repository *repo,
                                   const char *var, const char *value);
  extern const struct submodule *submodule_from_name(
-               const unsigned char *commit_or_tree, const char *name);
+               const struct object_id *commit_or_tree, const char *name);
  extern const struct submodule *submodule_from_path(
-               const unsigned char *commit_or_tree, const char *path);
+               const struct object_id *commit_or_tree, const char *path);
  extern const struct submodule *submodule_from_cache(struct repository *repo,
-                                                   const unsigned char *treeish_name,
+                                                   const struct object_id *treeish_name,
                                                    const char *key);
- extern int gitmodule_sha1_from_commit(const unsigned char *commit_sha1,
-                                     unsigned char *gitmodules_sha1,
-                                     struct strbuf *rev);
+ extern int gitmodule_oid_from_commit(const struct object_id *commit_oid,
+                                    struct object_id *gitmodules_oid,
+                                    struct strbuf *rev);
  extern void submodule_free(void);
  
  #endif /* SUBMODULE_CONFIG_H */
diff --combined submodule.c
index 9d5eacaf9f2ffad4a7f5d17ced4137e0162215d5,f39cb4f6eafc09642ed6a7131d1cbf7a3efc34d8..5139b9256b589a6524e6158dbb1c2ae492ea4f70
  #include "worktree.h"
  #include "parse-options.h"
  
 -static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
  static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
 -static int parallel_jobs = 1;
  static struct string_list changed_submodule_paths = STRING_LIST_INIT_DUP;
  static int initialized_fetch_ref_tips;
  static struct oid_array ref_tips_before_fetch;
  static struct oid_array ref_tips_after_fetch;
  
  /*
 - * The following flag is set if the .gitmodules file is unmerged. We then
 - * disable recursion for all submodules where .git/config doesn't have a
 - * matching config entry because we can't guess what might be configured in
 - * .gitmodules unless the user resolves the conflict. When a command line
 - * option is given (which always overrides configuration) this flag will be
 - * ignored.
 + * Check if the .gitmodules file is unmerged. Parsing of the .gitmodules file
 + * will be disabled because we can't guess what might be configured in
 + * .gitmodules unless the user resolves the conflict.
   */
 -static int gitmodules_is_unmerged;
 +int is_gitmodules_unmerged(const struct index_state *istate)
 +{
 +      int pos = index_name_pos(istate, GITMODULES_FILE, strlen(GITMODULES_FILE));
 +      if (pos < 0) { /* .gitmodules not found or isn't merged */
 +              pos = -1 - pos;
 +              if (istate->cache_nr > pos) {  /* there is a .gitmodules */
 +                      const struct cache_entry *ce = istate->cache[pos];
 +                      if (ce_namelen(ce) == strlen(GITMODULES_FILE) &&
 +                          !strcmp(ce->name, GITMODULES_FILE))
 +                              return 1;
 +              }
 +      }
 +
 +      return 0;
 +}
  
  /*
 - * This flag is set if the .gitmodules file had unstaged modifications on
 - * startup. This must be checked before allowing modifications to the
 - * .gitmodules file with the intention to stage them later, because when
 - * continuing we would stage the modifications the user didn't stage herself
 - * too. That might change in a future version when we learn to stage the
 - * changes we do ourselves without staging any previous modifications.
 + * Check if the .gitmodules file has unstaged modifications.  This must be
 + * checked before allowing modifications to the .gitmodules file with the
 + * intention to stage them later, because when continuing we would stage the
 + * modifications the user didn't stage herself too. That might change in a
 + * future version when we learn to stage the changes we do ourselves without
 + * staging any previous modifications.
   */
 -static int gitmodules_is_modified;
 -
 -int is_staging_gitmodules_ok(void)
 +int is_staging_gitmodules_ok(const struct index_state *istate)
  {
 -      return !gitmodules_is_modified;
 +      int pos = index_name_pos(istate, GITMODULES_FILE, strlen(GITMODULES_FILE));
 +
 +      if ((pos >= 0) && (pos < istate->cache_nr)) {
 +              struct stat st;
 +              if (lstat(GITMODULES_FILE, &st) == 0 &&
 +                  ce_match_stat(istate->cache[pos], &st, 0) & DATA_CHANGED)
 +                      return 0;
 +      }
 +
 +      return 1;
  }
  
  /*
@@@ -79,13 -63,13 +79,13 @@@ int update_path_in_gitmodules(const cha
        struct strbuf entry = STRBUF_INIT;
        const struct submodule *submodule;
  
 -      if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */
 +      if (!file_exists(GITMODULES_FILE)) /* Do nothing without .gitmodules */
                return -1;
  
 -      if (gitmodules_is_unmerged)
 +      if (is_gitmodules_unmerged(&the_index))
                die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
  
-       submodule = submodule_from_path(null_sha1, oldpath);
+       submodule = submodule_from_path(&null_oid, oldpath);
        if (!submodule || !submodule->name) {
                warning(_("Could not find section in .gitmodules where path=%s"), oldpath);
                return -1;
@@@ -93,7 -77,7 +93,7 @@@
        strbuf_addstr(&entry, "submodule.");
        strbuf_addstr(&entry, submodule->name);
        strbuf_addstr(&entry, ".path");
 -      if (git_config_set_in_file_gently(".gitmodules", entry.buf, newpath) < 0) {
 +      if (git_config_set_in_file_gently(GITMODULES_FILE, entry.buf, newpath) < 0) {
                /* Maybe the user already did that, don't error out here */
                warning(_("Could not update .gitmodules entry %s"), entry.buf);
                strbuf_release(&entry);
@@@ -113,20 -97,20 +113,20 @@@ int remove_path_from_gitmodules(const c
        struct strbuf sect = STRBUF_INIT;
        const struct submodule *submodule;
  
 -      if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */
 +      if (!file_exists(GITMODULES_FILE)) /* Do nothing without .gitmodules */
                return -1;
  
 -      if (gitmodules_is_unmerged)
 +      if (is_gitmodules_unmerged(&the_index))
                die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
  
-       submodule = submodule_from_path(null_sha1, path);
+       submodule = submodule_from_path(&null_oid, path);
        if (!submodule || !submodule->name) {
                warning(_("Could not find section in .gitmodules where path=%s"), path);
                return -1;
        }
        strbuf_addstr(&sect, "submodule.");
        strbuf_addstr(&sect, submodule->name);
 -      if (git_config_rename_section_in_file(".gitmodules", sect.buf, NULL) < 0) {
 +      if (git_config_rename_section_in_file(GITMODULES_FILE, sect.buf, NULL) < 0) {
                /* Maybe the user already did that, don't error out here */
                warning(_("Could not remove .gitmodules entry for %s"), path);
                strbuf_release(&sect);
  
  void stage_updated_gitmodules(void)
  {
 -      if (add_file_to_cache(".gitmodules", 0))
 +      if (add_file_to_cache(GITMODULES_FILE, 0))
                die(_("staging updated .gitmodules failed"));
  }
  
@@@ -163,11 -147,11 +163,11 @@@ done
  void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
                                             const char *path)
  {
-       const struct submodule *submodule = submodule_from_path(null_sha1, path);
+       const struct submodule *submodule = submodule_from_path(&null_oid, path);
        if (submodule) {
                if (submodule->ignore)
                        handle_ignore_submodules_arg(diffopt, submodule->ignore);
 -              else if (gitmodules_is_unmerged)
 +              else if (is_gitmodules_unmerged(&the_index))
                        DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
        }
  }
  /* For loading from the .gitmodules file. */
  static int git_modules_config(const char *var, const char *value, void *cb)
  {
 -      if (!strcmp(var, "submodule.fetchjobs")) {
 -              parallel_jobs = git_config_int(var, value);
 -              if (parallel_jobs < 0)
 -                      die(_("negative values not allowed for submodule.fetchJobs"));
 -              return 0;
 -      } else if (starts_with(var, "submodule."))
 +      if (starts_with(var, "submodule."))
                return parse_submodule_config_option(var, value);
 -      else if (!strcmp(var, "fetch.recursesubmodules")) {
 -              config_fetch_recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
 -              return 0;
 -      }
        return 0;
  }
  
@@@ -230,6 -223,39 +230,6 @@@ void load_submodule_cache(void
        git_config(submodule_config, NULL);
  }
  
 -void gitmodules_config(void)
 -{
 -      const char *work_tree = get_git_work_tree();
 -      if (work_tree) {
 -              struct strbuf gitmodules_path = STRBUF_INIT;
 -              int pos;
 -              strbuf_addstr(&gitmodules_path, work_tree);
 -              strbuf_addstr(&gitmodules_path, "/.gitmodules");
 -              if (read_cache() < 0)
 -                      die("index file corrupt");
 -              pos = cache_name_pos(".gitmodules", 11);
 -              if (pos < 0) { /* .gitmodules not found or isn't merged */
 -                      pos = -1 - pos;
 -                      if (active_nr > pos) {  /* there is a .gitmodules */
 -                              const struct cache_entry *ce = active_cache[pos];
 -                              if (ce_namelen(ce) == 11 &&
 -                                  !memcmp(ce->name, ".gitmodules", 11))
 -                                      gitmodules_is_unmerged = 1;
 -                      }
 -              } else if (pos < active_nr) {
 -                      struct stat st;
 -                      if (lstat(".gitmodules", &st) == 0 &&
 -                          ce_match_stat(active_cache[pos], &st, 0) & DATA_CHANGED)
 -                              gitmodules_is_modified = 1;
 -              }
 -
 -              if (!gitmodules_is_unmerged)
 -                      git_config_from_file(git_modules_config,
 -                              gitmodules_path.buf, NULL);
 -              strbuf_release(&gitmodules_path);
 -      }
 -}
 -
  static int gitmodules_cb(const char *var, const char *value, void *data)
  {
        struct repository *repo = data;
  
  void repo_read_gitmodules(struct repository *repo)
  {
 -      char *gitmodules_path = repo_worktree_path(repo, ".gitmodules");
 +      if (repo->worktree) {
 +              char *gitmodules;
 +
 +              if (repo_read_index(repo) < 0)
 +                      return;
 +
 +              gitmodules = repo_worktree_path(repo, GITMODULES_FILE);
 +
 +              if (!is_gitmodules_unmerged(repo->index))
 +                      git_config_from_file(gitmodules_cb, gitmodules, repo);
  
 -      git_config_from_file(gitmodules_cb, gitmodules_path, repo);
 -      free(gitmodules_path);
 +              free(gitmodules);
 +      }
 +}
 +
 +void gitmodules_config(void)
 +{
 +      repo_read_gitmodules(the_repository);
  }
  
- void gitmodules_config_sha1(const unsigned char *commit_sha1)
+ void gitmodules_config_oid(const struct object_id *commit_oid)
  {
        struct strbuf rev = STRBUF_INIT;
-       unsigned char sha1[20];
+       struct object_id oid;
  
-       if (gitmodule_sha1_from_commit(commit_sha1, sha1, &rev)) {
-               git_config_from_blob_sha1(git_modules_config, rev.buf,
-                                         sha1, NULL);
+       if (gitmodule_oid_from_commit(commit_oid, &oid, &rev)) {
+               git_config_from_blob_oid(submodule_config, rev.buf,
+                                        &oid, NULL);
        }
        strbuf_release(&rev);
  }
@@@ -281,7 -293,7 +281,7 @@@ int is_submodule_active(struct reposito
        const struct string_list *sl;
        const struct submodule *module;
  
-       module = submodule_from_cache(repo, null_sha1, path);
+       module = submodule_from_cache(repo, &null_oid, path);
  
        /* early return if there isn't a path->module mapping */
        if (!module)
@@@ -708,6 -720,11 +708,6 @@@ done
                clear_commit_marks(right, ~0);
  }
  
 -void set_config_fetch_recurse_submodules(int value)
 -{
 -      config_fetch_recurse_submodules = value;
 -}
 -
  int should_update_submodules(void)
  {
        return config_update_recurse_submodules == RECURSE_SUBMODULES_ON;
@@@ -721,7 -738,7 +721,7 @@@ const struct submodule *submodule_from_
        if (!should_update_submodules())
                return NULL;
  
-       return submodule_from_path(null_sha1, ce->name);
+       return submodule_from_path(&null_oid, ce->name);
  }
  
  static struct oid_array *submodule_commits(struct string_list *submodules,
@@@ -1121,43 -1138,16 +1121,43 @@@ static void calculate_changed_submodule
        initialized_fetch_ref_tips = 0;
  }
  
 +int submodule_touches_in_range(struct object_id *excl_oid,
 +                             struct object_id *incl_oid)
 +{
 +      struct string_list subs = STRING_LIST_INIT_DUP;
 +      struct argv_array args = ARGV_ARRAY_INIT;
 +      int ret;
 +
 +      gitmodules_config();
 +      /* No need to check if there are no submodules configured */
 +      if (!submodule_from_path(NULL, NULL))
 +              return 0;
 +
 +      argv_array_push(&args, "--"); /* args[0] program name */
 +      argv_array_push(&args, oid_to_hex(incl_oid));
 +      argv_array_push(&args, "--not");
 +      argv_array_push(&args, oid_to_hex(excl_oid));
 +
 +      collect_changed_submodules(&subs, &args);
 +      ret = subs.nr;
 +
 +      argv_array_clear(&args);
 +
 +      free_submodules_oids(&subs);
 +      return ret;
 +}
 +
  struct submodule_parallel_fetch {
        int count;
        struct argv_array args;
        const char *work_tree;
        const char *prefix;
        int command_line_option;
 +      int default_option;
        int quiet;
        int result;
  };
 -#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0}
 +#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0, 0}
  
  static int get_next_submodule(struct child_process *cp,
                              struct strbuf *err, void *data, void **task_cb)
                if (!S_ISGITLINK(ce->ce_mode))
                        continue;
  
-               submodule = submodule_from_path(null_sha1, ce->name);
+               submodule = submodule_from_path(&null_oid, ce->name);
                if (!submodule)
-                       submodule = submodule_from_name(null_sha1, ce->name);
+                       submodule = submodule_from_name(&null_oid, ce->name);
  
                default_argv = "yes";
                if (spf->command_line_option == RECURSE_SUBMODULES_DEFAULT) {
                                        default_argv = "on-demand";
                                }
                        } else {
 -                              if ((config_fetch_recurse_submodules == RECURSE_SUBMODULES_OFF) ||
 -                                  gitmodules_is_unmerged)
 +                              if (spf->default_option == RECURSE_SUBMODULES_OFF)
                                        continue;
 -                              if (config_fetch_recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) {
 +                              if (spf->default_option == RECURSE_SUBMODULES_ON_DEMAND) {
                                        if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
                                                continue;
                                        default_argv = "on-demand";
@@@ -1264,7 -1255,6 +1264,7 @@@ static int fetch_finish(int retvalue, s
  
  int fetch_populated_submodules(const struct argv_array *options,
                               const char *prefix, int command_line_option,
 +                             int default_option,
                               int quiet, int max_parallel_jobs)
  {
        int i;
  
        spf.work_tree = get_git_work_tree();
        spf.command_line_option = command_line_option;
 +      spf.default_option = default_option;
        spf.quiet = quiet;
        spf.prefix = prefix;
  
        argv_array_push(&spf.args, "--recurse-submodules-default");
        /* default value, "--submodule-prefix" and its value are added later */
  
 -      if (max_parallel_jobs < 0)
 -              max_parallel_jobs = parallel_jobs;
 -
        calculate_changed_submodule_paths();
        run_processes_parallel(max_parallel_jobs,
                               get_next_submodule,
@@@ -1552,7 -1544,7 +1552,7 @@@ int submodule_move_head(const char *pat
        if (old && !is_submodule_populated_gently(path, error_code_ptr))
                return 0;
  
-       sub = submodule_from_path(null_sha1, path);
+       sub = submodule_from_path(&null_oid, path);
  
        if (!sub)
                die("BUG: could not get submodule information for '%s'", path);
@@@ -1807,6 -1799,11 +1807,6 @@@ int merge_submodule(struct object_id *r
        return 0;
  }
  
 -int parallel_submodules(void)
 -{
 -      return parallel_jobs;
 -}
 -
  /*
   * Embeds a single submodules git directory into the superprojects git dir,
   * non recursively.
@@@ -1829,7 -1826,7 +1829,7 @@@ static void relocate_single_git_dir_int
  
        real_old_git_dir = real_pathdup(old_git_dir, 1);
  
-       sub = submodule_from_path(null_sha1, path);
+       sub = submodule_from_path(&null_oid, path);
        if (!sub)
                die(_("could not lookup name for submodule '%s'"), path);
  
@@@ -1885,7 -1882,7 +1885,7 @@@ void absorb_git_dir_into_superproject(c
                * superproject did not rewrite the git file links yet,
                * fix it now.
                */
-               sub = submodule_from_path(null_sha1, path);
+               sub = submodule_from_path(&null_oid, path);
                if (!sub)
                        die(_("could not lookup name for submodule '%s'"), path);
                connect_work_tree_and_git_dir(path,
@@@ -2028,7 -2025,7 +2028,7 @@@ int submodule_to_gitdir(struct strbuf *
        }
        if (!is_git_directory(buf->buf)) {
                gitmodules_config();
-               sub = submodule_from_path(null_sha1, submodule);
+               sub = submodule_from_path(&null_oid, submodule);
                if (!sub) {
                        ret = -1;
                        goto cleanup;
diff --combined submodule.h
index 8022faa591f0d35d57189e50670ef28f66134d86,93411bdffd46b59f08ca236977643ccbd1a9f47f..e402b004ff0a7d983d196eb1fc0e34bdd2bacb93
@@@ -33,8 -33,7 +33,8 @@@ struct submodule_update_strategy 
  };
  #define SUBMODULE_UPDATE_STRATEGY_INIT {SM_UPDATE_UNSPECIFIED, NULL}
  
 -extern int is_staging_gitmodules_ok(void);
 +extern int is_gitmodules_unmerged(const struct index_state *istate);
 +extern int is_staging_gitmodules_ok(const struct index_state *istate);
  extern int update_path_in_gitmodules(const char *oldpath, const char *newpath);
  extern int remove_path_from_gitmodules(const char *path);
  extern void stage_updated_gitmodules(void);
@@@ -49,7 -48,7 +49,7 @@@ int option_parse_recurse_submodules_wor
  void load_submodule_cache(void);
  extern void gitmodules_config(void);
  extern void repo_read_gitmodules(struct repository *repo);
- extern void gitmodules_config_sha1(const unsigned char *commit_sha1);
+ extern void gitmodules_config_oid(const struct object_id *commit_oid);
  extern int is_submodule_active(struct repository *repo, const char *path);
  /*
   * Determine if a submodule has been populated at a given 'path' by checking if
@@@ -77,6 -76,7 +77,6 @@@ extern void show_submodule_inline_diff(
                unsigned dirty_submodule, const char *meta,
                const char *del, const char *add, const char *reset,
                const struct diff_options *opt);
 -extern void set_config_fetch_recurse_submodules(int value);
  /* Check if we want to update any submodule.*/
  extern int should_update_submodules(void);
  /*
@@@ -87,7 -87,6 +87,7 @@@ extern const struct submodule *submodul
  extern void check_for_new_submodule_commits(struct object_id *oid);
  extern int fetch_populated_submodules(const struct argv_array *options,
                               const char *prefix, int command_line_option,
 +                             int default_option,
                               int quiet, int max_parallel_jobs);
  extern unsigned is_submodule_modified(const char *path, int ignore_untracked);
  extern int submodule_uses_gitfile(const char *path);
@@@ -100,10 -99,6 +100,10 @@@ extern int merge_submodule(struct objec
                           const struct object_id *base,
                           const struct object_id *a,
                           const struct object_id *b, int search);
 +
 +/* Checks if there are submodule changes in a..b. */
 +extern int submodule_touches_in_range(struct object_id *a,
 +                                    struct object_id *b);
  extern int find_unpushed_submodules(struct oid_array *commits,
                                    const char *remotes_name,
                                    struct string_list *needs_pushing);
@@@ -113,6 -108,7 +113,6 @@@ extern int push_unpushed_submodules(str
                                    const struct string_list *push_options,
                                    int dry_run);
  extern void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
 -extern int parallel_submodules(void);
  /*
   * Given a submodule path (as in the index), return the repository
   * path of that submodule in 'buf'. Return -1 on error or when the