Merge branch 'ab/test-2'
[gitweb.git] / fast-import.c
index 74f08bd554ae4cab1dc9ee38272376e5cbec1200..2317b0fe7509b957577234890135509143c0872b 100644 (file)
@@ -267,7 +267,7 @@ struct hash_list
 typedef enum {
        WHENSPEC_RAW = 1,
        WHENSPEC_RFC2822,
-       WHENSPEC_NOW,
+       WHENSPEC_NOW
 } whenspec_type;
 
 struct recent_command
@@ -980,29 +980,6 @@ static void cycle_packfile(void)
        start_packfile();
 }
 
-static size_t encode_header(
-       enum object_type type,
-       uintmax_t size,
-       unsigned char *hdr)
-{
-       int n = 1;
-       unsigned char c;
-
-       if (type < OBJ_COMMIT || type > OBJ_REF_DELTA)
-               die("bad type %d", type);
-
-       c = (type << 4) | (size & 15);
-       size >>= 4;
-       while (size) {
-               *hdr++ = c | 0x80;
-               c = size & 0x7f;
-               size >>= 7;
-               n++;
-       }
-       *hdr = c;
-       return n;
-}
-
 static int store_object(
        enum object_type type,
        struct strbuf *dat,
@@ -1103,7 +1080,7 @@ static int store_object(
                delta_count_by_type[type]++;
                e->depth = last->depth + 1;
 
-               hdrlen = encode_header(OBJ_OFS_DELTA, deltalen, hdr);
+               hdrlen = encode_in_pack_object_header(OBJ_OFS_DELTA, deltalen, hdr);
                sha1write(pack_file, hdr, hdrlen);
                pack_size += hdrlen;
 
@@ -1114,7 +1091,7 @@ static int store_object(
                pack_size += sizeof(hdr) - pos;
        } else {
                e->depth = 0;
-               hdrlen = encode_header(type, dat->len, hdr);
+               hdrlen = encode_in_pack_object_header(type, dat->len, hdr);
                sha1write(pack_file, hdr, hdrlen);
                pack_size += hdrlen;
        }
@@ -1188,7 +1165,7 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark)
        memset(&s, 0, sizeof(s));
        deflateInit(&s, pack_compression_level);
 
-       hdrlen = encode_header(OBJ_BLOB, len, out_buf);
+       hdrlen = encode_in_pack_object_header(OBJ_BLOB, len, out_buf);
        if (out_sz <= hdrlen)
                die("impossibly large object header");
 
@@ -1551,6 +1528,14 @@ static int tree_content_remove(
        for (i = 0; i < t->entry_count; i++) {
                e = t->entries[i];
                if (e->name->str_len == n && !strncmp(p, e->name->str_dat, n)) {
+                       if (slash1 && !S_ISDIR(e->versions[1].mode))
+                               /*
+                                * If p names a file in some subdirectory, and a
+                                * file or symlink matching the name of the
+                                * parent directory of p exists, then p cannot
+                                * exist and need not be deleted.
+                                */
+                               return 1;
                        if (!slash1 || !S_ISDIR(e->versions[1].mode))
                                goto del_entry;
                        if (!e->tree)
@@ -1689,7 +1674,7 @@ static void dump_marks_helper(FILE *f,
        if (m->shift) {
                for (k = 0; k < 1024; k++) {
                        if (m->data.sets[k])
-                               dump_marks_helper(f, (base + k) << m->shift,
+                               dump_marks_helper(f, base + (k << m->shift),
                                        m->data.sets[k]);
                }
        } else {
@@ -2154,6 +2139,7 @@ static void file_change_m(struct branch *b)
        case S_IFREG | 0644:
        case S_IFREG | 0755:
        case S_IFLNK:
+       case S_IFDIR:
        case S_IFGITLINK:
                /* ok */
                break;
@@ -2199,23 +2185,28 @@ static void file_change_m(struct branch *b)
                 * another repository.
                 */
        } else if (inline_data) {
+               if (S_ISDIR(mode))
+                       die("Directories cannot be specified 'inline': %s",
+                               command_buf.buf);
                if (p != uq.buf) {
                        strbuf_addstr(&uq, p);
                        p = uq.buf;
                }
                read_next_command();
                parse_and_store_blob(&last_blob, sha1, 0);
-       } else if (oe) {
-               if (oe->type != OBJ_BLOB)
-                       die("Not a blob (actually a %s): %s",
-                               typename(oe->type), command_buf.buf);
        } else {
-               enum object_type type = sha1_object_info(sha1, NULL);
+               enum object_type expected = S_ISDIR(mode) ?
+                                               OBJ_TREE: OBJ_BLOB;
+               enum object_type type = oe ? oe->type :
+                                       sha1_object_info(sha1, NULL);
                if (type < 0)
-                       die("Blob not found: %s", command_buf.buf);
-               if (type != OBJ_BLOB)
-                       die("Not a blob (actually a %s): %s",
-                           typename(type), command_buf.buf);
+                       die("%s not found: %s",
+                                       S_ISDIR(mode) ?  "Tree" : "Blob",
+                                       command_buf.buf);
+               if (type != expected)
+                       die("Not a %s (actually a %s): %s",
+                               typename(expected), typename(type),
+                               command_buf.buf);
        }
 
        tree_content_set(&b->branch_tree, p, sha1, mode, NULL);
@@ -2730,6 +2721,7 @@ static void option_import_marks(const char *marks, int from_stream)
        }
 
        import_marks_file = make_fast_import_path(marks);
+       safe_create_leading_directories_const(import_marks_file);
        import_marks_file_from_stream = from_stream;
 }
 
@@ -2760,6 +2752,7 @@ static void option_active_branches(const char *branches)
 static void option_export_marks(const char *marks)
 {
        export_marks_file = make_fast_import_path(marks);
+       safe_create_leading_directories_const(export_marks_file);
 }
 
 static void option_export_pack_edges(const char *edges)