log,diff-tree: add --combined-all-paths option
[gitweb.git] / read-cache.c
index 7acc2c86f401bb9aa8c86ec3c6be305f75582411..bfff271a3db92cfaaa93d23c5bf52297dda0419e 100644 (file)
@@ -24,6 +24,7 @@
 #include "utf8.h"
 #include "fsmonitor.h"
 #include "thread-utils.h"
+#include "progress.h"
 
 /* Mask for the name length in ce_flags in the on-disk index */
 
@@ -208,14 +209,16 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
        }
 }
 
-static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
+static int ce_compare_data(struct index_state *istate,
+                          const struct cache_entry *ce,
+                          struct stat *st)
 {
        int match = -1;
        int fd = git_open_cloexec(ce->name, O_RDONLY);
 
        if (fd >= 0) {
                struct object_id oid;
-               if (!index_fd(&oid, fd, st, OBJ_BLOB, ce->name, 0))
+               if (!index_fd(istate, &oid, fd, st, OBJ_BLOB, ce->name, 0))
                        match = !oideq(&oid, &ce->oid);
                /* index_fd() closed the file descriptor already */
        }
@@ -260,11 +263,13 @@ static int ce_compare_gitlink(const struct cache_entry *ce)
        return !oideq(&oid, &ce->oid);
 }
 
-static int ce_modified_check_fs(const struct cache_entry *ce, struct stat *st)
+static int ce_modified_check_fs(struct index_state *istate,
+                               const struct cache_entry *ce,
+                               struct stat *st)
 {
        switch (st->st_mode & S_IFMT) {
        case S_IFREG:
-               if (ce_compare_data(ce, st))
+               if (ce_compare_data(istate, ce, st))
                        return DATA_CHANGED;
                break;
        case S_IFLNK:
@@ -311,7 +316,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
                        changed |= DATA_CHANGED;
                return changed;
        default:
-               die("internal error: ce_mode is %o", ce->ce_mode);
+               BUG("unsupported ce_mode: %o", ce->ce_mode);
        }
 
        changed |= match_stat_data(&ce->ce_stat_data, st);
@@ -340,7 +345,7 @@ static int is_racy_stat(const struct index_state *istate,
                );
 }
 
-static int is_racy_timestamp(const struct index_state *istate,
+int is_racy_timestamp(const struct index_state *istate,
                             const struct cache_entry *ce)
 {
        return (!S_ISGITLINK(ce->ce_mode) &&
@@ -410,7 +415,7 @@ int ie_match_stat(struct index_state *istate,
                if (assume_racy_is_modified)
                        changed |= DATA_CHANGED;
                else
-                       changed |= ce_modified_check_fs(ce, st);
+                       changed |= ce_modified_check_fs(istate, ce, st);
        }
 
        return changed;
@@ -450,7 +455,7 @@ int ie_modified(struct index_state *istate,
            (S_ISGITLINK(ce->ce_mode) || ce->ce_stat_data.sd_size != 0))
                return changed;
 
-       changed_fs = ce_modified_check_fs(ce, st);
+       changed_fs = ce_modified_check_fs(istate, ce, st);
        if (changed_fs)
                return changed | changed_fs;
        return 0;
@@ -667,7 +672,8 @@ static struct cache_entry *create_alias_ce(struct index_state *istate,
        struct cache_entry *new_entry;
 
        if (alias->ce_flags & CE_ADDED)
-               die("Will not add file alias '%s' ('%s' already exists in index)", ce->name, alias->name);
+               die(_("will not add file alias '%s' ('%s' already exists in index)"),
+                   ce->name, alias->name);
 
        /* Ok, create the new entry using the name of the existing alias */
        len = ce_namelen(alias);
@@ -682,7 +688,7 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
 {
        struct object_id oid;
        if (write_object_file("", 0, blob_type, &oid))
-               die("cannot create an empty blob in the object database");
+               die(_("cannot create an empty blob in the object database"));
        oidcpy(&ce->oid, &oid);
 }
 
@@ -703,7 +709,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
                newflags |= HASH_RENORMALIZE;
 
        if (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))
-               return error("%s: can only add regular files, symbolic links or git-directories", path);
+               return error(_("%s: can only add regular files, symbolic links or git-directories"), path);
 
        namelen = strlen(path);
        if (S_ISDIR(st_mode)) {
@@ -756,9 +762,9 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
                }
        }
        if (!intent_only) {
-               if (index_path(&ce->oid, path, st, newflags)) {
+               if (index_path(istate, &ce->oid, path, st, newflags)) {
                        discard_cache_entry(ce);
-                       return error("unable to index file %s", path);
+                       return error(_("unable to index file '%s'"), path);
                }
        } else
                set_object_name_for_intent_to_add_entry(ce);
@@ -777,7 +783,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
                discard_cache_entry(ce);
        else if (add_index_entry(istate, ce, add_option)) {
                discard_cache_entry(ce);
-               return error("unable to add %s to index", path);
+               return error(_("unable to add '%s' to index"), path);
        }
        if (verbose && !was_same)
                printf("add '%s'\n", path);
@@ -788,7 +794,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int flags)
 {
        struct stat st;
        if (lstat(path, &st))
-               die_errno("unable to stat '%s'", path);
+               die_errno(_("unable to stat '%s'"), path);
        return add_to_index(istate, path, &st, flags);
 }
 
@@ -813,7 +819,7 @@ struct cache_entry *make_cache_entry(struct index_state *istate,
        int len;
 
        if (!verify_path(path, mode)) {
-               error("Invalid path '%s'", path);
+               error(_("invalid path '%s'"), path);
                return NULL;
        }
 
@@ -826,7 +832,7 @@ struct cache_entry *make_cache_entry(struct index_state *istate,
        ce->ce_namelen = len;
        ce->ce_mode = create_ce_mode(mode);
 
-       ret = refresh_cache_entry(&the_index, ce, refresh_options);
+       ret = refresh_cache_entry(istate, ce, refresh_options);
        if (ret != ce)
                discard_cache_entry(ce);
        return ret;
@@ -839,7 +845,7 @@ struct cache_entry *make_transient_cache_entry(unsigned int mode, const struct o
        int len;
 
        if (!verify_path(path, mode)) {
-               error("Invalid path '%s'", path);
+               error(_("invalid path '%s'"), path);
                return NULL;
        }
 
@@ -1292,12 +1298,12 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
        if (!ok_to_add)
                return -1;
        if (!verify_path(ce->name, ce->ce_mode))
-               return error("Invalid path '%s'", ce->name);
+               return error(_("invalid path '%s'"), ce->name);
 
        if (!skip_df_check &&
            check_file_directory_conflict(istate, ce, pos, ok_to_replace)) {
                if (!ok_to_replace)
-                       return error("'%s' appears as both a file and as a directory",
+                       return error(_("'%s' appears as both a file and as a directory"),
                                     ce->name);
                pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce));
                pos = -pos-1;
@@ -1479,13 +1485,24 @@ int refresh_index(struct index_state *istate, unsigned int flags,
        const char *typechange_fmt;
        const char *added_fmt;
        const char *unmerged_fmt;
+       struct progress *progress = NULL;
+
+       if (flags & REFRESH_PROGRESS && isatty(2))
+               progress = start_delayed_progress(_("Refresh index"),
+                                                 istate->cache_nr);
 
        trace_performance_enter();
-       modified_fmt = (in_porcelain ? "M\t%s\n" : "%s: needs update\n");
-       deleted_fmt = (in_porcelain ? "D\t%s\n" : "%s: needs update\n");
-       typechange_fmt = (in_porcelain ? "T\t%s\n" : "%s needs update\n");
-       added_fmt = (in_porcelain ? "A\t%s\n" : "%s needs update\n");
-       unmerged_fmt = (in_porcelain ? "U\t%s\n" : "%s: needs merge\n");
+       modified_fmt   = in_porcelain ? "M\t%s\n" : "%s: needs update\n";
+       deleted_fmt    = in_porcelain ? "D\t%s\n" : "%s: needs update\n";
+       typechange_fmt = in_porcelain ? "T\t%s\n" : "%s: needs update\n";
+       added_fmt      = in_porcelain ? "A\t%s\n" : "%s: needs update\n";
+       unmerged_fmt   = in_porcelain ? "U\t%s\n" : "%s: needs merge\n";
+       /*
+        * Use the multi-threaded preload_index() to refresh most of the
+        * cache entries quickly then in the single threaded loop below,
+        * we only have to do the special cases that are left.
+        */
+       preload_index(istate, pathspec, 0);
        for (i = 0; i < istate->cache_nr; i++) {
                struct cache_entry *ce, *new_entry;
                int cache_errno = 0;
@@ -1496,7 +1513,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
                if (ignore_submodules && S_ISGITLINK(ce->ce_mode))
                        continue;
 
-               if (pathspec && !ce_path_match(&the_index, ce, pathspec, seen))
+               if (pathspec && !ce_path_match(istate, ce, pathspec, seen))
                        filtered = 1;
 
                if (ce_stage(ce)) {
@@ -1519,6 +1536,8 @@ int refresh_index(struct index_state *istate, unsigned int flags,
                new_entry = refresh_cache_ent(istate, ce, options, &cache_errno, &changed);
                if (new_entry == ce)
                        continue;
+               if (progress)
+                       display_progress(progress, i);
                if (!new_entry) {
                        const char *fmt;
 
@@ -1550,6 +1569,10 @@ int refresh_index(struct index_state *istate, unsigned int flags,
 
                replace_index_entry(istate, i, new_entry);
        }
+       if (progress) {
+               display_progress(progress, istate->cache_nr);
+               stop_progress(&progress);
+       }
        trace_performance_leave("refresh index");
        return has_errors;
 }
@@ -1660,10 +1683,10 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)
        int hdr_version;
 
        if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
-               return error("bad signature");
+               return error(_("bad signature 0x%08x"), hdr->hdr_signature);
        hdr_version = ntohl(hdr->hdr_version);
        if (hdr_version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < hdr_version)
-               return error("bad index version %d", hdr_version);
+               return error(_("bad index version %d"), hdr_version);
 
        if (!verify_index_checksum)
                return 0;
@@ -1672,7 +1695,7 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)
        the_hash_algo->update_fn(&c, hdr, size - the_hash_algo->rawsz);
        the_hash_algo->final_fn(hash, &c);
        if (!hasheq(hash, (unsigned char *)hdr + size - the_hash_algo->rawsz))
-               return error("bad index file sha1 signature");
+               return error(_("bad index file sha1 signature"));
        return 0;
 }
 
@@ -1702,9 +1725,9 @@ static int read_index_extension(struct index_state *istate,
                break;
        default:
                if (*ext < 'A' || 'Z' < *ext)
-                       return error("index uses %.4s extension, which we do not understand",
+                       return error(_("index uses %.4s extension, which we do not understand"),
                                     ext);
-               fprintf(stderr, "ignoring %.4s extension\n", ext);
+               fprintf_ln(stderr, _("ignoring %.4s extension"), ext);
                break;
        }
        return 0;
@@ -1730,7 +1753,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
        size_t len;
        const char *name;
        unsigned int flags;
-       size_t copy_len;
+       size_t copy_len = 0;
        /*
         * Adjacent cache entries tend to share the leading paths, so it makes
         * sense to only store the differences in later entries.  In the v4
@@ -1751,7 +1774,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
                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);
+                       die(_("unknown index entry format 0x%08x"), extended_flags);
                flags |= extended_flags;
                name = ondisk2->name;
        }
@@ -1770,8 +1793,6 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
                                die(_("malformed name field in the index, near path '%s'"),
                                        previous_ce->name);
                        copy_len = previous_len - strip_len;
-               } else {
-                       copy_len = 0;
                }
                name = (const char *)cp;
        }
@@ -1824,13 +1845,13 @@ static void check_ce_order(struct index_state *istate)
                int name_compare = strcmp(ce->name, next_ce->name);
 
                if (0 < name_compare)
-                       die("unordered stage entries in index");
+                       die(_("unordered stage entries in index"));
                if (!name_compare) {
                        if (!ce_stage(ce))
-                               die("multiple stage entries for merged file '%s'",
+                               die(_("multiple stage entries for merged file '%s'"),
                                    ce->name);
                        if (ce_stage(ce) > ce_stage(next_ce))
-                               die("unordered stage entries for '%s'",
+                               die(_("unordered stage entries for '%s'"),
                                    ce->name);
                }
        }
@@ -1904,19 +1925,15 @@ struct index_entry_offset_table
        struct index_entry_offset entries[FLEX_ARRAY];
 };
 
-#ifndef NO_PTHREADS
 static struct index_entry_offset_table *read_ieot_extension(const char *mmap, size_t mmap_size, size_t offset);
 static void write_ieot_extension(struct strbuf *sb, struct index_entry_offset_table *ieot);
-#endif
 
 static size_t read_eoie_extension(const char *mmap, size_t mmap_size);
 static void write_eoie_extension(struct strbuf *sb, git_hash_ctx *eoie_context, size_t offset);
 
 struct load_index_extensions
 {
-#ifndef NO_PTHREADS
        pthread_t pthread;
-#endif
        struct index_state *istate;
        const char *mmap;
        size_t mmap_size;
@@ -1994,8 +2011,6 @@ static unsigned long load_all_cache_entries(struct index_state *istate,
        return consumed;
 }
 
-#ifndef NO_PTHREADS
-
 /*
  * Mostly randomly chosen maximum thread counts: we
  * cap the parallelism to online_cpus() threads, and we want
@@ -2106,7 +2121,6 @@ static unsigned long load_cache_entries_threaded(struct index_state *istate, con
 
        return consumed;
 }
-#endif
 
 /* remember to discard_cache() before reading a different cache! */
 int do_read_index(struct index_state *istate, const char *path, int must_exist)
@@ -2119,10 +2133,8 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
        size_t mmap_size;
        struct load_index_extensions p;
        size_t extension_offset = 0;
-#ifndef NO_PTHREADS
        int nr_threads, cpus;
        struct index_entry_offset_table *ieot = NULL;
-#endif
 
        if (istate->initialized)
                return istate->cache_nr;
@@ -2133,19 +2145,19 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
        if (fd < 0) {
                if (!must_exist && errno == ENOENT)
                        return 0;
-               die_errno("%s: index file open failed", path);
+               die_errno(_("%s: index file open failed"), path);
        }
 
        if (fstat(fd, &st))
-               die_errno("cannot stat the open index");
+               die_errno(_("%s: cannot stat the open index"), path);
 
        mmap_size = xsize_t(st.st_size);
        if (mmap_size < sizeof(struct cache_header) + the_hash_algo->rawsz)
-               die("index file smaller than expected");
+               die(_("%s: index file smaller than expected"), path);
 
        mmap = xmmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE, fd, 0);
        if (mmap == MAP_FAILED)
-               die_errno("unable to map index file");
+               die_errno(_("%s: unable to map index file"), path);
        close(fd);
 
        hdr = (const struct cache_header *)mmap;
@@ -2165,8 +2177,8 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
 
        src_offset = sizeof(*hdr);
 
-#ifndef NO_PTHREADS
-       nr_threads = git_config_get_index_threads();
+       if (git_config_get_index_threads(&nr_threads))
+               nr_threads = 1;
 
        /* TODO: does creating more threads than cores help? */
        if (!nr_threads) {
@@ -2176,6 +2188,9 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
                        nr_threads = cpus;
        }
 
+       if (!HAVE_THREADS)
+               nr_threads = 1;
+
        if (nr_threads > 1) {
                extension_offset = read_eoie_extension(mmap, mmap_size);
                if (extension_offset) {
@@ -2203,22 +2218,16 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
        } else {
                src_offset += load_all_cache_entries(istate, mmap, mmap_size, src_offset);
        }
-#else
-       src_offset += load_all_cache_entries(istate, mmap, mmap_size, src_offset);
-#endif
 
        istate->timestamp.sec = st.st_mtime;
        istate->timestamp.nsec = ST_MTIME_NSEC(st);
 
        /* if we created a thread, join it otherwise load the extensions on the primary thread */
-#ifndef NO_PTHREADS
        if (extension_offset) {
                int ret = pthread_join(p.pthread, NULL);
                if (ret)
                        die(_("unable to join load_index_extensions thread: %s"), strerror(ret));
-       }
-#endif
-       if (!extension_offset) {
+       } else {
                p.src_offset = src_offset;
                load_index_extensions(&p);
        }
@@ -2227,7 +2236,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
 
 unmap:
        munmap((void *)mmap, mmap_size);
-       die("index file corrupt");
+       die(_("index file corrupt"));
 }
 
 /*
@@ -2239,7 +2248,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
 static void freshen_shared_index(const char *shared_index, int warn)
 {
        if (!check_and_freshen_file(shared_index, 1) && warn)
-               warning("could not freshen shared index '%s'", shared_index);
+               warning(_("could not freshen shared index '%s'"), shared_index);
 }
 
 int read_index_from(struct index_state *istate, const char *path,
@@ -2274,15 +2283,15 @@ int read_index_from(struct index_state *istate, const char *path,
        base_path = xstrfmt("%s/sharedindex.%s", gitdir, base_oid_hex);
        ret = do_read_index(split_index->base, base_path, 1);
        if (!oideq(&split_index->base_oid, &split_index->base->oid))
-               die("broken index, expect %s in %s, got %s",
+               die(_("broken index, expect %s in %s, got %s"),
                    base_oid_hex, base_path,
                    oid_to_hex(&split_index->base->oid));
 
        freshen_shared_index(base_path, 0);
        merge_base_index(istate);
        post_read_index_from(istate);
-       free(base_path);
        trace_performance_leave("read cache %s", base_path);
+       free(base_path);
        return ret;
 }
 
@@ -2340,14 +2349,14 @@ void validate_cache_entries(const struct index_state *istate)
 
        for (i = 0; i < istate->cache_nr; i++) {
                if (!istate) {
-                       die("internal error: cache entry is not allocated from expected memory pool");
+                       BUG("cache entry is not allocated from expected memory pool");
                } else if (!istate->ce_mem_pool ||
                        !mem_pool_contains(istate->ce_mem_pool, istate->cache[i])) {
                        if (!istate->split_index ||
                                !istate->split_index->base ||
                                !istate->split_index->base->ce_mem_pool ||
                                !mem_pool_contains(istate->split_index->base->ce_mem_pool, istate->cache[i])) {
-                               die("internal error: cache entry is not allocated from expected memory pool");
+                               BUG("cache entry is not allocated from expected memory pool");
                        }
                }
        }
@@ -2366,7 +2375,7 @@ int unmerged_index(const struct index_state *istate)
        return 0;
 }
 
-int index_has_changes(const struct index_state *istate,
+int index_has_changes(struct index_state *istate,
                      struct tree *tree,
                      struct strbuf *sb)
 {
@@ -2381,7 +2390,7 @@ int index_has_changes(const struct index_state *istate,
        if (tree || !get_oid_tree("HEAD", &cmp)) {
                struct diff_options opt;
 
-               diff_setup(&opt);
+               repo_diff_setup(the_repository, &opt);
                opt.flags.exit_with_status = 1;
                if (!sb)
                        opt.flags.quick = 1;
@@ -2478,7 +2487,8 @@ static int ce_flush(git_hash_ctx *context, int fd, unsigned char *hash)
        return (write_in_full(fd, write_buffer, left) < 0) ? -1 : 0;
 }
 
-static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
+static void ce_smudge_racily_clean_entry(struct index_state *istate,
+                                        struct cache_entry *ce)
 {
        /*
         * The only thing we care about in this function is to smudge the
@@ -2497,7 +2507,7 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
                return;
        if (ce_match_stat_basic(ce, &st))
                return;
-       if (ce_modified_check_fs(ce, &st)) {
+       if (ce_modified_check_fs(istate, ce, &st)) {
                /* This is "racily clean"; smudge it.  Note that this
                 * is a tricky code.  At first glance, it may appear
                 * that it can break with this sequence:
@@ -2681,6 +2691,36 @@ void update_index_if_able(struct index_state *istate, struct lock_file *lockfile
                rollback_lock_file(lockfile);
 }
 
+static int record_eoie(void)
+{
+       int val;
+
+       if (!git_config_get_bool("index.recordendofindexentries", &val))
+               return val;
+
+       /*
+        * As a convenience, the end of index entries extension
+        * used for threading is written by default if the user
+        * explicitly requested threaded index reads.
+        */
+       return !git_config_get_index_threads(&val) && val != 1;
+}
+
+static int record_ieot(void)
+{
+       int val;
+
+       if (!git_config_get_bool("index.recordoffsettable", &val))
+               return val;
+
+       /*
+        * As a convenience, the offset table used for threading is
+        * written by default if the user explicitly requested
+        * threaded index reads.
+        */
+       return !git_config_get_index_threads(&val) && val != 1;
+}
+
 /*
  * On success, `tempfile` is closed. If it is the temporary file
  * of a `struct lock_file`, we will therefore effectively perform
@@ -2739,9 +2779,10 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
        if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
                return -1;
 
-#ifndef NO_PTHREADS
-       nr_threads = git_config_get_index_threads();
-       if (nr_threads != 1) {
+       if (!HAVE_THREADS || git_config_get_index_threads(&nr_threads))
+               nr_threads = 1;
+
+       if (nr_threads != 1 && record_ieot()) {
                int ieot_blocks, cpus;
 
                /*
@@ -2770,7 +2811,6 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
                        ieot_entries = DIV_ROUND_UP(entries, ieot_blocks);
                }
        }
-#endif
 
        offset = lseek(newfd, 0, SEEK_CUR);
        if (offset < 0) {
@@ -2786,7 +2826,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
                if (ce->ce_flags & CE_REMOVE)
                        continue;
                if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
-                       ce_smudge_racily_clean_entry(ce);
+                       ce_smudge_racily_clean_entry(istate, ce);
                if (is_null_oid(&ce->oid)) {
                        static const char msg[] = "cache entry has null sha1: %s";
                        static int allow = -1;
@@ -2854,7 +2894,6 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
         * strip_extensions parameter as we need it when loading the shared
         * index.
         */
-#ifndef NO_PTHREADS
        if (ieot) {
                struct strbuf sb = STRBUF_INIT;
 
@@ -2866,7 +2905,6 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
                if (err)
                        return -1;
        }
-#endif
 
        if (!strip_extensions && istate->split_index) {
                struct strbuf sb = STRBUF_INIT;
@@ -2928,7 +2966,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
         * read.  Write it out regardless of the strip_extensions parameter as we need it
         * when loading the shared index.
         */
-       if (offset) {
+       if (offset && record_eoie()) {
                struct strbuf sb = STRBUF_INIT;
 
                write_eoie_extension(&sb, &eoie_c, offset);
@@ -3059,7 +3097,7 @@ static int write_shared_index(struct index_state *istate,
                return ret;
        ret = adjust_shared_perm(get_tempfile_path(*temp));
        if (ret) {
-               error("cannot fix permission bits on %s", get_tempfile_path(*temp));
+               error(_("cannot fix permission bits on '%s'"), get_tempfile_path(*temp));
                return ret;
        }
        ret = rename_tempfile(temp,
@@ -3109,7 +3147,7 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
        struct split_index *si = istate->split_index;
 
        if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0))
-               cache_tree_verify(istate);
+               cache_tree_verify(the_repository, istate);
 
        if ((flags & SKIP_IF_UNCHANGED) && !istate->cache_changed) {
                if (flags & COMMIT_LOCK)
@@ -3142,7 +3180,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
                struct tempfile *temp;
                int saved_errno;
 
-               temp = mks_tempfile(git_path("sharedindex_XXXXXX"));
+               /* Same initial permissions as the main .git/index file */
+               temp = mks_tempfile_sm(git_path("sharedindex_XXXXXX"), 0, 0666);
                if (!temp) {
                        oidclr(&si->base_oid);
                        ret = do_write_locked_index(istate, lock, flags);
@@ -3205,7 +3244,7 @@ int read_index_unmerged(struct index_state *istate)
                new_ce->ce_namelen = len;
                new_ce->ce_mode = ce->ce_mode;
                if (add_index_entry(istate, new_ce, ADD_CACHE_SKIP_DFCHECK))
-                       return error("%s: cannot drop to stage #0",
+                       return error(_("%s: cannot drop to stage #0"),
                                     new_ce->name);
        }
        return unmerged;
@@ -3452,77 +3491,75 @@ static void write_eoie_extension(struct strbuf *sb, git_hash_ctx *eoie_context,
        strbuf_add(sb, hash, the_hash_algo->rawsz);
 }
 
-#ifndef NO_PTHREADS
 #define IEOT_VERSION   (1)
 
 static struct index_entry_offset_table *read_ieot_extension(const char *mmap, size_t mmap_size, size_t offset)
 {
-       const char *index = NULL;
-       uint32_t extsize, ext_version;
-       struct index_entry_offset_table *ieot;
-       int i, nr;
-
-       /* find the IEOT extension */
-       if (!offset)
-              return NULL;
-       while (offset <= mmap_size - the_hash_algo->rawsz - 8) {
-              extsize = get_be32(mmap + offset + 4);
-              if (CACHE_EXT((mmap + offset)) == CACHE_EXT_INDEXENTRYOFFSETTABLE) {
-                      index = mmap + offset + 4 + 4;
-                      break;
-              }
-              offset += 8;
-              offset += extsize;
-       }
-       if (!index)
-              return NULL;
-
-       /* validate the version is IEOT_VERSION */
-       ext_version = get_be32(index);
-       if (ext_version != IEOT_VERSION) {
-              error("invalid IEOT version %d", ext_version);
-              return NULL;
-       }
-       index += sizeof(uint32_t);
-
-       /* extension size - version bytes / bytes per entry */
-       nr = (extsize - sizeof(uint32_t)) / (sizeof(uint32_t) + sizeof(uint32_t));
-       if (!nr) {
-              error("invalid number of IEOT entries %d", nr);
-              return NULL;
-       }
-       ieot = xmalloc(sizeof(struct index_entry_offset_table)
-              + (nr * sizeof(struct index_entry_offset)));
-       ieot->nr = nr;
-       for (i = 0; i < nr; i++) {
-              ieot->entries[i].offset = get_be32(index);
-              index += sizeof(uint32_t);
-              ieot->entries[i].nr = get_be32(index);
-              index += sizeof(uint32_t);
-       }
-
-       return ieot;
+       const char *index = NULL;
+       uint32_t extsize, ext_version;
+       struct index_entry_offset_table *ieot;
+       int i, nr;
+
+       /* find the IEOT extension */
+       if (!offset)
+               return NULL;
+       while (offset <= mmap_size - the_hash_algo->rawsz - 8) {
+               extsize = get_be32(mmap + offset + 4);
+               if (CACHE_EXT((mmap + offset)) == CACHE_EXT_INDEXENTRYOFFSETTABLE) {
+                       index = mmap + offset + 4 + 4;
+                       break;
+               }
+               offset += 8;
+               offset += extsize;
+       }
+       if (!index)
+               return NULL;
+
+       /* validate the version is IEOT_VERSION */
+       ext_version = get_be32(index);
+       if (ext_version != IEOT_VERSION) {
+               error("invalid IEOT version %d", ext_version);
+               return NULL;
+       }
+       index += sizeof(uint32_t);
+
+       /* extension size - version bytes / bytes per entry */
+       nr = (extsize - sizeof(uint32_t)) / (sizeof(uint32_t) + sizeof(uint32_t));
+       if (!nr) {
+               error("invalid number of IEOT entries %d", nr);
+               return NULL;
+       }
+       ieot = xmalloc(sizeof(struct index_entry_offset_table)
+                      + (nr * sizeof(struct index_entry_offset)));
+       ieot->nr = nr;
+       for (i = 0; i < nr; i++) {
+               ieot->entries[i].offset = get_be32(index);
+               index += sizeof(uint32_t);
+               ieot->entries[i].nr = get_be32(index);
+               index += sizeof(uint32_t);
+       }
+
+       return ieot;
 }
 
 static void write_ieot_extension(struct strbuf *sb, struct index_entry_offset_table *ieot)
 {
-       uint32_t buffer;
-       int i;
+       uint32_t buffer;
+       int i;
 
-       /* version */
-       put_be32(&buffer, IEOT_VERSION);
-       strbuf_add(sb, &buffer, sizeof(uint32_t));
+       /* version */
+       put_be32(&buffer, IEOT_VERSION);
+       strbuf_add(sb, &buffer, sizeof(uint32_t));
 
-       /* ieot */
-       for (i = 0; i < ieot->nr; i++) {
+       /* ieot */
+       for (i = 0; i < ieot->nr; i++) {
 
-              /* offset */
-              put_be32(&buffer, ieot->entries[i].offset);
-              strbuf_add(sb, &buffer, sizeof(uint32_t));
+               /* offset */
+               put_be32(&buffer, ieot->entries[i].offset);
+               strbuf_add(sb, &buffer, sizeof(uint32_t));
 
-              /* count */
-              put_be32(&buffer, ieot->entries[i].nr);
-              strbuf_add(sb, &buffer, sizeof(uint32_t));
-       }
+               /* count */
+               put_be32(&buffer, ieot->entries[i].nr);
+               strbuf_add(sb, &buffer, sizeof(uint32_t));
+       }
 }
-#endif