Merge branch 'ab/free-and-null'
authorJunio C Hamano <gitster@pobox.com>
Sat, 24 Jun 2017 21:28:41 +0000 (14:28 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 24 Jun 2017 21:28:41 +0000 (14:28 -0700)
A common pattern to free a piece of memory and assign NULL to the
pointer that used to point at it has been replaced with a new
FREE_AND_NULL() macro.

* ab/free-and-null:
*.[ch] refactoring: make use of the FREE_AND_NULL() macro
coccinelle: make use of the "expression" FREE_AND_NULL() rule
coccinelle: add a rule to make "expression" code use FREE_AND_NULL()
coccinelle: make use of the "type" FREE_AND_NULL() rule
coccinelle: add a rule to make "type" code use FREE_AND_NULL()
git-compat-util: add a FREE_AND_NULL() wrapper around free(ptr); ptr = NULL

38 files changed:
1  2 
alias.c
apply.c
attr.c
blame.c
branch.c
builtin/am.c
builtin/clean.c
builtin/config.c
builtin/index-pack.c
builtin/pack-objects.c
builtin/unpack-objects.c
builtin/worktree.c
config.c
credential.c
diff-lib.c
diff.c
diffcore-rename.c
dir.c
fast-import.c
gpg-interface.c
grep.c
help.c
http.c
imap-send.c
line-log.c
ll-merge.c
mailinfo.c
pathspec.c
read-cache.c
refs/files-backend.c
remote-testsvn.c
rerere.c
sequencer.c
sha1_file.c
split-index.c
transport.c
tree-diff.c
tree.c
diff --combined alias.c
index de8e6a3f496accd9bd06916411ebb7e10b27d4cb,911481855f555c29c0b50a04d954accdf5b1c6f2..39f622e4141576b1170131f6c4b14316becb1a71
+++ b/alias.c
@@@ -1,29 -1,14 +1,29 @@@
  #include "cache.h"
 +#include "config.h"
 +
 +struct config_alias_data {
 +      const char *alias;
 +      char *v;
 +};
 +
 +static int config_alias_cb(const char *key, const char *value, void *d)
 +{
 +      struct config_alias_data *data = d;
 +      const char *p;
 +
 +      if (skip_prefix(key, "alias.", &p) && !strcmp(p, data->alias))
 +              return git_config_string((const char **)&data->v, key, value);
 +
 +      return 0;
 +}
  
  char *alias_lookup(const char *alias)
  {
 -      char *v = NULL;
 -      struct strbuf key = STRBUF_INIT;
 -      strbuf_addf(&key, "alias.%s", alias);
 -      if (git_config_key_is_valid(key.buf))
 -              git_config_get_string(key.buf, &v);
 -      strbuf_release(&key);
 -      return v;
 +      struct config_alias_data data = { alias, NULL };
 +
 +      read_early_config(config_alias_cb, &data);
 +
 +      return data.v;
  }
  
  #define SPLIT_CMDLINE_BAD_ENDING 1
@@@ -62,8 -47,7 +62,7 @@@ int split_cmdline(char *cmdline, const 
                                src++;
                                c = cmdline[src];
                                if (!c) {
-                                       free(*argv);
-                                       *argv = NULL;
+                                       FREE_AND_NULL(*argv);
                                        return -SPLIT_CMDLINE_BAD_ENDING;
                                }
                        }
@@@ -75,8 -59,7 +74,7 @@@
        cmdline[dst] = 0;
  
        if (quoted) {
-               free(*argv);
-               *argv = NULL;
+               FREE_AND_NULL(*argv);
                return -SPLIT_CMDLINE_UNCLOSED_QUOTE;
        }
  
diff --combined apply.c
index f7251ccc8b42c789c1bed785d93cdeba4406480f,e78de0affa92beb8408304d4fe90684891017766..b963d7d8fb7ee81300d4383b7bc007fc74af84c5
+++ b/apply.c
@@@ -8,7 -8,6 +8,7 @@@
   */
  
  #include "cache.h"
 +#include "config.h"
  #include "blob.h"
  #include "delta.h"
  #include "diff.h"
@@@ -763,6 -762,17 +763,6 @@@ static char *find_name_traditional(stru
        return find_name_common(state, line, def, p_value, line + len, 0);
  }
  
 -static int count_slashes(const char *cp)
 -{
 -      int cnt = 0;
 -      char ch;
 -
 -      while ((ch = *cp++))
 -              if (ch == '/')
 -                      cnt++;
 -      return cnt;
 -}
 -
  /*
   * Given the string after "--- " or "+++ ", guess the appropriate
   * p_value for the given patch.
@@@ -2257,7 -2267,7 +2257,7 @@@ static int read_old_data(struct stat *s
        case S_IFREG:
                if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
                        return error(_("unable to open or read %s"), path);
 -              convert_to_git(path, buf->buf, buf->len, buf, 0);
 +              convert_to_git(&the_index, path, buf->buf, buf->len, buf, 0);
                return 0;
        default:
                return -1;
@@@ -3695,8 -3705,7 +3695,7 @@@ static int check_preimage(struct apply_
   is_new:
        patch->is_new = 1;
        patch->is_delete = 0;
-       free(patch->old_name);
-       patch->old_name = NULL;
+       FREE_AND_NULL(patch->old_name);
        return 0;
  }
  
diff --combined attr.c
index 6e4b247acd91d30ac5a879183332725d54e756a0,ebdcfb0b8a8e9ddb50f559336146140b4b167e06..37454999d21e9dcea73e6717da608d80720235e8
--- 1/attr.c
--- 2/attr.c
+++ b/attr.c
@@@ -9,7 -9,6 +9,7 @@@
  
  #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
 +#include "config.h"
  #include "exec_cmd.h"
  #include "attr.h"
  #include "dir.h"
@@@ -639,13 -638,11 +639,11 @@@ void attr_check_reset(struct attr_chec
  
  void attr_check_clear(struct attr_check *check)
  {
-       free(check->items);
-       check->items = NULL;
+       FREE_AND_NULL(check->items);
        check->alloc = 0;
        check->nr = 0;
  
-       free(check->all_attrs);
-       check->all_attrs = NULL;
+       FREE_AND_NULL(check->all_attrs);
        check->all_attrs_nr = 0;
  
        drop_attr_stack(&check->stack);
diff --combined blame.c
index 6d57ab9715665a8bc6a2ba02015342ad851b6d2f,1183943960fab33f19067b28c346d12a6b99ec43..91e26e93e8a23d0af63e1bc8a74e9f7690276ab4
+++ b/blame.c
@@@ -229,7 -229,7 +229,7 @@@ static struct commit *fake_working_tree
                if (strbuf_read(&buf, 0, 0) < 0)
                        die_errno("failed to read from stdin");
        }
 -      convert_to_git(path, buf.buf, buf.len, &buf, 0);
 +      convert_to_git(&the_index, path, buf.buf, buf.len, &buf, 0);
        origin->file.ptr = buf.buf;
        origin->file.size = buf.len;
        pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_oid.hash);
@@@ -314,8 -314,7 +314,7 @@@ static void fill_origin_blob(struct dif
  static void drop_origin_blob(struct blame_origin *o)
  {
        if (o->file.ptr) {
-               free(o->file.ptr);
-               o->file.ptr = NULL;
+               FREE_AND_NULL(o->file.ptr);
        }
  }
  
@@@ -556,9 -555,9 +555,9 @@@ static struct blame_origin *find_origin
        if (is_null_oid(&origin->commit->object.oid))
                do_diff_cache(&parent->tree->object.oid, &diff_opts);
        else
 -              diff_tree_sha1(parent->tree->object.oid.hash,
 -                             origin->commit->tree->object.oid.hash,
 -                             "", &diff_opts);
 +              diff_tree_oid(&parent->tree->object.oid,
 +                            &origin->commit->tree->object.oid,
 +                            "", &diff_opts);
        diffcore_std(&diff_opts);
  
        if (!diff_queued_diff.nr) {
@@@ -625,9 -624,9 +624,9 @@@ static struct blame_origin *find_rename
        if (is_null_oid(&origin->commit->object.oid))
                do_diff_cache(&parent->tree->object.oid, &diff_opts);
        else
 -              diff_tree_sha1(parent->tree->object.oid.hash,
 -                             origin->commit->tree->object.oid.hash,
 -                             "", &diff_opts);
 +              diff_tree_oid(&parent->tree->object.oid,
 +                            &origin->commit->tree->object.oid,
 +                            "", &diff_opts);
        diffcore_std(&diff_opts);
  
        for (i = 0; i < diff_queued_diff.nr; i++) {
@@@ -1247,7 -1246,7 +1246,7 @@@ static void find_copy_in_parent(struct 
        /* Try "find copies harder" on new path if requested;
         * we do not want to use diffcore_rename() actually to
         * match things up; find_copies_harder is set only to
 -       * force diff_tree_sha1() to feed all filepairs to diff_queue,
 +       * force diff_tree_oid() to feed all filepairs to diff_queue,
         * and this code needs to be after diff_setup_done(), which
         * usually makes find-copies-harder imply copy detection.
         */
        if (is_null_oid(&target->commit->object.oid))
                do_diff_cache(&parent->tree->object.oid, &diff_opts);
        else
 -              diff_tree_sha1(parent->tree->object.oid.hash,
 -                             target->commit->tree->object.oid.hash,
 -                             "", &diff_opts);
 +              diff_tree_oid(&parent->tree->object.oid,
 +                            &target->commit->tree->object.oid,
 +                            "", &diff_opts);
  
        if (!DIFF_OPT_TST(&diff_opts, FIND_COPIES_HARDER))
                diffcore_std(&diff_opts);
diff --combined branch.c
index a8a548ccf2870c99bbdbcdc7036003aa648faa0c,2347cb86495c97d4e6941c72b31895c865ed421c..36541d05cd7b934bceba1af4fd4c121e51cd862b
+++ b/branch.c
@@@ -1,6 -1,5 +1,6 @@@
  #include "git-compat-util.h"
  #include "cache.h"
 +#include "config.h"
  #include "branch.h"
  #include "refs.h"
  #include "remote.h"
@@@ -25,8 -24,7 +25,7 @@@ static int find_tracked_branch(struct r
                } else {
                        free(tracking->spec.src);
                        if (tracking->src) {
-                               free(tracking->src);
-                               tracking->src = NULL;
+                               FREE_AND_NULL(tracking->src);
                        }
                }
                tracking->spec.src = NULL;
diff --combined builtin/am.c
index 7c7b916d2328be8e6dc7abb7e08bb9416b21d2e6,80368b6fe6affa5b28d19266b09d343e1ac55324..c973bd96dcb5d630d56e935733bfa4530ccd2872
@@@ -4,7 -4,6 +4,7 @@@
   * Based on git-am.sh by Junio C Hamano.
   */
  #include "cache.h"
 +#include "config.h"
  #include "builtin.h"
  #include "exec_cmd.h"
  #include "parse-options.h"
@@@ -484,8 -483,7 +484,7 @@@ static int run_applypatch_msg_hook(stru
        ret = run_hook_le(NULL, "applypatch-msg", am_path(state, "final-commit"), NULL);
  
        if (!ret) {
-               free(state->msg);
-               state->msg = NULL;
+               FREE_AND_NULL(state->msg);
                if (read_commit_msg(state) < 0)
                        die(_("'%s' was deleted by the applypatch-msg hook"),
                                am_path(state, "final-commit"));
@@@ -564,7 -562,7 +563,7 @@@ static int copy_notes_for_rebase(const 
                        goto finish;
                }
  
 -              if (copy_note_for_rewrite(c, from_obj.hash, to_obj.hash))
 +              if (copy_note_for_rewrite(c, &from_obj, &to_obj))
                        ret = error(_("Failed to copy notes from '%s' to '%s'"),
                                        oid_to_hex(&from_obj), oid_to_hex(&to_obj));
        }
@@@ -1074,17 -1072,10 +1073,10 @@@ static void am_next(struct am_state *st
  {
        struct object_id head;
  
-       free(state->author_name);
-       state->author_name = NULL;
-       free(state->author_email);
-       state->author_email = NULL;
-       free(state->author_date);
-       state->author_date = NULL;
-       free(state->msg);
-       state->msg = NULL;
+       FREE_AND_NULL(state->author_name);
+       FREE_AND_NULL(state->author_email);
+       FREE_AND_NULL(state->author_date);
+       FREE_AND_NULL(state->msg);
        state->msg_len = 0;
  
        unlink(am_path(state, "author-script"));
diff --combined builtin/clean.c
index ed954134d2dd03242a06eef88bcaec71cc41ffe9,bff5a07330ea2e7e2609d4fb138ff71b7f527614..057fc97fe4494338e6a85ac9f695563f1fcb9596
@@@ -8,7 -8,6 +8,7 @@@
  
  #include "builtin.h"
  #include "cache.h"
 +#include "config.h"
  #include "dir.h"
  #include "parse-options.h"
  #include "string-list.h"
@@@ -838,8 -837,7 +838,7 @@@ static void interactive_main_loop(void
                        int ret;
                        ret = menus[*chosen].fn();
                        if (ret != MENU_RETURN_NO_LOOP) {
-                               free(chosen);
-                               chosen = NULL;
+                               FREE_AND_NULL(chosen);
                                if (!del_list.nr) {
                                        clean_print_color(CLEAN_COLOR_ERROR);
                                        printf_ln(_("No more files to clean, exiting."));
                        quit_cmd();
                }
  
-               free(chosen);
-               chosen = NULL;
+               FREE_AND_NULL(chosen);
                break;
        }
  }
diff --combined builtin/config.c
index 82db29fae71551a44150c64a4c1187ef4ebd572a,18c2158630d85b389f43204fa58c538c0d021b40..70ff231e9c5bce550e7af20ddfe91b8b68ee32ae
@@@ -1,6 -1,5 +1,6 @@@
  #include "builtin.h"
  #include "cache.h"
 +#include "config.h"
  #include "color.h"
  #include "parse-options.h"
  #include "urlmatch.h"
@@@ -215,8 -214,7 +215,7 @@@ static int get_value(const char *key_, 
                key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(key_regexp, key, REG_EXTENDED)) {
                        error("invalid key pattern: %s", key_);
-                       free(key_regexp);
-                       key_regexp = NULL;
+                       FREE_AND_NULL(key_regexp);
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
                regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(regexp, regex_, REG_EXTENDED)) {
                        error("invalid pattern: %s", regex_);
-                       free(regexp);
-                       regexp = NULL;
+                       FREE_AND_NULL(regexp);
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
        }
  
 -      git_config_with_options(collect_config, &values,
 -                              &given_config_source, &config_options);
 +      config_with_options(collect_config, &values,
 +                          &given_config_source, &config_options);
  
        ret = !values.nr;
  
@@@ -321,8 -318,8 +319,8 @@@ static void get_color(const char *var, 
        get_color_slot = var;
        get_color_found = 0;
        parsed_color[0] = '\0';
 -      git_config_with_options(git_get_color_config, NULL,
 -                              &given_config_source, &config_options);
 +      config_with_options(git_get_color_config, NULL,
 +                          &given_config_source, &config_options);
  
        if (!get_color_found && def_color) {
                if (color_parse(def_color, parsed_color) < 0)
@@@ -353,8 -350,8 +351,8 @@@ static int get_colorbool(const char *va
        get_colorbool_found = -1;
        get_diff_color_found = -1;
        get_color_ui_found = -1;
 -      git_config_with_options(git_get_colorbool_config, NULL,
 -                              &given_config_source, &config_options);
 +      config_with_options(git_get_colorbool_config, NULL,
 +                          &given_config_source, &config_options);
  
        if (get_colorbool_found < 0) {
                if (!strcmp(get_colorbool_slot, "color.diff"))
@@@ -442,8 -439,8 +440,8 @@@ static int get_urlmatch(const char *var
                show_keys = 1;
        }
  
 -      git_config_with_options(urlmatch_config_entry, &config,
 -                              &given_config_source, &config_options);
 +      config_with_options(urlmatch_config_entry, &config,
 +                          &given_config_source, &config_options);
  
        ret = !values.nr;
  
@@@ -539,10 -536,6 +537,10 @@@ int cmd_config(int argc, const char **a
                config_options.respect_includes = !given_config_source.file;
        else
                config_options.respect_includes = respect_includes_opt;
 +      if (!nongit) {
 +              config_options.commondir = get_git_common_dir();
 +              config_options.git_dir = get_git_dir();
 +      }
  
        if (end_null) {
                term = '\0';
  
        if (actions == ACTION_LIST) {
                check_argc(argc, 0, 0);
 -              if (git_config_with_options(show_all_config, NULL,
 -                                          &given_config_source,
 -                                          &config_options) < 0) {
 +              if (config_with_options(show_all_config, NULL,
 +                                      &given_config_source,
 +                                      &config_options) < 0) {
                        if (given_config_source.file)
                                die_errno("unable to read config file '%s'",
                                          given_config_source.file);
diff --combined builtin/index-pack.c
index edc1a91d89b308b1e164c48c1dfb06c8f6ebf0d1,f3b16520c2e838fd6fb29aaa61e548fc7218b9c4..ad4de3517853892e979d43511e2e7260746c3ba9
@@@ -1,5 -1,4 +1,5 @@@
  #include "builtin.h"
 +#include "config.h"
  #include "delta.h"
  #include "pack.h"
  #include "csum-file.h"
@@@ -389,8 -388,7 +389,7 @@@ static struct base_data *alloc_base_dat
  static void free_base_data(struct base_data *c)
  {
        if (c->data) {
-               free(c->data);
-               c->data = NULL;
+               FREE_AND_NULL(c->data);
                get_thread_data()->base_cache_used -= c->size;
        }
  }
@@@ -606,8 -604,7 +605,7 @@@ static void *unpack_data(struct object_
        git_inflate_end(&stream);
        free(inbuf);
        if (consume) {
-               free(data);
-               data = NULL;
+               FREE_AND_NULL(data);
        }
        return data;
  }
diff --combined builtin/pack-objects.c
index d5e96ed2d0ce0d74a40961f6729896722dacf9a2,790615b2c3a5782e9233206f4edaa277de6c9972..f4a8441fe913850e7a1cadf3376837237519e761
@@@ -1,6 -1,5 +1,6 @@@
  #include "builtin.h"
  #include "cache.h"
 +#include "config.h"
  #include "attr.h"
  #include "object.h"
  #include "blob.h"
@@@ -265,8 -264,7 +265,7 @@@ static unsigned long write_no_reuse_obj
                 * make sure no cached delta data remains from a
                 * previous attempt before a pack split occurred.
                 */
-               free(entry->delta_data);
-               entry->delta_data = NULL;
+               FREE_AND_NULL(entry->delta_data);
                entry->z_delta_size = 0;
        } else if (entry->delta_data) {
                size = entry->delta_size;
@@@ -1376,12 -1374,10 +1375,10 @@@ static void cleanup_preferred_base(void
                if (!pbase_tree_cache[i])
                        continue;
                free(pbase_tree_cache[i]->tree_data);
-               free(pbase_tree_cache[i]);
-               pbase_tree_cache[i] = NULL;
+               FREE_AND_NULL(pbase_tree_cache[i]);
        }
  
-       free(done_pbase_paths);
-       done_pbase_paths = NULL;
+       FREE_AND_NULL(done_pbase_paths);
        done_pbase_paths_num = done_pbase_paths_alloc = 0;
  }
  
@@@ -1971,8 -1967,7 +1968,7 @@@ static unsigned long free_unpacked(stru
        n->index = NULL;
        if (n->data) {
                freed_mem += n->entry->size;
-               free(n->data);
-               n->data = NULL;
+               FREE_AND_NULL(n->data);
        }
        n->entry = NULL;
        n->depth = 0;
diff --combined builtin/unpack-objects.c
index 193f8b9d57f0759c38004fd1d99f660919ac30e3,60bfe487893f9ac6c2523242f20ad3d335e3a7fd..689a29fac1a50df6e5b8fc3cda617ef1c6d060b3
@@@ -1,6 -1,5 +1,6 @@@
  #include "builtin.h"
  #include "cache.h"
 +#include "config.h"
  #include "object.h"
  #include "delta.h"
  #include "pack.h"
@@@ -113,8 -112,7 +113,7 @@@ static void *get_data(unsigned long siz
                        break;
                if (ret != Z_OK) {
                        error("inflate returned %d", ret);
-                       free(buf);
-                       buf = NULL;
+                       FREE_AND_NULL(buf);
                        if (!recover)
                                exit(1);
                        has_errors = 1;
diff --combined builtin/worktree.c
index 0c5476ee9de464cb0fae22c49775bc10efb0731b,41d1c007a4d6bf52c270f8eaf6933f72a97d1909..c98e2ce5f57c1f41ccaf90041a1a22233ae75551
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "builtin.h"
  #include "dir.h"
  #include "parse-options.h"
@@@ -300,10 -299,8 +300,8 @@@ static int add_worktree(const char *pat
        }
  
        is_junk = 0;
-       free(junk_work_tree);
-       free(junk_git_dir);
-       junk_work_tree = NULL;
-       junk_git_dir = NULL;
+       FREE_AND_NULL(junk_work_tree);
+       FREE_AND_NULL(junk_git_dir);
  
  done:
        if (ret || !opts->keep_locked) {
diff --combined config.c
index 6f0f8b30f39ba3a32d1a1795bdf12d78c5ea97f9,0501a60dd241320b686fa76ff570fd72ff9ce895..1cd40a5fe6802db723de0d0c78b7d316735e80b3
+++ b/config.c
@@@ -6,7 -6,6 +6,7 @@@
   *
   */
  #include "cache.h"
 +#include "config.h"
  #include "lockfile.h"
  #include "exec_cmd.h"
  #include "strbuf.h"
@@@ -219,6 -218,8 +219,6 @@@ static int include_by_gitdir(const stru
  
        if (opts->git_dir)
                git_dir = opts->git_dir;
 -      else if (have_git_dir())
 -              git_dir = get_git_dir();
        else
                goto done;
  
@@@ -394,8 -395,7 +394,7 @@@ static int git_config_parse_key_1(cons
  
  out_free_ret_1:
        if (store_key) {
-               free(*store_key);
-               *store_key = NULL;
+               FREE_AND_NULL(*store_key);
        }
        return -CONFIG_INVALID_KEY;
  }
@@@ -603,8 -603,7 +602,8 @@@ static int get_value(config_fn_t fn, vo
         */
        cf->linenr--;
        ret = fn(name->buf, value, data);
 -      cf->linenr++;
 +      if (ret >= 0)
 +              cf->linenr++;
        return ret;
  }
  
@@@ -1545,8 -1544,10 +1544,8 @@@ static int do_git_config_sequence(cons
        char *user_config = expand_user_path("~/.gitconfig", 0);
        char *repo_config;
  
 -      if (opts->git_dir)
 -              repo_config = mkpathdup("%s/config", opts->git_dir);
 -      else if (have_git_dir())
 -              repo_config = git_pathdup("config");
 +      if (opts->commondir)
 +              repo_config = mkpathdup("%s/config", opts->commondir);
        else
                repo_config = NULL;
  
        return ret;
  }
  
 -int git_config_with_options(config_fn_t fn, void *data,
 -                          struct git_config_source *config_source,
 -                          const struct config_options *opts)
 +int config_with_options(config_fn_t fn, void *data,
 +                      struct git_config_source *config_source,
 +                      const struct config_options *opts)
  {
        struct config_include_data inc = CONFIG_INCLUDE_INIT;
  
@@@ -1610,14 -1611,9 +1609,14 @@@ static void git_config_raw(config_fn_t 
        struct config_options opts = {0};
  
        opts.respect_includes = 1;
 -      if (git_config_with_options(fn, data, NULL, &opts) < 0)
 +      if (have_git_dir()) {
 +              opts.commondir = get_git_common_dir();
 +              opts.git_dir = get_git_dir();
 +      }
 +
 +      if (config_with_options(fn, data, NULL, &opts) < 0)
                /*
 -               * git_config_with_options() normally returns only
 +               * config_with_options() normally returns only
                 * zero, as most errors are fatal, and
                 * non-fatal potential errors are guarded by "if"
                 * statements that are entered only when no error is
@@@ -1656,13 -1652,11 +1655,13 @@@ static void configset_iter(struct confi
  void read_early_config(config_fn_t cb, void *data)
  {
        struct config_options opts = {0};
 -      struct strbuf buf = STRBUF_INIT;
 +      struct strbuf commondir = STRBUF_INIT;
 +      struct strbuf gitdir = STRBUF_INIT;
  
        opts.respect_includes = 1;
  
 -      if (have_git_dir())
 +      if (have_git_dir()) {
 +              opts.commondir = get_git_common_dir();
                opts.git_dir = get_git_dir();
        /*
         * When setup_git_directory() was not yet asked to discover the
         * notably, the current working directory is still the same after the
         * call).
         */
 -      else if (discover_git_directory(&buf))
 -              opts.git_dir = buf.buf;
 +      } else if (!discover_git_directory(&commondir, &gitdir)) {
 +              opts.commondir = commondir.buf;
 +              opts.git_dir = gitdir.buf;
 +      }
  
 -      git_config_with_options(cb, data, NULL, &opts);
 +      config_with_options(cb, data, NULL, &opts);
  
 -      strbuf_release(&buf);
 +      strbuf_release(&commondir);
 +      strbuf_release(&gitdir);
  }
  
  static void git_config_check_init(void);
diff --combined credential.c
index 67a523353b105764783b683a23b51d7d6a3bfda3,924ab58538accd8815d8a7c39d5c42ba9441f28e..9747f47b18bf2e622f11f41889faaa4b1845ac8d
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "credential.h"
  #include "string-list.h"
  #include "run-command.h"
@@@ -94,8 -93,7 +94,7 @@@ static void credential_apply_config(str
        c->configured = 1;
  
        if (!c->use_http_path && proto_is_http(c->protocol)) {
-               free(c->path);
-               c->path = NULL;
+               FREE_AND_NULL(c->path);
        }
  }
  
@@@ -315,10 -313,8 +314,8 @@@ void credential_reject(struct credentia
        for (i = 0; i < c->helpers.nr; i++)
                credential_do(c, c->helpers.items[i].string, "erase");
  
-       free(c->username);
-       c->username = NULL;
-       free(c->password);
-       c->password = NULL;
+       FREE_AND_NULL(c->username);
+       FREE_AND_NULL(c->password);
        c->approved = 0;
  }
  
diff --combined diff-lib.c
index 0c0e20f7c004119cd86bc377722eca6d318cdf5d,7528f4163f87f10628405e6e82e9facac7e0fc35..2a52b079546cb01d8dfe708f7e7c7e38ec582435
@@@ -101,7 -101,7 +101,7 @@@ int run_diff_files(struct rev_info *rev
                struct cache_entry *ce = active_cache[i];
                int changed;
                unsigned dirty_submodule = 0;
 -              const unsigned char *old_sha1, *new_sha1;
 +              const struct object_id *old_oid, *new_oid;
  
                if (diff_can_quit_early(&revs->diffopt))
                        break;
                                free(dpath);
                                continue;
                        }
-                       free(dpath);
-                       dpath = NULL;
+                       FREE_AND_NULL(dpath);
  
                        /*
                         * Show the diff for the 'ce' if we found the one
                                        continue;
                                }
                                diff_addremove(&revs->diffopt, '-', ce->ce_mode,
 -                                             ce->oid.hash,
 +                                             &ce->oid,
                                               !is_null_oid(&ce->oid),
                                               ce->name, 0);
                                continue;
                        } else if (revs->diffopt.ita_invisible_in_index &&
                                   ce_intent_to_add(ce)) {
                                diff_addremove(&revs->diffopt, '+', ce->ce_mode,
 -                                             EMPTY_BLOB_SHA1_BIN, 0,
 +                                             &empty_tree_oid, 0,
                                               ce->name, 0);
                                continue;
                        }
                                continue;
                }
                oldmode = ce->ce_mode;
 -              old_sha1 = ce->oid.hash;
 -              new_sha1 = changed ? null_sha1 : ce->oid.hash;
 +              old_oid = &ce->oid;
 +              new_oid = changed ? &null_oid : &ce->oid;
                diff_change(&revs->diffopt, oldmode, newmode,
 -                          old_sha1, new_sha1,
 -                          !is_null_sha1(old_sha1),
 -                          !is_null_sha1(new_sha1),
 +                          old_oid, new_oid,
 +                          !is_null_oid(old_oid),
 +                          !is_null_oid(new_oid),
                            ce->name, 0, dirty_submodule);
  
        }
  static void diff_index_show_file(struct rev_info *revs,
                                 const char *prefix,
                                 const struct cache_entry *ce,
 -                               const unsigned char *sha1, int sha1_valid,
 +                               const struct object_id *oid, int oid_valid,
                                 unsigned int mode,
                                 unsigned dirty_submodule)
  {
        diff_addremove(&revs->diffopt, prefix[0], mode,
 -                     sha1, sha1_valid, ce->name, dirty_submodule);
 +                     oid, oid_valid, ce->name, dirty_submodule);
  }
  
  static int get_stat_data(const struct cache_entry *ce,
 -                       const unsigned char **sha1p,
 +                       const struct object_id **oidp,
                         unsigned int *modep,
                         int cached, int match_missing,
                         unsigned *dirty_submodule, struct diff_options *diffopt)
  {
 -      const unsigned char *sha1 = ce->oid.hash;
 +      const struct object_id *oid = &ce->oid;
        unsigned int mode = ce->ce_mode;
  
        if (!cached && !ce_uptodate(ce)) {
                        return -1;
                else if (changed) {
                        if (match_missing) {
 -                              *sha1p = sha1;
 +                              *oidp = oid;
                                *modep = mode;
                                return 0;
                        }
                                                    0, dirty_submodule);
                if (changed) {
                        mode = ce_mode_from_stat(ce, st.st_mode);
 -                      sha1 = null_sha1;
 +                      oid = &null_oid;
                }
        }
  
 -      *sha1p = sha1;
 +      *oidp = oid;
        *modep = mode;
        return 0;
  }
@@@ -303,7 -302,7 +302,7 @@@ static void show_new_file(struct rev_in
                          const struct cache_entry *new,
                          int cached, int match_missing)
  {
 -      const unsigned char *sha1;
 +      const struct object_id *oid;
        unsigned int mode;
        unsigned dirty_submodule = 0;
  
         * New file in the index: it might actually be different in
         * the working tree.
         */
 -      if (get_stat_data(new, &sha1, &mode, cached, match_missing,
 +      if (get_stat_data(new, &oid, &mode, cached, match_missing,
            &dirty_submodule, &revs->diffopt) < 0)
                return;
  
 -      diff_index_show_file(revs, "+", new, sha1, !is_null_sha1(sha1), mode, dirty_submodule);
 +      diff_index_show_file(revs, "+", new, oid, !is_null_oid(oid), mode, dirty_submodule);
  }
  
  static int show_modified(struct rev_info *revs,
                         int cached, int match_missing)
  {
        unsigned int mode, oldmode;
 -      const unsigned char *sha1;
 +      const struct object_id *oid;
        unsigned dirty_submodule = 0;
  
 -      if (get_stat_data(new, &sha1, &mode, cached, match_missing,
 +      if (get_stat_data(new, &oid, &mode, cached, match_missing,
                          &dirty_submodule, &revs->diffopt) < 0) {
                if (report_missing)
                        diff_index_show_file(revs, "-", old,
 -                                           old->oid.hash, 1, old->ce_mode,
 +                                           &old->oid, 1, old->ce_mode,
                                             0);
                return -1;
        }
  
        if (revs->combine_merges && !cached &&
 -          (hashcmp(sha1, old->oid.hash) || oidcmp(&old->oid, &new->oid))) {
 +          (oidcmp(oid, &old->oid) || oidcmp(&old->oid, &new->oid))) {
                struct combine_diff_path *p;
                int pathlen = ce_namelen(new);
  
        }
  
        oldmode = old->ce_mode;
 -      if (mode == oldmode && !hashcmp(sha1, old->oid.hash) && !dirty_submodule &&
 +      if (mode == oldmode && !oidcmp(oid, &old->oid) && !dirty_submodule &&
            !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
                return 0;
  
        diff_change(&revs->diffopt, oldmode, mode,
 -                  old->oid.hash, sha1, 1, !is_null_sha1(sha1),
 +                  &old->oid, oid, 1, !is_null_oid(oid),
                    old->name, 0, dirty_submodule);
        return 0;
  }
@@@ -409,7 -408,7 +408,7 @@@ static void do_oneway_diff(struct unpac
                struct diff_filepair *pair;
                pair = diff_unmerge(&revs->diffopt, idx->name);
                if (tree)
 -                      fill_filespec(pair->one, tree->oid.hash, 1,
 +                      fill_filespec(pair->one, &tree->oid, 1,
                                      tree->ce_mode);
                return;
        }
         * Something removed from the tree?
         */
        if (!idx) {
 -              diff_index_show_file(revs, "-", tree, tree->oid.hash, 1,
 +              diff_index_show_file(revs, "-", tree, &tree->oid, 1,
                                     tree->ce_mode, 0);
                return;
        }
diff --combined diff.c
index 41295d4ea9ff5564fa73d45aaa3afaab20103d87,3561adf49f3f742d88767f63980c7a17bd27ff20..00b4c86698e6badb5d2904cacb3ba7d92c018d76
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -2,7 -2,6 +2,7 @@@
   * Copyright (C) 2005 Junio C Hamano
   */
  #include "cache.h"
 +#include "config.h"
  #include "tempfile.h"
  #include "quote.h"
  #include "diff.h"
@@@ -1219,8 -1218,7 +1219,7 @@@ static void free_diff_words_data(struc
                        regfree(ecbdata->diff_words->word_regex);
                        free(ecbdata->diff_words->word_regex);
                }
-               free(ecbdata->diff_words);
-               ecbdata->diff_words = NULL;
+               FREE_AND_NULL(ecbdata->diff_words);
        }
  }
  
@@@ -2703,13 -2701,13 +2702,13 @@@ void free_filespec(struct diff_filespe
        }
  }
  
 -void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
 -                 int sha1_valid, unsigned short mode)
 +void fill_filespec(struct diff_filespec *spec, const struct object_id *oid,
 +                 int oid_valid, unsigned short mode)
  {
        if (mode) {
                spec->mode = canon_mode(mode);
 -              hashcpy(spec->oid.hash, sha1);
 -              spec->oid_valid = sha1_valid;
 +              oidcpy(&spec->oid, oid);
 +              spec->oid_valid = oid_valid;
        }
  }
  
   * the work tree has that object contents, return true, so that
   * prepare_temp_file() does not have to inflate and extract.
   */
 -static int reuse_worktree_file(const char *name, const unsigned char *sha1, int want_file)
 +static int reuse_worktree_file(const char *name, const struct object_id *oid, int want_file)
  {
        const struct cache_entry *ce;
        struct stat st;
         * objects however would tend to be slower as they need
         * to be individually opened and inflated.
         */
 -      if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1))
 +      if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(oid->hash))
                return 0;
  
        /*
         * Similarly, if we'd have to convert the file contents anyway, that
         * makes the optimization not worthwhile.
         */
 -      if (!want_file && would_convert_to_git(name))
 +      if (!want_file && would_convert_to_git(&the_index, name))
                return 0;
  
        len = strlen(name);
         * This is not the sha1 we are looking for, or
         * unreusable because it is not a regular file.
         */
 -      if (hashcmp(sha1, ce->oid.hash) || !S_ISREG(ce->ce_mode))
 +      if (oidcmp(oid, &ce->oid) || !S_ISREG(ce->ce_mode))
                return 0;
  
        /*
@@@ -2843,7 -2841,7 +2842,7 @@@ int diff_populate_filespec(struct diff_
                return diff_populate_gitlink(s, size_only);
  
        if (!s->oid_valid ||
 -          reuse_worktree_file(s->path, s->oid.hash, 0)) {
 +          reuse_worktree_file(s->path, &s->oid, 0)) {
                struct strbuf buf = STRBUF_INIT;
                struct stat st;
                int fd;
                 * point if the path requires us to run the content
                 * conversion.
                 */
 -              if (size_only && !would_convert_to_git(s->path))
 +              if (size_only && !would_convert_to_git(&the_index, s->path))
                        return 0;
  
                /*
                /*
                 * Convert from working tree format to canonical git format
                 */
 -              if (convert_to_git(s->path, s->data, s->size, &buf, crlf_warn)) {
 +              if (convert_to_git(&the_index, s->path, s->data, s->size, &buf, crlf_warn)) {
                        size_t size = 0;
                        munmap(s->data, s->size);
                        s->should_munmap = 0;
@@@ -2952,8 -2950,7 +2951,7 @@@ void diff_free_filespec_blob(struct dif
  void diff_free_filespec_data(struct diff_filespec *s)
  {
        diff_free_filespec_blob(s);
-       free(s->cnt_data);
-       s->cnt_data = NULL;
+       FREE_AND_NULL(s->cnt_data);
  }
  
  static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
@@@ -3009,7 -3006,7 +3007,7 @@@ static struct diff_tempfile *prepare_te
  
        if (!S_ISGITLINK(one->mode) &&
            (!one->oid_valid ||
 -           reuse_worktree_file(name, one->oid.hash, 1))) {
 +           reuse_worktree_file(name, &one->oid, 1))) {
                struct stat st;
                if (lstat(name, &st) < 0) {
                        if (errno == ENOENT)
                        /* we can borrow from the file in the work tree */
                        temp->name = name;
                        if (!one->oid_valid)
 -                              sha1_to_hex_r(temp->hex, null_sha1);
 +                              oid_to_hex_r(temp->hex, &null_oid);
                        else
                                oid_to_hex_r(temp->hex, &one->oid);
                        /* Even though we may sometimes borrow the
                         * contents from the work tree, we always want
                         * one->mode.  mode is trustworthy even when
 -                       * !(one->sha1_valid), as long as
 +                       * !(one->oid_valid), as long as
                         * DIFF_FILE_VALID(one).
                         */
                        xsnprintf(temp->mode, sizeof(temp->mode), "%06o", one->mode);
@@@ -3240,7 -3237,7 +3238,7 @@@ static void run_diff_cmd(const char *pg
                fprintf(o->file, "* Unmerged path %s\n", name);
  }
  
 -static void diff_fill_sha1_info(struct diff_filespec *one)
 +static void diff_fill_oid_info(struct diff_filespec *one)
  {
        if (DIFF_FILE_VALID(one)) {
                if (!one->oid_valid) {
@@@ -3299,8 -3296,8 +3297,8 @@@ static void run_diff(struct diff_filepa
                return;
        }
  
 -      diff_fill_sha1_info(one);
 -      diff_fill_sha1_info(two);
 +      diff_fill_oid_info(one);
 +      diff_fill_oid_info(two);
  
        if (!pgm &&
            DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
@@@ -3345,8 -3342,8 +3343,8 @@@ static void run_diffstat(struct diff_fi
        if (o->prefix_length)
                strip_prefix(o->prefix_length, &name, &other);
  
 -      diff_fill_sha1_info(p->one);
 -      diff_fill_sha1_info(p->two);
 +      diff_fill_oid_info(p->one);
 +      diff_fill_oid_info(p->two);
  
        builtin_diffstat(name, other, p->one, p->two, diffstat, o, p);
  }
@@@ -3369,8 -3366,8 +3367,8 @@@ static void run_checkdiff(struct diff_f
        if (o->prefix_length)
                strip_prefix(o->prefix_length, &name, &other);
  
 -      diff_fill_sha1_info(p->one);
 -      diff_fill_sha1_info(p->two);
 +      diff_fill_oid_info(p->one);
 +      diff_fill_oid_info(p->two);
  
        builtin_checkdiff(name, other, attr_path, p->one, p->two, o);
  }
@@@ -4583,7 -4580,7 +4581,7 @@@ static void patch_id_add_mode(git_SHA_C
  }
  
  /* returns 0 upon success, and writes result into sha1 */
 -static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only)
 +static int diff_get_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only)
  {
        struct diff_queue_struct *q = &diff_queued_diff;
        int i;
                if (DIFF_PAIR_UNMERGED(p))
                        continue;
  
 -              diff_fill_sha1_info(p->one);
 -              diff_fill_sha1_info(p->two);
 +              diff_fill_oid_info(p->one);
 +              diff_fill_oid_info(p->two);
  
                len1 = remove_space(p->one->path, strlen(p->one->path));
                len2 = remove_space(p->two->path, strlen(p->two->path));
                if (diff_filespec_is_binary(p->one) ||
                    diff_filespec_is_binary(p->two)) {
                        git_SHA1_Update(&ctx, oid_to_hex(&p->one->oid),
 -                                      40);
 +                                      GIT_SHA1_HEXSZ);
                        git_SHA1_Update(&ctx, oid_to_hex(&p->two->oid),
 -                                      40);
 +                                      GIT_SHA1_HEXSZ);
                        continue;
                }
  
                                     p->one->path);
        }
  
 -      git_SHA1_Final(sha1, &ctx);
 +      git_SHA1_Final(oid->hash, &ctx);
        return 0;
  }
  
 -int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only)
 +int diff_flush_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only)
  {
        struct diff_queue_struct *q = &diff_queued_diff;
        int i;
 -      int result = diff_get_patch_id(options, sha1, diff_header_only);
 +      int result = diff_get_patch_id(options, oid, diff_header_only);
  
        for (i = 0; i < q->nr; i++)
                diff_free_filepair(q->queue[i]);
@@@ -5078,8 -5075,8 +5076,8 @@@ static int is_submodule_ignored(const c
  
  void diff_addremove(struct diff_options *options,
                    int addremove, unsigned mode,
 -                  const unsigned char *sha1,
 -                  int sha1_valid,
 +                  const struct object_id *oid,
 +                  int oid_valid,
                    const char *concatpath, unsigned dirty_submodule)
  {
        struct diff_filespec *one, *two;
        two = alloc_filespec(concatpath);
  
        if (addremove != '+')
 -              fill_filespec(one, sha1, sha1_valid, mode);
 +              fill_filespec(one, oid, oid_valid, mode);
        if (addremove != '-') {
 -              fill_filespec(two, sha1, sha1_valid, mode);
 +              fill_filespec(two, oid, oid_valid, mode);
                two->dirty_submodule = dirty_submodule;
        }
  
  
  void diff_change(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
 -               const unsigned char *old_sha1,
 -               const unsigned char *new_sha1,
 -               int old_sha1_valid, int new_sha1_valid,
 +               const struct object_id *old_oid,
 +               const struct object_id *new_oid,
 +               int old_oid_valid, int new_oid_valid,
                 const char *concatpath,
                 unsigned old_dirty_submodule, unsigned new_dirty_submodule)
  {
  
        if (DIFF_OPT_TST(options, REVERSE_DIFF)) {
                SWAP(old_mode, new_mode);
 -              SWAP(old_sha1, new_sha1);
 -              SWAP(old_sha1_valid, new_sha1_valid);
 +              SWAP(old_oid, new_oid);
 +              SWAP(old_oid_valid, new_oid_valid);
                SWAP(old_dirty_submodule, new_dirty_submodule);
        }
  
  
        one = alloc_filespec(concatpath);
        two = alloc_filespec(concatpath);
 -      fill_filespec(one, old_sha1, old_sha1_valid, old_mode);
 -      fill_filespec(two, new_sha1, new_sha1_valid, new_mode);
 +      fill_filespec(one, old_oid, old_oid_valid, old_mode);
 +      fill_filespec(two, new_oid, new_oid_valid, new_mode);
        one->dirty_submodule = old_dirty_submodule;
        two->dirty_submodule = new_dirty_submodule;
        p = diff_queue(&diff_queued_diff, one, two);
@@@ -5278,7 -5275,7 +5276,7 @@@ int textconv_object(const char *path
        struct userdiff_driver *textconv;
  
        df = alloc_filespec(path);
 -      fill_filespec(df, oid->hash, oid_valid, mode);
 +      fill_filespec(df, oid, oid_valid, mode);
        textconv = get_textconv(df);
        if (!textconv) {
                free_filespec(df);
diff --combined diffcore-rename.c
index 03d1e8d40bb78d03c6b7257b05275de739693671,6d8daf9c003587b7b96cccc29aa63b78365ef40e..1e4678b7d7cb56ee52f160b55924ddeb863e2872
@@@ -60,7 -60,7 +60,7 @@@ static int add_rename_dst(struct diff_f
                memmove(rename_dst + first + 1, rename_dst + first,
                        (rename_dst_nr - first - 1) * sizeof(*rename_dst));
        rename_dst[first].two = alloc_filespec(two->path);
 -      fill_filespec(rename_dst[first].two, two->oid.hash, two->oid_valid,
 +      fill_filespec(rename_dst[first].two, &two->oid, two->oid_valid,
                      two->mode);
        rename_dst[first].pair = NULL;
        return 0;
@@@ -464,7 -464,7 +464,7 @@@ void diffcore_rename(struct diff_option
                                 strcmp(options->single_follow, p->two->path))
                                continue; /* not interested */
                        else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
 -                               is_empty_blob_sha1(p->two->oid.hash))
 +                               is_empty_blob_oid(&p->two->oid))
                                continue;
                        else if (add_rename_dst(p->two) < 0) {
                                warning("skipping rename detection, detected"
                        }
                }
                else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
 -                       is_empty_blob_sha1(p->one->oid.hash))
 +                       is_empty_blob_oid(&p->one->oid))
                        continue;
                else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) {
                        /*
        for (i = 0; i < rename_dst_nr; i++)
                free_filespec(rename_dst[i].two);
  
-       free(rename_dst);
-       rename_dst = NULL;
+       FREE_AND_NULL(rename_dst);
        rename_dst_nr = rename_dst_alloc = 0;
-       free(rename_src);
-       rename_src = NULL;
+       FREE_AND_NULL(rename_src);
        rename_src_nr = rename_src_alloc = 0;
        return;
  }
diff --combined dir.c
index f6795473f7e52c790605d23628f81e3b295155d8,7dc168b80621fa5a196dd27066c5b95b3a0a1915..332f9d8095faf0ec4549cab41811167aecea31d3
--- 1/dir.c
--- 2/dir.c
+++ b/dir.c
@@@ -9,7 -9,6 +9,7 @@@
   */
  #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
 +#include "config.h"
  #include "dir.h"
  #include "attr.h"
  #include "refs.h"
@@@ -53,15 -52,6 +53,15 @@@ static enum path_treatment read_directo
  static int get_dtype(struct dirent *de, struct index_state *istate,
                     const char *path, int len);
  
 +int count_slashes(const char *s)
 +{
 +      int cnt = 0;
 +      while (*s)
 +              if (*s++ == '/')
 +                      cnt++;
 +      return cnt;
 +}
 +
  int fspathcmp(const char *a, const char *b)
  {
        return ignore_case ? strcasecmp(a, b) : strcmp(a, b);
@@@ -805,7 -795,7 +805,7 @@@ static int add_excludes(const char *fna
                                 (pos = index_name_pos(istate, fname, strlen(fname))) >= 0 &&
                                 !ce_stage(istate->cache[pos]) &&
                                 ce_uptodate(istate->cache[pos]) &&
 -                               !would_convert_to_git(fname))
 +                               !would_convert_to_git(istate, fname))
                                hashcpy(sha1_stat->sha1,
                                        istate->cache[pos]->oid.hash);
                        else
@@@ -2127,8 -2117,7 +2127,7 @@@ int read_directory(struct dir_struct *d
                for (i = j = 0; j < dir->nr; j++) {
                        if (i &&
                            check_dir_entry_contains(dir->entries[i - 1], dir->entries[j])) {
-                               free(dir->entries[j]);
-                               dir->entries[j] = NULL;
+                               FREE_AND_NULL(dir->entries[j]);
                        } else {
                                dir->entries[i++] = dir->entries[j];
                        }
                     dir->untracked->dir_invalidated))
                        istate->cache_changed |= UNTRACKED_CHANGED;
                if (dir->untracked != istate->untracked) {
-                       free(dir->untracked);
-                       dir->untracked = NULL;
+                       FREE_AND_NULL(dir->untracked);
                }
        }
        return dir->nr;
@@@ -2498,8 -2486,7 +2496,7 @@@ void write_untracked_extension(struct s
        strbuf_addbuf(out, &untracked->ident);
  
        strbuf_add(out, ouc, ouc_size(len));
-       free(ouc);
-       ouc = NULL;
+       FREE_AND_NULL(ouc);
  
        if (!untracked->root) {
                varint_len = encode_varint(0, varbuf);
diff --combined fast-import.c
index 12b90fe9e34a6431ec241e80398b833264363361,eeab927d5ab9f8bca61e68ef3fe29b565a11fdc1..a959161b4631e134602aa9b5502105ee5c5bcfb8
@@@ -154,7 -154,6 +154,7 @@@ Format of STDIN stream
  
  #include "builtin.h"
  #include "cache.h"
 +#include "config.h"
  #include "lockfile.h"
  #include "object.h"
  #include "blob.h"
@@@ -281,7 -280,7 +281,7 @@@ struct recent_command 
  };
  
  /* Configured limits on output */
 -static unsigned long max_depth = 10;
 +static unsigned long max_depth = 50;
  static off_t max_packsize;
  static int unpack_limit = 100;
  static int force_update;
@@@ -1064,8 -1063,7 +1064,7 @@@ discard_pack
                close(pack_data->pack_fd);
                unlink_or_warn(pack_data->pack_name);
        }
-       free(pack_data);
-       pack_data = NULL;
+       FREE_AND_NULL(pack_data);
        running = 0;
  
        /* We can't carry a delta across packfiles. */
@@@ -1150,8 -1148,7 +1149,7 @@@ static int store_object
  
                /* We cannot carry a delta into the new pack. */
                if (delta) {
-                       free(delta);
-                       delta = NULL;
+                       FREE_AND_NULL(delta);
  
                        git_deflate_init(&s, pack_compression_level);
                        s.next_in = (void *)dat->buf;
diff --combined gpg-interface.c
index 8ab32df457d8947156bec1a838de39b60d9d545a,3f377f89d0e748ef7fcbf4e26c4e74ff5d7632ad..d936f3a32fe5d38c2b41ae0488ac2c02250a1618
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "run-command.h"
  #include "strbuf.h"
  #include "gpg-interface.h"
@@@ -14,16 -13,11 +14,11 @@@ static const char *gpg_program = "gpg"
  
  void signature_check_clear(struct signature_check *sigc)
  {
-       free(sigc->payload);
-       free(sigc->gpg_output);
-       free(sigc->gpg_status);
-       free(sigc->signer);
-       free(sigc->key);
-       sigc->payload = NULL;
-       sigc->gpg_output = NULL;
-       sigc->gpg_status = NULL;
-       sigc->signer = NULL;
-       sigc->key = NULL;
+       FREE_AND_NULL(sigc->payload);
+       FREE_AND_NULL(sigc->gpg_output);
+       FREE_AND_NULL(sigc->gpg_status);
+       FREE_AND_NULL(sigc->signer);
+       FREE_AND_NULL(sigc->key);
  }
  
  static struct {
diff --combined grep.c
index 1fca83be86525957158fc20d09c91b3208a1974e,909f35a98417eed473c39605caa1c684256a9b94..98733db623ae2a0c4b3c11b71e3560429ec975ff
--- 1/grep.c
--- 2/grep.c
+++ b/grep.c
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "grep.h"
  #include "userdiff.h"
  #include "xdiff-interface.h"
@@@ -180,37 -179,22 +180,37 @@@ static void grep_set_pattern_type_optio
        case GREP_PATTERN_TYPE_BRE:
                opt->fixed = 0;
                opt->pcre1 = 0;
 +              opt->pcre2 = 0;
                break;
  
        case GREP_PATTERN_TYPE_ERE:
                opt->fixed = 0;
                opt->pcre1 = 0;
 +              opt->pcre2 = 0;
                opt->regflags |= REG_EXTENDED;
                break;
  
        case GREP_PATTERN_TYPE_FIXED:
                opt->fixed = 1;
                opt->pcre1 = 0;
 +              opt->pcre2 = 0;
                break;
  
        case GREP_PATTERN_TYPE_PCRE:
                opt->fixed = 0;
 +#ifdef USE_LIBPCRE2
 +              opt->pcre1 = 0;
 +              opt->pcre2 = 1;
 +#else
 +              /*
 +               * It's important that pcre1 always be assigned to
 +               * even when there's no USE_LIBPCRE* defined. We still
 +               * call the PCRE stub function, it just dies with
 +               * "cannot use Perl-compatible regexes[...]".
 +               */
                opt->pcre1 = 1;
 +              opt->pcre2 = 0;
 +#endif
                break;
        }
  }
@@@ -381,22 -365,9 +381,22 @@@ static void compile_pcre1_regexp(struc
        if (!p->pcre1_regexp)
                compile_regexp_failed(p, error);
  
 -      p->pcre1_extra_info = pcre_study(p->pcre1_regexp, 0, &error);
 +      p->pcre1_extra_info = pcre_study(p->pcre1_regexp, PCRE_STUDY_JIT_COMPILE, &error);
        if (!p->pcre1_extra_info && error)
                die("%s", error);
 +
 +#ifdef GIT_PCRE1_USE_JIT
 +      pcre_config(PCRE_CONFIG_JIT, &p->pcre1_jit_on);
 +      if (p->pcre1_jit_on == 1) {
 +              p->pcre1_jit_stack = pcre_jit_stack_alloc(1, 1024 * 1024);
 +              if (!p->pcre1_jit_stack)
 +                      die("Couldn't allocate PCRE JIT stack");
 +              pcre_assign_jit_stack(p->pcre1_extra_info, NULL, p->pcre1_jit_stack);
 +      } else if (p->pcre1_jit_on != 0) {
 +              die("BUG: The pcre1_jit_on variable should be 0 or 1, not %d",
 +                  p->pcre1_jit_on);
 +      }
 +#endif
  }
  
  static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
        if (eflags & REG_NOTBOL)
                flags |= PCRE_NOTBOL;
  
 -      ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line, eol - line,
 -                      0, flags, ovector, ARRAY_SIZE(ovector));
 +#ifdef GIT_PCRE1_USE_JIT
 +      if (p->pcre1_jit_on) {
 +              ret = pcre_jit_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
 +                                  eol - line, 0, flags, ovector,
 +                                  ARRAY_SIZE(ovector), p->pcre1_jit_stack);
 +      } else
 +#endif
 +      {
 +              ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
 +                              eol - line, 0, flags, ovector,
 +                              ARRAY_SIZE(ovector));
 +      }
 +
        if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
                die("pcre_exec failed with error code %d", ret);
        if (ret > 0) {
  static void free_pcre1_regexp(struct grep_pat *p)
  {
        pcre_free(p->pcre1_regexp);
 -      pcre_free(p->pcre1_extra_info);
 +#ifdef GIT_PCRE1_USE_JIT
 +      if (p->pcre1_jit_on) {
 +              pcre_free_study(p->pcre1_extra_info);
 +              pcre_jit_stack_free(p->pcre1_jit_stack);
 +      } else
 +#endif
 +      {
 +              pcre_free(p->pcre1_extra_info);
 +      }
        pcre_free((void *)p->pcre1_tables);
  }
  #else /* !USE_LIBPCRE1 */
@@@ -462,127 -414,6 +462,127 @@@ static void free_pcre1_regexp(struct gr
  }
  #endif /* !USE_LIBPCRE1 */
  
 +#ifdef USE_LIBPCRE2
 +static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
 +{
 +      int error;
 +      PCRE2_UCHAR errbuf[256];
 +      PCRE2_SIZE erroffset;
 +      int options = PCRE2_MULTILINE;
 +      const uint8_t *character_tables = NULL;
 +      int jitret;
 +
 +      assert(opt->pcre2);
 +
 +      p->pcre2_compile_context = NULL;
 +
 +      if (opt->ignore_case) {
 +              if (has_non_ascii(p->pattern)) {
 +                      character_tables = pcre2_maketables(NULL);
 +                      p->pcre2_compile_context = pcre2_compile_context_create(NULL);
 +                      pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
 +              }
 +              options |= PCRE2_CASELESS;
 +      }
 +      if (is_utf8_locale() && has_non_ascii(p->pattern))
 +              options |= PCRE2_UTF;
 +
 +      p->pcre2_pattern = pcre2_compile((PCRE2_SPTR)p->pattern,
 +                                       p->patternlen, options, &error, &erroffset,
 +                                       p->pcre2_compile_context);
 +
 +      if (p->pcre2_pattern) {
 +              p->pcre2_match_data = pcre2_match_data_create_from_pattern(p->pcre2_pattern, NULL);
 +              if (!p->pcre2_match_data)
 +                      die("Couldn't allocate PCRE2 match data");
 +      } else {
 +              pcre2_get_error_message(error, errbuf, sizeof(errbuf));
 +              compile_regexp_failed(p, (const char *)&errbuf);
 +      }
 +
 +      pcre2_config(PCRE2_CONFIG_JIT, &p->pcre2_jit_on);
 +      if (p->pcre2_jit_on == 1) {
 +              jitret = pcre2_jit_compile(p->pcre2_pattern, PCRE2_JIT_COMPLETE);
 +              if (jitret)
 +                      die("Couldn't JIT the PCRE2 pattern '%s', got '%d'\n", p->pattern, jitret);
 +              p->pcre2_jit_stack = pcre2_jit_stack_create(1, 1024 * 1024, NULL);
 +              if (!p->pcre2_jit_stack)
 +                      die("Couldn't allocate PCRE2 JIT stack");
 +              p->pcre2_match_context = pcre2_match_context_create(NULL);
 +              if (!p->pcre2_match_context)
 +                      die("Couldn't allocate PCRE2 match context");
 +              pcre2_jit_stack_assign(p->pcre2_match_context, NULL, p->pcre2_jit_stack);
 +      } else if (p->pcre2_jit_on != 0) {
 +              die("BUG: The pcre2_jit_on variable should be 0 or 1, not %d",
 +                  p->pcre1_jit_on);
 +      }
 +}
 +
 +static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
 +              regmatch_t *match, int eflags)
 +{
 +      int ret, flags = 0;
 +      PCRE2_SIZE *ovector;
 +      PCRE2_UCHAR errbuf[256];
 +
 +      if (eflags & REG_NOTBOL)
 +              flags |= PCRE2_NOTBOL;
 +
 +      if (p->pcre2_jit_on)
 +              ret = pcre2_jit_match(p->pcre2_pattern, (unsigned char *)line,
 +                                    eol - line, 0, flags, p->pcre2_match_data,
 +                                    NULL);
 +      else
 +              ret = pcre2_match(p->pcre2_pattern, (unsigned char *)line,
 +                                eol - line, 0, flags, p->pcre2_match_data,
 +                                NULL);
 +
 +      if (ret < 0 && ret != PCRE2_ERROR_NOMATCH) {
 +              pcre2_get_error_message(ret, errbuf, sizeof(errbuf));
 +              die("%s failed with error code %d: %s",
 +                  (p->pcre2_jit_on ? "pcre2_jit_match" : "pcre2_match"), ret,
 +                  errbuf);
 +      }
 +      if (ret > 0) {
 +              ovector = pcre2_get_ovector_pointer(p->pcre2_match_data);
 +              ret = 0;
 +              match->rm_so = (int)ovector[0];
 +              match->rm_eo = (int)ovector[1];
 +      }
 +
 +      return ret;
 +}
 +
 +static void free_pcre2_pattern(struct grep_pat *p)
 +{
 +      pcre2_compile_context_free(p->pcre2_compile_context);
 +      pcre2_code_free(p->pcre2_pattern);
 +      pcre2_match_data_free(p->pcre2_match_data);
 +      pcre2_jit_stack_free(p->pcre2_jit_stack);
 +      pcre2_match_context_free(p->pcre2_match_context);
 +}
 +#else /* !USE_LIBPCRE2 */
 +static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
 +{
 +      /*
 +       * Unreachable until USE_LIBPCRE2 becomes synonymous with
 +       * USE_LIBPCRE. See the sibling comment in
 +       * grep_set_pattern_type_option().
 +       */
 +      die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
 +}
 +
 +static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
 +              regmatch_t *match, int eflags)
 +{
 +      return 1;
 +}
 +
 +static void free_pcre2_pattern(struct grep_pat *p)
 +{
 +}
 +#endif /* !USE_LIBPCRE2 */
 +
  static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
  {
        struct strbuf sb = STRBUF_INIT;
@@@ -648,11 -479,6 +648,11 @@@ static void compile_regexp(struct grep_
                return;
        }
  
 +      if (opt->pcre2) {
 +              compile_pcre2_pattern(p, opt);
 +              return;
 +      }
 +
        if (opt->pcre1) {
                compile_pcre1_regexp(p, opt);
                return;
@@@ -1012,8 -838,6 +1012,8 @@@ void free_grep_patterns(struct grep_op
                                kwsfree(p->kws);
                        else if (p->pcre1_regexp)
                                free_pcre1_regexp(p);
 +                      else if (p->pcre2_pattern)
 +                              free_pcre2_pattern(p);
                        else
                                regfree(&p->regexp);
                        free(p->pattern);
@@@ -1094,8 -918,6 +1094,8 @@@ static int patmatch(struct grep_pat *p
                hit = !fixmatch(p, line, eol, match);
        else if (p->pcre1_regexp)
                hit = !pcre1match(p, line, eol, match, eflags);
 +      else if (p->pcre2_pattern)
 +              hit = !pcre2match(p, line, eol, match, eflags);
        else
                hit = !regexec_buf(&p->regexp, line, eol - line, 1, match,
                                   eflags);
@@@ -1585,11 -1407,11 +1585,11 @@@ static int fill_textconv_grep(struct us
         */
        df = alloc_filespec(gs->path);
        switch (gs->type) {
 -      case GREP_SOURCE_SHA1:
 +      case GREP_SOURCE_OID:
                fill_filespec(df, gs->identifier, 1, 0100644);
                break;
        case GREP_SOURCE_FILE:
 -              fill_filespec(df, null_sha1, 0, 0100644);
 +              fill_filespec(df, &null_oid, 0, 0100644);
                break;
        default:
                die("BUG: attempt to textconv something without a path?");
@@@ -1929,8 -1751,9 +1929,8 @@@ void grep_source_init(struct grep_sourc
                 * If the identifier is non-NULL (in the submodule case) it
                 * will be a SHA1 that needs to be copied.
                 */
 -      case GREP_SOURCE_SHA1:
 -              gs->identifier = xmalloc(20);
 -              hashcpy(gs->identifier, identifier);
 +      case GREP_SOURCE_OID:
 +              gs->identifier = oiddup(identifier);
                break;
        case GREP_SOURCE_BUF:
                gs->identifier = NULL;
  
  void grep_source_clear(struct grep_source *gs)
  {
-       free(gs->name);
-       gs->name = NULL;
-       free(gs->path);
-       gs->path = NULL;
-       free(gs->identifier);
-       gs->identifier = NULL;
+       FREE_AND_NULL(gs->name);
+       FREE_AND_NULL(gs->path);
+       FREE_AND_NULL(gs->identifier);
        grep_source_clear_data(gs);
  }
  
@@@ -1953,10 -1773,9 +1950,9 @@@ void grep_source_clear_data(struct grep
  {
        switch (gs->type) {
        case GREP_SOURCE_FILE:
 -      case GREP_SOURCE_SHA1:
 +      case GREP_SOURCE_OID:
        case GREP_SOURCE_SUBMODULE:
-               free(gs->buf);
-               gs->buf = NULL;
+               FREE_AND_NULL(gs->buf);
                gs->size = 0;
                break;
        case GREP_SOURCE_BUF:
        }
  }
  
 -static int grep_source_load_sha1(struct grep_source *gs)
 +static int grep_source_load_oid(struct grep_source *gs)
  {
        enum object_type type;
  
        if (!gs->buf)
                return error(_("'%s': unable to read %s"),
                             gs->name,
 -                           sha1_to_hex(gs->identifier));
 +                           oid_to_hex(gs->identifier));
        return 0;
  }
  
@@@ -2022,8 -1841,8 +2018,8 @@@ static int grep_source_load(struct grep
        switch (gs->type) {
        case GREP_SOURCE_FILE:
                return grep_source_load_file(gs);
 -      case GREP_SOURCE_SHA1:
 -              return grep_source_load_sha1(gs);
 +      case GREP_SOURCE_OID:
 +              return grep_source_load_oid(gs);
        case GREP_SOURCE_BUF:
                return gs->buf ? 0 : -1;
        case GREP_SOURCE_SUBMODULE:
diff --combined help.c
index 8ba0777410bd6377a1325622f7d73a53a0aa5a60,a2f48c0df3f5456a880533f55b5168c454ea5b20..07b185389decdda8e8cc10a2cd18ece81d0eaf94
--- 1/help.c
--- 2/help.c
+++ b/help.c
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "builtin.h"
  #include "exec_cmd.h"
  #include "run-command.h"
@@@ -10,7 -9,6 +10,7 @@@
  #include "column.h"
  #include "version.h"
  #include "refs.h"
 +#include "parse-options.h"
  
  void add_cmdname(struct cmdnames *cmds, const char *name, int len)
  {
@@@ -269,9 -267,8 +269,8 @@@ static void add_cmd_list(struct cmdname
  
        for (i = 0; i < old->cnt; i++)
                cmds->names[cmds->cnt++] = old->names[i];
-       free(old->names);
+       FREE_AND_NULL(old->names);
        old->cnt = 0;
-       old->names = NULL;
  }
  
  /* An empirically derived magic number */
@@@ -291,7 -288,7 +290,7 @@@ const char *help_unknown_cmd(const cha
        memset(&other_cmds, 0, sizeof(other_cmds));
        memset(&aliases, 0, sizeof(aliases));
  
 -      git_config(git_unknown_cmd_config, NULL);
 +      read_early_config(git_unknown_cmd_config, NULL);
  
        load_command_list("git-", &main_cmds, &other_cmds);
  
  
  int cmd_version(int argc, const char **argv, const char *prefix)
  {
 +      int build_options = 0;
 +      const char * const usage[] = {
 +              N_("git version [<options>]"),
 +              NULL
 +      };
 +      struct option options[] = {
 +              OPT_BOOL(0, "build-options", &build_options,
 +                       "also print build options"),
 +              OPT_END()
 +      };
 +
 +      argc = parse_options(argc, argv, prefix, options, usage, 0);
 +
        /*
         * The format of this string should be kept stable for compatibility
         * with external projects that rely on the output of "git version".
 +       *
 +       * Always show the version, even if other options are given.
         */
        printf("git version %s\n", git_version_string);
 -      while (*++argv) {
 -              if (!strcmp(*argv, "--build-options")) {
 -                      printf("sizeof-long: %d\n", (int)sizeof(long));
 -                      /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */
 -              }
 +
 +      if (build_options) {
 +              printf("sizeof-long: %d\n", (int)sizeof(long));
 +              /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */
        }
        return 0;
  }
diff --combined http.c
index 013bb0cc650888426156fd1c8d173544c1ec90e1,77f46bef0f50b7614b1c48a32c06b371c13b0bbb..c6c010f8816f4a01c4b7658a9044b179515590ea
--- 1/http.c
--- 2/http.c
+++ b/http.c
@@@ -1,6 -1,5 +1,6 @@@
  #include "git-compat-util.h"
  #include "http.h"
 +#include "config.h"
  #include "pack.h"
  #include "sideband.h"
  #include "run-command.h"
@@@ -1027,8 -1026,7 +1027,7 @@@ void http_cleanup(void
  
        if (proxy_auth.password) {
                memset(proxy_auth.password, 0, strlen(proxy_auth.password));
-               free(proxy_auth.password);
-               proxy_auth.password = NULL;
+               FREE_AND_NULL(proxy_auth.password);
        }
  
        free((void *)curl_proxyuserpwd);
  
        if (cert_auth.password != NULL) {
                memset(cert_auth.password, 0, strlen(cert_auth.password));
-               free(cert_auth.password);
-               cert_auth.password = NULL;
+               FREE_AND_NULL(cert_auth.password);
        }
        ssl_cert_password_required = 0;
  
-       free(cached_accept_language);
-       cached_accept_language = NULL;
+       FREE_AND_NULL(cached_accept_language);
  }
  
  struct active_request_slot *get_active_slot(void)
@@@ -1897,8 -1893,7 +1894,7 @@@ static char *fetch_pack_index(unsigned 
  
        if (http_get_file(url, tmp, NULL) != HTTP_OK) {
                error("Unable to get pack index %s", url);
-               free(tmp);
-               tmp = NULL;
+               FREE_AND_NULL(tmp);
        }
  
        free(url);
@@@ -2329,8 -2324,7 +2325,7 @@@ void release_http_object_request(struc
                freq->localfile = -1;
        }
        if (freq->url != NULL) {
-               free(freq->url);
-               freq->url = NULL;
+               FREE_AND_NULL(freq->url);
        }
        if (freq->slot != NULL) {
                freq->slot->callback_func = NULL;
diff --combined imap-send.c
index 59e9b12d294da13fcfc2955c61f50709de1ae84f,40ddb496e6b7b9b1d9db9f16e0cf5ae5a9396892..351e84aea172415c94d7159c47b58abf508e0576
@@@ -23,7 -23,6 +23,7 @@@
   */
  
  #include "cache.h"
 +#include "config.h"
  #include "credential.h"
  #include "exec_cmd.h"
  #include "run-command.h"
@@@ -777,8 -776,7 +777,7 @@@ static int get_cmd_result(struct imap_s
                               offsetof(struct imap_cmd, next));
                        if (cmdp->cb.data) {
                                n = socket_write(&imap->buf.sock, cmdp->cb.data, cmdp->cb.dlen);
-                               free(cmdp->cb.data);
-                               cmdp->cb.data = NULL;
+                               FREE_AND_NULL(cmdp->cb.data);
                                if (n != (int)cmdp->cb.dlen)
                                        return RESP_BAD;
                        } else if (cmdp->cb.cont) {
diff --combined line-log.c
index 2588ce076749ecbb6bfbe591666430edf4ff9073,2d60c347ca6a3be17f84336c95b11a6b3cd7de3c..ab0709f9aecaacdfaf44aa31c88873b4ab5d8278
@@@ -34,9 -34,8 +34,8 @@@ void range_set_init(struct range_set *r
  
  void range_set_release(struct range_set *rs)
  {
-       free(rs->ranges);
+       FREE_AND_NULL(rs->ranges);
        rs->alloc = rs->nr = 0;
-       rs->ranges = NULL;
  }
  
  /* dst must be uninitialized! */
@@@ -500,12 -499,12 +499,12 @@@ static struct commit *check_single_comm
  static void fill_blob_sha1(struct commit *commit, struct diff_filespec *spec)
  {
        unsigned mode;
 -      unsigned char sha1[20];
 +      struct object_id oid;
  
        if (get_tree_entry(commit->object.oid.hash, spec->path,
 -                         sha1, &mode))
 +                         oid.hash, &mode))
                die("There is no path %s in the commit", spec->path);
 -      fill_filespec(spec, sha1, 1, mode);
 +      fill_filespec(spec, &oid, 1, mode);
  
        return;
  }
@@@ -610,8 -609,7 +609,7 @@@ parse_lines(struct commit *commit, cons
                line_log_data_insert(&ranges, full_name, begin, end);
  
                free_filespec(spec);
-               free(ends);
-               ends = NULL;
+               FREE_AND_NULL(ends);
        }
  
        for (p = ranges; p; p = p->next)
@@@ -819,8 -817,8 +817,8 @@@ static void queue_diffs(struct line_log
        assert(commit);
  
        DIFF_QUEUE_CLEAR(&diff_queued_diff);
 -      diff_tree_sha1(parent ? parent->tree->object.oid.hash : NULL,
 -                      commit->tree->object.oid.hash, "", opt);
 +      diff_tree_oid(parent ? &parent->tree->object.oid : NULL,
 +                    &commit->tree->object.oid, "", opt);
        if (opt->detect_rename) {
                filter_diffs_for_paths(range, 1);
                if (diff_might_be_rename())
diff --combined ll-merge.c
index b9576efe97b98d8b7971045b7be3698b9592c5e6,91ff519cef1e9c274d69a4d29faaa886c03040c8..9fb855a90030e07e28c1ae9d0994006da22cd4ed
@@@ -5,7 -5,6 +5,7 @@@
   */
  
  #include "cache.h"
 +#include "config.h"
  #include "attr.h"
  #include "xdiff-interface.h"
  #include "run-command.h"
@@@ -210,8 -209,7 +210,7 @@@ static int ll_ext_merge(const struct ll
        result->size = st.st_size;
        result->ptr = xmallocz(result->size);
        if (read_in_full(fd, result->ptr, result->size) != result->size) {
-               free(result->ptr);
-               result->ptr = NULL;
+               FREE_AND_NULL(result->ptr);
                result->size = 0;
        }
   close_bad:
@@@ -340,7 -338,7 +339,7 @@@ static const struct ll_merge_driver *fi
  static void normalize_file(mmfile_t *mm, const char *path)
  {
        struct strbuf strbuf = STRBUF_INIT;
 -      if (renormalize_buffer(path, mm->ptr, mm->size, &strbuf)) {
 +      if (renormalize_buffer(&the_index, path, mm->ptr, mm->size, &strbuf)) {
                free(mm->ptr);
                mm->size = strbuf.len;
                mm->ptr = strbuf_detach(&strbuf, NULL);
diff --combined mailinfo.c
index f59162453eecdfb841383f71911303b594aa81e4,44f829edb169ad4f3822b5a8cc1a7b0f6037087b..1652ec11f5b173ad8078a7598590f6f198e2dbb9
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "utf8.h"
  #include "strbuf.h"
  #include "mailinfo.h"
@@@ -920,8 -919,7 +920,7 @@@ again
                /* we hit an end boundary */
                /* pop the current boundary off the stack */
                strbuf_release(*(mi->content_top));
-               free(*(mi->content_top));
-               *(mi->content_top) = NULL;
+               FREE_AND_NULL(*(mi->content_top));
  
                /* technically won't happen as is_multipart_boundary()
                   will fail first.  But just in case..
diff --combined pathspec.c
index ecc5331c232ef81f26343fd958a9b66e92a3fa5e,54aab8bc0146c6f2213993f40f5a3b3ac026569a..a5f4df31eab7fd465c2e68c7a400287756c34c51
@@@ -1,6 -1,5 +1,6 @@@
  #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
 +#include "config.h"
  #include "dir.h"
  #include "pathspec.h"
  #include "attr.h"
@@@ -663,7 -662,6 +663,6 @@@ void clear_pathspec(struct pathspec *pa
                        attr_check_free(pathspec->items[i].attr_check);
        }
  
-       free(pathspec->items);
-       pathspec->items = NULL;
+       FREE_AND_NULL(pathspec->items);
        pathspec->nr = 0;
  }
diff --combined read-cache.c
index ad692e198d9b869883017c941be76b05be6f7d7a,66c413657e7e51a839d9baab1c5ab79a23b6280e..3c4354ee21c898813e3fdbecf82a5e703e3f1b5e
@@@ -5,7 -5,6 +5,7 @@@
   */
  #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
 +#include "config.h"
  #include "tempfile.h"
  #include "lockfile.h"
  #include "cache-tree.h"
@@@ -1878,15 -1877,9 +1878,15 @@@ int discard_index(struct index_state *i
  {
        int i;
  
 -      unshare_split_index(istate, 1);
 -      for (i = 0; i < istate->cache_nr; i++)
 +      for (i = 0; i < istate->cache_nr; i++) {
 +              if (istate->cache[i]->index &&
 +                  istate->split_index &&
 +                  istate->split_index->base &&
 +                  istate->cache[i]->index <= istate->split_index->base->cache_nr &&
 +                  istate->cache[i] == istate->split_index->base->cache[istate->cache[i]->index - 1])
 +                      continue;
                free(istate->cache[i]);
 +      }
        resolve_undo_clear_index(istate);
        istate->cache_nr = 0;
        istate->cache_changed = 0;
        free_name_hash(istate);
        cache_tree_free(&(istate->cache_tree));
        istate->initialized = 0;
-       free(istate->cache);
-       istate->cache = NULL;
+       FREE_AND_NULL(istate->cache);
        istate->cache_alloc = 0;
        discard_split_index(istate);
        free_untracked_cache(istate->untracked);
@@@ -2610,8 -2602,7 +2609,7 @@@ void *read_blob_data_from_index(const s
  
  void stat_validity_clear(struct stat_validity *sv)
  {
-       free(sv->sd);
-       sv->sd = NULL;
+       FREE_AND_NULL(sv->sd);
  }
  
  int stat_validity_check(struct stat_validity *sv, const char *path)
diff --combined refs/files-backend.c
index 621a4086c37362180f151cc1648444d4cfd69d13,c1bd99d60fa5f5773de3b49b70a4a0bca1643174..5ef88eda8b71448e7215db6b5d7bfac2df9c492d
@@@ -1,5 -1,4 +1,5 @@@
  #include "../cache.h"
 +#include "../config.h"
  #include "../refs.h"
  #include "refs-internal.h"
  #include "ref-cache.h"
@@@ -2945,8 -2944,7 +2945,7 @@@ static int files_transaction_prepare(st
                                       head_oid.hash, &head_type);
  
        if (head_ref && !(head_type & REF_ISSYMREF)) {
-               free(head_ref);
-               head_ref = NULL;
+               FREE_AND_NULL(head_ref);
        }
  
        /*
diff --combined remote-testsvn.c
index e034ea00d49c81675d664085c0d67763609bfd8a,078b0c3139e6797f9021876c7a8f1906901f70b1..0ff4a312629d4ed4250a076f39a9d78e76917158
@@@ -51,23 -51,22 +51,22 @@@ static void terminate_batch(void
  }
  
  /* NOTE: 'ref' refers to a git reference, while 'rev' refers to a svn revision. */
 -static char *read_ref_note(const unsigned char sha1[20])
 +static char *read_ref_note(const struct object_id *oid)
  {
 -      const unsigned char *note_sha1;
 +      const struct object_id *note_oid;
        char *msg = NULL;
        unsigned long msglen;
        enum object_type type;
  
        init_notes(NULL, notes_ref, NULL, 0);
 -      if (!(note_sha1 = get_note(NULL, sha1)))
 +      if (!(note_oid = get_note(NULL, oid)))
                return NULL;    /* note tree not found */
 -      if (!(msg = read_sha1_file(note_sha1, &type, &msglen)))
 +      if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen)))
                error("Empty notes tree. %s", notes_ref);
        else if (!msglen || type != OBJ_BLOB) {
                error("Note contains unusable content. "
                        "Is something else using this notes tree? %s", notes_ref);
-               free(msg);
-               msg = NULL;
+               FREE_AND_NULL(msg);
        }
        free_notes(NULL);
        return msg;
@@@ -99,8 -98,8 +98,8 @@@ static int parse_rev_note(const char *m
        return -1;
  }
  
 -static int note2mark_cb(const unsigned char *object_sha1,
 -              const unsigned char *note_sha1, char *note_path,
 +static int note2mark_cb(const struct object_id *object_oid,
 +              const struct object_id *note_oid, char *note_path,
                void *cb_data)
  {
        FILE *file = (FILE *)cb_data;
        enum object_type type;
        struct rev_note note;
  
 -      if (!(msg = read_sha1_file(note_sha1, &type, &msglen)) ||
 +      if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen)) ||
                        !msglen || type != OBJ_BLOB) {
                free(msg);
                return 1;
        }
        if (parse_rev_note(msg, &note))
                return 2;
 -      if (fprintf(file, ":%d %s\n", note.rev_nr, sha1_to_hex(object_sha1)) < 1)
 +      if (fprintf(file, ":%d %s\n", note.rev_nr, oid_to_hex(object_oid)) < 1)
                return 3;
        return 0;
  }
@@@ -170,15 -169,15 +169,15 @@@ static int cmd_import(const char *line
        int code;
        int dumpin_fd;
        char *note_msg;
 -      unsigned char head_sha1[20];
 +      struct object_id head_oid;
        unsigned int startrev;
        struct child_process svndump_proc = CHILD_PROCESS_INIT;
        const char *command = "svnrdump";
  
 -      if (read_ref(private_ref, head_sha1))
 +      if (read_ref(private_ref, head_oid.hash))
                startrev = 0;
        else {
 -              note_msg = read_ref_note(head_sha1);
 +              note_msg = read_ref_note(&head_oid);
                if(note_msg == NULL) {
                        warning("No note found for %s.", private_ref);
                        startrev = 0;
diff --combined rerere.c
index 829b3b0f08f7546c168e2728687d5729c4607cfa,61f3804a1eb2d7d6af8f1f0408945a41d880bc94..70634d456cc0b70cdbac1579b82016761252c7d9
+++ b/rerere.c
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "lockfile.h"
  #include "string-list.h"
  #include "rerere.h"
@@@ -40,9 -39,8 +40,8 @@@ static void free_rerere_dirs(void
                free(rerere_dir[i]->status);
                free(rerere_dir[i]);
        }
-       free(rerere_dir);
+       FREE_AND_NULL(rerere_dir);
        rerere_dir_nr = rerere_dir_alloc = 0;
-       rerere_dir = NULL;
  }
  
  static void free_rerere_id(struct string_list_item *item)
diff --combined sequencer.c
index 224afe79b96c89a70a36db85aa6c61826b2ebec1,070b42f240474dfb03f85ea1bb5b1a21c464400a..98cdfe74fdac47da5ca2f640ae8ae2dbaa6051d4
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "lockfile.h"
  #include "sequencer.h"
  #include "dir.h"
@@@ -1212,8 -1211,7 +1212,7 @@@ struct todo_list 
  static void todo_list_release(struct todo_list *todo_list)
  {
        strbuf_release(&todo_list->buf);
-       free(todo_list->items);
-       todo_list->items = NULL;
+       FREE_AND_NULL(todo_list->items);
        todo_list->nr = todo_list->alloc = 0;
  }
  
@@@ -2131,8 -2129,8 +2130,8 @@@ cleanup_head_ref
                        if (read_oneliner(&buf, rebase_path_orig_head(), 0) &&
                            !get_sha1(buf.buf, orig.hash) &&
                            !get_sha1("HEAD", head.hash)) {
 -                              diff_tree_sha1(orig.hash, head.hash,
 -                                             "", &log_tree_opt.diffopt);
 +                              diff_tree_oid(&orig, &head, "",
 +                                            &log_tree_opt.diffopt);
                                log_tree_diff_flush(&log_tree_opt);
                        }
                }
diff --combined sha1_file.c
index a900b280428fa4931b1a60a9ac788edaff89634e,d67c88bb8d3483475ce8b6ecd7330d30a9311a81..fb1fd809dcbda2ed91c7d9337584a709a248971b
@@@ -7,7 -7,6 +7,7 @@@
   * creation etc.
   */
  #include "cache.h"
 +#include "config.h"
  #include "string-list.h"
  #include "lockfile.h"
  #include "delta.h"
@@@ -611,8 -610,7 +611,7 @@@ char *compute_alternate_path(const cha
  
  out:
        if (seen_error) {
-               free(ref_git);
-               ref_git = NULL;
+               FREE_AND_NULL(ref_git);
        }
  
        return ref_git;
@@@ -3547,7 -3545,7 +3546,7 @@@ static int index_mem(unsigned char *sha
         */
        if ((type == OBJ_BLOB) && path) {
                struct strbuf nbuf = STRBUF_INIT;
 -              if (convert_to_git(path, buf, size, &nbuf,
 +              if (convert_to_git(&the_index, path, buf, size, &nbuf,
                                   write_object ? safe_crlf : SAFE_CRLF_FALSE)) {
                        buf = strbuf_detach(&nbuf, &size);
                        re_allocated = 1;
@@@ -3581,7 -3579,7 +3580,7 @@@ static int index_stream_convert_blob(un
        assert(path);
        assert(would_convert_to_git_filter_fd(path));
  
 -      convert_to_git_filter_fd(path, fd, &sbuf,
 +      convert_to_git_filter_fd(&the_index, path, fd, &sbuf,
                                 write_object ? safe_crlf : SAFE_CRLF_FALSE);
  
        if (write_object)
@@@ -3669,7 -3667,7 +3668,7 @@@ int index_fd(unsigned char *sha1, int f
        else if (!S_ISREG(st->st_mode))
                ret = index_pipe(sha1, fd, type, path, flags);
        else if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||
 -               (path && would_convert_to_git(path)))
 +               (path && would_convert_to_git(&the_index, path)))
                ret = index_core(sha1, fd, xsize_t(st->st_size), type, path,
                                 flags);
        else
diff --combined split-index.c
index f519e60f87578386ec9b4ea764bf530be0f64836,20477c6a488bcf80e07aceb12c8b45cee5323818..83e39ec8d7739816188ba909a4cb9da302d48f73
@@@ -73,10 -73,17 +73,10 @@@ void move_cache_to_base_index(struct in
        int i;
  
        /*
 -       * If "si" is shared with another index_state (e.g. by
 -       * unpack-trees code), we will need to duplicate split_index
 -       * struct. It's not happening now though, luckily.
 +       * do not delete old si->base, its index entries may be shared
 +       * with istate->cache[]. Accept a bit of leaking here because
 +       * this code is only used by short-lived update-index.
         */
 -      assert(si->refcount <= 1);
 -
 -      unshare_split_index(istate, 0);
 -      if (si->base) {
 -              discard_index(si->base);
 -              free(si->base);
 -      }
        si->base = xcalloc(1, sizeof(*si->base));
        si->base->version = istate->version;
        /* zero timestamp disables racy test in ce_write_index() */
@@@ -167,10 -174,9 +167,9 @@@ void merge_base_index(struct index_stat
  
        ewah_free(si->delete_bitmap);
        ewah_free(si->replace_bitmap);
-       free(si->saved_cache);
+       FREE_AND_NULL(si->saved_cache);
        si->delete_bitmap  = NULL;
        si->replace_bitmap = NULL;
-       si->saved_cache    = NULL;
        si->saved_cache_nr = 0;
  }
  
@@@ -275,11 -281,41 +274,11 @@@ void finish_writing_split_index(struct 
        istate->cache_nr = si->saved_cache_nr;
  }
  
 -void unshare_split_index(struct index_state *istate, int discard)
 -{
 -      struct split_index *si = istate->split_index;
 -      int i;
 -
 -      if (!si || !si->base)
 -              return;
 -
 -      for (i = 0; i < istate->cache_nr; i++) {
 -              struct cache_entry *ce = istate->cache[i];
 -              struct cache_entry *new = NULL;
 -
 -              if (!ce->index ||
 -                  ce->index > si->base->cache_nr ||
 -                  ce != si->base->cache[ce->index - 1])
 -                      continue;
 -
 -              if (!discard) {
 -                      int len = ce_namelen(ce);
 -                      new = xcalloc(1, cache_entry_size(len));
 -                      copy_cache_entry(new, ce);
 -                      memcpy(new->name, ce->name, len);
 -                      new->index = 0;
 -              }
 -              istate->cache[i] = new;
 -      }
 -}
 -
 -
  void discard_split_index(struct index_state *istate)
  {
        struct split_index *si = istate->split_index;
        if (!si)
                return;
 -      unshare_split_index(istate, 0);
        istate->split_index = NULL;
        si->refcount--;
        if (si->refcount)
@@@ -328,14 -364,8 +327,14 @@@ void add_split_index(struct index_stat
  
  void remove_split_index(struct index_state *istate)
  {
 -      if (!istate->split_index)
 -              return;
 -      discard_split_index(istate);
 -      istate->cache_changed |= SOMETHING_CHANGED;
 +      if (istate->split_index) {
 +              /*
 +               * can't discard_split_index(&the_index); because that
 +               * will destroy split_index->base->cache[], which may
 +               * be shared with the_index.cache[]. So yeah we're
 +               * leaking a bit here.
 +               */
 +              istate->split_index = NULL;
 +              istate->cache_changed |= SOMETHING_CHANGED;
 +      }
  }
diff --combined transport.c
index b9995306f259da0a929babdfe1fb5b99eaacead8,cf3508800132b8843d8dcad3f34f25feb593474b..d75ff0514d8d4dd05da1d618ddf2602e5a4f26a9
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "transport.h"
  #include "run-command.h"
  #include "pkt-line.h"
@@@ -1146,8 -1145,7 +1146,7 @@@ void transport_unlock_pack(struct trans
  {
        if (transport->pack_lockfile) {
                unlink_or_warn(transport->pack_lockfile);
-               free(transport->pack_lockfile);
-               transport->pack_lockfile = NULL;
+               FREE_AND_NULL(transport->pack_lockfile);
        }
  }
  
diff --combined tree-diff.c
index 467e3817243567dadfaf853fddef8a0ef894f270,1e1b393d083935555058aed475ab804a839738c0..bd6d65a40920a547b9f27512e31341231273fa75
  } while(0)
  
  static struct combine_diff_path *ll_diff_tree_paths(
 -      struct combine_diff_path *p, const unsigned char *sha1,
 -      const unsigned char **parents_sha1, int nparent,
 +      struct combine_diff_path *p, const struct object_id *oid,
 +      const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt);
 -static int ll_diff_tree_sha1(const unsigned char *old, const unsigned char *new,
 -                           struct strbuf *base, struct diff_options *opt);
 +static int ll_diff_tree_oid(const struct object_id *old_oid,
 +                          const struct object_id *new_oid,
 +                          struct strbuf *base, struct diff_options *opt);
  
  /*
   * Compare two tree entries, taking into account only path/S_ISDIR(mode),
@@@ -75,25 -74,25 +75,25 @@@ static int emit_diff_first_parent_only(
  {
        struct combine_diff_parent *p0 = &p->parent[0];
        if (p->mode && p0->mode) {
 -              opt->change(opt, p0->mode, p->mode, p0->oid.hash, p->oid.hash,
 +              opt->change(opt, p0->mode, p->mode, &p0->oid, &p->oid,
                        1, 1, p->path, 0, 0);
        }
        else {
 -              const unsigned char *sha1;
 +              const struct object_id *oid;
                unsigned int mode;
                int addremove;
  
                if (p->mode) {
                        addremove = '+';
 -                      sha1 = p->oid.hash;
 +                      oid = &p->oid;
                        mode = p->mode;
                } else {
                        addremove = '-';
 -                      sha1 = p0->oid.hash;
 +                      oid = &p0->oid;
                        mode = p0->mode;
                }
  
 -              opt->add_remove(opt, addremove, mode, sha1, 1, p->path, 0);
 +              opt->add_remove(opt, addremove, mode, oid, 1, p->path, 0);
        }
  
        return 0;       /* we are done with p */
   */
  static struct combine_diff_path *path_appendnew(struct combine_diff_path *last,
        int nparent, const struct strbuf *base, const char *path, int pathlen,
 -      unsigned mode, const unsigned char *sha1)
 +      unsigned mode, const struct object_id *oid)
  {
        struct combine_diff_path *p;
        size_t len = st_add(base->len, pathlen);
        /* if last->next is !NULL - it is a pre-allocated memory, we can reuse */
        p = last->next;
        if (p && (alloclen > (intptr_t)p->next)) {
-               free(p);
-               p = NULL;
+               FREE_AND_NULL(p);
        }
  
        if (!p) {
        memcpy(p->path + base->len, path, pathlen);
        p->path[len] = 0;
        p->mode = mode;
 -      hashcpy(p->oid.hash, sha1 ? sha1 : null_sha1);
 +      oidcpy(&p->oid, oid ? oid : &null_oid);
  
        return p;
  }
@@@ -184,7 -182,7 +183,7 @@@ static struct combine_diff_path *emit_p
  {
        unsigned mode;
        const char *path;
 -      const unsigned char *sha1;
 +      const struct object_id *oid;
        int pathlen;
        int old_baselen = base->len;
        int i, isdir, recurse = 0, emitthis = 1;
  
        if (t) {
                /* path present in resulting tree */
 -              sha1 = tree_entry_extract(t, &path, &mode)->hash;
 +              oid = tree_entry_extract(t, &path, &mode);
                pathlen = tree_entry_len(&t->entry);
                isdir = S_ISDIR(mode);
        } else {
                pathlen = tree_entry_len(&tp[imin].entry);
  
                isdir = S_ISDIR(mode);
 -              sha1 = NULL;
 +              oid = NULL;
                mode = 0;
        }
  
        if (emitthis) {
                int keep;
                struct combine_diff_path *pprev = p;
 -              p = path_appendnew(p, nparent, base, path, pathlen, mode, sha1);
 +              p = path_appendnew(p, nparent, base, path, pathlen, mode, oid);
  
                for (i = 0; i < nparent; ++i) {
                        /*
                         */
                        int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ);
  
 -                      const unsigned char *sha1_i;
 +                      const struct object_id *oid_i;
                        unsigned mode_i;
  
                        p->parent[i].status =
                                                DIFF_STATUS_ADDED;
  
                        if (tpi_valid) {
 -                              sha1_i = tp[i].entry.oid->hash;
 +                              oid_i = tp[i].entry.oid;
                                mode_i = tp[i].entry.mode;
                        }
                        else {
 -                              sha1_i = NULL;
 +                              oid_i = &null_oid;
                                mode_i = 0;
                        }
  
                        p->parent[i].mode = mode_i;
 -                      hashcpy(p->parent[i].oid.hash, sha1_i ? sha1_i : null_sha1);
 +                      oidcpy(&p->parent[i].oid, oid_i);
                }
  
                keep = 1;
        }
  
        if (recurse) {
 -              const unsigned char **parents_sha1;
 +              const struct object_id **parents_oid;
  
 -              FAST_ARRAY_ALLOC(parents_sha1, nparent);
 +              FAST_ARRAY_ALLOC(parents_oid, nparent);
                for (i = 0; i < nparent; ++i) {
                        /* same rule as in emitthis */
                        int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ);
  
 -                      parents_sha1[i] = tpi_valid ? tp[i].entry.oid->hash
 -                                                  : NULL;
 +                      parents_oid[i] = tpi_valid ? tp[i].entry.oid : NULL;
                }
  
                strbuf_add(base, path, pathlen);
                strbuf_addch(base, '/');
 -              p = ll_diff_tree_paths(p, sha1, parents_sha1, nparent, base, opt);
 -              FAST_ARRAY_FREE(parents_sha1, nparent);
 +              p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt);
 +              FAST_ARRAY_FREE(parents_oid, nparent);
        }
  
        strbuf_setlen(base, old_baselen);
@@@ -312,7 -311,7 +311,7 @@@ static void skip_uninteresting(struct t
  
  
  /*
 - * generate paths for combined diff D(sha1,parents_sha1[])
 + * generate paths for combined diff D(sha1,parents_oid[])
   *
   * Resulting paths are appended to combine_diff_path linked list, and also, are
   * emitted on the go via opt->pathchange() callback, so it is possible to
@@@ -404,8 -403,8 +403,8 @@@ static inline void update_tp_entries(st
  }
  
  static struct combine_diff_path *ll_diff_tree_paths(
 -      struct combine_diff_path *p, const unsigned char *sha1,
 -      const unsigned char **parents_sha1, int nparent,
 +      struct combine_diff_path *p, const struct object_id *oid,
 +      const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt)
  {
        struct tree_desc t, *tp;
         * load parents first, as they are probably already cached.
         *
         * ( log_tree_diff() parses commit->parent before calling here via
 -       *   diff_tree_sha1(parent, commit) )
 +       *   diff_tree_oid(parent, commit) )
         */
        for (i = 0; i < nparent; ++i)
 -              tptree[i] = fill_tree_descriptor(&tp[i], parents_sha1[i]);
 -      ttree = fill_tree_descriptor(&t, sha1);
 +              tptree[i] = fill_tree_descriptor(&tp[i], parents_oid[i]->hash);
 +      ttree = fill_tree_descriptor(&t, oid->hash);
  
        /* Enable recursion indefinitely */
        opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
  }
  
  struct combine_diff_path *diff_tree_paths(
 -      struct combine_diff_path *p, const unsigned char *sha1,
 -      const unsigned char **parents_sha1, int nparent,
 +      struct combine_diff_path *p, const struct object_id *oid,
 +      const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt)
  {
 -      p = ll_diff_tree_paths(p, sha1, parents_sha1, nparent, base, opt);
 +      p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt);
  
        /*
         * free pre-allocated last element, if any
         * (see path_appendnew() for details about why)
         */
        if (p->next) {
-               free(p->next);
-               p->next = NULL;
+               FREE_AND_NULL(p->next);
        }
  
        return p;
@@@ -577,9 -575,7 +575,9 @@@ static inline int diff_might_be_rename(
                !DIFF_FILE_VALID(diff_queued_diff.queue[0]->one);
  }
  
 -static void try_to_follow_renames(const unsigned char *old, const unsigned char *new, struct strbuf *base, struct diff_options *opt)
 +static void try_to_follow_renames(const struct object_id *old_oid,
 +                                const struct object_id *new_oid,
 +                                struct strbuf *base, struct diff_options *opt)
  {
        struct diff_options diff_opts;
        struct diff_queue_struct *q = &diff_queued_diff;
        diff_opts.break_opt = opt->break_opt;
        diff_opts.rename_score = opt->rename_score;
        diff_setup_done(&diff_opts);
 -      ll_diff_tree_sha1(old, new, base, &diff_opts);
 +      ll_diff_tree_oid(old_oid, new_oid, base, &diff_opts);
        diffcore_std(&diff_opts);
        clear_pathspec(&diff_opts.pathspec);
  
        q->nr = 1;
  }
  
 -static int ll_diff_tree_sha1(const unsigned char *old, const unsigned char *new,
 -                           struct strbuf *base, struct diff_options *opt)
 +static int ll_diff_tree_oid(const struct object_id *old_oid,
 +                          const struct object_id *new_oid,
 +                          struct strbuf *base, struct diff_options *opt)
  {
        struct combine_diff_path phead, *p;
        pathchange_fn_t pathchange_old = opt->pathchange;
  
        phead.next = NULL;
        opt->pathchange = emit_diff_first_parent_only;
 -      diff_tree_paths(&phead, new, &old, 1, base, opt);
 +      diff_tree_paths(&phead, new_oid, &old_oid, 1, base, opt);
  
        for (p = phead.next; p;) {
                struct combine_diff_path *pprev = p;
        return 0;
  }
  
 -int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base_str, struct diff_options *opt)
 +int diff_tree_oid(const struct object_id *old_oid,
 +                const struct object_id *new_oid,
 +                const char *base_str, struct diff_options *opt)
  {
        struct strbuf base;
        int retval;
        strbuf_init(&base, PATH_MAX);
        strbuf_addstr(&base, base_str);
  
 -      retval = ll_diff_tree_sha1(old, new, &base, opt);
 +      retval = ll_diff_tree_oid(old_oid, new_oid, &base, opt);
        if (!*base_str && DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename())
 -              try_to_follow_renames(old, new, &base, opt);
 +              try_to_follow_renames(old_oid, new_oid, &base, opt);
  
        strbuf_release(&base);
  
        return retval;
  }
  
 -int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt)
 +int diff_root_tree_oid(const struct object_id *new_oid, const char *base, struct diff_options *opt)
  {
 -      return diff_tree_sha1(NULL, new, base, opt);
 +      return diff_tree_oid(NULL, new_oid, base, opt);
  }
diff --combined tree.c
index dd69423d9a3c1e1b9dd83df729ede543bfedc90a,614f91586d6f4d70815214812ace3e1981a697b5..b224115e0f4d61368560eba406a04f0259b7c4f0
--- 1/tree.c
--- 2/tree.c
+++ b/tree.c
@@@ -1,4 -1,3 +1,4 @@@
 +#define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "cache-tree.h"
  #include "tree.h"
@@@ -9,11 -8,7 +9,11 @@@
  
  const char *tree_type = "tree";
  
 -static int read_one_entry_opt(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, int opt)
 +static int read_one_entry_opt(struct index_state *istate,
 +                            const unsigned char *sha1,
 +                            const char *base, int baselen,
 +                            const char *pathname,
 +                            unsigned mode, int stage, int opt)
  {
        int len;
        unsigned int size;
        memcpy(ce->name, base, baselen);
        memcpy(ce->name + baselen, pathname, len+1);
        hashcpy(ce->oid.hash, sha1);
 -      return add_cache_entry(ce, opt);
 +      return add_index_entry(istate, ce, opt);
  }
  
  static int read_one_entry(const unsigned char *sha1, struct strbuf *base,
                          const char *pathname, unsigned mode, int stage,
                          void *context)
  {
 -      return read_one_entry_opt(sha1, base->buf, base->len, pathname,
 +      struct index_state *istate = context;
 +      return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname,
                                  mode, stage,
                                  ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
  }
@@@ -53,8 -47,7 +53,8 @@@ static int read_one_entry_quick(const u
                                const char *pathname, unsigned mode, int stage,
                                void *context)
  {
 -      return read_one_entry_opt(sha1, base->buf, base->len, pathname,
 +      struct index_state *istate = context;
 +      return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname,
                                  mode, stage,
                                  ADD_CACHE_JUST_APPEND);
  }
@@@ -151,8 -144,7 +151,8 @@@ static int cmp_cache_name_compare(cons
                                  ce2->name, ce2->ce_namelen, ce_stage(ce2));
  }
  
 -int read_tree(struct tree *tree, int stage, struct pathspec *match)
 +int read_tree(struct tree *tree, int stage, struct pathspec *match,
 +            struct index_state *istate)
  {
        read_tree_fn_t fn = NULL;
        int i, err;
         * do it the original slow way, otherwise, append and then
         * sort at the end.
         */
 -      for (i = 0; !fn && i < active_nr; i++) {
 -              const struct cache_entry *ce = active_cache[i];
 +      for (i = 0; !fn && i < istate->cache_nr; i++) {
 +              const struct cache_entry *ce = istate->cache[i];
                if (ce_stage(ce) == stage)
                        fn = read_one_entry;
        }
  
        if (!fn)
                fn = read_one_entry_quick;
 -      err = read_tree_recursive(tree, "", 0, stage, match, fn, NULL);
 +      err = read_tree_recursive(tree, "", 0, stage, match, fn, istate);
        if (fn == read_one_entry || err)
                return err;
  
        /*
         * Sort the cache entry -- we need to nuke the cache tree, though.
         */
 -      cache_tree_free(&active_cache_tree);
 -      QSORT(active_cache, active_nr, cmp_cache_name_compare);
 +      cache_tree_free(&istate->cache_tree);
 +      QSORT(istate->cache, istate->cache_nr, cmp_cache_name_compare);
        return 0;
  }
  
@@@ -234,8 -226,7 +234,7 @@@ int parse_tree_gently(struct tree *item
  
  void free_tree_buffer(struct tree *tree)
  {
-       free(tree->buffer);
-       tree->buffer = NULL;
+       FREE_AND_NULL(tree->buffer);
        tree->size = 0;
        tree->object.parsed = 0;
  }