Merge branch 'rj/warning-uninitialized-fix'
authorJunio C Hamano <gitster@pobox.com>
Wed, 21 Mar 2018 18:30:15 +0000 (11:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 21 Mar 2018 18:30:15 +0000 (11:30 -0700)
Compilation fix.

* rj/warning-uninitialized-fix:
read-cache: fix an -Wmaybe-uninitialized warning
-Wuninitialized: remove some 'init-self' workarounds

1  2 
builtin/rev-list.c
fast-import.c
merge-recursive.c
read-cache.c
diff --combined builtin/rev-list.c
index d320b6f1e3bcbcd429d5e2baa94b453035572db7,fbfc62de41468bd96a7effe3b3aedcf4ecb0e314..6f5b9b0847321ca214b4d32719eaeacefffd5ce4
@@@ -15,7 -15,6 +15,7 @@@
  #include "progress.h"
  #include "reflog-walk.h"
  #include "oidset.h"
 +#include "packfile.h"
  
  static const char rev_list_usage[] =
  "git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
@@@ -68,7 -67,6 +68,7 @@@ enum missing_action 
        MA_ERROR = 0,    /* fail if any missing objects are encountered */
        MA_ALLOW_ANY,    /* silently allow ALL missing objects */
        MA_PRINT,        /* print ALL missing objects in special section */
 +      MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */
  };
  static enum missing_action arg_missing_action;
  
@@@ -134,7 -132,7 +134,7 @@@ static void show_commit(struct commit *
        else
                putchar('\n');
  
 -      if (revs->verbose_header && get_cached_commit_buffer(commit, NULL)) {
 +      if (revs->verbose_header) {
                struct strbuf buf = STRBUF_INIT;
                struct pretty_print_context ctx = {0};
                ctx.abbrev = revs->abbrev;
@@@ -199,12 -197,6 +199,12 @@@ static void finish_commit(struct commi
  
  static inline void finish_object__ma(struct object *obj)
  {
 +      /*
 +       * Whether or not we try to dynamically fetch missing objects
 +       * from the server, we currently DO NOT have the object.  We
 +       * can either print, allow (ignore), or conditionally allow
 +       * (ignore) them.
 +       */
        switch (arg_missing_action) {
        case MA_ERROR:
                die("missing blob object '%s'", oid_to_hex(&obj->oid));
                oidset_insert(&missing_objects, &obj->oid);
                return;
  
 +      case MA_ALLOW_PROMISOR:
 +              if (is_promisor_object(&obj->oid))
 +                      return;
 +              die("unexpected missing blob object '%s'",
 +                  oid_to_hex(&obj->oid));
 +              return;
 +
        default:
                BUG("unhandled missing_action");
                return;
        }
  }
  
 -static void finish_object(struct object *obj, const char *name, void *cb_data)
 +static int finish_object(struct object *obj, const char *name, void *cb_data)
  {
        struct rev_list_info *info = cb_data;
 -      if (obj->type == OBJ_BLOB && !has_object_file(&obj->oid))
 +      if (obj->type == OBJ_BLOB && !has_object_file(&obj->oid)) {
                finish_object__ma(obj);
 +              return 1;
 +      }
        if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
                parse_object(&obj->oid);
 +      return 0;
  }
  
  static void show_object(struct object *obj, const char *name, void *cb_data)
  {
        struct rev_list_info *info = cb_data;
 -      finish_object(obj, name, cb_data);
 +      if (finish_object(obj, name, cb_data))
 +              return;
        display_progress(progress, ++progress_counter);
        if (info->flags & REV_LIST_QUIET)
                return;
@@@ -334,19 -315,11 +334,19 @@@ static inline int parse_missing_action_
  
        if (!strcmp(value, "allow-any")) {
                arg_missing_action = MA_ALLOW_ANY;
 +              fetch_if_missing = 0;
                return 1;
        }
  
        if (!strcmp(value, "print")) {
                arg_missing_action = MA_PRINT;
 +              fetch_if_missing = 0;
 +              return 1;
 +      }
 +
 +      if (!strcmp(value, "allow-promisor")) {
 +              arg_missing_action = MA_ALLOW_PROMISOR;
 +              fetch_if_missing = 0;
                return 1;
        }
  
@@@ -371,35 -344,6 +371,35 @@@ int cmd_rev_list(int argc, const char *
        init_revisions(&revs, prefix);
        revs.abbrev = DEFAULT_ABBREV;
        revs.commit_format = CMIT_FMT_UNSPECIFIED;
 +
 +      /*
 +       * Scan the argument list before invoking setup_revisions(), so that we
 +       * know if fetch_if_missing needs to be set to 0.
 +       *
 +       * "--exclude-promisor-objects" acts as a pre-filter on missing objects
 +       * by not crossing the boundary from realized objects to promisor
 +       * objects.
 +       *
 +       * Let "--missing" to conditionally set fetch_if_missing.
 +       */
 +      for (i = 1; i < argc; i++) {
 +              const char *arg = argv[i];
 +              if (!strcmp(arg, "--exclude-promisor-objects")) {
 +                      fetch_if_missing = 0;
 +                      revs.exclude_promisor_objects = 1;
 +                      break;
 +              }
 +      }
 +      for (i = 1; i < argc; i++) {
 +              const char *arg = argv[i];
 +              if (skip_prefix(arg, "--missing=", &arg)) {
 +                      if (revs.exclude_promisor_objects)
 +                              die(_("cannot combine --exclude-promisor-objects and --missing"));
 +                      if (parse_missing_action_value(arg))
 +                              break;
 +              }
 +      }
 +
        argc = setup_revisions(argc, argv, &revs, NULL);
  
        memset(&info, 0, sizeof(info));
                        continue;
                }
                if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
 -                      list_objects_filter_release(&filter_options);
 +                      list_objects_filter_set_no_filter(&filter_options);
                        continue;
                }
                if (!strcmp(arg, "--filter-print-omitted")) {
                        continue;
                }
  
 -              if (skip_prefix(arg, "--missing=", &arg) &&
 -                  parse_missing_action_value(arg))
 -                      continue;
 +              if (!strcmp(arg, "--exclude-promisor-objects"))
 +                      continue; /* already handled above */
 +              if (skip_prefix(arg, "--missing=", &arg))
 +                      continue; /* already handled above */
  
                usage(rev_list_usage);
  
                mark_edges_uninteresting(&revs, show_edge);
  
        if (bisect_list) {
-               int reaches = reaches, all = all;
+               int reaches, all;
  
                find_bisection(&revs.commits, &reaches, &all, bisect_find_all);
  
diff --combined fast-import.c
index 58ef360da43d3d7d55733cb8ee66014351814921,1f01a2205506054a4d9e1c80e74a29aa0f974b0d..b5db5d20b1b20c642cf97f990eb538ee6fbaa299
@@@ -316,7 -316,7 +316,7 @@@ static struct atom_str **atom_table
  /* The .pack file being generated */
  static struct pack_idx_option pack_idx_opts;
  static unsigned int pack_id;
 -static struct sha1file *pack_file;
 +static struct hashfile *pack_file;
  static struct packed_git *pack_data;
  static struct packed_git **all_packs;
  static off_t pack_size;
@@@ -905,12 -905,12 +905,12 @@@ static void start_packfile(void
  
        p->pack_fd = pack_fd;
        p->do_not_close = 1;
 -      pack_file = sha1fd(pack_fd, p->pack_name);
 +      pack_file = hashfd(pack_fd, p->pack_name);
  
        hdr.hdr_signature = htonl(PACK_SIGNATURE);
        hdr.hdr_version = htonl(2);
        hdr.hdr_entries = 0;
 -      sha1write(pack_file, &hdr, sizeof(hdr));
 +      hashwrite(pack_file, &hdr, sizeof(hdr));
  
        pack_data = p;
        pack_size = sizeof(hdr);
@@@ -1016,7 -1016,7 +1016,7 @@@ static void end_packfile(void
                struct tag *t;
  
                close_pack_windows(pack_data);
 -              sha1close(pack_file, cur_pack_oid.hash, 0);
 +              hashclose(pack_file, cur_pack_oid.hash, 0);
                fixup_pack_header_footer(pack_data->pack_fd, pack_data->sha1,
                                    pack_data->pack_name, object_count,
                                    cur_pack_oid.hash, pack_size);
@@@ -1092,15 -1092,15 +1092,15 @@@ static int store_object
        unsigned char hdr[96];
        struct object_id oid;
        unsigned long hdrlen, deltalen;
 -      git_SHA_CTX c;
 +      git_hash_ctx c;
        git_zstream s;
  
        hdrlen = xsnprintf((char *)hdr, sizeof(hdr), "%s %lu",
 -                         typename(type), (unsigned long)dat->len) + 1;
 -      git_SHA1_Init(&c);
 -      git_SHA1_Update(&c, hdr, hdrlen);
 -      git_SHA1_Update(&c, dat->buf, dat->len);
 -      git_SHA1_Final(oid.hash, &c);
 +                         type_name(type), (unsigned long)dat->len) + 1;
 +      the_hash_algo->init_fn(&c);
 +      the_hash_algo->update_fn(&c, hdr, hdrlen);
 +      the_hash_algo->update_fn(&c, dat->buf, dat->len);
 +      the_hash_algo->final_fn(oid.hash, &c);
        if (oidout)
                oidcpy(oidout, &oid);
  
                return 1;
        }
  
 -      if (last && last->data.buf && last->depth < max_depth && dat->len > 20) {
 +      if (last && last->data.buf && last->depth < max_depth
 +              && dat->len > the_hash_algo->rawsz) {
 +
                delta_count_attempts_by_type[type]++;
                delta = diff_delta(last->data.buf, last->data.len,
                        dat->buf, dat->len,
 -                      &deltalen, dat->len - 20);
 +                      &deltalen, dat->len - the_hash_algo->rawsz);
        } else
                delta = NULL;
  
  
                hdrlen = encode_in_pack_object_header(hdr, sizeof(hdr),
                                                      OBJ_OFS_DELTA, deltalen);
 -              sha1write(pack_file, hdr, hdrlen);
 +              hashwrite(pack_file, hdr, hdrlen);
                pack_size += hdrlen;
  
                hdr[pos] = ofs & 127;
                while (ofs >>= 7)
                        hdr[--pos] = 128 | (--ofs & 127);
 -              sha1write(pack_file, hdr + pos, sizeof(hdr) - pos);
 +              hashwrite(pack_file, hdr + pos, sizeof(hdr) - pos);
                pack_size += sizeof(hdr) - pos;
        } else {
                e->depth = 0;
                hdrlen = encode_in_pack_object_header(hdr, sizeof(hdr),
                                                      type, dat->len);
 -              sha1write(pack_file, hdr, hdrlen);
 +              hashwrite(pack_file, hdr, hdrlen);
                pack_size += hdrlen;
        }
  
 -      sha1write(pack_file, out, s.total_out);
 +      hashwrite(pack_file, out, s.total_out);
        pack_size += s.total_out;
  
        e->idx.crc32 = crc32_end(pack_file);
        return 0;
  }
  
 -static void truncate_pack(struct sha1file_checkpoint *checkpoint)
 +static void truncate_pack(struct hashfile_checkpoint *checkpoint)
  {
 -      if (sha1file_truncate(pack_file, checkpoint))
 +      if (hashfile_truncate(pack_file, checkpoint))
                die_errno("cannot truncate pack to skip duplicate");
        pack_size = checkpoint->offset;
  }
@@@ -1233,9 -1231,9 +1233,9 @@@ static void stream_blob(uintmax_t len, 
        struct object_id oid;
        unsigned long hdrlen;
        off_t offset;
 -      git_SHA_CTX c;
 +      git_hash_ctx c;
        git_zstream s;
 -      struct sha1file_checkpoint checkpoint;
 +      struct hashfile_checkpoint checkpoint;
        int status = Z_OK;
  
        /* Determine if we should auto-checkpoint. */
                || (pack_size + 60 + len) < pack_size)
                cycle_packfile();
  
 -      sha1file_checkpoint(pack_file, &checkpoint);
 +      hashfile_checkpoint(pack_file, &checkpoint);
        offset = checkpoint.offset;
  
        hdrlen = xsnprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1;
  
 -      git_SHA1_Init(&c);
 -      git_SHA1_Update(&c, out_buf, hdrlen);
 +      the_hash_algo->init_fn(&c);
 +      the_hash_algo->update_fn(&c, out_buf, hdrlen);
  
        crc32_begin(pack_file);
  
                        if (!n && feof(stdin))
                                die("EOF in data (%" PRIuMAX " bytes remaining)", len);
  
 -                      git_SHA1_Update(&c, in_buf, n);
 +                      the_hash_algo->update_fn(&c, in_buf, n);
                        s.next_in = in_buf;
                        s.avail_in = n;
                        len -= n;
  
                if (!s.avail_out || status == Z_STREAM_END) {
                        size_t n = s.next_out - out_buf;
 -                      sha1write(pack_file, out_buf, n);
 +                      hashwrite(pack_file, out_buf, n);
                        pack_size += n;
                        s.next_out = out_buf;
                        s.avail_out = out_sz;
                }
        }
        git_deflate_end(&s);
 -      git_SHA1_Final(oid.hash, &c);
 +      the_hash_algo->final_fn(oid.hash, &c);
  
        if (oidout)
                oidcpy(oidout, &oid);
@@@ -1352,25 -1350,25 +1352,25 @@@ static void *gfi_unpack_entry
  {
        enum object_type type;
        struct packed_git *p = all_packs[oe->pack_id];
 -      if (p == pack_data && p->pack_size < (pack_size + 20)) {
 +      if (p == pack_data && p->pack_size < (pack_size + the_hash_algo->rawsz)) {
                /* The object is stored in the packfile we are writing to
                 * and we have modified it since the last time we scanned
                 * back to read a previously written object.  If an old
 -               * window covered [p->pack_size, p->pack_size + 20) its
 +               * window covered [p->pack_size, p->pack_size + rawsz) its
                 * data is stale and is not valid.  Closing all windows
                 * and updating the packfile length ensures we can read
                 * the newly written data.
                 */
                close_pack_windows(p);
 -              sha1flush(pack_file);
 +              hashflush(pack_file);
  
 -              /* We have to offer 20 bytes additional on the end of
 +              /* We have to offer rawsz bytes additional on the end of
                 * the packfile as the core unpacker code assumes the
                 * footer is present at the file end and must promise
 -               * at least 20 bytes within any window it maps.  But
 +               * at least rawsz bytes within any window it maps.  But
                 * we don't actually create the footer here.
                 */
 -              p->pack_size = pack_size + 20;
 +              p->pack_size = pack_size + the_hash_algo->rawsz;
        }
        return unpack_entry(p, oe->idx.offset, &type, sizep);
  }
@@@ -2206,7 -2204,7 +2206,7 @@@ static void construct_path_with_fanout(
                unsigned char fanout, char *path)
  {
        unsigned int i = 0, j = 0;
 -      if (fanout >= 20)
 +      if (fanout >= the_hash_algo->rawsz)
                die("Too large fanout (%u)", fanout);
        while (fanout) {
                path[i++] = hex_sha1[j++];
                path[i++] = '/';
                fanout--;
        }
 -      memcpy(path + i, hex_sha1 + j, GIT_SHA1_HEXSZ - j);
 -      path[i + GIT_SHA1_HEXSZ - j] = '\0';
 +      memcpy(path + i, hex_sha1 + j, the_hash_algo->hexsz - j);
 +      path[i + the_hash_algo->hexsz - j] = '\0';
  }
  
  static uintmax_t do_change_note_fanout(
@@@ -2423,7 -2421,7 +2423,7 @@@ static void file_change_m(const char *p
                else if (oe) {
                        if (oe->type != OBJ_COMMIT)
                                die("Not a commit (actually a %s): %s",
 -                                      typename(oe->type), command_buf.buf);
 +                                      type_name(oe->type), command_buf.buf);
                }
                /*
                 * Accept the sha1 without checking; it expected to be in
                                        command_buf.buf);
                if (type != expected)
                        die("Not a %s (actually a %s): %s",
 -                              typename(expected), typename(type),
 +                              type_name(expected), type_name(type),
                                command_buf.buf);
        }
  
@@@ -2601,14 -2599,14 +2601,14 @@@ static void note_change_n(const char *p
        } else if (oe) {
                if (oe->type != OBJ_BLOB)
                        die("Not a blob (actually a %s): %s",
 -                              typename(oe->type), command_buf.buf);
 +                              type_name(oe->type), command_buf.buf);
        } else if (!is_null_oid(&oid)) {
                enum object_type type = sha1_object_info(oid.hash, NULL);
                if (type < 0)
                        die("Blob not found: %s", command_buf.buf);
                if (type != OBJ_BLOB)
                        die("Not a blob (actually a %s): %s",
 -                          typename(type), command_buf.buf);
 +                          type_name(type), command_buf.buf);
        }
  
        construct_path_with_fanout(oid_to_hex(&commit_oid), *old_fanout, path);
@@@ -2916,7 -2914,7 +2916,7 @@@ static void parse_new_tag(const char *a
                    "object %s\n"
                    "type %s\n"
                    "tag %s\n",
 -                  oid_to_hex(&oid), typename(type), t->name);
 +                  oid_to_hex(&oid), type_name(type), t->name);
        if (tagger)
                strbuf_addf(&new_data,
                            "tagger %s\n", tagger);
@@@ -2987,10 -2985,10 +2987,10 @@@ static void cat_blob(struct object_entr
                die("Can't read object %s", oid_to_hex(oid));
        if (type != OBJ_BLOB)
                die("Object %s is a %s but a blob was expected.",
 -                  oid_to_hex(oid), typename(type));
 +                  oid_to_hex(oid), type_name(type));
        strbuf_reset(&line);
        strbuf_addf(&line, "%s %s %lu\n", oid_to_hex(oid),
 -                                              typename(type), size);
 +                                              type_name(type), size);
        cat_blob_write(line.buf, line.len);
        strbuf_release(&line);
        cat_blob_write(buf, size);
  
  static void parse_get_mark(const char *p)
  {
-       struct object_entry *oe = oe;
+       struct object_entry *oe;
        char output[GIT_MAX_HEXSZ + 2];
  
        /* get-mark SP <object> LF */
  
  static void parse_cat_blob(const char *p)
  {
-       struct object_entry *oe = oe;
+       struct object_entry *oe;
        struct object_id oid;
  
        /* cat-blob SP <object> LF */
diff --combined merge-recursive.c
index 2f232ad3b40e6a94ea78bd856a4ea2deaaf1d468,7dad1646921d4f5c503646af40446de2edb09d1f..869092f7b9bc0ce1104a1c43c7201acdee2eb4f8
@@@ -513,25 -513,6 +513,25 @@@ static void record_df_conflict_files(st
  
  struct rename {
        struct diff_filepair *pair;
 +      /*
 +       * Purpose of src_entry and dst_entry:
 +       *
 +       * If 'before' is renamed to 'after' then src_entry will contain
 +       * the versions of 'before' from the merge_base, HEAD, and MERGE in
 +       * stages 1, 2, and 3; dst_entry will contain the respective
 +       * versions of 'after' in corresponding locations.  Thus, we have a
 +       * total of six modes and oids, though some will be null.  (Stage 0
 +       * is ignored; we're interested in handling conflicts.)
 +       *
 +       * Since we don't turn on break-rewrites by default, neither
 +       * src_entry nor dst_entry can have all three of their stages have
 +       * non-null oids, meaning at most four of the six will be non-null.
 +       * Also, since this is a rename, both src_entry and dst_entry will
 +       * have at least one non-null oid, meaning at least two will be
 +       * non-null.  Of the six oids, a typical rename will have three be
 +       * non-null.  Only two implies a rename/delete, and four implies a
 +       * rename/add.
 +       */
        struct stage_data *src_entry;
        struct stage_data *dst_entry;
        unsigned processed:1;
@@@ -1028,9 -1009,8 +1028,9 @@@ static int merge_file_1(struct merge_op
                        if ((merge_status < 0) || !result_buf.ptr)
                                ret = err(o, _("Failed to execute internal merge"));
  
 -                      if (!ret && write_sha1_file(result_buf.ptr, result_buf.size,
 -                                                  blob_type, result->oid.hash))
 +                      if (!ret &&
 +                          write_object_file(result_buf.ptr, result_buf.size,
 +                                            blob_type, &result->oid))
                                ret = err(o, _("Unable to add %s to database"),
                                          a->path);
  
@@@ -2018,10 -1998,10 +2018,10 @@@ int merge_trees(struct merge_options *o
                get_files_dirs(o, merge);
  
                entries = get_unmerged();
 -              record_df_conflict_files(o, entries);
                re_head  = get_renames(o, head, common, head, merge, entries);
                re_merge = get_renames(o, merge, common, head, merge, entries);
                clean = process_renames(o, re_head, re_merge);
 +              record_df_conflict_files(o, entries);
                if (clean < 0)
                        goto cleanup;
                for (i = entries->nr-1; 0 <= i; i--) {
@@@ -2090,7 -2070,7 +2090,7 @@@ int merge_recursive(struct merge_option
  {
        struct commit_list *iter;
        struct commit *merged_common_ancestors;
-       struct tree *mrtree = mrtree;
+       struct tree *mrtree;
        int clean;
  
        if (show(o, 4)) {
@@@ -2218,13 -2198,11 +2218,13 @@@ int merge_recursive_generic(struct merg
        hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
        clean = merge_recursive(o, head_commit, next_commit, ca,
                        result);
 -      if (clean < 0)
 +      if (clean < 0) {
 +              rollback_lock_file(&lock);
                return clean;
 +      }
  
 -      if (active_cache_changed &&
 -          write_locked_index(&the_index, &lock, COMMIT_LOCK))
 +      if (write_locked_index(&the_index, &lock,
 +                             COMMIT_LOCK | SKIP_IF_UNCHANGED))
                return err(o, _("Unable to write index."));
  
        return clean ? 0 : 1;
diff --combined read-cache.c
index a5dc7c7e6718972b158aebfd36b4625f54887341,49607ddcd7078fb47bac660c39a777a5569d3f80..59a73f4a81d76a19b8a2280e9643f7c1e715a5d4
@@@ -62,7 -62,6 +62,7 @@@ static void replace_index_entry(struct 
        replace_index_entry_in_base(istate, old, ce);
        remove_name_hash(istate, old);
        free(old);
 +      ce->ce_flags &= ~CE_HASHED;
        set_index_entry(istate, nr, ce);
        ce->ce_flags |= CE_UPDATE_IN_BASE;
        mark_fsmonitor_invalid(istate, ce);
  
  void rename_index_entry_at(struct index_state *istate, int nr, const char *new_name)
  {
 -      struct cache_entry *old = istate->cache[nr], *new;
 +      struct cache_entry *old_entry = istate->cache[nr], *new_entry;
        int namelen = strlen(new_name);
  
 -      new = xmalloc(cache_entry_size(namelen));
 -      copy_cache_entry(new, old);
 -      new->ce_flags &= ~CE_HASHED;
 -      new->ce_namelen = namelen;
 -      new->index = 0;
 -      memcpy(new->name, new_name, namelen + 1);
 +      new_entry = xmalloc(cache_entry_size(namelen));
 +      copy_cache_entry(new_entry, old_entry);
 +      new_entry->ce_flags &= ~CE_HASHED;
 +      new_entry->ce_namelen = namelen;
 +      new_entry->index = 0;
 +      memcpy(new_entry->name, new_name, namelen + 1);
  
 -      cache_tree_invalidate_path(istate, old->name);
 -      untracked_cache_remove_from_index(istate, old->name);
 +      cache_tree_invalidate_path(istate, old_entry->name);
 +      untracked_cache_remove_from_index(istate, old_entry->name);
        remove_index_entry_at(istate, nr);
 -      add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
 +      add_index_entry(istate, new_entry, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
  }
  
  void fill_stat_data(struct stat_data *sd, struct stat *st)
@@@ -616,26 -615,26 +616,26 @@@ static struct cache_entry *create_alias
                                           struct cache_entry *alias)
  {
        int len;
 -      struct cache_entry *new;
 +      struct cache_entry *new_entry;
  
        if (alias->ce_flags & CE_ADDED)
                die("Will not add file alias '%s' ('%s' already exists in index)", ce->name, alias->name);
  
        /* Ok, create the new entry using the name of the existing alias */
        len = ce_namelen(alias);
 -      new = xcalloc(1, cache_entry_size(len));
 -      memcpy(new->name, alias->name, len);
 -      copy_cache_entry(new, ce);
 +      new_entry = xcalloc(1, cache_entry_size(len));
 +      memcpy(new_entry->name, alias->name, len);
 +      copy_cache_entry(new_entry, ce);
        save_or_free_index_entry(istate, ce);
 -      return new;
 +      return new_entry;
  }
  
  void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
  {
 -      unsigned char sha1[20];
 -      if (write_sha1_file("", 0, blob_type, sha1))
 +      struct object_id oid;
 +      if (write_object_file("", 0, blob_type, &oid))
                die("cannot create an empty blob in the object database");
 -      hashcpy(ce->oid.hash, sha1);
 +      oidcpy(&ce->oid, &oid);
  }
  
  int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
@@@ -1218,8 -1217,9 +1218,8 @@@ int add_index_entry(struct index_state 
        /* Add it in.. */
        istate->cache_nr++;
        if (istate->cache_nr > pos + 1)
 -              memmove(istate->cache + pos + 1,
 -                      istate->cache + pos,
 -                      (istate->cache_nr - pos - 1) * sizeof(ce));
 +              MOVE_ARRAY(istate->cache + pos + 1, istate->cache + pos,
 +                         istate->cache_nr - pos - 1);
        set_index_entry(istate, pos, ce);
        istate->cache_changed |= CE_ENTRY_ADDED;
        return 0;
@@@ -1325,8 -1325,7 +1325,8 @@@ static struct cache_entry *refresh_cach
  
        size = ce_size(ce);
        updated = xmalloc(size);
 -      memcpy(updated, ce, size);
 +      copy_cache_entry(updated, ce);
 +      memcpy(updated->name, ce->name, ce->ce_namelen + 1);
        fill_stat_cache_info(updated, &st);
        /*
         * If ignore_valid is not set, we should leave CE_VALID bit
@@@ -1373,7 -1372,6 +1373,7 @@@ int refresh_index(struct index_state *i
        const char *typechange_fmt;
        const char *added_fmt;
        const char *unmerged_fmt;
 +      uint64_t start = getnanotime();
  
        modified_fmt = (in_porcelain ? "M\t%s\n" : "%s: needs update\n");
        deleted_fmt = (in_porcelain ? "D\t%s\n" : "%s: needs update\n");
        added_fmt = (in_porcelain ? "A\t%s\n" : "%s needs update\n");
        unmerged_fmt = (in_porcelain ? "U\t%s\n" : "%s: needs merge\n");
        for (i = 0; i < istate->cache_nr; i++) {
 -              struct cache_entry *ce, *new;
 +              struct cache_entry *ce, *new_entry;
                int cache_errno = 0;
                int changed = 0;
                int filtered = 0;
                if (filtered)
                        continue;
  
 -              new = refresh_cache_ent(istate, ce, options, &cache_errno, &changed);
 -              if (new == ce)
 +              new_entry = refresh_cache_ent(istate, ce, options, &cache_errno, &changed);
 +              if (new_entry == ce)
                        continue;
 -              if (!new) {
 +              if (!new_entry) {
                        const char *fmt;
  
                        if (really && cache_errno == EINVAL) {
                        continue;
                }
  
 -              replace_index_entry(istate, i, new);
 +              replace_index_entry(istate, i, new_entry);
        }
 +      trace_performance_since(start, "refresh index");
        return has_errors;
  }
  
@@@ -1548,8 -1545,8 +1548,8 @@@ int verify_ce_order
  
  static int verify_hdr(struct cache_header *hdr, unsigned long size)
  {
 -      git_SHA_CTX c;
 -      unsigned char sha1[20];
 +      git_hash_ctx c;
 +      unsigned char hash[GIT_MAX_RAWSZ];
        int hdr_version;
  
        if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
        if (!verify_index_checksum)
                return 0;
  
 -      git_SHA1_Init(&c);
 -      git_SHA1_Update(&c, hdr, size - 20);
 -      git_SHA1_Final(sha1, &c);
 -      if (hashcmp(sha1, (unsigned char *)hdr + size - 20))
 +      the_hash_algo->init_fn(&c);
 +      the_hash_algo->update_fn(&c, hdr, size - the_hash_algo->rawsz);
 +      the_hash_algo->final_fn(hash, &c);
 +      if (hashcmp(hash, (unsigned char *)hdr + size - the_hash_algo->rawsz))
                return error("bad index file sha1 signature");
        return 0;
  }
@@@ -1606,7 -1603,7 +1606,7 @@@ int hold_locked_index(struct lock_file 
  
  int read_index(struct index_state *istate)
  {
 -      return read_index_from(istate, get_index_file());
 +      return read_index_from(istate, get_index_file(), get_git_dir());
  }
  
  static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *ondisk,
@@@ -1794,7 -1791,7 +1794,7 @@@ int do_read_index(struct index_state *i
                die_errno("cannot stat the open index");
  
        mmap_size = xsize_t(st.st_size);
 -      if (mmap_size < sizeof(struct cache_header) + 20)
 +      if (mmap_size < sizeof(struct cache_header) + the_hash_algo->rawsz)
                die("index file smaller than expected");
  
        mmap = xmmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE, fd, 0);
        if (verify_hdr(hdr, mmap_size) < 0)
                goto unmap;
  
 -      hashcpy(istate->sha1, (const unsigned char *)hdr + mmap_size - 20);
 +      hashcpy(istate->sha1, (const unsigned char *)hdr + mmap_size - the_hash_algo->rawsz);
        istate->version = ntohl(hdr->hdr_version);
        istate->cache_nr = ntohl(hdr->hdr_entries);
        istate->cache_alloc = alloc_nr(istate->cache_nr);
        istate->timestamp.sec = st.st_mtime;
        istate->timestamp.nsec = ST_MTIME_NSEC(st);
  
 -      while (src_offset <= mmap_size - 20 - 8) {
 +      while (src_offset <= mmap_size - the_hash_algo->rawsz - 8) {
                /* After an array of active_nr index entries,
                 * there can be arbitrary number of extended
                 * sections, each of which is prefixed with
@@@ -1866,27 -1863,26 +1866,27 @@@ unmap
   * This way, shared index can be removed if they have not been used
   * for some time.
   */
 -static void freshen_shared_index(char *base_sha1_hex, int warn)
 +static void freshen_shared_index(const char *shared_index, int warn)
  {
 -      char *shared_index = git_pathdup("sharedindex.%s", base_sha1_hex);
        if (!check_and_freshen_file(shared_index, 1) && warn)
                warning("could not freshen shared index '%s'", shared_index);
 -      free(shared_index);
  }
  
 -int read_index_from(struct index_state *istate, const char *path)
 +int read_index_from(struct index_state *istate, const char *path,
 +                  const char *gitdir)
  {
 +      uint64_t start = getnanotime();
        struct split_index *split_index;
        int ret;
        char *base_sha1_hex;
 -      const char *base_path;
 +      char *base_path;
  
        /* istate->initialized covers both .git/index and .git/sharedindex.xxx */
        if (istate->initialized)
                return istate->cache_nr;
  
        ret = do_read_index(istate, path, 0);
 +      trace_performance_since(start, "read cache %s", path);
  
        split_index = istate->split_index;
        if (!split_index || is_null_sha1(split_index->base_sha1)) {
                split_index->base = xcalloc(1, sizeof(*split_index->base));
  
        base_sha1_hex = sha1_to_hex(split_index->base_sha1);
 -      base_path = git_path("sharedindex.%s", base_sha1_hex);
 +      base_path = xstrfmt("%s/sharedindex.%s", gitdir, base_sha1_hex);
        ret = do_read_index(split_index->base, base_path, 1);
        if (hashcmp(split_index->base_sha1, split_index->base->sha1))
                die("broken index, expect %s in %s, got %s",
                    base_sha1_hex, base_path,
                    sha1_to_hex(split_index->base->sha1));
  
 -      freshen_shared_index(base_sha1_hex, 0);
 +      freshen_shared_index(base_path, 0);
        merge_base_index(istate);
        post_read_index_from(istate);
 +      trace_performance_since(start, "read cache %s", base_path);
 +      free(base_path);
        return ret;
  }
  
@@@ -1963,11 -1957,11 +1963,11 @@@ int unmerged_index(const struct index_s
  static unsigned char write_buffer[WRITE_BUFFER_SIZE];
  static unsigned long write_buffer_len;
  
 -static int ce_write_flush(git_SHA_CTX *context, int fd)
 +static int ce_write_flush(git_hash_ctx *context, int fd)
  {
        unsigned int buffered = write_buffer_len;
        if (buffered) {
 -              git_SHA1_Update(context, write_buffer, buffered);
 +              the_hash_algo->update_fn(context, write_buffer, buffered);
                if (write_in_full(fd, write_buffer, buffered) < 0)
                        return -1;
                write_buffer_len = 0;
        return 0;
  }
  
 -static int ce_write(git_SHA_CTX *context, int fd, void *data, unsigned int len)
 +static int ce_write(git_hash_ctx *context, int fd, void *data, unsigned int len)
  {
        while (len) {
                unsigned int buffered = write_buffer_len;
        return 0;
  }
  
 -static int write_index_ext_header(git_SHA_CTX *context, int fd,
 +static int write_index_ext_header(git_hash_ctx *context, int fd,
                                  unsigned int ext, unsigned int sz)
  {
        ext = htonl(ext);
                (ce_write(context, fd, &sz, 4) < 0)) ? -1 : 0;
  }
  
 -static int ce_flush(git_SHA_CTX *context, int fd, unsigned char *sha1)
 +static int ce_flush(git_hash_ctx *context, int fd, unsigned char *hash)
  {
        unsigned int left = write_buffer_len;
  
        if (left) {
                write_buffer_len = 0;
 -              git_SHA1_Update(context, write_buffer, left);
 +              the_hash_algo->update_fn(context, write_buffer, left);
        }
  
 -      /* Flush first if not enough space for SHA1 signature */
 -      if (left + 20 > WRITE_BUFFER_SIZE) {
 +      /* Flush first if not enough space for hash signature */
 +      if (left + the_hash_algo->rawsz > WRITE_BUFFER_SIZE) {
                if (write_in_full(fd, write_buffer, left) < 0)
                        return -1;
                left = 0;
        }
  
 -      /* Append the SHA1 signature at the end */
 -      git_SHA1_Final(write_buffer + left, context);
 -      hashcpy(sha1, write_buffer + left);
 -      left += 20;
 +      /* Append the hash signature at the end */
 +      the_hash_algo->final_fn(write_buffer + left, context);
 +      hashcpy(hash, write_buffer + left);
 +      left += the_hash_algo->rawsz;
        return (write_in_full(fd, write_buffer, left) < 0) ? -1 : 0;
  }
  
@@@ -2106,17 -2100,19 +2106,19 @@@ static void copy_cache_entry_to_ondisk(
        }
  }
  
 -static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
 +static int ce_write_entry(git_hash_ctx *c, int fd, struct cache_entry *ce,
                          struct strbuf *previous_name, struct ondisk_cache_entry *ondisk)
  {
        int size;
-       int saved_namelen = saved_namelen; /* compiler workaround */
        int result;
+       unsigned int saved_namelen;
+       int stripped_name = 0;
        static unsigned char padding[8] = { 0x00 };
  
        if (ce->ce_flags & CE_STRIP_NAME) {
                saved_namelen = ce_namelen(ce);
                ce->ce_namelen = 0;
+               stripped_name = 1;
        }
  
        if (ce->ce_flags & CE_EXTENDED)
                strbuf_splice(previous_name, common, to_remove,
                              ce->name + common, ce_namelen(ce) - common);
        }
-       if (ce->ce_flags & CE_STRIP_NAME) {
+       if (stripped_name) {
                ce->ce_namelen = saved_namelen;
                ce->ce_flags &= ~CE_STRIP_NAME;
        }
@@@ -2173,7 -2169,7 +2175,7 @@@ static int verify_index_from(const stru
        int fd;
        ssize_t n;
        struct stat st;
 -      unsigned char sha1[20];
 +      unsigned char hash[GIT_MAX_RAWSZ];
  
        if (!istate->initialized)
                return 0;
        if (fstat(fd, &st))
                goto out;
  
 -      if (st.st_size < sizeof(struct cache_header) + 20)
 +      if (st.st_size < sizeof(struct cache_header) + the_hash_algo->rawsz)
                goto out;
  
 -      n = pread_in_full(fd, sha1, 20, st.st_size - 20);
 -      if (n != 20)
 +      n = pread_in_full(fd, hash, the_hash_algo->rawsz, st.st_size - the_hash_algo->rawsz);
 +      if (n != the_hash_algo->rawsz)
                goto out;
  
 -      if (hashcmp(istate->sha1, sha1))
 +      if (hashcmp(istate->sha1, hash))
                goto out;
  
        close(fd);
@@@ -2240,9 -2236,8 +2242,9 @@@ void update_index_if_able(struct index_
  static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
                          int strip_extensions)
  {
 +      uint64_t start = getnanotime();
        int newfd = tempfile->fd;
 -      git_SHA_CTX c;
 +      git_hash_ctx c;
        struct cache_header hdr;
        int i, err = 0, removed, extended, hdr_version;
        struct cache_entry **cache = istate->cache;
        struct stat st;
        struct ondisk_cache_entry_extended ondisk;
        struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
 -      int drop_cache_tree = 0;
 +      int drop_cache_tree = istate->drop_cache_tree;
  
        for (i = removed = extended = 0; i < entries; i++) {
                if (cache[i]->ce_flags & CE_REMOVE)
        hdr.hdr_version = htonl(hdr_version);
        hdr.hdr_entries = htonl(entries - removed);
  
 -      git_SHA1_Init(&c);
 +      the_hash_algo->init_fn(&c);
        if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
                return -1;
  
                return -1;
        istate->timestamp.sec = (unsigned int)st.st_mtime;
        istate->timestamp.nsec = ST_MTIME_NSEC(st);
 +      trace_performance_since(start, "write index, changed mask = %x", istate->cache_changed);
        return 0;
  }
  
@@@ -2480,21 -2474,32 +2482,21 @@@ static int clean_shared_index_files(con
  }
  
  static int write_shared_index(struct index_state *istate,
 -                            struct lock_file *lock, unsigned flags)
 +                            struct tempfile **temp)
  {
 -      struct tempfile *temp;
        struct split_index *si = istate->split_index;
        int ret;
  
 -      temp = mks_tempfile(git_path("sharedindex_XXXXXX"));
 -      if (!temp) {
 -              hashclr(si->base_sha1);
 -              return do_write_locked_index(istate, lock, flags);
 -      }
        move_cache_to_base_index(istate);
 -      ret = do_write_index(si->base, temp, 1);
 -      if (ret) {
 -              delete_tempfile(&temp);
 +      ret = do_write_index(si->base, *temp, 1);
 +      if (ret)
                return ret;
 -      }
 -      ret = adjust_shared_perm(get_tempfile_path(temp));
 +      ret = adjust_shared_perm(get_tempfile_path(*temp));
        if (ret) {
 -              int save_errno = errno;
 -              error("cannot fix permission bits on %s", get_tempfile_path(temp));
 -              delete_tempfile(&temp);
 -              errno = save_errno;
 +              error("cannot fix permission bits on %s", get_tempfile_path(*temp));
                return ret;
        }
 -      ret = rename_tempfile(&temp,
 +      ret = rename_tempfile(temp,
                              git_path("sharedindex.%s", sha1_to_hex(si->base->sha1)));
        if (!ret) {
                hashcpy(si->base_sha1, si->base->sha1);
@@@ -2540,12 -2545,6 +2542,12 @@@ int write_locked_index(struct index_sta
        int new_shared_index, ret;
        struct split_index *si = istate->split_index;
  
 +      if ((flags & SKIP_IF_UNCHANGED) && !istate->cache_changed) {
 +              if (flags & COMMIT_LOCK)
 +                      rollback_lock_file(lock);
 +              return 0;
 +      }
 +
        if (istate->fsmonitor_last_update)
                fill_fsmonitor_bitmap(istate);
  
        new_shared_index = istate->cache_changed & SPLIT_INDEX_ORDERED;
  
        if (new_shared_index) {
 -              ret = write_shared_index(istate, lock, flags);
 +              struct tempfile *temp;
 +              int saved_errno;
 +
 +              temp = mks_tempfile(git_path("sharedindex_XXXXXX"));
 +              if (!temp) {
 +                      hashclr(si->base_sha1);
 +                      ret = do_write_locked_index(istate, lock, flags);
 +                      goto out;
 +              }
 +              ret = write_shared_index(istate, &temp);
 +
 +              saved_errno = errno;
 +              if (is_tempfile_active(temp))
 +                      delete_tempfile(&temp);
 +              errno = saved_errno;
 +
                if (ret)
                        goto out;
        }
        ret = write_split_index(istate, lock, flags);
  
        /* Freshen the shared index only if the split-index was written */
 -      if (!ret && !new_shared_index)
 -              freshen_shared_index(sha1_to_hex(si->base_sha1), 1);
 +      if (!ret && !new_shared_index) {
 +              const char *shared_index = git_path("sharedindex.%s",
 +                                                  sha1_to_hex(si->base_sha1));
 +              freshen_shared_index(shared_index, 1);
 +      }
  
  out:
        if (flags & COMMIT_LOCK)