diff options
Diffstat (limited to 'builtin-pack-objects.c')
-rw-r--r-- | builtin-pack-objects.c | 121 |
1 files changed, 62 insertions, 59 deletions
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 447d492dbb..fb5e14d56e 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -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; } |