]> git.ipfire.org Git - thirdparty/git.git/blobdiff - fast-import.c
Merge branch 'bc/http-push-flagsfix'
[thirdparty/git.git] / fast-import.c
index 202dda11a6b206162a7199718c21c43beb698e22..0dfa14dc8c3c07bfb8f19275d2366a5f63576212 100644 (file)
 
 struct object_entry {
        struct pack_idx_entry idx;
-       struct object_entry *next;
+       struct hashmap_entry ent;
        uint32_t type : TYPE_BITS,
                pack_id : PACK_ID_BITS,
                depth : DEPTH_BITS;
 };
 
+static int object_entry_hashcmp(const void *map_data,
+                               const struct hashmap_entry *eptr,
+                               const struct hashmap_entry *entry_or_key,
+                               const void *keydata)
+{
+       const struct object_id *oid = keydata;
+       const struct object_entry *e1, *e2;
+
+       e1 = container_of(eptr, const struct object_entry, ent);
+       if (oid)
+               return oidcmp(&e1->idx.oid, oid);
+
+       e2 = container_of(entry_or_key, const struct object_entry, ent);
+       return oidcmp(&e1->idx.oid, &e2->idx.oid);
+}
+
 struct object_entry_pool {
        struct object_entry_pool *next_pool;
        struct object_entry *next_free;
@@ -123,6 +139,7 @@ struct hash_list {
 
 typedef enum {
        WHENSPEC_RAW = 1,
+       WHENSPEC_RAW_PERMISSIVE,
        WHENSPEC_RFC2822,
        WHENSPEC_NOW
 } whenspec_type;
@@ -178,7 +195,7 @@ static off_t pack_size;
 /* Table of objects we've written. */
 static unsigned int object_entry_alloc = 5000;
 static struct object_entry_pool *blocks;
-static struct object_entry *object_table[1 << 16];
+static struct hashmap object_table;
 static struct mark_set *marks;
 static const char *export_marks_file;
 static const char *import_marks_file;
@@ -455,44 +472,37 @@ static struct object_entry *new_object(struct object_id *oid)
 
 static struct object_entry *find_object(struct object_id *oid)
 {
-       unsigned int h = oid->hash[0] << 8 | oid->hash[1];
-       struct object_entry *e;
-       for (e = object_table[h]; e; e = e->next)
-               if (oideq(oid, &e->idx.oid))
-                       return e;
-       return NULL;
+       return hashmap_get_entry_from_hash(&object_table, oidhash(oid), oid,
+                                          struct object_entry, ent);
 }
 
 static struct object_entry *insert_object(struct object_id *oid)
 {
-       unsigned int h = oid->hash[0] << 8 | oid->hash[1];
-       struct object_entry *e = object_table[h];
+       struct object_entry *e;
+       unsigned int hash = oidhash(oid);
 
-       while (e) {
-               if (oideq(oid, &e->idx.oid))
-                       return e;
-               e = e->next;
+       e = hashmap_get_entry_from_hash(&object_table, hash, oid,
+                                       struct object_entry, ent);
+       if (!e) {
+               e = new_object(oid);
+               e->idx.offset = 0;
+               hashmap_entry_init(&e->ent, hash);
+               hashmap_add(&object_table, &e->ent);
        }
 
-       e = new_object(oid);
-       e->next = object_table[h];
-       e->idx.offset = 0;
-       object_table[h] = e;
        return e;
 }
 
 static void invalidate_pack_id(unsigned int id)
 {
-       unsigned int h;
        unsigned long lu;
        struct tag *t;
+       struct hashmap_iter iter;
+       struct object_entry *e;
 
-       for (h = 0; h < ARRAY_SIZE(object_table); h++) {
-               struct object_entry *e;
-
-               for (e = object_table[h]; e; e = e->next)
-                       if (e->pack_id == id)
-                               e->pack_id = MAX_PACK_ID;
+       hashmap_for_each_entry(&object_table, &iter, e, ent) {
+               if (e->pack_id == id)
+                       e->pack_id = MAX_PACK_ID;
        }
 
        for (lu = 0; lu < branch_table_sz; lu++) {
@@ -1902,7 +1912,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
        return 1;
 }
 
-static int validate_raw_date(const char *src, struct strbuf *result)
+static int validate_raw_date(const char *src, struct strbuf *result, int strict)
 {
        const char *orig_src = src;
        char *endp;
@@ -1911,7 +1921,11 @@ static int validate_raw_date(const char *src, struct strbuf *result)
        errno = 0;
 
        num = strtoul(src, &endp, 10);
-       /* NEEDSWORK: perhaps check for reasonable values? */
+       /*
+        * NEEDSWORK: perhaps check for reasonable values? For example, we
+        *            could error on values representing times more than a
+        *            day in the future.
+        */
        if (errno || endp == src || *endp != ' ')
                return -1;
 
@@ -1920,7 +1934,13 @@ static int validate_raw_date(const char *src, struct strbuf *result)
                return -1;
 
        num = strtoul(src + 1, &endp, 10);
-       if (errno || endp == src + 1 || *endp || 1400 < num)
+       /*
+        * NEEDSWORK: check for brokenness other than num > 1400, such as
+        *            (num % 100) >= 60, or ((num % 100) % 15) != 0 ?
+        */
+       if (errno || endp == src + 1 || *endp || /* did not parse */
+           (strict && (1400 < num))             /* parsed a broken timezone */
+          )
                return -1;
 
        strbuf_addstr(result, orig_src);
@@ -1954,7 +1974,11 @@ static char *parse_ident(const char *buf)
 
        switch (whenspec) {
        case WHENSPEC_RAW:
-               if (validate_raw_date(ltgt, &ident) < 0)
+               if (validate_raw_date(ltgt, &ident, 1) < 0)
+                       die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
+               break;
+       case WHENSPEC_RAW_PERMISSIVE:
+               if (validate_raw_date(ltgt, &ident, 0) < 0)
                        die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
                break;
        case WHENSPEC_RFC2822:
@@ -3249,6 +3273,8 @@ static void option_date_format(const char *fmt)
 {
        if (!strcmp(fmt, "raw"))
                whenspec = WHENSPEC_RAW;
+       else if (!strcmp(fmt, "raw-permissive"))
+               whenspec = WHENSPEC_RAW_PERMISSIVE;
        else if (!strcmp(fmt, "rfc2822"))
                whenspec = WHENSPEC_RFC2822;
        else if (!strcmp(fmt, "now"))
@@ -3511,6 +3537,8 @@ int cmd_main(int argc, const char **argv)
        avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
        marks = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set));
 
+       hashmap_init(&object_table, object_entry_hashcmp, NULL, 0);
+
        /*
         * We don't parse most options until after we've seen the set of
         * "feature" lines at the start of the stream (which allows the command