Merge branch 'bc/object-id'
authorJunio C Hamano <gitster@pobox.com>
Fri, 11 Aug 2017 20:26:55 +0000 (13:26 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 11 Aug 2017 20:26:55 +0000 (13:26 -0700)
Conversion from uchar[20] to struct object_id continues.

* 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

1  2 
builtin/grep.c
cache.h
config.c
refs.c
remote.c
revision.c
submodule-config.c
submodule-config.h
submodule.c
submodule.h
diff --combined builtin/grep.c
index 7e79eb1a754a5f604829e3e9e6d98d83712be9b6,9124450163ebf71eec82ee466b155fc2a749d93e..b10062902373590e0ebba0fc960b640b418a07dc
@@@ -653,7 -653,7 +653,7 @@@ static int grep_submodule(struct grep_o
                 */
                if (oid) {
                        const struct submodule *sub =
-                                       submodule_from_path(null_sha1, path);
+                                       submodule_from_path(&null_oid, path);
                        if (sub)
                                path = git_path("modules/%s", sub->name);
  
@@@ -862,7 -862,7 +862,7 @@@ static int grep_objects(struct grep_op
                /* 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)) {
                        hit = 1;
@@@ -1170,6 -1170,8 +1170,6 @@@ int cmd_grep(int argc, const char **arg
  
        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;
diff --combined cache.h
index a09a5017fb940a72f7a9a08c6652563b8651f2a8,cfc3698ebacb8f4961356609e94c64c8306e98cd..55eeac8148b0597fd1a539736f4e81908bd96839
+++ b/cache.h
@@@ -1146,14 -1146,6 +1146,14 @@@ char *strip_path_suffix(const char *pat
  int daemon_avoid_alias(const char *path);
  extern int is_ntfs_dotgit(const char *name);
  
 +/*
 + * Returns true iff "str" could be confused as a command-line option when
 + * passed to a sub-program like "ssh". Note that this has nothing to do with
 + * shell-quoting, which should be handled separately; we're assuming here that
 + * the string makes it verbatim to the sub-program.
 + */
 +int looks_like_command_line_option(const char *str);
 +
  /**
   * Return a newly allocated string with the evaluation of
   * "$XDG_CONFIG_HOME/git/$filename" if $XDG_CONFIG_HOME is non-empty, otherwise
@@@ -1291,38 -1283,37 +1291,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 231f9a750b96deda8d62f5a5debb384f40481566,014151d0321297098b39e8057ab7b1e10a535e6b..a1b66fe764e66e5c57bb984dd1514c01022cae22
+++ 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;
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 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 5fe2d0787745de4d97218c738b808667dc8348d3,89de1d6a53db0c2222c008f98f2bb61bb9b25df7..d48403f25eef4ea549591fdc0633b67ec3401af9
@@@ -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;
  }
  
@@@ -253,27 -250,6 +253,27 @@@ int parse_fetch_recurse_submodules_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)
  {
@@@ -441,19 -417,19 +441,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;
        }
@@@ -564,14 -540,14 +564,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 233bfcb7fff0b2dedc64fbb11d167734bf0fad7e,5f52e6567b7064bbf197f1ac8edcfde0154c9714..4ffa2fa840a5fc27ac209a2e976b118b15b124ef
@@@ -28,24 -28,21 +28,24 @@@ struct repository
  extern void submodule_cache_free(struct submodule_cache *cache);
  
  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 6531c5d6094e47b251e69ce741699abfee7a64df,f39cb4f6eafc09642ed6a7131d1cbf7a3efc34d8..27de65a4a04a45c75479ae60d43dfdab0cf6d1aa
@@@ -69,7 -69,7 +69,7 @@@ int update_path_in_gitmodules(const cha
        if (gitmodules_is_unmerged)
                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;
@@@ -103,7 -103,7 +103,7 @@@ int remove_path_from_gitmodules(const c
        if (gitmodules_is_unmerged)
                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;
@@@ -147,7 -147,7 +147,7 @@@ 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);
@@@ -270,14 -270,14 +270,14 @@@ void repo_read_gitmodules(struct reposi
        free(gitmodules_path);
  }
  
- 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);
  }
@@@ -293,7 -293,7 +293,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)
@@@ -738,7 -738,7 +738,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,
@@@ -1138,32 -1138,6 +1138,32 @@@ 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;
@@@ -1192,9 -1166,9 +1192,9 @@@ static int get_next_submodule(struct ch
                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) {
@@@ -1570,7 -1544,7 +1570,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);
@@@ -1852,7 -1826,7 +1852,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);
  
@@@ -1908,7 -1882,7 +1908,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,
@@@ -2051,7 -2025,7 +2051,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 e85b1448638ac7255a48a1bc1e2d6409c3a85ba6,93411bdffd46b59f08ca236977643ccbd1a9f47f..f1aa3ffeb19e4e477295b66f85ab4cb85d24437e
@@@ -48,7 -48,7 +48,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
@@@ -99,10 -99,6 +99,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);