Merge branch 'jk/loose-object-cache-oid'
authorJunio C Hamano <gitster@pobox.com>
Thu, 7 Feb 2019 06:05:27 +0000 (22:05 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 7 Feb 2019 06:05:27 +0000 (22:05 -0800)
Code clean-up.

* jk/loose-object-cache-oid:
prefer "hash mismatch" to "sha1 mismatch"
sha1-file: avoid "sha1 file" for generic use in messages
sha1-file: prefer "loose object file" to "sha1 file" in messages
sha1-file: drop has_sha1_file()
convert has_sha1_file() callers to has_object_file()
sha1-file: convert pass-through functions to object_id
sha1-file: modernize loose header/stream functions
sha1-file: modernize loose object file functions
http: use struct object_id instead of bare sha1
update comment references to sha1_object_info()
sha1-file: fix outdated sha1 comment references

15 files changed:
1  2 
apply.c
builtin/cat-file.c
builtin/fetch.c
builtin/pack-objects.c
builtin/reflog.c
cache-tree.c
cache.h
http-push.c
http.c
http.h
object-store.h
object.c
send-pack.c
sha1-file.c
streaming.c
diff --combined apply.c
index beed3091d2a347116a11cb4b593a70b2c90406f8,b8e257ead24a3fe19b0dc9585f471a70b570730f..892ede5a318f751c80fcceab036a8cbaee391774
+++ b/apply.c
@@@ -467,6 -467,7 +467,6 @@@ static char *squash_slash(char *name
  
  static char *find_name_gnu(struct apply_state *state,
                           const char *line,
 -                         const char *def,
                           int p_value)
  {
        struct strbuf name = STRBUF_INIT;
@@@ -713,7 -714,7 +713,7 @@@ static char *find_name(struct apply_sta
                       int terminate)
  {
        if (*line == '"') {
 -              char *name = find_name_gnu(state, line, def, p_value);
 +              char *name = find_name_gnu(state, line, p_value);
                if (name)
                        return name;
        }
@@@ -730,7 -731,7 +730,7 @@@ static char *find_name_traditional(stru
        size_t date_len;
  
        if (*line == '"') {
 -              char *name = find_name_gnu(state, line, def, p_value);
 +              char *name = find_name_gnu(state, line, p_value);
                if (name)
                        return name;
        }
@@@ -3182,7 -3183,7 +3182,7 @@@ static int apply_binary(struct apply_st
                return 0; /* deletion patch */
        }
  
-       if (has_sha1_file(oid.hash)) {
+       if (has_object_file(&oid)) {
                /* We already have the postimage */
                enum object_type type;
                unsigned long size;
@@@ -3351,8 -3352,7 +3351,8 @@@ static int checkout_target(struct index
  
        costate.refresh_cache = 1;
        costate.istate = istate;
 -      if (checkout_entry(ce, &costate, NULL) || lstat(ce->name, st))
 +      if (checkout_entry(ce, &costate, NULL, NULL) ||
 +          lstat(ce->name, st))
                return error(_("cannot checkout %s"), ce->name);
        return 0;
  }
@@@ -4019,7 -4019,7 +4019,7 @@@ static int read_apply_cache(struct appl
                return read_index_from(state->repo->index, state->index_file,
                                       get_git_dir());
        else
 -              return read_index(state->repo->index);
 +              return repo_read_index(state->repo);
  }
  
  /* This function tries to read the object name from the current index */
@@@ -4712,8 -4712,7 +4712,8 @@@ static int apply_patch(struct apply_sta
                                                  state->index_file,
                                                  LOCK_DIE_ON_ERROR);
                else
 -                      hold_locked_index(&state->lock_file, LOCK_DIE_ON_ERROR);
 +                      repo_hold_locked_index(state->repo, &state->lock_file,
 +                                             LOCK_DIE_ON_ERROR);
        }
  
        if (state->check_index && read_apply_cache(state) < 0) {
diff --combined builtin/cat-file.c
index 8487cd7dba0681087a5700039c234084f071333c,baaafbdcf375f87f7c3b5af239c51172f8320f84..0f092382e175cf7ebe43d2f53ef1c5c79c338568
@@@ -3,7 -3,6 +3,7 @@@
   *
   * Copyright (C) Linus Torvalds, 2005
   */
 +#define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "builtin.h"
@@@ -74,8 -73,7 +74,8 @@@ static int cat_one_file(int opt, const 
        if (unknown_type)
                flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
  
 -      if (get_oid_with_context(obj_name, GET_OID_RECORD_PATH,
 +      if (get_oid_with_context(the_repository, obj_name,
 +                               GET_OID_RECORD_PATH,
                                 &oid, &obj_context))
                die("Not a valid object name %s", obj_name);
  
@@@ -211,14 -209,14 +211,14 @@@ struct expand_data 
  
        /*
         * After a mark_query run, this object_info is set up to be
-        * passed to sha1_object_info_extended. It will point to the data
+        * passed to oid_object_info_extended. It will point to the data
         * elements above, so you can retrieve the response from there.
         */
        struct object_info info;
  
        /*
         * This flag will be true if the requested batch format and options
-        * don't require us to call sha1_object_info, which can then be
+        * don't require us to call oid_object_info, which can then be
         * optimized out.
         */
        unsigned skip_object_info : 1;
@@@ -382,18 -380,14 +382,18 @@@ static void batch_one_object(const cha
  {
        struct object_context ctx;
        int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
 -      enum follow_symlinks_result result;
 +      enum get_oid_result result;
  
 -      result = get_oid_with_context(obj_name, flags, &data->oid, &ctx);
 +      result = get_oid_with_context(the_repository, obj_name,
 +                                    flags, &data->oid, &ctx);
        if (result != FOUND) {
                switch (result) {
                case MISSING_OBJECT:
                        printf("%s missing\n", obj_name);
                        break;
 +              case SHORT_NAME_AMBIGUOUS:
 +                      printf("%s ambiguous\n", obj_name);
 +                      break;
                case DANGLING_SYMLINK:
                        printf("dangling %"PRIuMAX"\n%s\n",
                               (uintmax_t)strlen(obj_name), obj_name);
@@@ -496,7 -490,7 +496,7 @@@ static int batch_objects(struct batch_o
  
        /*
         * Expand once with our special mark_query flag, which will prime the
-        * object_info to be handed to sha1_object_info_extended for each
+        * object_info to be handed to oid_object_info_extended for each
         * object.
         */
        memset(&data, 0, sizeof(data));
diff --combined builtin/fetch.c
index 39c42106109f35f49550133580bf34b6eb60aa26,57f35c6a0af4d0f12be41ad71876911de049920b..5a09fe24cddac79bb66f90b0405f5bcc9855dbee
@@@ -317,8 -317,7 +317,7 @@@ static void find_non_local_tags(const s
                            !has_object_file_with_flags(&ref->old_oid,
                                                        OBJECT_INFO_QUICK) &&
                            !will_fetch(head, ref->old_oid.hash) &&
-                           !has_sha1_file_with_flags(item->oid.hash,
-                                                     OBJECT_INFO_QUICK) &&
+                           !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
                            !will_fetch(head, item->oid.hash))
                                oidclr(&item->oid);
                        item = NULL;
                 * fetch.
                 */
                if (item &&
-                   !has_sha1_file_with_flags(item->oid.hash, OBJECT_INFO_QUICK) &&
+                   !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
                    !will_fetch(head, item->oid.hash))
                        oidclr(&item->oid);
  
         * checked to see if it needs fetching.
         */
        if (item &&
-           !has_sha1_file_with_flags(item->oid.hash, OBJECT_INFO_QUICK) &&
+           !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
            !will_fetch(head, item->oid.hash))
                oidclr(&item->oid);
  
@@@ -629,14 -628,9 +628,14 @@@ static int find_and_replace(struct strb
                            const char *needle,
                            const char *placeholder)
  {
 -      const char *p = strstr(haystack->buf, needle);
 +      const char *p = NULL;
        int plen, nlen;
  
 +      nlen = strlen(needle);
 +      if (ends_with(haystack->buf, needle))
 +              p = haystack->buf + haystack->len - nlen;
 +      else
 +              p = strstr(haystack->buf, needle);
        if (!p)
                return 0;
  
                return 0;
  
        plen = strlen(p);
 -      nlen = strlen(needle);
        if (plen > nlen && p[nlen] != '/')
                return 0;
  
@@@ -767,6 -762,9 +766,6 @@@ static int update_local_ref(struct ref 
                        what = _("[new ref]");
                }
  
 -              if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
 -                  (recurse_submodules != RECURSE_SUBMODULES_ON))
 -                      check_for_new_submodule_commits(&ref->new_oid);
                r = s_update_ref(msg, ref, 0);
                format_display(display, r ? '!' : '*', what,
                               r ? _("unable to update local ref") : NULL,
                strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
                strbuf_addstr(&quickref, "..");
                strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
 -              if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
 -                  (recurse_submodules != RECURSE_SUBMODULES_ON))
 -                      check_for_new_submodule_commits(&ref->new_oid);
                r = s_update_ref("fast-forward", ref, 1);
                format_display(display, r ? '!' : ' ', quickref.buf,
                               r ? _("unable to update local ref") : NULL,
                strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
                strbuf_addstr(&quickref, "...");
                strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
 -              if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
 -                  (recurse_submodules != RECURSE_SUBMODULES_ON))
 -                      check_for_new_submodule_commits(&ref->new_oid);
                r = s_update_ref("forced-update", ref, 1);
                format_display(display, r ? '!' : '+', quickref.buf,
                               r ? _("unable to update local ref") : _("forced update"),
@@@ -887,8 -891,6 +886,8 @@@ static int store_updated_refs(const cha
                                ref->force = rm->peer_ref->force;
                        }
  
 +                      if (recurse_submodules != RECURSE_SUBMODULES_OFF)
 +                              check_for_new_submodule_commits(&rm->old_oid);
  
                        if (!strcmp(rm->name, "HEAD")) {
                                kind = "";
@@@ -1169,7 -1171,6 +1168,7 @@@ static void add_negotiation_tips(struc
  static struct transport *prepare_transport(struct remote *remote, int deepen)
  {
        struct transport *transport;
 +
        transport = transport_get(remote, NULL);
        transport_set_verbosity(transport, verbosity, progress);
        transport->family = family;
        if (update_shallow)
                set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
        if (filter_options.choice) {
 +              struct strbuf expanded_filter_spec = STRBUF_INIT;
 +              expand_list_objects_filter_spec(&filter_options,
 +                                              &expanded_filter_spec);
                set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER,
 -                         filter_options.filter_spec);
 +                         expanded_filter_spec.buf);
                set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
 +              strbuf_release(&expanded_filter_spec);
        }
        if (negotiation_tip.nr) {
                if (transport->smart_options)
@@@ -1480,8 -1477,7 +1479,8 @@@ static inline void fetch_one_setup_part
         */
        if (strcmp(remote->name, repository_format_partial_clone)) {
                if (filter_options.choice)
 -                      die(_("--filter can only be used with the remote configured in core.partialClone"));
 +                      die(_("--filter can only be used with the remote "
 +                            "configured in extensions.partialclone"));
                return;
        }
  
@@@ -1649,8 -1645,7 +1648,8 @@@ int cmd_fetch(int argc, const char **ar
                result = fetch_one(remote, argc, argv, prune_tags_ok);
        } else {
                if (filter_options.choice)
 -                      die(_("--filter can only be used with the remote configured in core.partialClone"));
 +                      die(_("--filter can only be used with the remote "
 +                            "configured in extensions.partialclone"));
                /* TODO should this also die if we have a previous partial-clone? */
                result = fetch_multiple(&list);
        }
diff --combined builtin/pack-objects.c
index bd67491c1633602a7fab3c48e86bde4421f92c4e,d4c3987f3e30dcc647f1fdcdece07db4e956574f..68e2e66db2b0996d1de1d3634594498331299b1e
@@@ -84,7 -84,6 +84,7 @@@ static unsigned long pack_size_limit
  static int depth = 50;
  static int delta_search_threads;
  static int pack_to_stdout;
 +static int sparse;
  static int thin;
  static int num_preferred_base;
  static struct progress *progress_state;
@@@ -971,7 -970,7 +971,7 @@@ static int no_try_delta(const char *pat
  
        if (!check)
                check = attr_check_initl("delta", NULL);
 -      git_check_attr(&the_index, path, check);
 +      git_check_attr(the_repository->index, path, check);
        if (ATTR_FALSE(check->items[0].value))
                return 1;
        return 0;
@@@ -1335,7 -1334,7 +1335,7 @@@ static void add_pbase_object(struct tre
                if (cmp < 0)
                        return;
                if (name[cmplen] != '/') {
 -                      add_object_entry(entry.oid,
 +                      add_object_entry(&entry.oid,
                                         object_type(entry.mode),
                                         fullname, 1);
                        return;
                        const char *down = name+cmplen+1;
                        int downlen = name_cmp_len(down);
  
 -                      tree = pbase_tree_get(entry.oid);
 +                      tree = pbase_tree_get(&entry.oid);
                        if (!tree)
                                return;
                        init_tree_desc(&sub, tree->tree_data, tree->tree_size);
@@@ -1643,7 -1642,7 +1643,7 @@@ static void check_object(struct object_
  
                /*
                 * No choice but to fall back to the recursive delta walk
-                * with sha1_object_info() to find about the object type
+                * with oid_object_info() to find about the object type
                 * at this point...
                 */
                give_up:
@@@ -1719,7 -1718,7 +1719,7 @@@ static void drop_reused_delta(struct ob
        if (packed_object_info(the_repository, IN_PACK(entry), entry->in_pack_offset, &oi) < 0) {
                /*
                 * We failed to get the info from this pack for some reason;
-                * fall back to sha1_object_info, which may find another copy.
+                * fall back to oid_object_info, which may find another copy.
                 * And if that fails, the error will be recorded in oe_type(entry)
                 * and dealt with in prepare_pack().
                 */
@@@ -1954,6 -1953,11 +1954,6 @@@ static int delta_cacheable(unsigned lon
        return 0;
  }
  
 -/* Protect access to object database */
 -static pthread_mutex_t read_mutex;
 -#define read_lock()           pthread_mutex_lock(&read_mutex)
 -#define read_unlock()         pthread_mutex_unlock(&read_mutex)
 -
  /* Protect delta_cache_size */
  static pthread_mutex_t cache_mutex;
  #define cache_lock()          pthread_mutex_lock(&cache_mutex)
@@@ -1989,11 -1993,11 +1989,11 @@@ unsigned long oe_get_size_slow(struct p
        unsigned long used, avail, size;
  
        if (e->type_ != OBJ_OFS_DELTA && e->type_ != OBJ_REF_DELTA) {
 -              read_lock();
 +              packing_data_lock(&to_pack);
                if (oid_object_info(the_repository, &e->idx.oid, &size) < 0)
                        die(_("unable to get size of %s"),
                            oid_to_hex(&e->idx.oid));
 -              read_unlock();
 +              packing_data_unlock(&to_pack);
                return size;
        }
  
        if (!p)
                BUG("when e->type is a delta, it must belong to a pack");
  
 -      read_lock();
 +      packing_data_lock(&to_pack);
        w_curs = NULL;
        buf = use_pack(p, &w_curs, e->in_pack_offset, &avail);
        used = unpack_object_header_buffer(buf, avail, &type, &size);
                    oid_to_hex(&e->idx.oid));
  
        unuse_pack(&w_curs);
 -      read_unlock();
 +      packing_data_unlock(&to_pack);
        return size;
  }
  
@@@ -2072,9 -2076,9 +2072,9 @@@ static int try_delta(struct unpacked *t
  
        /* Load data if not already done */
        if (!trg->data) {
 -              read_lock();
 +              packing_data_lock(&to_pack);
                trg->data = read_object_file(&trg_entry->idx.oid, &type, &sz);
 -              read_unlock();
 +              packing_data_unlock(&to_pack);
                if (!trg->data)
                        die(_("object %s cannot be read"),
                            oid_to_hex(&trg_entry->idx.oid));
                *mem_usage += sz;
        }
        if (!src->data) {
 -              read_lock();
 +              packing_data_lock(&to_pack);
                src->data = read_object_file(&src_entry->idx.oid, &type, &sz);
 -              read_unlock();
 +              packing_data_unlock(&to_pack);
                if (!src->data) {
                        if (src_entry->preferred_base) {
                                static int warned = 0;
@@@ -2333,9 -2337,9 +2333,9 @@@ static void find_deltas(struct object_e
  
  static void try_to_free_from_threads(size_t size)
  {
 -      read_lock();
 +      packing_data_lock(&to_pack);
        release_pack_memory(size);
 -      read_unlock();
 +      packing_data_unlock(&to_pack);
  }
  
  static try_to_free_t old_try_to_free_routine;
@@@ -2377,6 -2381,7 +2377,6 @@@ static pthread_cond_t progress_cond
   */
  static void init_threaded_search(void)
  {
 -      init_recursive_mutex(&read_mutex);
        pthread_mutex_init(&cache_mutex, NULL);
        pthread_mutex_init(&progress_mutex, NULL);
        pthread_cond_init(&progress_cond, NULL);
@@@ -2387,6 -2392,7 +2387,6 @@@ static void cleanup_threaded_search(voi
  {
        set_try_to_free_routine(old_try_to_free_routine);
        pthread_cond_destroy(&progress_cond);
 -      pthread_mutex_destroy(&read_mutex);
        pthread_mutex_destroy(&cache_mutex);
        pthread_mutex_destroy(&progress_mutex);
  }
@@@ -2704,10 -2710,6 +2704,10 @@@ static int git_pack_config(const char *
                use_bitmap_index_default = git_config_bool(k, v);
                return 0;
        }
 +      if (!strcmp(k, "pack.usesparse")) {
 +              sparse = git_config_bool(k, v);
 +              return 0;
 +      }
        if (!strcmp(k, "pack.threads")) {
                delta_search_threads = git_config_int(k, v);
                if (delta_search_threads < 0)
@@@ -3082,16 -3084,14 +3082,16 @@@ static void record_recent_commit(struc
  static void get_object_list(int ac, const char **av)
  {
        struct rev_info revs;
 +      struct setup_revision_opt s_r_opt = {
 +              .allow_exclude_promisor_objects = 1,
 +      };
        char line[1000];
        int flags = 0;
        int save_warning;
  
        repo_init_revisions(the_repository, &revs, NULL);
        save_commit_buffer = 0;
 -      revs.allow_exclude_promisor_objects_opt = 1;
 -      setup_revisions(ac, av, &revs, NULL);
 +      setup_revisions(ac, av, &revs, &s_r_opt);
  
        /* make sure shallows are read */
        is_repository_shallow(the_repository);
  
        if (prepare_revision_walk(&revs))
                die(_("revision walk setup failed"));
 -      mark_edges_uninteresting(&revs, show_edge);
 +      mark_edges_uninteresting(&revs, show_edge, sparse);
  
        if (!fn_show_object)
                fn_show_object = show_object;
@@@ -3292,8 -3292,6 +3292,8 @@@ int cmd_pack_objects(int argc, const ch
                { OPTION_CALLBACK, 0, "unpack-unreachable", NULL, N_("time"),
                  N_("unpack unreachable objects newer than <time>"),
                  PARSE_OPT_OPTARG, option_parse_unpack_unreachable },
 +              OPT_BOOL(0, "sparse", &sparse,
 +                       N_("use the sparse reachability algorithm")),
                OPT_BOOL(0, "thin", &thin,
                         N_("create thin packs")),
                OPT_BOOL(0, "shallow", &shallow,
  
        read_replace_refs = 0;
  
 +      sparse = git_env_bool("GIT_TEST_PACK_SPARSE", 0);
        reset_pack_idx_option(&pack_idx_opts);
        git_config(git_pack_config, NULL);
  
diff --combined builtin/reflog.c
index 1f1010e2d9aec2b95487007ec30509fcbda605d6,45e9e15006d4e8417b51c8649823c2dd878d9f69..4d3430900d06d82e8e06441f8fdfea00f7aecf78
@@@ -94,8 -94,8 +94,8 @@@ static int tree_is_complete(const struc
        init_tree_desc(&desc, tree->buffer, tree->size);
        complete = 1;
        while (tree_entry(&desc, &entry)) {
-               if (!has_sha1_file(entry.oid.hash) ||
 -              if (!has_object_file(entry.oid) ||
 -                  (S_ISDIR(entry.mode) && !tree_is_complete(entry.oid))) {
++              if (!has_object_file(&entry.oid) ||
 +                  (S_ISDIR(entry.mode) && !tree_is_complete(&entry.oid))) {
                        tree->object.flags |= INCOMPLETE;
                        complete = 0;
                }
diff --combined cache-tree.c
index c4b8a1fa16d4e1376c1df3f2784db32c20001314,47f3464a1f25a3e2b73b060b1841c695f1825c9c..b13bfaf71e9e1554173beca4cfd8acf5929bc9ce
@@@ -225,7 -225,7 +225,7 @@@ int cache_tree_fully_valid(struct cache
        int i;
        if (!it)
                return 0;
-       if (it->entry_count < 0 || !has_sha1_file(it->oid.hash))
+       if (it->entry_count < 0 || !has_object_file(&it->oid))
                return 0;
        for (i = 0; i < it->subtree_nr; i++) {
                if (!cache_tree_fully_valid(it->down[i]->cache_tree))
@@@ -253,7 -253,7 +253,7 @@@ static int update_one(struct cache_tre
  
        *skip_count = 0;
  
-       if (0 <= it->entry_count && has_sha1_file(it->oid.hash))
+       if (0 <= it->entry_count && has_object_file(&it->oid))
                return it->entry_count;
  
        /*
@@@ -448,7 -448,7 +448,7 @@@ int cache_tree_update(struct index_stat
  }
  
  static void write_one(struct strbuf *buffer, struct cache_tree *it,
 -                      const char *path, int pathlen)
 +                    const char *path, int pathlen)
  {
        int i;
  
@@@ -675,7 -675,7 +675,7 @@@ static void prime_cache_tree_rec(struc
                        cnt++;
                else {
                        struct cache_tree_sub *sub;
 -                      struct tree *subtree = lookup_tree(r, entry.oid);
 +                      struct tree *subtree = lookup_tree(r, &entry.oid);
                        if (!subtree->object.parsed)
                                parse_tree(subtree);
                        sub = cache_tree_sub(it, entry.path);
@@@ -724,7 -724,7 +724,7 @@@ int cache_tree_matches_traversal(struc
  
        it = find_cache_tree_from_traversal(root, info);
        it = cache_tree_find(it, ent->path);
 -      if (it && it->entry_count > 0 && oideq(ent->oid, &it->oid))
 +      if (it && it->entry_count > 0 && oideq(&ent->oid, &it->oid))
                return it->entry_count;
        return 0;
  }
diff --combined cache.h
index ef9f3c4eaf2956c416b3b698ce965acb9c58ca98,653c36d0b7fa263d1b2a86bdc5f98a568fd122ea..27fe635f622c49e2a21ffcb91d3113d3b3fbad8c
+++ b/cache.h
@@@ -45,20 -45,10 +45,20 @@@ unsigned long git_deflate_bound(git_zst
  /* The length in bytes and in hex digits of an object name (SHA-1 value). */
  #define GIT_SHA1_RAWSZ 20
  #define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
 +/* The block size of SHA-1. */
 +#define GIT_SHA1_BLKSZ 64
 +
 +/* The length in bytes and in hex digits of an object name (SHA-256 value). */
 +#define GIT_SHA256_RAWSZ 32
 +#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ)
 +/* The block size of SHA-256. */
 +#define GIT_SHA256_BLKSZ 64
  
  /* The length in byte and in hex digits of the largest possible hash value. */
 -#define GIT_MAX_RAWSZ GIT_SHA1_RAWSZ
 -#define GIT_MAX_HEXSZ GIT_SHA1_HEXSZ
 +#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ
 +#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ
 +/* The largest possible block size for any supported hash. */
 +#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ
  
  struct object_id {
        unsigned char hash[GIT_MAX_RAWSZ];
@@@ -348,6 -338,8 +348,6 @@@ struct index_state 
        struct mem_pool *ce_mem_pool;
  };
  
 -extern struct index_state the_index;
 -
  /* Name hashing */
  extern int test_lazy_init_name_hash(struct index_state *istate, int try_threaded);
  extern void add_name_hash(struct index_state *istate, struct cache_entry *ce);
@@@ -409,20 -401,18 +409,20 @@@ struct cache_entry *dup_cache_entry(con
   */
  void validate_cache_entries(const struct index_state *istate);
  
 -#ifndef NO_THE_INDEX_COMPATIBILITY_MACROS
 +#ifdef USE_THE_INDEX_COMPATIBILITY_MACROS
 +extern struct index_state the_index;
 +
  #define active_cache (the_index.cache)
  #define active_nr (the_index.cache_nr)
  #define active_alloc (the_index.cache_alloc)
  #define active_cache_changed (the_index.cache_changed)
  #define active_cache_tree (the_index.cache_tree)
  
 -#define read_cache() read_index(&the_index)
 +#define read_cache() repo_read_index(the_repository)
  #define read_cache_from(path) read_index_from(&the_index, (path), (get_git_dir()))
 -#define read_cache_preload(pathspec) read_index_preload(&the_index, (pathspec), 0)
 +#define read_cache_preload(pathspec) repo_read_index_preload(the_repository, (pathspec), 0)
  #define is_cache_unborn() is_index_unborn(&the_index)
 -#define read_cache_unmerged() read_index_unmerged(&the_index)
 +#define read_cache_unmerged() repo_read_index_unmerged(the_repository)
  #define discard_cache() discard_index(&the_index)
  #define unmerged_cache() unmerged_index(&the_index)
  #define cache_name_pos(name, namelen) index_name_pos(&the_index,(name),(namelen))
  #define unmerge_cache_entry_at(at) unmerge_index_entry_at(&the_index, at)
  #define unmerge_cache(pathspec) unmerge_index(&the_index, pathspec)
  #define read_blob_data_from_cache(path, sz) read_blob_data_from_index(&the_index, (path), (sz))
 +#define hold_locked_index(lock_file, flags) repo_hold_locked_index(the_repository, (lock_file), (flags))
  #endif
  
  #define TYPE_BITS 3
@@@ -671,14 -660,19 +671,14 @@@ extern int daemonize(void)
  
  /* Initialize and use the cache information */
  struct lock_file;
 -extern int read_index(struct index_state *);
  extern void preload_index(struct index_state *index,
                          const struct pathspec *pathspec,
                          unsigned int refresh_flags);
 -extern int read_index_preload(struct index_state *,
 -                            const struct pathspec *pathspec,
 -                            unsigned int refresh_flags);
  extern int do_read_index(struct index_state *istate, const char *path,
                         int must_exist); /* for testting only! */
  extern int read_index_from(struct index_state *, const char *path,
                           const char *gitdir);
  extern int is_index_unborn(struct index_state *);
 -extern int read_index_unmerged(struct index_state *);
  
  /* For use with `write_locked_index()`. */
  #define COMMIT_LOCK           (1 << 0)
@@@ -716,9 -710,9 +716,9 @@@ extern int unmerged_index(const struct 
   * provided, the space-separated list of files that differ will be appended
   * to it.
   */
 -extern int index_has_changes(struct index_state *istate,
 -                           struct tree *tree,
 -                           struct strbuf *sb);
 +extern int repo_index_has_changes(struct repository *repo,
 +                                struct tree *tree,
 +                                struct strbuf *sb);
  
  extern int verify_path(const char *path, unsigned mode);
  extern int strcmp_offset(const char *s1, const char *s2, size_t *first_change);
@@@ -751,7 -745,6 +751,7 @@@ extern int index_name_pos(const struct 
  #define ADD_CACHE_JUST_APPEND 8               /* Append only; tree.c::read_tree() */
  #define ADD_CACHE_NEW_ONLY 16         /* Do not replace existing ones */
  #define ADD_CACHE_KEEP_CACHE_TREE 32  /* Do not invalidate cache-tree */
 +#define ADD_CACHE_RENORMALIZE 64        /* Pass along HASH_RENORMALIZE */
  extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
  extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
  
@@@ -834,6 -827,13 +834,6 @@@ extern void fill_stat_cache_info(struc
  extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
  extern struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int);
  
 -/*
 - * Opportunistically update the index but do not complain if we can't.
 - * The lockfile is always committed or rolled back.
 - */
 -extern void update_index_if_able(struct index_state *, struct lock_file *);
 -
 -extern int hold_locked_index(struct lock_file *, int);
  extern void set_alternate_index_output(const char *);
  
  extern int verify_index_checksum;
@@@ -1028,12 -1028,16 +1028,12 @@@ extern const struct object_id null_oid
  static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
  {
        /*
 -       * This is a temporary optimization hack. By asserting the size here,
 -       * we let the compiler know that it's always going to be 20, which lets
 -       * it turn this fixed-size memcmp into a few inline instructions.
 -       *
 -       * This will need to be extended or ripped out when we learn about
 -       * hashes of different sizes.
 +       * Teach the compiler that there are only two possibilities of hash size
 +       * here, so that it can optimize for this case as much as possible.
         */
 -      if (the_hash_algo->rawsz != 20)
 -              BUG("hash size not yet supported by hashcmp");
 -      return memcmp(sha1, sha2, the_hash_algo->rawsz);
 +      if (the_hash_algo->rawsz == GIT_MAX_RAWSZ)
 +              return memcmp(sha1, sha2, GIT_MAX_RAWSZ);
 +      return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
  }
  
  static inline int oidcmp(const struct object_id *oid1, const struct object_id *oid2)
  
  static inline int hasheq(const unsigned char *sha1, const unsigned char *sha2)
  {
 -      return !hashcmp(sha1, sha2);
 +      /*
 +       * We write this here instead of deferring to hashcmp so that the
 +       * compiler can properly inline it and avoid calling memcmp.
 +       */
 +      if (the_hash_algo->rawsz == GIT_MAX_RAWSZ)
 +              return !memcmp(sha1, sha2, GIT_MAX_RAWSZ);
 +      return !memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
  }
  
  static inline int oideq(const struct object_id *oid1, const struct object_id *oid2)
@@@ -1074,7 -1072,7 +1074,7 @@@ static inline void hashcpy(unsigned cha
  
  static inline void oidcpy(struct object_id *dst, const struct object_id *src)
  {
 -      hashcpy(dst->hash, src->hash);
 +      memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ);
  }
  
  static inline struct object_id *oiddup(const struct object_id *src)
@@@ -1271,8 -1269,8 +1271,8 @@@ extern char *xdg_cache_home(const char 
  
  extern int git_open_cloexec(const char *name, int flags);
  #define git_open(name) git_open_cloexec(name, O_RDONLY)
- extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
- extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
+ extern int unpack_loose_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
+ extern int parse_loose_header(const char *hdr, unsigned long *sizep);
  
  extern int check_object_signature(const struct object_id *oid, void *buf, unsigned long size, const char *type);
  
@@@ -1334,24 -1332,6 +1334,24 @@@ struct object_context 
        GET_OID_TREE | GET_OID_TREEISH | \
        GET_OID_BLOB)
  
 +enum get_oid_result {
 +      FOUND = 0,
 +      MISSING_OBJECT = -1, /* The requested object is missing */
 +      SHORT_NAME_AMBIGUOUS = -2,
 +      /* The following only apply when symlinks are followed */
 +      DANGLING_SYMLINK = -4, /*
 +                              * The initial symlink is there, but
 +                              * (transitively) points to a missing
 +                              * in-tree file
 +                              */
 +      SYMLINK_LOOP = -5,
 +      NOT_DIR = -6, /*
 +                     * Somewhere along the symlink chain, a path is
 +                     * requested which contains a file as a
 +                     * non-final element.
 +                     */
 +};
 +
  extern int get_oid(const char *str, struct object_id *oid);
  extern int get_oid_commit(const char *str, struct object_id *oid);
  extern int get_oid_committish(const char *str, struct object_id *oid);
@@@ -1359,9 -1339,8 +1359,9 @@@ extern int get_oid_tree(const char *str
  extern int get_oid_treeish(const char *str, struct object_id *oid);
  extern int get_oid_blob(const char *str, struct object_id *oid);
  extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
 -extern int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);
 -
 +extern enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
 +                              unsigned flags, struct object_id *oid,
 +                              struct object_context *oc);
  
  typedef int each_abbrev_fn(const struct object_id *oid, void *);
  extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *);
@@@ -1386,9 -1365,9 +1386,9 @@@ extern int get_oid_hex(const char *hex
  extern int hex_to_bytes(unsigned char *binary, const char *hex, size_t len);
  
  /*
 - * Convert a binary sha1 to its hex equivalent. The `_r` variant is reentrant,
 + * Convert a binary hash to its hex equivalent. The `_r` variant is reentrant,
   * and writes the NUL-terminated output to the buffer `out`, which must be at
 - * least `GIT_SHA1_HEXSZ + 1` bytes, and returns a pointer to out for
 + * least `GIT_MAX_HEXSZ + 1` bytes, and returns a pointer to out for
   * convenience.
   *
   * The non-`_r` variant returns a static buffer, but uses a ring of 4
   *
   *   printf("%s -> %s", sha1_to_hex(one), sha1_to_hex(two));
   */
 -extern char *sha1_to_hex_r(char *out, const unsigned char *sha1);
 -extern char *oid_to_hex_r(char *out, const struct object_id *oid);
 -extern char *sha1_to_hex(const unsigned char *sha1);  /* static buffer result! */
 -extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */
 +char *hash_to_hex_algop_r(char *buffer, const unsigned char *hash, const struct git_hash_algo *);
 +char *sha1_to_hex_r(char *out, const unsigned char *sha1);
 +char *oid_to_hex_r(char *out, const struct object_id *oid);
 +char *hash_to_hex_algop(const unsigned char *hash, const struct git_hash_algo *);     /* static buffer result! */
 +char *sha1_to_hex(const unsigned char *sha1);                                         /* same static buffer */
 +char *hash_to_hex(const unsigned char *hash);                                         /* same static buffer */
 +char *oid_to_hex(const struct object_id *oid);                                                /* same static buffer */
  
  /*
   * Parse a 40-character hexadecimal object ID starting from hex, updating the
@@@ -1463,7 -1439,6 +1463,7 @@@ extern struct object *peel_to_type(cons
  
  enum date_mode_type {
        DATE_NORMAL = 0,
 +      DATE_HUMAN,
        DATE_RELATIVE,
        DATE_SHORT,
        DATE_ISO8601,
@@@ -1489,9 -1464,7 +1489,9 @@@ struct date_mode 
  struct date_mode *date_mode_from_type(enum date_mode_type type);
  
  const char *show_date(timestamp_t time, int timezone, const struct date_mode *mode);
 -void show_date_relative(timestamp_t time, int tz, const struct timeval *now,
 +void show_date_relative(timestamp_t time, const struct timeval *now,
 +                      struct strbuf *timebuf);
 +void show_date_human(timestamp_t time, int tz, const struct timeval *now,
                        struct strbuf *timebuf);
  int parse_date(const char *date, struct strbuf *out);
  int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset);
@@@ -1566,9 -1539,9 +1566,9 @@@ struct checkout 
  #define CHECKOUT_INIT { NULL, "" }
  
  #define TEMPORARY_FILENAME_LENGTH 25
 -extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
 +extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath, int *nr_checkouts);
  extern void enable_delayed_checkout(struct checkout *state);
 -extern int finish_delayed_checkout(struct checkout *state);
 +extern int finish_delayed_checkout(struct checkout *state, int *nr_checkouts);
  
  struct cache_def {
        struct strbuf path;
@@@ -1619,7 -1592,7 +1619,7 @@@ extern int odb_mkstemp(struct strbuf *t
  extern int odb_pack_keep(const char *name);
  
  /*
-  * Set this to 0 to prevent sha1_object_info_extended() from fetching missing
+  * Set this to 0 to prevent oid_object_info_extended() from fetching missing
   * blobs. This has a difference only if extensions.partialClone is set.
   *
   * Its default value is 1.
@@@ -1815,7 -1788,4 +1815,7 @@@ void safe_create_dir(const char *dir, i
   */
  extern int print_sha1_ellipsis(void);
  
 +/* Return 1 if the file is empty or does not exists, 0 otherwise. */
 +extern int is_empty_or_missing_file(const char *filename);
 +
  #endif /* CACHE_H */
diff --combined http-push.c
index 77e2e22852d769a04dc0275498964eff86e362d8,0141b0ad537589296a43bff2b99df148e7346b91..b22c7caea0c3facd8264a9ff5e779cec01003060
@@@ -255,7 -255,7 +255,7 @@@ static void start_fetch_loose(struct tr
        struct active_request_slot *slot;
        struct http_object_request *obj_req;
  
-       obj_req = new_http_object_request(repo->url, request->obj->oid.hash);
+       obj_req = new_http_object_request(repo->url, &request->obj->oid);
        if (obj_req == NULL) {
                request->state = ABORTED;
                return;
@@@ -1311,11 -1311,11 +1311,11 @@@ static struct object_list **process_tre
        while (tree_entry(&desc, &entry))
                switch (object_type(entry.mode)) {
                case OBJ_TREE:
 -                      p = process_tree(lookup_tree(the_repository, entry.oid),
 +                      p = process_tree(lookup_tree(the_repository, &entry.oid),
                                         p);
                        break;
                case OBJ_BLOB:
 -                      p = process_blob(lookup_blob(the_repository, entry.oid),
 +                      p = process_blob(lookup_blob(the_repository, &entry.oid),
                                         p);
                        break;
                default:
@@@ -1933,7 -1933,7 +1933,7 @@@ int cmd_main(int argc, const char **arg
                pushing = 0;
                if (prepare_revision_walk(&revs))
                        die("revision walk setup failed");
 -              mark_edges_uninteresting(&revs, NULL);
 +              mark_edges_uninteresting(&revs, NULL, 0);
                objects_to_send = get_delta(&revs, ref_lock);
                finish_all_active_slots();
  
diff --combined http.c
index 954bebf6842510ea3fb83334ffe2684ade072f05,43d06dd0741c0be52ff6b7bd0dddbd2d9df85119..a32ad36ddf6b813ce0e02c85e7b61b4613517a9c
--- 1/http.c
--- 2/http.c
+++ b/http.c
@@@ -1876,6 -1876,8 +1876,6 @@@ static int http_request(const char *url
        strbuf_addstr(&buf, "Pragma:");
        if (options && options->no_cache)
                strbuf_addstr(&buf, " no-cache");
 -      if (options && options->keep_error)
 -              curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
        if (options && options->initial_request &&
            http_follow_config == HTTP_FOLLOW_INITIAL)
                curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
 +      curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
  
        ret = run_one_slot(slot, &results);
  
@@@ -1988,26 -1989,19 +1988,26 @@@ static int http_request_reauth(const ch
                return ret;
  
        /*
 -       * If we are using KEEP_ERROR, the previous request may have
 -       * put cruft into our output stream; we should clear it out before
 -       * making our next request. We only know how to do this for
 -       * the strbuf case, but that is enough to satisfy current callers.
 +       * The previous request may have put cruft into our output stream; we
 +       * should clear it out before making our next request.
         */
 -      if (options && options->keep_error) {
 -              switch (target) {
 -              case HTTP_REQUEST_STRBUF:
 -                      strbuf_reset(result);
 -                      break;
 -              default:
 -                      BUG("HTTP_KEEP_ERROR is only supported with strbufs");
 +      switch (target) {
 +      case HTTP_REQUEST_STRBUF:
 +              strbuf_reset(result);
 +              break;
 +      case HTTP_REQUEST_FILE:
 +              if (fflush(result)) {
 +                      error_errno("unable to flush a file");
 +                      return HTTP_START_FAILED;
 +              }
 +              rewind(result);
 +              if (ftruncate(fileno(result), 0) < 0) {
 +                      error_errno("unable to truncate a file");
 +                      return HTTP_START_FAILED;
                }
 +              break;
 +      default:
 +              BUG("Unknown http_request target");
        }
  
        credential_fill(&http_auth);
@@@ -2343,9 -2337,9 +2343,9 @@@ static size_t fwrite_sha1_file(char *pt
  }
  
  struct http_object_request *new_http_object_request(const char *base_url,
-       unsigned char *sha1)
+                                                   const struct object_id *oid)
  {
-       char *hex = sha1_to_hex(sha1);
+       char *hex = oid_to_hex(oid);
        struct strbuf filename = STRBUF_INIT;
        struct strbuf prevfile = STRBUF_INIT;
        int prevlocal;
  
        freq = xcalloc(1, sizeof(*freq));
        strbuf_init(&freq->tmpfile, 0);
-       hashcpy(freq->sha1, sha1);
+       oidcpy(&freq->oid, oid);
        freq->localfile = -1;
  
-       loose_object_path(the_repository, &filename, sha1);
+       loose_object_path(the_repository, &filename, oid);
        strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf);
  
        strbuf_addf(&prevfile, "%s.prev", filename.buf);
@@@ -2501,16 -2495,16 +2501,16 @@@ int finish_http_object_request(struct h
        }
  
        git_inflate_end(&freq->stream);
-       git_SHA1_Final(freq->real_sha1, &freq->c);
+       git_SHA1_Final(freq->real_oid.hash, &freq->c);
        if (freq->zret != Z_STREAM_END) {
                unlink_or_warn(freq->tmpfile.buf);
                return -1;
        }
-       if (!hasheq(freq->sha1, freq->real_sha1)) {
+       if (!oideq(&freq->oid, &freq->real_oid)) {
                unlink_or_warn(freq->tmpfile.buf);
                return -1;
        }
-       loose_object_path(the_repository, &filename, freq->sha1);
+       loose_object_path(the_repository, &filename, &freq->oid);
        freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf);
        strbuf_release(&filename);
  
diff --combined http.h
index eebf40688cf6f695d12f9fe78e8e6b99bb44a8c4,66c52b2e1e7dcf0f7ea27d056b8d144cb5375cf2..4eb4e808e5731a3a9a650ca4c1efb3e471604d05
--- 1/http.h
--- 2/http.h
+++ b/http.h
@@@ -146,6 -146,7 +146,6 @@@ extern char *get_remote_object_url(cons
  /* Options for http_get_*() */
  struct http_get_options {
        unsigned no_cache:1,
 -               keep_error:1,
                 initial_request:1;
  
        /* If non-NULL, returns the content-type of the response. */
@@@ -223,8 -224,8 +223,8 @@@ struct http_object_request 
        CURLcode curl_result;
        char errorstr[CURL_ERROR_SIZE];
        long http_code;
-       unsigned char sha1[20];
-       unsigned char real_sha1[20];
+       struct object_id oid;
+       struct object_id real_oid;
        git_SHA_CTX c;
        git_zstream stream;
        int zret;
  };
  
  extern struct http_object_request *new_http_object_request(
-       const char *base_url, unsigned char *sha1);
+       const char *base_url, const struct object_id *oid);
  extern void process_http_object_request(struct http_object_request *freq);
  extern int finish_http_object_request(struct http_object_request *freq);
  extern void abort_http_object_request(struct http_object_request *freq);
diff --combined object-store.h
index ba57630677fac412c6f8a771ed64eccf6000e833,a7808bb6244b2c74cbf28aab86ba9291c4b0b477..14fc935bd1bf8b4fec70489825661dd7f6f2255c
@@@ -154,26 -154,21 +154,28 @@@ void raw_object_store_clear(struct raw_
  
  /*
   * Put in `buf` the name of the file in the local object database that
-  * would be used to store a loose object with the specified sha1.
+  * would be used to store a loose object with the specified oid.
   */
- const char *loose_object_path(struct repository *r, struct strbuf *buf, const unsigned char *sha1);
+ const char *loose_object_path(struct repository *r, struct strbuf *buf,
+                             const struct object_id *oid);
  
- void *map_sha1_file(struct repository *r, const unsigned char *sha1, unsigned long *size);
+ void *map_loose_object(struct repository *r, const struct object_id *oid,
+                      unsigned long *size);
  
 -extern void *read_object_file_extended(const struct object_id *oid,
 +extern void *read_object_file_extended(struct repository *r,
 +                                     const struct object_id *oid,
                                       enum object_type *type,
                                       unsigned long *size, int lookup_replace);
 -static inline void *read_object_file(const struct object_id *oid, enum object_type *type, unsigned long *size)
 +static inline void *repo_read_object_file(struct repository *r,
 +                                        const struct object_id *oid,
 +                                        enum object_type *type,
 +                                        unsigned long *size)
  {
 -      return read_object_file_extended(oid, type, size, 1);
 +      return read_object_file_extended(r, oid, type, size, 1);
  }
 +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
 +#define read_object_file(oid, type, size) repo_read_object_file(the_repository, oid, type, size)
 +#endif
  
  /* Read and unpack an object file into memory, write memory to an object file */
  int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);
@@@ -206,32 -201,16 +208,19 @@@ int read_loose_object(const char *path
                      unsigned long *size,
                      void **contents);
  
--/*
-  * Convenience for sha1_object_info_extended() with a NULL struct
 - * Convenience for oid_object_info_extended() with a NULL struct
-- * object_info. OBJECT_INFO_SKIP_CACHED is automatically set; pass
-- * nonzero flags to also set other flags.
-- */
- int repo_has_sha1_file_with_flags(struct repository *r,
-                                 const unsigned char *sha1, int flags);
- static inline int repo_has_sha1_file(struct repository *r,
-                                    const unsigned char *sha1)
 -int has_object_file_with_flags(const struct object_id *oid, int flags);
 -static inline int has_object_file(const struct object_id *oid)
--{
-       return repo_has_sha1_file_with_flags(r, sha1, 0);
 -      return has_object_file_with_flags(oid, 0);
--}
 +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
 +#define has_sha1_file_with_flags(sha1, flags) repo_has_sha1_file_with_flags(the_repository, sha1, flags)
 +#define has_sha1_file(sha1) repo_has_sha1_file(the_repository, sha1)
 +#endif
 +
 +/* Same as the above, except for struct object_id. */
 +int repo_has_object_file(struct repository *r, const struct object_id *oid);
 +int repo_has_object_file_with_flags(struct repository *r,
 +                                  const struct object_id *oid, int flags);
 +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
 +#define has_object_file(oid) repo_has_object_file(the_repository, oid)
 +#define has_object_file_with_flags(oid, flags) repo_has_object_file_with_flags(the_repository, oid, flags)
 +#endif
  
  /*
   * Return true iff an alternate object database has a loose object
diff --combined object.c
index 5dc5eec367354ae4817b813b181423e096179a8a,df72914bdc54292b8e0fad722c3eefd238496ec7..59ea24c4aab6e58ac64ef55598182da460acd6ad
+++ b/object.c
@@@ -164,9 -164,8 +164,9 @@@ void *object_as_type(struct repository 
                return obj;
        else if (obj->type == OBJ_NONE) {
                if (type == OBJ_COMMIT)
 -                      ((struct commit *)obj)->index = alloc_commit_index(r);
 -              obj->type = type;
 +                      init_commit_node(r, (struct commit *) obj);
 +              else
 +                      obj->type = type;
                return obj;
        }
        else {
@@@ -260,22 -259,22 +260,22 @@@ struct object *parse_object(struct repo
        if (obj && obj->parsed)
                return obj;
  
 -      if ((obj && obj->type == OBJ_BLOB && has_object_file(oid)) ||
 -          (!obj && has_object_file(oid) &&
 +      if ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||
 +          (!obj && repo_has_object_file(r, oid) &&
             oid_object_info(r, oid, NULL) == OBJ_BLOB)) {
                if (check_object_signature(repl, NULL, 0, NULL) < 0) {
-                       error(_("sha1 mismatch %s"), oid_to_hex(oid));
+                       error(_("hash mismatch %s"), oid_to_hex(oid));
                        return NULL;
                }
                parse_blob_buffer(lookup_blob(r, oid), NULL, 0);
                return lookup_object(r, oid->hash);
        }
  
 -      buffer = read_object_file(oid, &type, &size);
 +      buffer = repo_read_object_file(r, oid, &type, &size);
        if (buffer) {
                if (check_object_signature(repl, buffer, size, type_name(type)) < 0) {
                        free(buffer);
-                       error(_("sha1 mismatch %s"), oid_to_hex(repl));
+                       error(_("hash mismatch %s"), oid_to_hex(repl));
                        return NULL;
                }
  
@@@ -541,7 -540,7 +541,7 @@@ void parsed_object_pool_clear(struct pa
                if (obj->type == OBJ_TREE)
                        free_tree_buffer((struct tree*)obj);
                else if (obj->type == OBJ_COMMIT)
 -                      release_commit_memory((struct commit*)obj);
 +                      release_commit_memory(o, (struct commit*)obj);
                else if (obj->type == OBJ_TAG)
                        release_tag_memory((struct tag*)obj);
        }
diff --combined send-pack.c
index 7b9829f165e7aff7abe804fb780cf7c9d88aaf73,c673d3ed06059301adf1e9a1257f32ab849850f8..6dc16c3211631402432207dcf99b1ef4e87f012b
@@@ -40,7 -40,7 +40,7 @@@ int option_parse_push_signed(const stru
  
  static void feed_object(const struct object_id *oid, FILE *fh, int negative)
  {
-       if (negative && !has_sha1_file(oid->hash))
+       if (negative && !has_object_file(oid))
                return;
  
        if (negative)
@@@ -135,36 -135,38 +135,36 @@@ static int pack_objects(int fd, struct 
        return 0;
  }
  
 -static int receive_unpack_status(int in)
 +static int receive_unpack_status(struct packet_reader *reader)
  {
 -      const char *line = packet_read_line(in, NULL);
 -      if (!line)
 +      if (packet_reader_read(reader) != PACKET_READ_NORMAL)
                return error(_("unexpected flush packet while reading remote unpack status"));
 -      if (!skip_prefix(line, "unpack ", &line))
 -              return error(_("unable to parse remote unpack status: %s"), line);
 -      if (strcmp(line, "ok"))
 -              return error(_("remote unpack failed: %s"), line);
 +      if (!skip_prefix(reader->line, "unpack ", &reader->line))
 +              return error(_("unable to parse remote unpack status: %s"), reader->line);
 +      if (strcmp(reader->line, "ok"))
 +              return error(_("remote unpack failed: %s"), reader->line);
        return 0;
  }
  
 -static int receive_status(int in, struct ref *refs)
 +static int receive_status(struct packet_reader *reader, struct ref *refs)
  {
        struct ref *hint;
        int ret;
  
        hint = NULL;
 -      ret = receive_unpack_status(in);
 +      ret = receive_unpack_status(reader);
        while (1) {
 -              char *refname;
 +              const char *refname;
                char *msg;
 -              char *line = packet_read_line(in, NULL);
 -              if (!line)
 +              if (packet_reader_read(reader) != PACKET_READ_NORMAL)
                        break;
 -              if (!starts_with(line, "ok ") && !starts_with(line, "ng ")) {
 -                      error("invalid ref status from remote: %s", line);
 +              if (!starts_with(reader->line, "ok ") && !starts_with(reader->line, "ng ")) {
 +                      error("invalid ref status from remote: %s", reader->line);
                        ret = -1;
                        break;
                }
  
 -              refname = line + 3;
 +              refname = reader->line + 3;
                msg = strchr(refname, ' ');
                if (msg)
                        *msg++ = '\0';
                        continue;
                }
  
 -              if (line[0] == 'o' && line[1] == 'k')
 +              if (reader->line[0] == 'o' && reader->line[1] == 'k')
                        hint->status = REF_STATUS_OK;
                else {
                        hint->status = REF_STATUS_REMOTE_REJECT;
@@@ -388,7 -390,6 +388,7 @@@ int send_pack(struct send_pack_args *ar
        int ret;
        struct async demux;
        const char *push_cert_nonce = NULL;
 +      struct packet_reader reader;
  
        /* Does the other end support the reporting? */
        if (server_supports("report-status"))
                in = demux.out;
        }
  
 +      packet_reader_init(&reader, in, NULL, 0,
 +                         PACKET_READ_CHOMP_NEWLINE |
 +                         PACKET_READ_DIE_ON_ERR_PACKET);
 +
        if (need_pack_data && cmds_sent) {
                if (pack_objects(out, remote_refs, extra_have, args) < 0) {
                        for (ref = remote_refs; ref; ref = ref->next)
                         * are failing, and just want the error() side effects.
                         */
                        if (status_report)
 -                              receive_unpack_status(in);
 +                              receive_unpack_status(&reader);
  
                        if (use_sideband) {
                                close(demux.out);
                packet_flush(out);
  
        if (status_report && cmds_sent)
 -              ret = receive_status(in, remote_refs);
 +              ret = receive_status(&reader, remote_refs);
        else
                ret = 0;
        if (args->stateless_rpc)
diff --combined sha1-file.c
index c8da9f34752c4d8f6518c8ed8c42164368e973a3,23564598f2bc17c6bc55b97e6a64ee356652045b..494606f7716923468e6f838dae0486a61b454101
  #define EMPTY_TREE_SHA1_BIN_LITERAL \
         "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \
         "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"
 +#define EMPTY_TREE_SHA256_BIN_LITERAL \
 +      "\x6e\xf1\x9b\x41\x22\x5c\x53\x69\xf1\xc1" \
 +      "\x04\xd4\x5d\x8d\x85\xef\xa9\xb0\x57\xb5" \
 +      "\x3b\x14\xb4\xb9\xb9\x39\xdd\x74\xde\xcc" \
 +      "\x53\x21"
  
  #define EMPTY_BLOB_SHA1_BIN_LITERAL \
        "\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b" \
        "\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91"
 +#define EMPTY_BLOB_SHA256_BIN_LITERAL \
 +      "\x47\x3a\x0f\x4c\x3b\xe8\xa9\x36\x81\xa2" \
 +      "\x67\xe3\xb1\xe9\xa7\xdc\xda\x11\x85\x43" \
 +      "\x6f\xe1\x41\xf7\x74\x91\x20\xa3\x03\x72" \
 +      "\x18\x13"
  
  const unsigned char null_sha1[GIT_MAX_RAWSZ];
  const struct object_id null_oid;
@@@ -63,12 -53,6 +63,12 @@@ static const struct object_id empty_tre
  static const struct object_id empty_blob_oid = {
        EMPTY_BLOB_SHA1_BIN_LITERAL
  };
 +static const struct object_id empty_tree_oid_sha256 = {
 +      EMPTY_TREE_SHA256_BIN_LITERAL
 +};
 +static const struct object_id empty_blob_oid_sha256 = {
 +      EMPTY_BLOB_SHA256_BIN_LITERAL
 +};
  
  static void git_hash_sha1_init(git_hash_ctx *ctx)
  {
@@@ -85,22 -69,6 +85,22 @@@ static void git_hash_sha1_final(unsigne
        git_SHA1_Final(hash, &ctx->sha1);
  }
  
 +
 +static void git_hash_sha256_init(git_hash_ctx *ctx)
 +{
 +      git_SHA256_Init(&ctx->sha256);
 +}
 +
 +static void git_hash_sha256_update(git_hash_ctx *ctx, const void *data, size_t len)
 +{
 +      git_SHA256_Update(&ctx->sha256, data, len);
 +}
 +
 +static void git_hash_sha256_final(unsigned char *hash, git_hash_ctx *ctx)
 +{
 +      git_SHA256_Final(hash, &ctx->sha256);
 +}
 +
  static void git_hash_unknown_init(git_hash_ctx *ctx)
  {
        BUG("trying to init unknown hash");
@@@ -122,7 -90,6 +122,7 @@@ const struct git_hash_algo hash_algos[G
                0x00000000,
                0,
                0,
 +              0,
                git_hash_unknown_init,
                git_hash_unknown_update,
                git_hash_unknown_final,
                NULL,
        },
        {
 -              "sha-1",
 +              "sha1",
                /* "sha1", big-endian */
                0x73686131,
                GIT_SHA1_RAWSZ,
                GIT_SHA1_HEXSZ,
 +              GIT_SHA1_BLKSZ,
                git_hash_sha1_init,
                git_hash_sha1_update,
                git_hash_sha1_final,
                &empty_tree_oid,
                &empty_blob_oid,
        },
 +      {
 +              "sha256",
 +              /* "s256", big-endian */
 +              0x73323536,
 +              GIT_SHA256_RAWSZ,
 +              GIT_SHA256_HEXSZ,
 +              GIT_SHA256_BLKSZ,
 +              git_hash_sha256_init,
 +              git_hash_sha256_update,
 +              git_hash_sha256_final,
 +              &empty_tree_oid_sha256,
 +              &empty_blob_oid_sha256,
 +      }
  };
  
  const char *empty_tree_oid_hex(void)
@@@ -169,30 -122,9 +169,30 @@@ const char *empty_blob_oid_hex(void
        return oid_to_hex_r(buf, the_hash_algo->empty_blob);
  }
  
 +int hash_algo_by_name(const char *name)
 +{
 +      int i;
 +      if (!name)
 +              return GIT_HASH_UNKNOWN;
 +      for (i = 1; i < GIT_HASH_NALGOS; i++)
 +              if (!strcmp(name, hash_algos[i].name))
 +                      return i;
 +      return GIT_HASH_UNKNOWN;
 +}
 +
 +int hash_algo_by_id(uint32_t format_id)
 +{
 +      int i;
 +      for (i = 1; i < GIT_HASH_NALGOS; i++)
 +              if (format_id == hash_algos[i].format_id)
 +                      return i;
 +      return GIT_HASH_UNKNOWN;
 +}
 +
 +
  /*
   * This is meant to hold a *small* number of objects that you would
-  * want read_sha1_file() to be able to return, but yet you do not want
+  * want read_object_file() to be able to return, but yet you do not want
   * to write them into the object store (e.g. a browse-only
   * application).
   */
@@@ -401,12 -333,12 +401,12 @@@ out
        return ret;
  }
  
- static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1)
+ static void fill_loose_path(struct strbuf *buf, const struct object_id *oid)
  {
        int i;
        for (i = 0; i < the_hash_algo->rawsz; i++) {
                static char hex[] = "0123456789abcdef";
-               unsigned int val = sha1[i];
+               unsigned int val = oid->hash[i];
                strbuf_addch(buf, hex[val >> 4]);
                strbuf_addch(buf, hex[val & 0xf]);
                if (!i)
  
  static const char *odb_loose_path(struct object_directory *odb,
                                  struct strbuf *buf,
-                                 const unsigned char *sha1)
+                                 const struct object_id *oid)
  {
        strbuf_reset(buf);
        strbuf_addstr(buf, odb->path);
        strbuf_addch(buf, '/');
-       fill_sha1_path(buf, sha1);
+       fill_loose_path(buf, oid);
        return buf->buf;
  }
  
  const char *loose_object_path(struct repository *r, struct strbuf *buf,
-                             const unsigned char *sha1)
+                             const struct object_id *oid)
  {
-       return odb_loose_path(r->objects->odb, buf, sha1);
+       return odb_loose_path(r->objects->odb, buf, oid);
  }
  
  /*
@@@ -789,7 -721,7 +789,7 @@@ static int check_and_freshen_odb(struc
                                 int freshen)
  {
        static struct strbuf path = STRBUF_INIT;
-       odb_loose_path(odb, &path, oid->hash);
+       odb_loose_path(odb, &path, oid);
        return check_and_freshen_file(path.buf, freshen);
  }
  
@@@ -866,8 -798,8 +866,8 @@@ void *xmmap(void *start, size_t length
  
  /*
   * With an in-core object data in "map", rehash it to make sure the
-  * object name actually matches "sha1" to detect object corruption.
-  * With "map" == NULL, try reading the object named with "sha1" using
+  * object name actually matches "oid" to detect object corruption.
+  * With "map" == NULL, try reading the object named with "oid" using
   * the streaming interface and rehash it to do the same.
   */
  int check_object_signature(const struct object_id *oid, void *map,
@@@ -940,22 -872,22 +940,22 @@@ int git_open_cloexec(const char *name, 
  }
  
  /*
-  * Find "sha1" as a loose object in the local repository or in an alternate.
+  * Find "oid" as a loose object in the local repository or in an alternate.
   * Returns 0 on success, negative on failure.
   *
   * The "path" out-parameter will give the path of the object we found (if any).
   * Note that it may point to static storage and is only valid until another
-  * call to stat_sha1_file().
+  * call to stat_loose_object().
   */
- static int stat_sha1_file(struct repository *r, const unsigned char *sha1,
-                         struct stat *st, const char **path)
+ static int stat_loose_object(struct repository *r, const struct object_id *oid,
+                            struct stat *st, const char **path)
  {
        struct object_directory *odb;
        static struct strbuf buf = STRBUF_INIT;
  
        prepare_alt_odb(r);
        for (odb = r->objects->odb; odb; odb = odb->next) {
-               *path = odb_loose_path(odb, &buf, sha1);
+               *path = odb_loose_path(odb, &buf, oid);
                if (!lstat(*path, st))
                        return 0;
        }
  }
  
  /*
-  * Like stat_sha1_file(), but actually open the object and return the
+  * Like stat_loose_object(), but actually open the object and return the
   * descriptor. See the caveats on the "path" parameter above.
   */
- static int open_sha1_file(struct repository *r,
-                         const unsigned char *sha1, const char **path)
+ static int open_loose_object(struct repository *r,
+                            const struct object_id *oid, const char **path)
  {
        int fd;
        struct object_directory *odb;
  
        prepare_alt_odb(r);
        for (odb = r->objects->odb; odb; odb = odb->next) {
-               *path = odb_loose_path(odb, &buf, sha1);
+               *path = odb_loose_path(odb, &buf, oid);
                fd = git_open(*path);
                if (fd >= 0)
                        return fd;
  }
  
  static int quick_has_loose(struct repository *r,
-                          const unsigned char *sha1)
+                          const struct object_id *oid)
  {
-       struct object_id oid;
        struct object_directory *odb;
  
-       hashcpy(oid.hash, sha1);
        prepare_alt_odb(r);
        for (odb = r->objects->odb; odb; odb = odb->next) {
-               if (oid_array_lookup(odb_loose_cache(odb, &oid), &oid) >= 0)
+               if (oid_array_lookup(odb_loose_cache(odb, oid), oid) >= 0)
                        return 1;
        }
        return 0;
  
  /*
   * Map the loose object at "path" if it is not NULL, or the path found by
-  * searching for a loose object named "sha1".
+  * searching for a loose object named "oid".
   */
- static void *map_sha1_file_1(struct repository *r, const char *path,
-                            const unsigned char *sha1, unsigned long *size)
+ static void *map_loose_object_1(struct repository *r, const char *path,
+                            const struct object_id *oid, unsigned long *size)
  {
        void *map;
        int fd;
        if (path)
                fd = git_open(path);
        else
-               fd = open_sha1_file(r, sha1, &path);
+               fd = open_loose_object(r, oid, &path);
        map = NULL;
        if (fd >= 0) {
                struct stat st;
                        if (!*size) {
                                /* mmap() is forbidden on empty files */
                                error(_("object file %s is empty"), path);
 +                              close(fd);
                                return NULL;
                        }
                        map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
        return map;
  }
  
- void *map_sha1_file(struct repository *r,
-                   const unsigned char *sha1, unsigned long *size)
+ void *map_loose_object(struct repository *r,
+                      const struct object_id *oid,
+                      unsigned long *size)
  {
-       return map_sha1_file_1(r, NULL, sha1, size);
+       return map_loose_object_1(r, NULL, oid, size);
  }
  
- static int unpack_sha1_short_header(git_zstream *stream,
-                                   unsigned char *map, unsigned long mapsize,
-                                   void *buffer, unsigned long bufsiz)
+ static int unpack_loose_short_header(git_zstream *stream,
+                                    unsigned char *map, unsigned long mapsize,
+                                    void *buffer, unsigned long bufsiz)
  {
        /* Get the data stream */
        memset(stream, 0, sizeof(*stream));
        return git_inflate(stream, 0);
  }
  
- int unpack_sha1_header(git_zstream *stream,
-                      unsigned char *map, unsigned long mapsize,
-                      void *buffer, unsigned long bufsiz)
+ int unpack_loose_header(git_zstream *stream,
+                       unsigned char *map, unsigned long mapsize,
+                       void *buffer, unsigned long bufsiz)
  {
-       int status = unpack_sha1_short_header(stream, map, mapsize,
-                                             buffer, bufsiz);
+       int status = unpack_loose_short_header(stream, map, mapsize,
+                                              buffer, bufsiz);
  
        if (status < Z_OK)
                return status;
        return 0;
  }
  
- static int unpack_sha1_header_to_strbuf(git_zstream *stream, unsigned char *map,
-                                       unsigned long mapsize, void *buffer,
-                                       unsigned long bufsiz, struct strbuf *header)
+ static int unpack_loose_header_to_strbuf(git_zstream *stream, unsigned char *map,
+                                        unsigned long mapsize, void *buffer,
+                                        unsigned long bufsiz, struct strbuf *header)
  {
        int status;
  
-       status = unpack_sha1_short_header(stream, map, mapsize, buffer, bufsiz);
+       status = unpack_loose_short_header(stream, map, mapsize, buffer, bufsiz);
        if (status < Z_OK)
                return -1;
  
        return -1;
  }
  
- static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long size, const unsigned char *sha1)
+ static void *unpack_loose_rest(git_zstream *stream,
+                              void *buffer, unsigned long size,
+                              const struct object_id *oid)
  {
        int bytes = strlen(buffer) + 1;
        unsigned char *buf = xmallocz(size);
        }
  
        if (status < 0)
-               error(_("corrupt loose object '%s'"), sha1_to_hex(sha1));
+               error(_("corrupt loose object '%s'"), oid_to_hex(oid));
        else if (stream->avail_in)
                error(_("garbage at end of loose object '%s'"),
-                     sha1_to_hex(sha1));
+                     oid_to_hex(oid));
        free(buf);
        return NULL;
  }
   * too permissive for what we want to check. So do an anal
   * object header parse by hand.
   */
- static int parse_sha1_header_extended(const char *hdr, struct object_info *oi,
-                              unsigned int flags)
+ static int parse_loose_header_extended(const char *hdr, struct object_info *oi,
+                                      unsigned int flags)
  {
        const char *type_buf = hdr;
        unsigned long size;
        return *hdr ? -1 : type;
  }
  
- int parse_sha1_header(const char *hdr, unsigned long *sizep)
+ int parse_loose_header(const char *hdr, unsigned long *sizep)
  {
        struct object_info oi = OBJECT_INFO_INIT;
  
        oi.sizep = sizep;
-       return parse_sha1_header_extended(hdr, &oi, 0);
+       return parse_loose_header_extended(hdr, &oi, 0);
  }
  
- static int sha1_loose_object_info(struct repository *r,
-                                 const unsigned char *sha1,
-                                 struct object_info *oi, int flags)
+ static int loose_object_info(struct repository *r,
+                            const struct object_id *oid,
+                            struct object_info *oi, int flags)
  {
        int status = 0;
        unsigned long mapsize;
                const char *path;
                struct stat st;
                if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
-                       return quick_has_loose(r, sha1) ? 0 : -1;
-               if (stat_sha1_file(r, sha1, &st, &path) < 0)
+                       return quick_has_loose(r, oid) ? 0 : -1;
+               if (stat_loose_object(r, oid, &st, &path) < 0)
                        return -1;
                if (oi->disk_sizep)
                        *oi->disk_sizep = st.st_size;
                return 0;
        }
  
-       map = map_sha1_file(r, sha1, &mapsize);
+       map = map_loose_object(r, oid, &mapsize);
        if (!map)
                return -1;
  
        if (oi->disk_sizep)
                *oi->disk_sizep = mapsize;
        if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE)) {
-               if (unpack_sha1_header_to_strbuf(&stream, map, mapsize, hdr, sizeof(hdr), &hdrbuf) < 0)
+               if (unpack_loose_header_to_strbuf(&stream, map, mapsize, hdr, sizeof(hdr), &hdrbuf) < 0)
                        status = error(_("unable to unpack %s header with --allow-unknown-type"),
-                                      sha1_to_hex(sha1));
-       } else if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
+                                      oid_to_hex(oid));
+       } else if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
                status = error(_("unable to unpack %s header"),
-                              sha1_to_hex(sha1));
+                              oid_to_hex(oid));
        if (status < 0)
                ; /* Do nothing */
        else if (hdrbuf.len) {
-               if ((status = parse_sha1_header_extended(hdrbuf.buf, oi, flags)) < 0)
+               if ((status = parse_loose_header_extended(hdrbuf.buf, oi, flags)) < 0)
                        status = error(_("unable to parse %s header with --allow-unknown-type"),
-                                      sha1_to_hex(sha1));
-       } else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)
-               status = error(_("unable to parse %s header"), sha1_to_hex(sha1));
+                                      oid_to_hex(oid));
+       } else if ((status = parse_loose_header_extended(hdr, oi, flags)) < 0)
+               status = error(_("unable to parse %s header"), oid_to_hex(oid));
  
        if (status >= 0 && oi->contentp) {
-               *oi->contentp = unpack_sha1_rest(&stream, hdr,
-                                                *oi->sizep, sha1);
+               *oi->contentp = unpack_loose_rest(&stream, hdr,
+                                                 *oi->sizep, oid);
                if (!*oi->contentp) {
                        git_inflate_end(&stream);
                        status = -1;
@@@ -1358,7 -1289,7 +1358,7 @@@ int oid_object_info_extended(struct rep
                        return -1;
  
                /* Most likely it's a loose object. */
-               if (!sha1_loose_object_info(r, real->hash, oi, flags))
+               if (!loose_object_info(r, real, oi, flags))
                        return 0;
  
                /* Not a loose object; someone else may have just packed it. */
@@@ -1421,21 -1352,16 +1421,17 @@@ int oid_object_info(struct repository *
        return type;
  }
  
 -static void *read_object(const struct object_id *oid, enum object_type *type,
 +static void *read_object(struct repository *r,
-                        const unsigned char *sha1,
-                        enum object_type *type,
++                       const struct object_id *oid, enum object_type *type,
                         unsigned long *size)
  {
-       struct object_id oid;
        struct object_info oi = OBJECT_INFO_INIT;
        void *content;
        oi.typep = type;
        oi.sizep = size;
        oi.contentp = &content;
  
-       hashcpy(oid.hash, sha1);
-       if (oid_object_info_extended(r, &oid, &oi, 0) < 0)
 -      if (oid_object_info_extended(the_repository, oid, &oi, 0) < 0)
++      if (oid_object_info_extended(r, oid, &oi, 0) < 0)
                return NULL;
        return content;
  }
@@@ -1446,7 -1372,7 +1442,7 @@@ int pretend_object_file(void *buf, unsi
        struct cached_object *co;
  
        hash_object_file(buf, len, type_name(type), oid);
-       if (has_sha1_file(oid->hash) || find_cached_object(oid))
+       if (has_object_file(oid) || find_cached_object(oid))
                return 0;
        ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc);
        co = &cached_objects[cached_object_nr++];
   * deal with them should arrange to call read_object() and give error
   * messages themselves.
   */
 -void *read_object_file_extended(const struct object_id *oid,
 +void *read_object_file_extended(struct repository *r,
 +                              const struct object_id *oid,
                                enum object_type *type,
                                unsigned long *size,
                                int lookup_replace)
        const char *path;
        struct stat st;
        const struct object_id *repl = lookup_replace ?
 -              lookup_replace_object(the_repository, oid) : oid;
 +              lookup_replace_object(r, oid) : oid;
  
        errno = 0;
-       data = read_object(r, repl->hash, type, size);
 -      data = read_object(repl, type, size);
++      data = read_object(r, repl, type, size);
        if (data)
                return data;
  
                die(_("replacement %s not found for %s"),
                    oid_to_hex(repl), oid_to_hex(oid));
  
-       if (!stat_sha1_file(r, repl->hash, &st, &path))
 -      if (!stat_loose_object(the_repository, repl, &st, &path))
++      if (!stat_loose_object(r, repl, &st, &path))
                die(_("loose object %s (stored in %s) is corrupt"),
                    oid_to_hex(repl), path);
  
 -      if ((p = has_packed_and_bad(repl->hash)) != NULL)
 +      if ((p = has_packed_and_bad(r, repl->hash)) != NULL)
                die(_("packed object %s (stored in %s) is corrupt"),
                    oid_to_hex(repl), p->pack_name);
  
@@@ -1596,7 -1521,7 +1592,7 @@@ int finalize_object_file(const char *tm
        unlink_or_warn(tmpfile);
        if (ret) {
                if (ret != EEXIST) {
-                       return error_errno(_("unable to write sha1 filename %s"), filename);
+                       return error_errno(_("unable to write file %s"), filename);
                }
                /* FIXME!!! Collision check here ? */
        }
@@@ -1624,12 -1549,12 +1620,12 @@@ int hash_object_file(const void *buf, u
  }
  
  /* Finalize a file on disk, and close it. */
- static void close_sha1_file(int fd)
+ static void close_loose_object(int fd)
  {
        if (fsync_object_files)
-               fsync_or_die(fd, "sha1 file");
+               fsync_or_die(fd, "loose object file");
        if (close(fd) != 0)
-               die_errno(_("error when closing sha1 file"));
+               die_errno(_("error when closing loose object file"));
  }
  
  /* Size of directory component, including the ending '/' */
@@@ -1689,7 -1614,7 +1685,7 @@@ static int write_loose_object(const str
        static struct strbuf tmp_file = STRBUF_INIT;
        static struct strbuf filename = STRBUF_INIT;
  
-       loose_object_path(the_repository, &filename, oid->hash);
+       loose_object_path(the_repository, &filename, oid);
  
        fd = create_tmpfile(&tmp_file, filename.buf);
        if (fd < 0) {
                ret = git_deflate(&stream, Z_FINISH);
                the_hash_algo->update_fn(&c, in0, stream.next_in - in0);
                if (write_buffer(fd, compressed, stream.next_out - compressed) < 0)
-                       die(_("unable to write sha1 file"));
+                       die(_("unable to write loose object file"));
                stream.next_out = compressed;
                stream.avail_out = sizeof(compressed);
        } while (ret == Z_OK);
                die(_("confused by unstable object source data for %s"),
                    oid_to_hex(oid));
  
-       close_sha1_file(fd);
+       close_loose_object(fd);
  
        if (mtime) {
                struct utimbuf utb;
@@@ -1817,9 -1742,9 +1813,9 @@@ int force_object_loose(const struct obj
  
        if (has_loose_object(oid))
                return 0;
-       buf = read_object(the_repository, oid->hash, &type, &len);
 -      buf = read_object(oid, &type, &len);
++      buf = read_object(the_repository, oid, &type, &len);
        if (!buf)
-               return error(_("cannot read sha1_file for %s"), oid_to_hex(oid));
+               return error(_("cannot read object for %s"), oid_to_hex(oid));
        hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1;
        ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime);
        free(buf);
        return ret;
  }
  
- int repo_has_sha1_file_with_flags(struct repository *r,
-                                 const unsigned char *sha1, int flags)
 -int has_object_file_with_flags(const struct object_id *oid, int flags)
++int repo_has_object_file_with_flags(struct repository *r,
++                                  const struct object_id *oid, int flags)
  {
-       struct object_id oid;
        if (!startup_info->have_repository)
                return 0;
-       hashcpy(oid.hash, sha1);
-       return oid_object_info_extended(r, &oid, NULL,
 -      return oid_object_info_extended(the_repository, oid, NULL,
++      return oid_object_info_extended(r, oid, NULL,
                                        flags | OBJECT_INFO_SKIP_CACHED) >= 0;
  }
  
-       return repo_has_sha1_file(r, oid->hash);
- }
- int repo_has_object_file_with_flags(struct repository *r,
-                                   const struct object_id *oid, int flags)
- {
-       return repo_has_sha1_file_with_flags(r, oid->hash, flags);
 +int repo_has_object_file(struct repository *r,
 +                       const struct object_id *oid)
 +{
++      return repo_has_object_file_with_flags(r, oid, 0);
 +}
 +
  static void check_tree(const void *buf, size_t size)
  {
        struct tree_desc desc;
@@@ -2258,14 -2168,14 +2246,14 @@@ void odb_clear_loose_cache(struct objec
               sizeof(odb->loose_objects_subdir_seen));
  }
  
- static int check_stream_sha1(git_zstream *stream,
-                            const char *hdr,
-                            unsigned long size,
-                            const char *path,
-                            const unsigned char *expected_sha1)
+ static int check_stream_oid(git_zstream *stream,
+                           const char *hdr,
+                           unsigned long size,
+                           const char *path,
+                           const struct object_id *expected_oid)
  {
        git_hash_ctx c;
-       unsigned char real_sha1[GIT_MAX_RAWSZ];
+       struct object_id real_oid;
        unsigned char buf[4096];
        unsigned long total_read;
        int status = Z_OK;
  
        /*
         * This size comparison must be "<=" to read the final zlib packets;
-        * see the comment in unpack_sha1_rest for details.
+        * see the comment in unpack_loose_rest for details.
         */
        while (total_read <= size &&
               (status == Z_OK ||
        git_inflate_end(stream);
  
        if (status != Z_STREAM_END) {
-               error(_("corrupt loose object '%s'"), sha1_to_hex(expected_sha1));
+               error(_("corrupt loose object '%s'"), oid_to_hex(expected_oid));
                return -1;
        }
        if (stream->avail_in) {
                error(_("garbage at end of loose object '%s'"),
-                     sha1_to_hex(expected_sha1));
+                     oid_to_hex(expected_oid));
                return -1;
        }
  
-       the_hash_algo->final_fn(real_sha1, &c);
-       if (!hasheq(expected_sha1, real_sha1)) {
-               error(_("sha1 mismatch for %s (expected %s)"), path,
-                     sha1_to_hex(expected_sha1));
+       the_hash_algo->final_fn(real_oid.hash, &c);
+       if (!oideq(expected_oid, &real_oid)) {
+               error(_("hash mismatch for %s (expected %s)"), path,
+                     oid_to_hex(expected_oid));
                return -1;
        }
  
@@@ -2330,18 -2240,18 +2318,18 @@@ int read_loose_object(const char *path
  
        *contents = NULL;
  
-       map = map_sha1_file_1(the_repository, path, NULL, &mapsize);
+       map = map_loose_object_1(the_repository, path, NULL, &mapsize);
        if (!map) {
                error_errno(_("unable to mmap %s"), path);
                goto out;
        }
  
-       if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0) {
+       if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0) {
                error(_("unable to unpack header of %s"), path);
                goto out;
        }
  
-       *type = parse_sha1_header(hdr, size);
+       *type = parse_loose_header(hdr, size);
        if (*type < 0) {
                error(_("unable to parse header of %s"), path);
                git_inflate_end(&stream);
        }
  
        if (*type == OBJ_BLOB && *size > big_file_threshold) {
-               if (check_stream_sha1(&stream, hdr, *size, path, expected_oid->hash) < 0)
+               if (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)
                        goto out;
        } else {
-               *contents = unpack_sha1_rest(&stream, hdr, *size, expected_oid->hash);
+               *contents = unpack_loose_rest(&stream, hdr, *size, expected_oid);
                if (!*contents) {
                        error(_("unable to unpack contents of %s"), path);
                        git_inflate_end(&stream);
                }
                if (check_object_signature(expected_oid, *contents,
                                         *size, type_name(*type))) {
-                       error(_("sha1 mismatch for %s (expected %s)"), path,
+                       error(_("hash mismatch for %s (expected %s)"), path,
                              oid_to_hex(expected_oid));
                        free(*contents);
                        goto out;
diff --combined streaming.c
index 891f82f51a753d065ce67b111bce86e790801599,998e6285d7f0def874c53eb1ca0a745e618bd824..fcd63032192ff4056946ce3a0a266c7fb021353b
@@@ -338,16 -338,16 +338,16 @@@ static struct stream_vtbl loose_vtbl = 
  
  static open_method_decl(loose)
  {
-       st->u.loose.mapped = map_sha1_file(the_repository,
-                                          oid->hash, &st->u.loose.mapsize);
+       st->u.loose.mapped = map_loose_object(the_repository,
+                                             oid, &st->u.loose.mapsize);
        if (!st->u.loose.mapped)
                return -1;
-       if ((unpack_sha1_header(&st->z,
-                               st->u.loose.mapped,
-                               st->u.loose.mapsize,
-                               st->u.loose.hdr,
-                               sizeof(st->u.loose.hdr)) < 0) ||
-           (parse_sha1_header(st->u.loose.hdr, &st->size) < 0)) {
+       if ((unpack_loose_header(&st->z,
+                                st->u.loose.mapped,
+                                st->u.loose.mapsize,
+                                st->u.loose.hdr,
+                                sizeof(st->u.loose.hdr)) < 0) ||
+           (parse_loose_header(st->u.loose.hdr, &st->size) < 0)) {
                git_inflate_end(&st->z);
                munmap(st->u.loose.mapped, st->u.loose.mapsize);
                return -1;
@@@ -499,7 -499,7 +499,7 @@@ static struct stream_vtbl incore_vtbl 
  
  static open_method_decl(incore)
  {
 -      st->u.incore.buf = read_object_file_extended(oid, type, &st->size, 0);
 +      st->u.incore.buf = read_object_file_extended(the_repository, oid, type, &st->size, 0);
        st->u.incore.read_ptr = 0;
        st->vtbl = &incore_vtbl;