]> git.ipfire.org Git - thirdparty/git.git/blobdiff - object-file.c
reftable: implement refname validation
[thirdparty/git.git] / object-file.c
index b9c3219793f8666c2578b328cd4a1c806dae3c7a..7bfd5e6e2e904db6ed8d3d85f6497ce891e95962 100644 (file)
@@ -164,7 +164,6 @@ static void git_hash_unknown_final_oid(struct object_id *oid, git_hash_ctx *ctx)
        BUG("trying to finalize unknown hash");
 }
 
-
 const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
        {
                NULL,
@@ -183,8 +182,7 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
        },
        {
                "sha1",
-               /* "sha1", big-endian */
-               0x73686131,
+               GIT_SHA1_FORMAT_ID,
                GIT_SHA1_RAWSZ,
                GIT_SHA1_HEXSZ,
                GIT_SHA1_BLKSZ,
@@ -199,8 +197,7 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
        },
        {
                "sha256",
-               /* "s256", big-endian */
-               0x73323536,
+               GIT_SHA256_FORMAT_ID,
                GIT_SHA256_RAWSZ,
                GIT_SHA256_HEXSZ,
                GIT_SHA256_BLKSZ,
@@ -517,9 +514,9 @@ const char *loose_object_path(struct repository *r, struct strbuf *buf,
  */
 static int alt_odb_usable(struct raw_object_store *o,
                          struct strbuf *path,
-                         const char *normalized_objdir)
+                         const char *normalized_objdir, khiter_t *pos)
 {
-       struct object_directory *odb;
+       int r;
 
        /* Detect cases where alternate disappeared */
        if (!is_directory(path->buf)) {
@@ -533,14 +530,20 @@ 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 (odb = o->odb; odb; odb = odb->next) {
-               if (!fspathcmp(path->buf, odb->path))
-                       return 0;
+       if (!o->odb_by_path) {
+               khiter_t p;
+
+               o->odb_by_path = kh_init_odb_path_map();
+               assert(!o->odb->next);
+               p = kh_put_odb_path_map(o->odb_by_path, o->odb->path, &r);
+               assert(r == 1); /* never used */
+               kh_value(o->odb_by_path, p) = o->odb;
        }
-       if (!fspathcmp(path->buf, normalized_objdir))
+       if (fspatheq(path->buf, normalized_objdir))
                return 0;
-
-       return 1;
+       *pos = kh_put_odb_path_map(o->odb_by_path, path->buf, &r);
+       /* r: 0 = exists, 1 = never used, 2 = deleted */
+       return r == 0 ? 0 : 1;
 }
 
 /*
@@ -561,17 +564,18 @@ static int alt_odb_usable(struct raw_object_store *o,
 static void read_info_alternates(struct repository *r,
                                 const char *relative_base,
                                 int depth);
-static int link_alt_odb_entry(struct repository *r, const char *entry,
+static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry,
        const char *relative_base, int depth, const char *normalized_objdir)
 {
        struct object_directory *ent;
        struct strbuf pathbuf = STRBUF_INIT;
+       khiter_t pos;
 
-       if (!is_absolute_path(entry) && relative_base) {
+       if (!is_absolute_path(entry->buf) && relative_base) {
                strbuf_realpath(&pathbuf, relative_base, 1);
                strbuf_addch(&pathbuf, '/');
        }
-       strbuf_addstr(&pathbuf, entry);
+       strbuf_addbuf(&pathbuf, entry);
 
        if (strbuf_normalize_path(&pathbuf) < 0 && relative_base) {
                error(_("unable to normalize alternate object path: %s"),
@@ -587,23 +591,25 @@ static int link_alt_odb_entry(struct repository *r, const char *entry,
        while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/')
                strbuf_setlen(&pathbuf, pathbuf.len - 1);
 
-       if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir)) {
+       if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir, &pos)) {
                strbuf_release(&pathbuf);
                return -1;
        }
 
        CALLOC_ARRAY(ent, 1);
-       ent->path = xstrdup(pathbuf.buf);
+       /* pathbuf.buf is already in r->objects->odb_by_path */
+       ent->path = strbuf_detach(&pathbuf, NULL);
 
        /* add the alternate entry */
        *r->objects->odb_tail = ent;
        r->objects->odb_tail = &(ent->next);
        ent->next = NULL;
+       assert(r->objects->odb_by_path);
+       kh_value(r->objects->odb_by_path, pos) = ent;
 
        /* recursively add alternates */
-       read_info_alternates(r, pathbuf.buf, depth + 1);
+       read_info_alternates(r, ent->path, depth + 1);
 
-       strbuf_release(&pathbuf);
        return 0;
 }
 
@@ -660,7 +666,7 @@ static void link_alt_odb_entries(struct repository *r, const char *alt,
                alt = parse_alt_odb_entry(alt, sep, &entry);
                if (!entry.len)
                        continue;
-               link_alt_odb_entry(r, entry.buf,
+               link_alt_odb_entry(r, &entry,
                                   relative_base, depth, objdirbuf.buf);
        }
        strbuf_release(&entry);
@@ -1178,7 +1184,7 @@ static int quick_has_loose(struct repository *r,
 
        prepare_alt_odb(r);
        for (odb = r->objects->odb; odb; odb = odb->next) {
-               if (oid_array_lookup(odb_loose_cache(odb, oid), oid) >= 0)
+               if (oidtree_contains(odb_loose_cache(odb, oid), oid))
                        return 1;
        }
        return 0;
@@ -1584,15 +1590,12 @@ static int do_oid_object_info_extended(struct repository *r,
                }
 
                /* Check if it is a missing object */
-               if (fetch_if_missing && has_promisor_remote() &&
-                   !already_retried && r == the_repository &&
+               if (fetch_if_missing && repo_has_promisor_remote(r) &&
+                   !already_retried &&
                    !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) {
                        /*
                         * TODO Investigate checking promisor_remote_get_direct()
                         * TODO return value and stopping on error here.
-                        * TODO Pass a repository struct through
-                        * promisor_remote_get_direct(), such that arbitrary
-                        * repositories work.
                         */
                        promisor_remote_get_direct(r, real, 1);
                        already_retried = 1;
@@ -2457,39 +2460,45 @@ int for_each_loose_object(each_loose_object_fn cb, void *data,
 static int append_loose_object(const struct object_id *oid, const char *path,
                               void *data)
 {
-       oid_array_append(data, oid);
+       oidtree_insert(data, oid);
        return 0;
 }
 
-struct oid_array *odb_loose_cache(struct object_directory *odb,
+struct oidtree *odb_loose_cache(struct object_directory *odb,
                                  const struct object_id *oid)
 {
        int subdir_nr = oid->hash[0];
        struct strbuf buf = STRBUF_INIT;
+       size_t word_bits = bitsizeof(odb->loose_objects_subdir_seen[0]);
+       size_t word_index = subdir_nr / word_bits;
+       size_t mask = 1u << (subdir_nr % word_bits);
+       uint32_t *bitmap;
 
        if (subdir_nr < 0 ||
-           subdir_nr >= ARRAY_SIZE(odb->loose_objects_subdir_seen))
+           subdir_nr >= bitsizeof(odb->loose_objects_subdir_seen))
                BUG("subdir_nr out of range");
 
-       if (odb->loose_objects_subdir_seen[subdir_nr])
-               return &odb->loose_objects_cache[subdir_nr];
-
+       bitmap = &odb->loose_objects_subdir_seen[word_index];
+       if (*bitmap & mask)
+               return odb->loose_objects_cache;
+       if (!odb->loose_objects_cache) {
+               ALLOC_ARRAY(odb->loose_objects_cache, 1);
+               oidtree_init(odb->loose_objects_cache);
+       }
        strbuf_addstr(&buf, odb->path);
        for_each_file_in_obj_subdir(subdir_nr, &buf,
                                    append_loose_object,
                                    NULL, NULL,
-                                   &odb->loose_objects_cache[subdir_nr]);
-       odb->loose_objects_subdir_seen[subdir_nr] = 1;
+                                   odb->loose_objects_cache);
+       *bitmap |= mask;
        strbuf_release(&buf);
-       return &odb->loose_objects_cache[subdir_nr];
+       return odb->loose_objects_cache;
 }
 
 void odb_clear_loose_cache(struct object_directory *odb)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(odb->loose_objects_cache); i++)
-               oid_array_clear(&odb->loose_objects_cache[i]);
+       oidtree_clear(odb->loose_objects_cache);
+       FREE_AND_NULL(odb->loose_objects_cache);
        memset(&odb->loose_objects_subdir_seen, 0,
               sizeof(odb->loose_objects_subdir_seen));
 }