handle alternates paths the same as the main object dir
[gitweb.git] / sha1-file.c
index 695e5c62764cf4befe09467f1a658b25c01baba1..15db6b61a9aa07dfb5dc3ec5554b4c1c4b56d0c2 100644 (file)
@@ -71,17 +71,17 @@ static void git_hash_sha1_final(unsigned char *hash, git_hash_ctx *ctx)
 
 static void git_hash_unknown_init(git_hash_ctx *ctx)
 {
-       die("trying to init unknown hash");
+       BUG("trying to init unknown hash");
 }
 
 static void git_hash_unknown_update(git_hash_ctx *ctx, const void *data, size_t len)
 {
-       die("trying to update unknown hash");
+       BUG("trying to update unknown hash");
 }
 
 static void git_hash_unknown_final(unsigned char *hash, git_hash_ctx *ctx)
 {
-       die("trying to finalize unknown hash");
+       BUG("trying to finalize unknown hash");
 }
 
 const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
@@ -149,10 +149,10 @@ static struct cached_object *find_cached_object(const struct object_id *oid)
        struct cached_object *co = cached_objects;
 
        for (i = 0; i < cached_object_nr; i++, co++) {
-               if (!oidcmp(&co->oid, oid))
+               if (oideq(&co->oid, oid))
                        return co;
        }
-       if (!oidcmp(oid, the_hash_algo->empty_tree))
+       if (oideq(oid, the_hash_algo->empty_tree))
                return &empty_tree;
        return NULL;
 }
@@ -336,7 +336,7 @@ int raceproof_create_file(const char *path, create_file_fn fn, void *cb)
 static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1)
 {
        int i;
-       for (i = 0; i < 20; i++) {
+       for (i = 0; i < the_hash_algo->rawsz; i++) {
                static char hex[] = "0123456789abcdef";
                unsigned int val = sha1[i];
                strbuf_addch(buf, hex[val >> 4]);
@@ -346,25 +346,20 @@ static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1)
        }
 }
 
-void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned char *sha1)
+static const char *odb_loose_path(const char *path, struct strbuf *buf,
+                                 const unsigned char *sha1)
 {
-       strbuf_addstr(buf, r->objects->objectdir);
+       strbuf_reset(buf);
+       strbuf_addstr(buf, path);
        strbuf_addch(buf, '/');
        fill_sha1_path(buf, sha1);
+       return buf->buf;
 }
 
-struct strbuf *alt_scratch_buf(struct alternate_object_database *alt)
+const char *loose_object_path(struct repository *r, struct strbuf *buf,
+                             const unsigned char *sha1)
 {
-       strbuf_setlen(&alt->scratch, alt->base_len);
-       return &alt->scratch;
-}
-
-static const char *alt_sha1_path(struct alternate_object_database *alt,
-                                const unsigned char *sha1)
-{
-       struct strbuf *buf = alt_scratch_buf(alt);
-       fill_sha1_path(buf, sha1);
-       return buf->buf;
+       return odb_loose_path(r->objects->objectdir, buf, sha1);
 }
 
 /*
@@ -374,12 +369,12 @@ static int alt_odb_usable(struct raw_object_store *o,
                          struct strbuf *path,
                          const char *normalized_objdir)
 {
-       struct alternate_object_database *alt;
+       struct object_directory *odb;
 
        /* Detect cases where alternate disappeared */
        if (!is_directory(path->buf)) {
-               error("object directory %s does not exist; "
-                     "check .git/objects/info/alternates.",
+               error(_("object directory %s does not exist; "
+                       "check .git/objects/info/alternates"),
                      path->buf);
                return 0;
        }
@@ -388,8 +383,8 @@ static int alt_odb_usable(struct raw_object_store *o,
         * Prevent the common mistake of listing the same
         * thing twice, or object directory itself.
         */
-       for (alt = o->alt_odb_list; alt; alt = alt->next) {
-               if (!fspathcmp(path->buf, alt->path))
+       for (odb = o->alt_odb_list; odb; odb = odb->next) {
+               if (!fspathcmp(path->buf, odb->path))
                        return 0;
        }
        if (!fspathcmp(path->buf, normalized_objdir))
@@ -402,7 +397,7 @@ static int alt_odb_usable(struct raw_object_store *o,
  * Prepare alternate object database registry.
  *
  * The variable alt_odb_list points at the list of struct
- * alternate_object_database.  The elements on this list come from
+ * object_directory.  The elements on this list come from
  * non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT
  * environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates,
  * whose contents is similar to that environment variable but can be
@@ -419,7 +414,7 @@ static void read_info_alternates(struct repository *r,
 static int link_alt_odb_entry(struct repository *r, const char *entry,
        const char *relative_base, int depth, const char *normalized_objdir)
 {
-       struct alternate_object_database *ent;
+       struct object_directory *ent;
        struct strbuf pathbuf = STRBUF_INIT;
 
        if (!is_absolute_path(entry) && relative_base) {
@@ -429,7 +424,7 @@ static int link_alt_odb_entry(struct repository *r, const char *entry,
        strbuf_addstr(&pathbuf, entry);
 
        if (strbuf_normalize_path(&pathbuf) < 0 && relative_base) {
-               error("unable to normalize alternate object path: %s",
+               error(_("unable to normalize alternate object path: %s"),
                      pathbuf.buf);
                strbuf_release(&pathbuf);
                return -1;
@@ -500,14 +495,14 @@ static void link_alt_odb_entries(struct repository *r, const char *alt,
                return;
 
        if (depth > 5) {
-               error("%s: ignoring alternate object stores, nesting too deep.",
+               error(_("%s: ignoring alternate object stores, nesting too deep"),
                                relative_base);
                return;
        }
 
        strbuf_add_absolute_path(&objdirbuf, r->objects->objectdir);
        if (strbuf_normalize_path(&objdirbuf) < 0)
-               die("unable to normalize object directory: %s",
+               die(_("unable to normalize object directory: %s"),
                    objdirbuf.buf);
 
        while (*alt) {
@@ -540,14 +535,11 @@ static void read_info_alternates(struct repository *r,
        free(path);
 }
 
-struct alternate_object_database *alloc_alt_odb(const char *dir)
+struct object_directory *alloc_alt_odb(const char *dir)
 {
-       struct alternate_object_database *ent;
+       struct object_directory *ent;
 
        FLEX_ALLOC_STR(ent, path, dir);
-       strbuf_init(&ent->scratch, 0);
-       strbuf_addf(&ent->scratch, "%s/", dir);
-       ent->base_len = ent->scratch.len;
 
        return ent;
 }
@@ -562,7 +554,7 @@ void add_to_alternates_file(const char *reference)
        hold_lock_file_for_update(&lock, alts, LOCK_DIE_ON_ERROR);
        out = fdopen_lock_file(&lock, "w");
        if (!out)
-               die_errno("unable to fdopen alternates lockfile");
+               die_errno(_("unable to fdopen alternates lockfile"));
 
        in = fopen(alts, "r");
        if (in) {
@@ -580,14 +572,14 @@ void add_to_alternates_file(const char *reference)
                fclose(in);
        }
        else if (errno != ENOENT)
-               die_errno("unable to read alternates file");
+               die_errno(_("unable to read alternates file"));
 
        if (found) {
                rollback_lock_file(&lock);
        } else {
                fprintf_or_die(out, "%s\n", reference);
                if (commit_lock_file(&lock))
-                       die_errno("unable to move new alternates file into place");
+                       die_errno(_("unable to move new alternates file into place"));
                if (the_repository->objects->alt_odb_tail)
                        link_alt_odb_entries(the_repository, reference,
                                             '\n', NULL, 0);
@@ -684,7 +676,7 @@ char *compute_alternate_path(const char *path, struct strbuf *err)
 
 int foreach_alt_odb(alt_odb_fn fn, void *cb)
 {
-       struct alternate_object_database *ent;
+       struct object_directory *ent;
        int r = 0;
 
        prepare_alt_odb(the_repository);
@@ -735,19 +727,20 @@ static int check_and_freshen_local(const struct object_id *oid, int freshen)
 {
        static struct strbuf buf = STRBUF_INIT;
 
-       strbuf_reset(&buf);
-       sha1_file_name(the_repository, &buf, oid->hash);
+       loose_object_path(the_repository, &buf, oid->hash);
 
        return check_and_freshen_file(buf.buf, freshen);
 }
 
 static int check_and_freshen_nonlocal(const struct object_id *oid, int freshen)
 {
-       struct alternate_object_database *alt;
+       struct object_directory *odb;
+       static struct strbuf path = STRBUF_INIT;
+
        prepare_alt_odb(the_repository);
-       for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) {
-               const char *path = alt_sha1_path(alt, oid->hash);
-               if (check_and_freshen_file(path, freshen))
+       for (odb = the_repository->objects->alt_odb_list; odb; odb = odb->next) {
+               odb_loose_path(odb->path, &path, oid->hash);
+               if (check_and_freshen_file(path.buf, freshen))
                        return 1;
        }
        return 0;
@@ -778,7 +771,7 @@ static void mmap_limit_check(size_t length)
                        limit = SIZE_MAX;
        }
        if (length > limit)
-               die("attempting to mmap %"PRIuMAX" over limit %"PRIuMAX,
+               die(_("attempting to mmap %"PRIuMAX" over limit %"PRIuMAX),
                    (uintmax_t)length, (uintmax_t)limit);
 }
 
@@ -803,7 +796,7 @@ void *xmmap(void *start, size_t length,
 {
        void *ret = xmmap_gently(start, length, prot, flags, fd, offset);
        if (ret == MAP_FAILED)
-               die_errno("mmap failed");
+               die_errno(_("mmap failed"));
        return ret;
 }
 
@@ -825,7 +818,7 @@ int check_object_signature(const struct object_id *oid, void *map,
 
        if (map) {
                hash_object_file(map, size, type, &real_oid);
-               return oidcmp(oid, &real_oid) ? -1 : 0;
+               return !oideq(oid, &real_oid) ? -1 : 0;
        }
 
        st = open_istream(oid, &obj_type, &size, NULL);
@@ -852,7 +845,7 @@ int check_object_signature(const struct object_id *oid, void *map,
        }
        the_hash_algo->final_fn(real_oid.hash, &c);
        close_istream(st);
-       return oidcmp(oid, &real_oid) ? -1 : 0;
+       return !oideq(oid, &real_oid) ? -1 : 0;
 }
 
 int git_open_cloexec(const char *name, int flags)
@@ -888,25 +881,22 @@ int git_open_cloexec(const char *name, int flags)
  *
  * 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 sha1_file_name(), etc.
+ * call to stat_sha1_file().
  */
 static int stat_sha1_file(struct repository *r, const unsigned char *sha1,
                          struct stat *st, const char **path)
 {
-       struct alternate_object_database *alt;
+       struct object_directory *odb;
        static struct strbuf buf = STRBUF_INIT;
 
-       strbuf_reset(&buf);
-       sha1_file_name(r, &buf, sha1);
-       *path = buf.buf;
-
+       *path = loose_object_path(r, &buf, sha1);
        if (!lstat(*path, st))
                return 0;
 
        prepare_alt_odb(r);
        errno = ENOENT;
-       for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
-               *path = alt_sha1_path(alt, sha1);
+       for (odb = r->objects->alt_odb_list; odb; odb = odb->next) {
+               *path = odb_loose_path(odb->path, &buf, sha1);
                if (!lstat(*path, st))
                        return 0;
        }
@@ -922,22 +912,19 @@ static int open_sha1_file(struct repository *r,
                          const unsigned char *sha1, const char **path)
 {
        int fd;
-       struct alternate_object_database *alt;
+       struct object_directory *odb;
        int most_interesting_errno;
        static struct strbuf buf = STRBUF_INIT;
 
-       strbuf_reset(&buf);
-       sha1_file_name(r, &buf, sha1);
-       *path = buf.buf;
-
+       *path = loose_object_path(r, &buf, sha1);
        fd = git_open(*path);
        if (fd >= 0)
                return fd;
        most_interesting_errno = errno;
 
        prepare_alt_odb(r);
-       for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
-               *path = alt_sha1_path(alt, sha1);
+       for (odb = r->objects->alt_odb_list; odb; odb = odb->next) {
+               *path = odb_loose_path(odb->path, &buf, sha1);
                fd = git_open(*path);
                if (fd >= 0)
                        return fd;
@@ -970,7 +957,7 @@ static void *map_sha1_file_1(struct repository *r, const char *path,
                        *size = xsize_t(st.st_size);
                        if (!*size) {
                                /* mmap() is forbidden on empty files */
-                               error("object file %s is empty", path);
+                               error(_("object file %s is empty"), path);
                                return NULL;
                        }
                        map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
@@ -1090,9 +1077,9 @@ static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long s
        }
 
        if (status < 0)
-               error("corrupt loose object '%s'", sha1_to_hex(sha1));
+               error(_("corrupt loose object '%s'"), sha1_to_hex(sha1));
        else if (stream->avail_in)
-               error("garbage at end of loose object '%s'",
+               error(_("garbage at end of loose object '%s'"),
                      sha1_to_hex(sha1));
        free(buf);
        return NULL;
@@ -1134,7 +1121,7 @@ static int parse_sha1_header_extended(const char *hdr, struct object_info *oi,
        if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE) && (type < 0))
                type = 0;
        else if (type < 0)
-               die("invalid object type");
+               die(_("invalid object type"));
        if (oi->typep)
                *oi->typep = type;
 
@@ -1216,19 +1203,19 @@ static int sha1_loose_object_info(struct repository *r,
                *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)
-                       status = error("unable to unpack %s header with --allow-unknown-type",
+                       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)
-               status = error("unable to unpack %s header",
+               status = error(_("unable to unpack %s header"),
                               sha1_to_hex(sha1));
        if (status < 0)
                ; /* Do nothing */
        else if (hdrbuf.len) {
                if ((status = parse_sha1_header_extended(hdrbuf.buf, oi, flags)) < 0)
-                       status = error("unable to parse %s header with --allow-unknown-type",
+                       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));
+               status = error(_("unable to parse %s header"), sha1_to_hex(sha1));
 
        if (status >= 0 && oi->contentp) {
                *oi->contentp = unpack_sha1_rest(&stream, hdr,
@@ -1317,7 +1304,7 @@ int oid_object_info_extended(struct repository *r, const struct object_id *oid,
                         * TODO Pass a repository struct through fetch_object,
                         * such that arbitrary repositories work.
                         */
-                       fetch_object(repository_format_partial_clone, real->hash);
+                       fetch_objects(repository_format_partial_clone, real, 1);
                        already_retried = 1;
                        continue;
                }
@@ -1419,19 +1406,19 @@ void *read_object_file_extended(const struct object_id *oid,
                return data;
 
        if (errno && errno != ENOENT)
-               die_errno("failed to read object %s", oid_to_hex(oid));
+               die_errno(_("failed to read object %s"), oid_to_hex(oid));
 
        /* die if we replaced an object with one that does not exist */
        if (repl != oid)
-               die("replacement %s not found for %s",
+               die(_("replacement %s not found for %s"),
                    oid_to_hex(repl), oid_to_hex(oid));
 
        if (!stat_sha1_file(the_repository, repl->hash, &st, &path))
-               die("loose object %s (stored in %s) is corrupt",
+               die(_("loose object %s (stored in %s) is corrupt"),
                    oid_to_hex(repl), path);
 
        if ((p = has_packed_and_bad(repl->hash)) != NULL)
-               die("packed object %s (stored in %s) is corrupt",
+               die(_("packed object %s (stored in %s) is corrupt"),
                    oid_to_hex(repl), p->pack_name);
 
        return NULL;
@@ -1473,7 +1460,7 @@ void *read_object_with_reference(const struct object_id *oid,
                }
                ref_length = strlen(ref_type);
 
-               if (ref_length + GIT_SHA1_HEXSZ > isize ||
+               if (ref_length + the_hash_algo->hexsz > isize ||
                    memcmp(buffer, ref_type, ref_length) ||
                    get_oid_hex((char *) buffer + ref_length, &actual_oid)) {
                        free(buffer);
@@ -1533,21 +1520,21 @@ int finalize_object_file(const char *tmpfile, const char *filename)
        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 sha1 filename %s"), filename);
                }
                /* FIXME!!! Collision check here ? */
        }
 
 out:
        if (adjust_shared_perm(filename))
-               return error("unable to set permission to '%s'", filename);
+               return error(_("unable to set permission to '%s'"), filename);
        return 0;
 }
 
 static int write_buffer(int fd, const void *buf, size_t len)
 {
        if (write_in_full(fd, buf, len) < 0)
-               return error_errno("file write error");
+               return error_errno(_("file write error"));
        return 0;
 }
 
@@ -1566,7 +1553,7 @@ static void close_sha1_file(int fd)
        if (fsync_object_files)
                fsync_or_die(fd, "sha1 file");
        if (close(fd) != 0)
-               die_errno("error when closing sha1 file");
+               die_errno(_("error when closing sha1 file"));
 }
 
 /* Size of directory component, including the ending '/' */
@@ -1626,15 +1613,14 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
        static struct strbuf tmp_file = STRBUF_INIT;
        static struct strbuf filename = STRBUF_INIT;
 
-       strbuf_reset(&filename);
-       sha1_file_name(the_repository, &filename, oid->hash);
+       loose_object_path(the_repository, &filename, oid->hash);
 
        fd = create_tmpfile(&tmp_file, filename.buf);
        if (fd < 0) {
                if (errno == EACCES)
-                       return error("insufficient permission for adding an object to repository database %s", get_object_directory());
+                       return error(_("insufficient permission for adding an object to repository database %s"), get_object_directory());
                else
-                       return error_errno("unable to create temporary file");
+                       return error_errno(_("unable to create temporary file"));
        }
 
        /* Set it up */
@@ -1658,21 +1644,21 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
                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 sha1 file"));
                stream.next_out = compressed;
                stream.avail_out = sizeof(compressed);
        } while (ret == Z_OK);
 
        if (ret != Z_STREAM_END)
-               die("unable to deflate new object %s (%d)", oid_to_hex(oid),
+               die(_("unable to deflate new object %s (%d)"), oid_to_hex(oid),
                    ret);
        ret = git_deflate_end_gently(&stream);
        if (ret != Z_OK)
-               die("deflateEnd on object %s failed (%d)", oid_to_hex(oid),
+               die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid),
                    ret);
        the_hash_algo->final_fn(parano_oid.hash, &c);
-       if (oidcmp(oid, &parano_oid) != 0)
-               die("confused by unstable object source data for %s",
+       if (!oideq(oid, &parano_oid))
+               die(_("confused by unstable object source data for %s"),
                    oid_to_hex(oid));
 
        close_sha1_file(fd);
@@ -1682,7 +1668,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
                utb.actime = mtime;
                utb.modtime = mtime;
                if (utime(tmp_file.buf, &utb) < 0)
-                       warning_errno("failed utime() on %s", tmp_file.buf);
+                       warning_errno(_("failed utime() on %s"), tmp_file.buf);
        }
 
        return finalize_object_file(tmp_file.buf, filename.buf);
@@ -1757,7 +1743,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
                return 0;
        buf = read_object(oid->hash, &type, &len);
        if (!buf)
-               return error("cannot read sha1_file for %s", oid_to_hex(oid));
+               return error(_("cannot read sha1_file for %s"), oid_to_hex(oid));
        hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", type_name(type), len) + 1;
        ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime);
        free(buf);
@@ -1801,19 +1787,20 @@ static void check_commit(const void *buf, size_t size)
 {
        struct commit c;
        memset(&c, 0, sizeof(c));
-       if (parse_commit_buffer(&c, buf, size))
-               die("corrupt commit");
+       if (parse_commit_buffer(the_repository, &c, buf, size, 0))
+               die(_("corrupt commit"));
 }
 
 static void check_tag(const void *buf, size_t size)
 {
        struct tag t;
        memset(&t, 0, sizeof(t));
-       if (parse_tag_buffer(&t, buf, size))
-               die("corrupt tag");
+       if (parse_tag_buffer(the_repository, &t, buf, size))
+               die(_("corrupt tag"));
 }
 
-static int index_mem(struct object_id *oid, void *buf, size_t size,
+static int index_mem(struct index_state *istate,
+                    struct object_id *oid, void *buf, size_t size,
                     enum object_type type,
                     const char *path, unsigned flags)
 {
@@ -1828,7 +1815,7 @@ static int index_mem(struct object_id *oid, void *buf, size_t size,
         */
        if ((type == OBJ_BLOB) && path) {
                struct strbuf nbuf = STRBUF_INIT;
-               if (convert_to_git(&the_index, path, buf, size, &nbuf,
+               if (convert_to_git(istate, path, buf, size, &nbuf,
                                   get_conv_flags(flags))) {
                        buf = strbuf_detach(&nbuf, &size);
                        re_allocated = 1;
@@ -1852,17 +1839,20 @@ static int index_mem(struct object_id *oid, void *buf, size_t size,
        return ret;
 }
 
-static int index_stream_convert_blob(struct object_id *oid, int fd,
-                                    const char *path, unsigned flags)
+static int index_stream_convert_blob(struct index_state *istate,
+                                    struct object_id *oid,
+                                    int fd,
+                                    const char *path,
+                                    unsigned flags)
 {
        int ret;
        const int write_object = flags & HASH_WRITE_OBJECT;
        struct strbuf sbuf = STRBUF_INIT;
 
        assert(path);
-       assert(would_convert_to_git_filter_fd(path));
+       assert(would_convert_to_git_filter_fd(istate, path));
 
-       convert_to_git_filter_fd(&the_index, path, fd, &sbuf,
+       convert_to_git_filter_fd(istate, path, fd, &sbuf,
                                 get_conv_flags(flags));
 
        if (write_object)
@@ -1875,14 +1865,15 @@ static int index_stream_convert_blob(struct object_id *oid, int fd,
        return ret;
 }
 
-static int index_pipe(struct object_id *oid, int fd, enum object_type type,
+static int index_pipe(struct index_state *istate, struct object_id *oid,
+                     int fd, enum object_type type,
                      const char *path, unsigned flags)
 {
        struct strbuf sbuf = STRBUF_INIT;
        int ret;
 
        if (strbuf_read(&sbuf, fd, 4096) >= 0)
-               ret = index_mem(oid, sbuf.buf, sbuf.len, type, path, flags);
+               ret = index_mem(istate, oid, sbuf.buf, sbuf.len, type, path, flags);
        else
                ret = -1;
        strbuf_release(&sbuf);
@@ -1891,29 +1882,30 @@ static int index_pipe(struct object_id *oid, int fd, enum object_type type,
 
 #define SMALL_FILE_SIZE (32*1024)
 
-static int index_core(struct object_id *oid, int fd, size_t size,
+static int index_core(struct index_state *istate,
+                     struct object_id *oid, int fd, size_t size,
                      enum object_type type, const char *path,
                      unsigned flags)
 {
        int ret;
 
        if (!size) {
-               ret = index_mem(oid, "", size, type, path, flags);
+               ret = index_mem(istate, oid, "", size, type, path, flags);
        } else if (size <= SMALL_FILE_SIZE) {
                char *buf = xmalloc(size);
                ssize_t read_result = read_in_full(fd, buf, size);
                if (read_result < 0)
-                       ret = error_errno("read error while indexing %s",
+                       ret = error_errno(_("read error while indexing %s"),
                                          path ? path : "<unknown>");
                else if (read_result != size)
-                       ret = error("short read while indexing %s",
+                       ret = error(_("short read while indexing %s"),
                                    path ? path : "<unknown>");
                else
-                       ret = index_mem(oid, buf, size, type, path, flags);
+                       ret = index_mem(istate, oid, buf, size, type, path, flags);
                free(buf);
        } else {
                void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
-               ret = index_mem(oid, buf, size, type, path, flags);
+               ret = index_mem(istate, oid, buf, size, type, path, flags);
                munmap(buf, size);
        }
        return ret;
@@ -1941,7 +1933,8 @@ static int index_stream(struct object_id *oid, int fd, size_t size,
        return index_bulk_checkin(oid, fd, size, type, path, flags);
 }
 
-int index_fd(struct object_id *oid, int fd, struct stat *st,
+int index_fd(struct index_state *istate, struct object_id *oid,
+            int fd, struct stat *st,
             enum object_type type, const char *path, unsigned flags)
 {
        int ret;
@@ -1950,14 +1943,14 @@ int index_fd(struct object_id *oid, int fd, struct stat *st,
         * Call xsize_t() only when needed to avoid potentially unnecessary
         * die() for large files.
         */
-       if (type == OBJ_BLOB && path && would_convert_to_git_filter_fd(path))
-               ret = index_stream_convert_blob(oid, fd, path, flags);
+       if (type == OBJ_BLOB && path && would_convert_to_git_filter_fd(istate, path))
+               ret = index_stream_convert_blob(istate, oid, fd, path, flags);
        else if (!S_ISREG(st->st_mode))
-               ret = index_pipe(oid, fd, type, path, flags);
+               ret = index_pipe(istate, oid, fd, type, path, flags);
        else if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||
-                (path && would_convert_to_git(&the_index, path)))
-               ret = index_core(oid, fd, xsize_t(st->st_size), type, path,
-                                flags);
+                (path && would_convert_to_git(istate, path)))
+               ret = index_core(istate, oid, fd, xsize_t(st->st_size),
+                                type, path, flags);
        else
                ret = index_stream(oid, fd, xsize_t(st->st_size), type, path,
                                   flags);
@@ -1965,7 +1958,8 @@ int index_fd(struct object_id *oid, int fd, struct stat *st,
        return ret;
 }
 
-int index_path(struct object_id *oid, const char *path, struct stat *st, unsigned flags)
+int index_path(struct index_state *istate, struct object_id *oid,
+              const char *path, struct stat *st, unsigned flags)
 {
        int fd;
        struct strbuf sb = STRBUF_INIT;
@@ -1976,8 +1970,8 @@ int index_path(struct object_id *oid, const char *path, struct stat *st, unsigne
                fd = open(path, O_RDONLY);
                if (fd < 0)
                        return error_errno("open(\"%s\")", path);
-               if (index_fd(oid, fd, st, OBJ_BLOB, path, flags) < 0)
-                       return error("%s: failed to insert into database",
+               if (index_fd(istate, oid, fd, st, OBJ_BLOB, path, flags) < 0)
+                       return error(_("%s: failed to insert into database"),
                                     path);
                break;
        case S_IFLNK:
@@ -1986,13 +1980,13 @@ int index_path(struct object_id *oid, const char *path, struct stat *st, unsigne
                if (!(flags & HASH_WRITE_OBJECT))
                        hash_object_file(sb.buf, sb.len, blob_type, oid);
                else if (write_object_file(sb.buf, sb.len, blob_type, oid))
-                       rc = error("%s: failed to insert into database", path);
+                       rc = error(_("%s: failed to insert into database"), path);
                strbuf_release(&sb);
                break;
        case S_IFDIR:
                return resolve_gitlink_ref(path, "HEAD", oid);
        default:
-               return error("%s: unsupported file type", path);
+               return error(_("%s: unsupported file type"), path);
        }
        return rc;
 }
@@ -2016,9 +2010,9 @@ void assert_oid_type(const struct object_id *oid, enum object_type expect)
 {
        enum object_type type = oid_object_info(the_repository, oid, NULL);
        if (type < 0)
-               die("%s is not a valid object", oid_to_hex(oid));
+               die(_("%s is not a valid object"), oid_to_hex(oid));
        if (type != expect)
-               die("%s is not a valid '%s' object", oid_to_hex(oid),
+               die(_("%s is not a valid '%s' object"), oid_to_hex(oid),
                    type_name(expect));
 }
 
@@ -2045,7 +2039,7 @@ int for_each_file_in_obj_subdir(unsigned int subdir_nr,
        dir = opendir(path->buf);
        if (!dir) {
                if (errno != ENOENT)
-                       r = error_errno("unable to open %s", path->buf);
+                       r = error_errno(_("unable to open %s"), path->buf);
                strbuf_setlen(path, origlen);
                return r;
        }
@@ -2062,9 +2056,9 @@ int for_each_file_in_obj_subdir(unsigned int subdir_nr,
                namelen = strlen(de->d_name);
                strbuf_setlen(path, baselen);
                strbuf_add(path, de->d_name, namelen);
-               if (namelen == GIT_SHA1_HEXSZ - 2 &&
+               if (namelen == the_hash_algo->hexsz - 2 &&
                    !hex_to_bytes(oid.hash + 1, de->d_name,
-                                 GIT_SHA1_RAWSZ - 1)) {
+                                 the_hash_algo->rawsz - 1)) {
                        if (obj_cb) {
                                r = obj_cb(&oid, path->buf, data);
                                if (r)
@@ -2131,14 +2125,14 @@ struct loose_alt_odb_data {
        void *data;
 };
 
-static int loose_from_alt_odb(struct alternate_object_database *alt,
+static int loose_from_alt_odb(struct object_directory *odb,
                              void *vdata)
 {
        struct loose_alt_odb_data *data = vdata;
        struct strbuf buf = STRBUF_INIT;
        int r;
 
-       strbuf_addstr(&buf, alt->path);
+       strbuf_addstr(&buf, odb->path);
        r = for_each_loose_file_in_objdir_buf(&buf,
                                              data->cb, NULL, NULL,
                                              data->data);
@@ -2146,7 +2140,8 @@ static int loose_from_alt_odb(struct alternate_object_database *alt,
        return r;
 }
 
-int for_each_loose_object(each_loose_object_fn cb, void *data, unsigned flags)
+int for_each_loose_object(each_loose_object_fn cb, void *data,
+                         enum for_each_object_flags flags)
 {
        struct loose_alt_odb_data alt;
        int r;
@@ -2202,18 +2197,18 @@ static int check_stream_sha1(git_zstream *stream,
        git_inflate_end(stream);
 
        if (status != Z_STREAM_END) {
-               error("corrupt loose object '%s'", sha1_to_hex(expected_sha1));
+               error(_("corrupt loose object '%s'"), sha1_to_hex(expected_sha1));
                return -1;
        }
        if (stream->avail_in) {
-               error("garbage at end of loose object '%s'",
+               error(_("garbage at end of loose object '%s'"),
                      sha1_to_hex(expected_sha1));
                return -1;
        }
 
        the_hash_algo->final_fn(real_sha1, &c);
-       if (hashcmp(expected_sha1, real_sha1)) {
-               error("sha1 mismatch for %s (expected %s)", path,
+       if (!hasheq(expected_sha1, real_sha1)) {
+               error(_("sha1 mismatch for %s (expected %s)"), path,
                      sha1_to_hex(expected_sha1));
                return -1;
        }
@@ -2237,18 +2232,18 @@ int read_loose_object(const char *path,
 
        map = map_sha1_file_1(the_repository, path, NULL, &mapsize);
        if (!map) {
-               error_errno("unable to mmap %s", path);
+               error_errno(_("unable to mmap %s"), path);
                goto out;
        }
 
        if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0) {
-               error("unable to unpack header of %s", path);
+               error(_("unable to unpack header of %s"), path);
                goto out;
        }
 
        *type = parse_sha1_header(hdr, size);
        if (*type < 0) {
-               error("unable to parse header of %s", path);
+               error(_("unable to parse header of %s"), path);
                git_inflate_end(&stream);
                goto out;
        }
@@ -2259,13 +2254,13 @@ int read_loose_object(const char *path,
        } else {
                *contents = unpack_sha1_rest(&stream, hdr, *size, expected_oid->hash);
                if (!*contents) {
-                       error("unable to unpack contents of %s", path);
+                       error(_("unable to unpack contents of %s"), path);
                        git_inflate_end(&stream);
                        goto out;
                }
                if (check_object_signature(expected_oid, *contents,
                                         *size, type_name(*type))) {
-                       error("sha1 mismatch for %s (expected %s)", path,
+                       error(_("sha1 mismatch for %s (expected %s)"), path,
                              oid_to_hex(expected_oid));
                        free(*contents);
                        goto out;