Merge branch 'tg/index-v4-format'
authorJunio C Hamano <gitster@pobox.com>
Fri, 14 Mar 2014 21:26:50 +0000 (14:26 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 14 Mar 2014 21:26:50 +0000 (14:26 -0700)
* tg/index-v4-format:
read-cache: add index.version config variable
test-lib: allow setting the index format version
introduce GIT_INDEX_VERSION environment variable

1  2 
Documentation/config.txt
Makefile
read-cache.c
t/test-lib-functions.sh
diff --combined Documentation/config.txt
index 73904bce55ff1d78bd10a5eb6b83f5fdf36ea74a,98200aaba2e32d7ab387adcb3f2e1c24a5ab1867..989eb80ac1d3b0c1b756fb7a88874fa50a00eae3
@@@ -142,13 -142,19 +142,13 @@@ advice.*:
  --
        pushUpdateRejected::
                Set this variable to 'false' if you want to disable
 -              'pushNonFFCurrent', 'pushNonFFDefault',
 +              'pushNonFFCurrent',
                'pushNonFFMatching', 'pushAlreadyExists',
                'pushFetchFirst', and 'pushNeedsForce'
                simultaneously.
        pushNonFFCurrent::
                Advice shown when linkgit:git-push[1] fails due to a
                non-fast-forward update to the current branch.
 -      pushNonFFDefault::
 -              Advice to set 'push.default' to 'upstream' or 'current'
 -              when you ran linkgit:git-push[1] and pushed 'matching
 -              refs' by default (i.e. you did not provide an explicit
 -              refspec, and no 'push.default' configuration was set)
 -              and it resulted in a non-fast-forward error.
        pushNonFFMatching::
                Advice shown when you ran linkgit:git-push[1] and pushed
                'matching refs' explicitly (i.e. you used ':', or
@@@ -986,14 -992,6 +986,14 @@@ commit.cleanup:
        have to remove the help lines that begin with `#` in the commit log
        template yourself, if you do this).
  
 +commit.gpgsign::
 +
 +      A boolean to specify whether all commits should be GPG signed.
 +      Use of this option when doing operations such as rebase can
 +      result in a large number of commits being signed. It may be
 +      convenient to use an agent to avoid typing your GPG passphrase
 +      several times.
 +
  commit.status::
        A boolean to enable/disable inclusion of status information in the
        commit message template when using an editor to prepare the commit
@@@ -1169,10 -1167,6 +1169,10 @@@ gc.autopacklimit:
        --auto` consolidates them into one larger pack.  The
        default value is 50.  Setting this to 0 disables it.
  
 +gc.autodetach::
 +      Make `git gc --auto` return immediately andrun in background
 +      if the system supports it. Default is true.
 +
  gc.packrefs::
        Running `git pack-refs` in a repository renders it
        unclonable by Git versions prior to 1.5.1.2 over dumb
@@@ -1607,6 -1601,10 +1607,10 @@@ imap:
        The configuration variables in the 'imap' section are described
        in linkgit:git-imap-send[1].
  
+ index.version::
+       Specify the version with which new index files should be
+       initialized.  This does not affect existing repositories.
  init.templatedir::
        Specify the directory from which templates will be copied.
        (See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
@@@ -1868,31 -1866,6 +1872,31 @@@ pack.packSizeLimit:
        Common unit suffixes of 'k', 'm', or 'g' are
        supported.
  
 +pack.useBitmaps::
 +      When true, git will use pack bitmaps (if available) when packing
 +      to stdout (e.g., during the server side of a fetch). Defaults to
 +      true. You should not generally need to turn this off unless
 +      you are debugging pack bitmaps.
 +
 +pack.writebitmaps::
 +      When true, git will write a bitmap index when packing all
 +      objects to disk (e.g., when `git repack -a` is run).  This
 +      index can speed up the "counting objects" phase of subsequent
 +      packs created for clones and fetches, at the cost of some disk
 +      space and extra time spent on the initial repack.  Defaults to
 +      false.
 +
 +pack.writeBitmapHashCache::
 +      When true, git will include a "hash cache" section in the bitmap
 +      index (if one is written). This cache can be used to feed git's
 +      delta heuristics, potentially leading to better deltas between
 +      bitmapped and non-bitmapped objects (e.g., when serving a fetch
 +      between an older, bitmapped pack and objects that have been
 +      pushed since the last gc). The downside is that it consumes 4
 +      bytes per object of disk space, and that JGit's bitmap
 +      implementation does not understand it, causing it to complain if
 +      Git and JGit are used on the same repository. Defaults to false.
 +
  pager.<cmd>::
        If the value is boolean, turns on or off pagination of the
        output of a particular Git subcommand when writing to a tty.
@@@ -1912,16 -1885,6 +1916,16 @@@ pretty.<name>:
        Note that an alias with the same name as a built-in format
        will be silently ignored.
  
 +pull.ff::
 +      By default, Git does not create an extra merge commit when merging
 +      a commit that is a descendant of the current commit. Instead, the
 +      tip of the current branch is fast-forwarded. When set to `false`,
 +      this variable tells Git to create an extra merge commit in such
 +      a case (equivalent to giving the `--no-ff` option from the command
 +      line). When set to `only`, only such fast-forward merges are
 +      allowed (equivalent to giving the `--ff-only` option from the
 +      command line).
 +
  pull.rebase::
        When true, rebase branches on top of the fetched branch, instead
        of merging the default branch from the default remote when "git
@@@ -1974,7 -1937,7 +1978,7 @@@ When pushing to a remote that is differ
  pull from, work as `current`.  This is the safest option and is suited
  for beginners.
  +
 -This mode will become the default in Git 2.0.
 +This mode has become the default in Git 2.0.
  
  * `matching` - push all branches having the same name on both ends.
    This makes the repository you are pushing to remember the set of
@@@ -1993,8 -1956,8 +1997,8 @@@ suitable for pushing into a shared cent
  people may add new branches there, or update the tip of existing
  branches outside your control.
  +
 -This is currently the default, but Git 2.0 will change the default
 -to `simple`.
 +This used to be the default, but not since Git 2.0 (`simple` is the
 +new default).
  
  --
  
diff --combined Makefile
index a20fbafd6249e13af9d6eb63e5626c0d32fb69b8,5caa3b2ed00205c7f40ce74b76506208b7214eef..f818eecaf380c109be248f424d5c8f3a537359e0
+++ b/Makefile
@@@ -101,6 -101,14 +101,6 @@@ all:
  #
  # Define NO_MKSTEMPS if you don't have mkstemps in the C library.
  #
 -# Define NO_FNMATCH if you don't have fnmatch in the C library.
 -#
 -# Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
 -# FNM_CASEFOLD GNU extension.
 -#
 -# Define NO_WILDMATCH if you do not want to use Git's wildmatch
 -# implementation as fnmatch
 -#
  # Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
  # in the C library.
  #
  # Define DEFAULT_HELP_FORMAT to "man", "info" or "html"
  # (defaults to "man") if you want to have a different default when
  # "git help" is called without a parameter specifying the format.
+ #
+ # Define TEST_GIT_INDEX_VERSION to 2, 3 or 4 to run the test suite
+ # with a different indexfile format version.  If it isn't set the index
+ # file format used is index-v[23].
  
  GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@@ -547,7 -559,6 +551,7 @@@ TEST_PROGRAMS_NEED_X += test-dat
  TEST_PROGRAMS_NEED_X += test-delta
  TEST_PROGRAMS_NEED_X += test-dump-cache-tree
  TEST_PROGRAMS_NEED_X += test-genrandom
 +TEST_PROGRAMS_NEED_X += test-hashmap
  TEST_PROGRAMS_NEED_X += test-index-version
  TEST_PROGRAMS_NEED_X += test-line-buffer
  TEST_PROGRAMS_NEED_X += test-match-trees
@@@ -656,8 -667,6 +660,8 @@@ LIB_H += diff.
  LIB_H += diffcore.h
  LIB_H += dir.h
  LIB_H += exec_cmd.h
 +LIB_H += ewah/ewok.h
 +LIB_H += ewah/ewok_rlw.h
  LIB_H += fetch-pack.h
  LIB_H += fmt-merge-msg.h
  LIB_H += fsck.h
@@@ -666,7 -675,7 +670,7 @@@ LIB_H += git-compat-util.
  LIB_H += gpg-interface.h
  LIB_H += graph.h
  LIB_H += grep.h
 -LIB_H += hash.h
 +LIB_H += hashmap.h
  LIB_H += help.h
  LIB_H += http.h
  LIB_H += kwset.h
@@@ -685,10 -694,8 +689,10 @@@ LIB_H += notes-merge.
  LIB_H += notes-utils.h
  LIB_H += notes.h
  LIB_H += object.h
 +LIB_H += pack-objects.h
  LIB_H += pack-revindex.h
  LIB_H += pack.h
 +LIB_H += pack-bitmap.h
  LIB_H += parse-options.h
  LIB_H += patch-ids.h
  LIB_H += pathspec.h
@@@ -792,10 -799,6 +796,10 @@@ LIB_OBJS += dir.
  LIB_OBJS += editor.o
  LIB_OBJS += entry.o
  LIB_OBJS += environment.o
 +LIB_OBJS += ewah/bitmap.o
 +LIB_OBJS += ewah/ewah_bitmap.o
 +LIB_OBJS += ewah/ewah_io.o
 +LIB_OBJS += ewah/ewah_rlw.o
  LIB_OBJS += exec_cmd.o
  LIB_OBJS += fetch-pack.o
  LIB_OBJS += fsck.o
@@@ -803,7 -806,7 +807,7 @@@ LIB_OBJS += gettext.
  LIB_OBJS += gpg-interface.o
  LIB_OBJS += graph.o
  LIB_OBJS += grep.o
 -LIB_OBJS += hash.o
 +LIB_OBJS += hashmap.o
  LIB_OBJS += help.o
  LIB_OBJS += hex.o
  LIB_OBJS += ident.o
@@@ -827,10 -830,7 +831,10 @@@ LIB_OBJS += notes-cache.
  LIB_OBJS += notes-merge.o
  LIB_OBJS += notes-utils.o
  LIB_OBJS += object.o
 +LIB_OBJS += pack-bitmap.o
 +LIB_OBJS += pack-bitmap-write.o
  LIB_OBJS += pack-check.o
 +LIB_OBJS += pack-objects.o
  LIB_OBJS += pack-revindex.o
  LIB_OBJS += pack-write.o
  LIB_OBJS += pager.o
@@@ -1275,6 -1275,20 +1279,6 @@@ endi
  ifdef NO_STRTOULL
        COMPAT_CFLAGS += -DNO_STRTOULL
  endif
 -ifdef NO_FNMATCH
 -      COMPAT_CFLAGS += -Icompat/fnmatch
 -      COMPAT_CFLAGS += -DNO_FNMATCH
 -      COMPAT_OBJS += compat/fnmatch/fnmatch.o
 -else
 -ifdef NO_FNMATCH_CASEFOLD
 -      COMPAT_CFLAGS += -Icompat/fnmatch
 -      COMPAT_CFLAGS += -DNO_FNMATCH_CASEFOLD
 -      COMPAT_OBJS += compat/fnmatch/fnmatch.o
 -endif
 -endif
 -ifndef NO_WILDMATCH
 -      COMPAT_CFLAGS += -DUSE_WILDMATCH
 -endif
  ifdef NO_SETENV
        COMPAT_CFLAGS += -DNO_SETENV
        COMPAT_OBJS += compat/setenv.o
@@@ -2212,6 -2226,9 +2216,9 @@@ endi
  ifdef GIT_PERF_MAKE_OPTS
        @echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@
  endif
+ ifdef TEST_GIT_INDEX_VERSION
+       @echo TEST_GIT_INDEX_VERSION=\''$(subst ','\'',$(subst ','\'',$(TEST_GIT_INDEX_VERSION)))'\' >>$@
+ endif
  
  ### Detect Python interpreter path changes
  ifndef NO_PYTHON
@@@ -2469,9 -2486,8 +2476,9 @@@ profile-clean
        $(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
  
  clean: profile-clean coverage-clean
 -      $(RM) *.o *.res block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o vcs-svn/*.o \
 -              builtin/*.o $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
 +      $(RM) *.o *.res block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o
 +      $(RM) xdiff/*.o vcs-svn/*.o ewah/*.o builtin/*.o
 +      $(RM) $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
        $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS) $(NO_INSTALL)
        $(RM) -r bin-wrappers $(dep_dirs)
diff --combined read-cache.c
index fb440b4d9d1aa002ebc760e4fa4e0f0d028fd868,6bc9724793dde0373d9e292908f11d2e80e9c34e..f23c44a81a56f43e95a0e14fb37a84bac1a06caf
@@@ -15,8 -15,7 +15,8 @@@
  #include "strbuf.h"
  #include "varint.h"
  
 -static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
 +static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
 +                                             unsigned int options);
  
  /* Mask for the name length in ce_flags in the on-disk index */
  
@@@ -48,7 -47,6 +48,7 @@@ static void replace_index_entry(struct 
        struct cache_entry *old = istate->cache[nr];
  
        remove_name_hash(istate, old);
 +      free(old);
        set_index_entry(istate, nr, ce);
        istate->cache_changed = 1;
  }
@@@ -60,7 -58,7 +60,7 @@@ void rename_index_entry_at(struct index
  
        new = xmalloc(cache_entry_size(namelen));
        copy_cache_entry(new, old);
 -      new->ce_flags &= ~CE_STATE_MASK;
 +      new->ce_flags &= ~CE_HASHED;
        new->ce_namelen = namelen;
        memcpy(new->name, new_name, namelen + 1);
  
@@@ -480,7 -478,6 +480,7 @@@ int remove_index_entry_at(struct index_
  
        record_resolve_undo(istate, ce);
        remove_name_hash(istate, ce);
 +      free(ce);
        istate->cache_changed = 1;
        istate->cache_nr--;
        if (pos >= istate->cache_nr)
@@@ -502,10 -499,8 +502,10 @@@ void remove_marked_cache_entries(struc
        unsigned int i, j;
  
        for (i = j = 0; i < istate->cache_nr; i++) {
 -              if (ce_array[i]->ce_flags & CE_REMOVE)
 +              if (ce_array[i]->ce_flags & CE_REMOVE) {
                        remove_name_hash(istate, ce_array[i]);
 +                      free(ce_array[i]);
 +              }
                else
                        ce_array[j++] = ce_array[i];
        }
@@@ -584,7 -579,7 +584,7 @@@ static struct cache_entry *create_alias
        return new;
  }
  
 -static void record_intent_to_add(struct cache_entry *ce)
 +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))
@@@ -670,7 -665,7 +670,7 @@@ int add_to_index(struct index_state *is
                if (index_path(ce->sha1, path, st, HASH_WRITE_OBJECT))
                        return error("unable to index file %s", path);
        } else
 -              record_intent_to_add(ce);
 +              set_object_name_for_intent_to_add_entry(ce);
  
        if (ignore_case && alias && different_name(ce, alias))
                ce = create_alias_ce(ce, alias);
@@@ -701,7 -696,7 +701,7 @@@ int add_file_to_index(struct index_stat
  
  struct cache_entry *make_cache_entry(unsigned int mode,
                const unsigned char *sha1, const char *path, int stage,
 -              int refresh)
 +              unsigned int refresh_options)
  {
        int size, len;
        struct cache_entry *ce;
        ce->ce_namelen = len;
        ce->ce_mode = create_ce_mode(mode);
  
 -      if (refresh)
 -              return refresh_cache_entry(ce, 0);
 -
 -      return ce;
 +      return refresh_cache_entry(ce, refresh_options);
  }
  
  int ce_same_name(const struct cache_entry *a, const struct cache_entry *b)
        return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
  }
  
 -int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec)
 -{
 -      return match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL);
 -}
 -
  /*
   * We fundamentally don't like some paths: we don't want
   * dot or dot-dot anywhere, and for obvious reasons don't
@@@ -1026,12 -1029,10 +1026,12 @@@ static struct cache_entry *refresh_cach
        struct stat st;
        struct cache_entry *updated;
        int changed, size;
 +      int refresh = options & CE_MATCH_REFRESH;
        int ignore_valid = options & CE_MATCH_IGNORE_VALID;
        int ignore_skip_worktree = options & CE_MATCH_IGNORE_SKIP_WORKTREE;
 +      int ignore_missing = options & CE_MATCH_IGNORE_MISSING;
  
 -      if (ce_uptodate(ce))
 +      if (!refresh || ce_uptodate(ce))
                return ce;
  
        /*
        }
  
        if (lstat(ce->name, &st) < 0) {
 +              if (ignore_missing && errno == ENOENT)
 +                      return ce;
                if (err)
                        *err = errno;
                return NULL;
@@@ -1128,9 -1127,7 +1128,9 @@@ int refresh_index(struct index_state *i
        int ignore_submodules = (flags & REFRESH_IGNORE_SUBMODULES) != 0;
        int first = 1;
        int in_porcelain = (flags & REFRESH_IN_PORCELAIN);
 -      unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0;
 +      unsigned int options = (CE_MATCH_REFRESH |
 +                              (really ? CE_MATCH_IGNORE_VALID : 0) |
 +                              (not_new ? CE_MATCH_IGNORE_MISSING : 0));
        const char *modified_fmt;
        const char *deleted_fmt;
        const char *typechange_fmt;
                if (ignore_submodules && S_ISGITLINK(ce->ce_mode))
                        continue;
  
 -              if (pathspec &&
 -                  !match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, seen))
 +              if (pathspec && !ce_path_match(ce, pathspec, seen))
                        filtered = 1;
  
                if (ce_stage(ce)) {
                if (!new) {
                        const char *fmt;
  
 -                      if (not_new && cache_errno == ENOENT)
 -                              continue;
                        if (really && cache_errno == EINVAL) {
                                /* If we are doing --really-refresh that
                                 * means the index is not valid anymore.
        return has_errors;
  }
  
 -static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
 +static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
 +                                             unsigned int options)
  {
 -      return refresh_cache_ent(&the_index, ce, really, NULL, NULL);
 +      return refresh_cache_ent(&the_index, ce, options, NULL, NULL);
  }
  
  
  
  #define INDEX_FORMAT_DEFAULT 3
  
+ static int index_format_config(const char *var, const char *value, void *cb)
+ {
+       unsigned int *version = cb;
+       if (!strcmp(var, "index.version")) {
+               *version = git_config_int(var, value);
+               return 0;
+       }
+       return 1;
+ }
+ static unsigned int get_index_format_default(void)
+ {
+       char *envversion = getenv("GIT_INDEX_VERSION");
+       char *endp;
+       unsigned int version = INDEX_FORMAT_DEFAULT;
+       if (!envversion) {
+               git_config(index_format_config, &version);
+               if (version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < version) {
+                       warning(_("index.version set, but the value is invalid.\n"
+                                 "Using version %i"), INDEX_FORMAT_DEFAULT);
+                       return INDEX_FORMAT_DEFAULT;
+               }
+               return version;
+       }
+       version = strtoul(envversion, &endp, 10);
+       if (*endp ||
+           version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < version) {
+               warning(_("GIT_INDEX_VERSION set, but the value is invalid.\n"
+                         "Using version %i"), INDEX_FORMAT_DEFAULT);
+               version = INDEX_FORMAT_DEFAULT;
+       }
+       return version;
+ }
  /*
   * dev/ino/uid/gid/size are also just tracked to the low 32 bits
   * Again - this is just a (very strong in practice) heuristic that
@@@ -1314,6 -1349,26 +1350,6 @@@ int read_index(struct index_state *ista
        return read_index_from(istate, get_index_file());
  }
  
 -#ifndef NEEDS_ALIGNED_ACCESS
 -#define ntoh_s(var) ntohs(var)
 -#define ntoh_l(var) ntohl(var)
 -#else
 -static inline uint16_t ntoh_s_force_align(void *p)
 -{
 -      uint16_t x;
 -      memcpy(&x, p, sizeof(x));
 -      return ntohs(x);
 -}
 -static inline uint32_t ntoh_l_force_align(void *p)
 -{
 -      uint32_t x;
 -      memcpy(&x, p, sizeof(x));
 -      return ntohl(x);
 -}
 -#define ntoh_s(var) ntoh_s_force_align(&(var))
 -#define ntoh_l(var) ntoh_l_force_align(&(var))
 -#endif
 -
  static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *ondisk,
                                                   unsigned int flags,
                                                   const char *name,
  {
        struct cache_entry *ce = xmalloc(cache_entry_size(len));
  
 -      ce->ce_stat_data.sd_ctime.sec = ntoh_l(ondisk->ctime.sec);
 -      ce->ce_stat_data.sd_mtime.sec = ntoh_l(ondisk->mtime.sec);
 -      ce->ce_stat_data.sd_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
 -      ce->ce_stat_data.sd_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
 -      ce->ce_stat_data.sd_dev   = ntoh_l(ondisk->dev);
 -      ce->ce_stat_data.sd_ino   = ntoh_l(ondisk->ino);
 -      ce->ce_mode  = ntoh_l(ondisk->mode);
 -      ce->ce_stat_data.sd_uid   = ntoh_l(ondisk->uid);
 -      ce->ce_stat_data.sd_gid   = ntoh_l(ondisk->gid);
 -      ce->ce_stat_data.sd_size  = ntoh_l(ondisk->size);
 +      ce->ce_stat_data.sd_ctime.sec = get_be32(&ondisk->ctime.sec);
 +      ce->ce_stat_data.sd_mtime.sec = get_be32(&ondisk->mtime.sec);
 +      ce->ce_stat_data.sd_ctime.nsec = get_be32(&ondisk->ctime.nsec);
 +      ce->ce_stat_data.sd_mtime.nsec = get_be32(&ondisk->mtime.nsec);
 +      ce->ce_stat_data.sd_dev   = get_be32(&ondisk->dev);
 +      ce->ce_stat_data.sd_ino   = get_be32(&ondisk->ino);
 +      ce->ce_mode  = get_be32(&ondisk->mode);
 +      ce->ce_stat_data.sd_uid   = get_be32(&ondisk->uid);
 +      ce->ce_stat_data.sd_gid   = get_be32(&ondisk->gid);
 +      ce->ce_stat_data.sd_size  = get_be32(&ondisk->size);
        ce->ce_flags = flags & ~CE_NAMEMASK;
        ce->ce_namelen = len;
        hashcpy(ce->sha1, ondisk->sha1);
@@@ -1370,14 -1425,14 +1406,14 @@@ static struct cache_entry *create_from_
        unsigned int flags;
  
        /* On-disk flags are just 16 bits */
 -      flags = ntoh_s(ondisk->flags);
 +      flags = get_be16(&ondisk->flags);
        len = flags & CE_NAMEMASK;
  
        if (flags & CE_EXTENDED) {
                struct ondisk_cache_entry_extended *ondisk2;
                int extended_flags;
                ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
 -              extended_flags = ntoh_s(ondisk2->flags2) << 16;
 +              extended_flags = get_be16(&ondisk2->flags2) << 16;
                /* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
                if (extended_flags & ~CE_EXTENDED_FLAGS)
                        die("Unknown index entry format %08x", extended_flags);
@@@ -1776,7 -1831,7 +1812,7 @@@ int write_index(struct index_state *ist
        }
  
        if (!istate->version)
-               istate->version = INDEX_FORMAT_DEFAULT;
+               istate->version = get_index_format_default();
  
        /* demote version 3 to version 2 when the latter suffices */
        if (istate->version == 3 || istate->version == 2)
@@@ -1875,7 -1930,7 +1911,7 @@@ int read_index_unmerged(struct index_st
                new_ce->ce_mode = ce->ce_mode;
                if (add_index_entry(istate, new_ce, 0))
                        return error("%s: cannot drop to stage #0",
 -                                   ce->name);
 +                                   new_ce->name);
                i = index_name_pos(istate, new_ce->name, len);
        }
        return unmerged;
diff --combined t/test-lib-functions.sh
index b333e3ff86aaaed41fa02b8c077848011907600e,0bf1e63ab5021349ae0b625e2ea3daf80b6d80b6..158e10a67e5878bb9031af2f28439b099b65fd50
@@@ -32,6 -32,11 +32,11 @@@ test_set_editor () 
        export EDITOR
  }
  
+ test_set_index_version () {
+     GIT_INDEX_VERSION="$1"
+     export GIT_INDEX_VERSION
+ }
  test_decode_color () {
        awk '
                function name(n) {
@@@ -716,64 -721,6 +721,64 @@@ perl () 
        command "$PERL_PATH" "$@"
  }
  
 +# Is the value one of the various ways to spell a boolean true/false?
 +test_normalize_bool () {
 +      git -c magic.variable="$1" config --bool magic.variable 2>/dev/null
 +}
 +
 +# Given a variable $1, normalize the value of it to one of "true",
 +# "false", or "auto" and store the result to it.
 +#
 +#     test_tristate GIT_TEST_HTTPD
 +#
 +# A variable set to an empty string is set to 'false'.
 +# A variable set to 'false' or 'auto' keeps its value.
 +# Anything else is set to 'true'.
 +# An unset variable defaults to 'auto'.
 +#
 +# The last rule is to allow people to set the variable to an empty
 +# string and export it to decline testing the particular feature
 +# for versions both before and after this change.  We used to treat
 +# both unset and empty variable as a signal for "do not test" and
 +# took any non-empty string as "please test".
 +
 +test_tristate () {
 +      if eval "test x\"\${$1+isset}\" = xisset"
 +      then
 +              # explicitly set
 +              eval "
 +                      case \"\$$1\" in
 +                      '')     $1=false ;;
 +                      auto)   ;;
 +                      *)      $1=\$(test_normalize_bool \$$1 || echo true) ;;
 +                      esac
 +              "
 +      else
 +              eval "$1=auto"
 +      fi
 +}
 +
 +# Exit the test suite, either by skipping all remaining tests or by
 +# exiting with an error. If "$1" is "auto", we then we assume we were
 +# opportunistically trying to set up some tests and we skip. If it is
 +# "true", then we report a failure.
 +#
 +# The error/skip message should be given by $2.
 +#
 +test_skip_or_die () {
 +      case "$1" in
 +      auto)
 +              skip_all=$2
 +              test_done
 +              ;;
 +      true)
 +              error "$2"
 +              ;;
 +      *)
 +              error "BUG: test tristate is '$1' (real error: $2)"
 +      esac
 +}
 +
  # The following mingw_* functions obey POSIX shell syntax, but are actually
  # bash scripts, and are meant to be used only with bash on Windows.