]> git.ipfire.org Git - thirdparty/git.git/blobdiff - fast-import.c
Reduce memory usage of fast-import.
[thirdparty/git.git] / fast-import.c
index 90adc680421540202aeca556c4223c72a3ea9b7a..9658c28413bc01b7f096b96841f6ed993d055b48 100644 (file)
@@ -7,6 +7,7 @@ Format of STDIN stream:
         | new_commit
         | new_tag
         | reset_branch
+        | checkpoint
         ;
 
   new_blob ::= 'blob' lf
@@ -25,10 +26,11 @@ Format of STDIN stream:
     lf;
   commit_msg ::= data;
 
-  file_change ::= 'M' sp mode sp (hexsha1 | idnum) sp path_str lf
-                | 'D' sp path_str lf
-                ;
-  mode ::= '644' | '755';
+  file_change ::= file_del | file_obm | file_inm;
+  file_del ::= 'D' sp path_str lf;
+  file_obm ::= 'M' sp mode sp (hexsha1 | idnum) sp path_str lf;
+  file_inm ::= 'M' sp mode sp 'inline' sp path_str lf
+    data;
 
   new_tag ::= 'tag' sp tag_str lf
     'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
@@ -77,6 +79,10 @@ Format of STDIN stream:
   sha1exp_str ::= sha1exp | '"' quoted(sha1exp) '"' ;
   tag_str     ::= tag     | '"' quoted(tag)     '"' ;
   path_str    ::= path    | '"' quoted(path)    '"' ;
+  mode        ::= '100644' | '644'
+                | '100755' | '755'
+                | '140000'
+                ;
 
   declen ::= # unsigned 32 bit value, ascii base10 notation;
   bigint ::= # unsigned integer value, ascii base10 notation;
@@ -124,7 +130,7 @@ Format of STDIN stream:
 struct object_entry
 {
        struct object_entry *next;
-       unsigned long offset;
+       uint32_t offset;
        unsigned type : TYPE_BITS;
        unsigned pack_id : PACK_ID_BITS;
        unsigned char sha1[20];
@@ -151,7 +157,7 @@ struct last_object
 {
        void *data;
        unsigned long len;
-       unsigned long offset;
+       uint32_t offset;
        unsigned int depth;
        unsigned no_free:1;
 };
@@ -167,7 +173,7 @@ struct mem_pool
 struct atom_str
 {
        struct atom_str *next_atom;
-       unsigned int str_len;
+       unsigned short str_len;
        char str_dat[FLEX_ARRAY]; /* more */
 };
 
@@ -178,7 +184,7 @@ struct tree_entry
        struct atom_str* name;
        struct tree_entry_ms
        {
-               unsigned int mode;
+               uint16_t mode;
                unsigned char sha1[20];
        } versions[2];
 };
@@ -458,7 +464,7 @@ static struct object_entry* find_mark(uintmax_t idnum)
        return oe;
 }
 
-static struct atom_str* to_atom(const char *s, size_t len)
+static struct atom_str* to_atom(const char *s, unsigned short len)
 {
        unsigned int hc = hc_str(s, len) % atom_table_sz;
        struct atom_str *c;
@@ -987,10 +993,10 @@ static void *gfi_unpack_entry(
        return unpack_entry(p, oe->offset, type, sizep);
 }
 
-static const char *get_mode(const char *str, unsigned int *modep)
+static const char *get_mode(const char *str, uint16_t *modep)
 {
        unsigned char c;
-       unsigned int mode = 0;
+       uint16_t mode = 0;
 
        while ((c = *str++) != ' ') {
                if (c < '0' || c > '7')
@@ -1040,7 +1046,7 @@ static void load_tree(struct tree_entry *root)
                if (!c)
                        die("Corrupt mode in %s", sha1_to_hex(sha1));
                e->versions[0].mode = e->versions[1].mode;
-               e->name = to_atom(c, strlen(c));
+               e->name = to_atom(c, (unsigned short)strlen(c));
                c += e->name->str_len + 1;
                hashcpy(e->versions[0].sha1, (unsigned char*)c);
                hashcpy(e->versions[1].sha1, (unsigned char*)c);
@@ -1092,7 +1098,7 @@ static void mktree(struct tree_content *t,
                struct tree_entry *e = t->entries[i];
                if (!e->versions[v].mode)
                        continue;
-               c += sprintf(c, "%o", e->versions[v].mode);
+               c += sprintf(c, "%o", (unsigned int)e->versions[v].mode);
                *c++ = ' ';
                strcpy(c, e->name->str_dat);
                c += e->name->str_len + 1;
@@ -1155,7 +1161,7 @@ static int tree_content_set(
        struct tree_entry *root,
        const char *p,
        const unsigned char *sha1,
-       const unsigned int mode)
+       const uint16_t mode)
 {
        struct tree_content *t = root->tree;
        const char *slash1;
@@ -1201,7 +1207,7 @@ static int tree_content_set(
        if (t->entry_count == t->entry_capacity)
                root->tree = t = grow_tree_content(t, 8);
        e = new_tree_entry();
-       e->name = to_atom(p, n);
+       e->name = to_atom(p, (unsigned short)n);
        e->versions[0].mode = 0;
        hashclr(e->versions[0].sha1);
        t->entries[t->entry_count++] = e;
@@ -1452,7 +1458,7 @@ static void file_change_m(struct branch *b)
        const char *endp;
        struct object_entry *oe;
        unsigned char sha1[20];
-       unsigned int mode;
+       uint16_t mode, inline_data = 0;
        char type[20];
 
        p = get_mode(p, &mode);
@@ -1475,6 +1481,9 @@ static void file_change_m(struct branch *b)
                oe = find_mark(strtoumax(p + 1, &x, 10));
                hashcpy(sha1, oe->sha1);
                p = x;
+       } else if (!strncmp("inline", p, 6)) {
+               inline_data = 1;
+               p += 6;
        } else {
                if (get_sha1_hex(p, sha1))
                        die("Invalid SHA1: %s", command_buf.buf);
@@ -1491,7 +1500,16 @@ static void file_change_m(struct branch *b)
                p = p_uq;
        }
 
-       if (oe) {
+       if (inline_data) {
+               size_t l;
+               void *d;
+               if (!p_uq)
+                       p = p_uq = xstrdup(p);
+               read_next_command();
+               d = cmd_data(&l);
+               if (store_object(OBJ_BLOB, d, l, &last_blob, sha1, 0))
+                       free(d);
+       } else if (oe) {
                if (oe->type != OBJ_BLOB)
                        die("Not a blob (actually a %s): %s",
                                command_buf.buf, type_names[oe->type]);
@@ -1910,7 +1928,6 @@ int main(int argc, const char **argv)
        int i;
        uintmax_t total_count, duplicate_count;
 
-       setup_ident();
        git_config(git_default_config);
 
        for (i = 1; i < argc; i++) {