Fix GIT_CEILING_DIRECTORIES on Windows
[gitweb.git] / builtin-pack-objects.c
index 447d492dbbfb578b8903293fa1d2a988eecfefac..fb5e14d56e5b9fec0a054eb9708be41a59ac0f13 100644 (file)
@@ -23,7 +23,7 @@
 #endif
 
 static const char pack_usage[] = "\
-git-pack-objects [{ -q | --progress | --all-progress }] \n\
+git pack-objects [{ -q | --progress | --all-progress }] \n\
        [--max-pack-size=N] [--local] [--incremental] \n\
        [--window=N] [--window-memory=N] [--depth=N] \n\
        [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\
@@ -71,6 +71,7 @@ static int reuse_delta = 1, reuse_object = 1;
 static int keep_unreachable, unpack_unreachable, include_tag;
 static int local;
 static int incremental;
+static int ignore_packed_keep;
 static int allow_ofs_delta;
 static const char *base_name;
 static int progress = 1;
@@ -209,28 +210,6 @@ static int check_pack_inflate(struct packed_git *p,
                stream.total_in == len) ? 0 : -1;
 }
 
-static int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,
-                         off_t offset, off_t len, unsigned int nr)
-{
-       const uint32_t *index_crc;
-       uint32_t data_crc = crc32(0, Z_NULL, 0);
-
-       do {
-               unsigned int avail;
-               void *data = use_pack(p, w_curs, offset, &avail);
-               if (avail > len)
-                       avail = len;
-               data_crc = crc32(data_crc, data, avail);
-               offset += avail;
-               len -= avail;
-       } while (len);
-
-       index_crc = p->index_data;
-       index_crc += 2 + 256 + p->num_objects * (20/4) + nr;
-
-       return data_crc != ntohl(*index_crc);
-}
-
 static void copy_pack_data(struct sha1file *f,
                struct packed_git *p,
                struct pack_window **w_curs,
@@ -267,8 +246,16 @@ static unsigned long write_object(struct sha1file *f,
        type = entry->type;
 
        /* write limit if limited packsize and not first object */
-       limit = pack_size_limit && nr_written ?
-                       pack_size_limit - write_offset : 0;
+       if (!pack_size_limit || !nr_written)
+               limit = 0;
+       else if (pack_size_limit <= write_offset)
+               /*
+                * the earlier object did not fit the limit; avoid
+                * mistaking this with unlimited (i.e. limit = 0).
+                */
+               limit = 1;
+       else
+               limit = pack_size_limit - write_offset;
 
        if (!entry->delta)
                usable_delta = 0;       /* no delta */
@@ -432,25 +419,22 @@ static unsigned long write_object(struct sha1file *f,
        return hdrlen + datalen;
 }
 
-static off_t write_one(struct sha1file *f,
+static int write_one(struct sha1file *f,
                               struct object_entry *e,
-                              off_t offset)
+                              off_t *offset)
 {
        unsigned long size;
 
        /* offset is non zero if object is written already. */
        if (e->idx.offset || e->preferred_base)
-               return offset;
+               return 1;
 
        /* if we are deltified, write out base object first. */
-       if (e->delta) {
-               offset = write_one(f, e->delta, offset);
-               if (!offset)
-                       return 0;
-       }
+       if (e->delta && !write_one(f, e->delta, offset))
+               return 0;
 
-       e->idx.offset = offset;
-       size = write_object(f, e, offset);
+       e->idx.offset = *offset;
+       size = write_object(f, e, *offset);
        if (!size) {
                e->idx.offset = 0;
                return 0;
@@ -458,9 +442,10 @@ static off_t write_one(struct sha1file *f,
        written_list[nr_written++] = &e->idx;
 
        /* make sure off_t is sufficiently large not to wrap */
-       if (offset > offset + size)
+       if (*offset > *offset + size)
                die("pack too large for current definition of off_t");
-       return offset + size;
+       *offset += size;
+       return 1;
 }
 
 /* forward declaration for write_pack_file */
@@ -470,7 +455,7 @@ static void write_pack_file(void)
 {
        uint32_t i = 0, j;
        struct sha1file *f;
-       off_t offset, offset_one, last_obj_offset = 0;
+       off_t offset;
        struct pack_header hdr;
        uint32_t nr_remaining = nr_result;
        time_t last_mtime = 0;
@@ -489,7 +474,7 @@ static void write_pack_file(void)
                        char tmpname[PATH_MAX];
                        int fd;
                        snprintf(tmpname, sizeof(tmpname),
-                                "%s/tmp_pack_XXXXXX", get_object_directory());
+                                "%s/pack/tmp_pack_XXXXXX", get_object_directory());
                        fd = xmkstemp(tmpname);
                        pack_tmp_name = xstrdup(tmpname);
                        f = sha1fd(fd, pack_tmp_name);
@@ -502,11 +487,8 @@ static void write_pack_file(void)
                offset = sizeof(hdr);
                nr_written = 0;
                for (; i < nr_objects; i++) {
-                       last_obj_offset = offset;
-                       offset_one = write_one(f, objects + i, offset);
-                       if (!offset_one)
+                       if (!write_one(f, objects + i, &offset))
                                break;
-                       offset = offset_one;
                        display_progress(progress_state, written);
                }
 
@@ -519,9 +501,9 @@ static void write_pack_file(void)
                } else if (nr_written == nr_remaining) {
                        sha1close(f, sha1, CSUM_FSYNC);
                } else {
-                       int fd = sha1close(f, NULL, 0);
-                       fixup_pack_header_footer(fd, sha1, pack_tmp_name, nr_written);
-                       fsync_or_die(fd, pack_tmp_name);
+                       int fd = sha1close(f, sha1, 0);
+                       fixup_pack_header_footer(fd, sha1, pack_tmp_name,
+                                                nr_written, sha1, offset);
                        close(fd);
                }
 
@@ -538,6 +520,7 @@ static void write_pack_file(void)
 
                        snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
                                 base_name, sha1_to_hex(sha1));
+                       free_pack_by_name(tmpname);
                        if (adjust_perm(pack_tmp_name, mode))
                                die("unable to make temporary pack file readable: %s",
                                    strerror(errno));
@@ -590,7 +573,8 @@ static void write_pack_file(void)
        free(written_list);
        stop_progress(&progress_state);
        if (written != nr_result)
-               die("wrote %u objects while expecting %u", written, nr_result);
+               die("wrote %"PRIu32" objects while expecting %"PRIu32,
+                       written, nr_result);
        /*
         * We have scanned through [0 ... i).  Since we have written
         * the correct number of objects,  the remaining [i ... nr_objects)
@@ -602,7 +586,8 @@ static void write_pack_file(void)
                j += !e->idx.offset && !e->preferred_base;
        }
        if (j)
-               die("wrote %u objects as expected but %u unwritten", written, j);
+               die("wrote %"PRIu32" objects as expected but %"PRIu32
+                       " unwritten", written, j);
 }
 
 static int locate_object_entry_hash(const unsigned char *sha1)
@@ -715,6 +700,9 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
                return 0;
        }
 
+       if (!exclude && local && has_loose_object_nonlocal(sha1))
+               return 0;
+
        for (p = packed_git; p; p = p->next) {
                off_t offset = find_pack_entry_one(sha1, p);
                if (offset) {
@@ -728,6 +716,8 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
                                return 0;
                        if (local && !p->pack_local)
                                return 0;
+                       if (ignore_packed_keep && p->pack_local && p->pack_keep)
+                               return 0;
                }
        }
 
@@ -1116,9 +1106,12 @@ static void check_object(struct object_entry *entry)
        }
 
        entry->type = sha1_object_info(entry->idx.sha1, &entry->size);
-       if (entry->type < 0)
-               die("unable to get type of object %s",
-                   sha1_to_hex(entry->idx.sha1));
+       /*
+        * The error condition is checked in prepare_pack().  This is
+        * to permit a missing preferred base object to be ignored
+        * as a preferred base.  Doing so can result in a larger
+        * pack file, but the transfer will still take place.
+        */
 }
 
 static int pack_offset_sort(const void *_a, const void *_b)
@@ -1148,8 +1141,6 @@ static void get_object_details(void)
                sorted_by_offset[i] = objects + i;
        qsort(sorted_by_offset, nr_objects, sizeof(*sorted_by_offset), pack_offset_sort);
 
-       init_pack_revindex();
-
        for (i = 0; i < nr_objects; i++)
                check_object(sorted_by_offset[i]);
 
@@ -1401,7 +1392,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
        memset(array, 0, array_size);
 
        for (;;) {
-               struct object_entry *entry = *list++;
+               struct object_entry *entry;
                struct unpacked *n = array + idx;
                int j, max_depth, best_base = -1;
 
@@ -1410,6 +1401,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
                        progress_unlock();
                        break;
                }
+               entry = *list++;
                (*list_size)--;
                if (!entry->preferred_base) {
                        (*processed)++;
@@ -1718,7 +1710,8 @@ static int add_ref_tag(const char *path, const unsigned char *sha1, int flag, vo
 static void prepare_pack(int window, int depth)
 {
        struct object_entry **delta_list;
-       uint32_t i, n, nr_deltas;
+       uint32_t i, nr_deltas;
+       unsigned n;
 
        get_object_details();
 
@@ -1743,8 +1736,12 @@ static void prepare_pack(int window, int depth)
                if (entry->no_try_delta)
                        continue;
 
-               if (!entry->preferred_base)
+               if (!entry->preferred_base) {
                        nr_deltas++;
+                       if (entry->type < 0)
+                               die("unable to get type of object %s",
+                                   sha1_to_hex(entry->idx.sha1));
+               }
 
                delta_list[n++] = entry;
        }
@@ -1809,7 +1806,8 @@ static int git_pack_config(const char *k, const char *v, void *cb)
        if (!strcmp(k, "pack.indexversion")) {
                pack_idx_default_version = git_config_int(k, v);
                if (pack_idx_default_version > 2)
-                       die("bad pack.indexversion=%d", pack_idx_default_version);
+                       die("bad pack.indexversion=%"PRIu32,
+                               pack_idx_default_version);
                return 0;
        }
        if (!strcmp(k, "pack.packsizelimit")) {
@@ -1890,7 +1888,7 @@ static void mark_in_pack_object(struct object *object, struct packed_git *p, str
 
 /*
  * Compare the objects in the offset order, in order to emulate the
- * "git-rev-list --objects" output that produced the pack originally.
+ * "git rev-list --objects" output that produced the pack originally.
  */
 static int ofscmp(const void *a_, const void *b_)
 {
@@ -2059,6 +2057,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                        incremental = 1;
                        continue;
                }
+               if (!strcmp("--honor-pack-keep", arg)) {
+                       ignore_packed_keep = 1;
+                       continue;
+               }
                if (!prefixcmp(arg, "--compression=")) {
                        char *end;
                        int level = strtoul(arg+14, &end, 0);
@@ -2243,7 +2245,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                prepare_pack(window, depth);
        write_pack_file();
        if (progress)
-               fprintf(stderr, "Total %u (delta %u), reused %u (delta %u)\n",
+               fprintf(stderr, "Total %"PRIu32" (delta %"PRIu32"),"
+                       " reused %"PRIu32" (delta %"PRIu32")\n",
                        written, written_delta, reused, reused_delta);
        return 0;
 }