X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-pack-objects.c;h=52a26a28f4f84180ae74dc9b3ebce9c49afc4166;hb=4d4fcc5451d9d653bebcc8afa18543cb426abeed;hp=a15906bdb2021e68a014344cad4e73e9de3367ca;hpb=89df580d0a2e97b0c7c072d87e5e815534deed56;p=git.git diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index a15906bdb..52a26a28f 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -25,7 +25,7 @@ git-pack-objects [{ -q | --progress | --all-progress }] \n\ [--window=N] [--window-memory=N] [--depth=N] \n\ [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\ [--threads=N] [--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\ - [--stdout | base-name] ["); } else { - int fd = open_object_dir_tmp("tmp_pack_XXXXXX"); + char tmpname[PATH_MAX]; + int fd; + snprintf(tmpname, sizeof(tmpname), + "%s/tmp_pack_XXXXXX", get_object_directory()); + fd = xmkstemp(tmpname); pack_tmp_name = xstrdup(tmpname); f = sha1fd(fd, pack_tmp_name); } @@ -632,8 +629,7 @@ static void write_pack_file(void) if (!offset_one) break; offset = offset_one; - if (do_progress) - display_progress(&progress_state, written); + display_progress(progress_state, written); } /* @@ -643,19 +639,21 @@ static void write_pack_file(void) if (pack_to_stdout || nr_written == nr_remaining) { sha1close(f, sha1, 1); } else { - sha1close(f, sha1, 0); - fixup_pack_header_footer(f->fd, sha1, pack_tmp_name, nr_written); - close(f->fd); + int fd = sha1close(f, NULL, 0); + fixup_pack_header_footer(fd, sha1, pack_tmp_name, nr_written); + close(fd); } if (!pack_to_stdout) { mode_t mode = umask(0); + char *idx_tmp_name, tmpname[PATH_MAX]; umask(mode); mode = 0444 & ~mode; idx_tmp_name = write_idx_file(NULL, - (struct pack_idx_entry **) written_list, nr_written, sha1); + (struct pack_idx_entry **) written_list, + nr_written, sha1); snprintf(tmpname, sizeof(tmpname), "%s-%s.pack", base_name, sha1_to_hex(sha1)); if (adjust_perm(pack_tmp_name, mode)) @@ -672,6 +670,8 @@ static void write_pack_file(void) if (rename(idx_tmp_name, tmpname)) die("unable to rename temporary index file: %s", strerror(errno)); + free(idx_tmp_name); + free(pack_tmp_name); puts(sha1_to_hex(sha1)); } @@ -683,8 +683,7 @@ static void write_pack_file(void) } while (nr_remaining && i < nr_objects); free(written_list); - if (do_progress) - stop_progress(&progress_state); + stop_progress(&progress_state); if (written != nr_result) die("wrote %u objects while expecting %u", written, nr_result); /* @@ -852,8 +851,7 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type, else object_ix[-1 - ix] = nr_objects; - if (progress) - display_progress(&progress_state, nr_objects); + display_progress(progress_state, nr_objects); if (name && no_try_delta(name)) entry->no_try_delta = 1; @@ -1516,8 +1514,7 @@ static void find_deltas(struct object_entry **list, unsigned list_size, progress_lock(); (*processed)++; - if (progress) - display_progress(&progress_state, *processed); + display_progress(progress_state, *processed); progress_unlock(); /* @@ -1714,16 +1711,14 @@ static void prepare_pack(int window, int depth) delta_list[n++] = entry; } - if (nr_deltas) { + if (nr_deltas && n > 1) { unsigned nr_done = 0; if (progress) - start_progress(&progress_state, - "Deltifying %u objects...", "", - nr_deltas); + progress_state = start_progress("Compressing objects", + nr_deltas); qsort(delta_list, n, sizeof(*delta_list), type_size_sort); ll_find_deltas(delta_list, n, window+1, depth, &nr_done); - if (progress) - stop_progress(&progress_state); + stop_progress(&progress_state); if (nr_done != nr_deltas) die("inconsistency with delta count"); } @@ -1807,15 +1802,19 @@ static void read_object_list_from_stdin(void) } } +#define OBJECT_ADDED (1u<<20) + static void show_commit(struct commit *commit) { add_object_entry(commit->object.sha1, OBJ_COMMIT, NULL, 0); + commit->object.flags |= OBJECT_ADDED; } static void show_object(struct object_array_entry *p) { add_preferred_base_object(p->name); add_object_entry(p->item->sha1, p->item->type, p->name, 0); + p->item->flags |= OBJECT_ADDED; } static void show_edge(struct commit *commit) @@ -1823,6 +1822,86 @@ static void show_edge(struct commit *commit) add_preferred_base(commit->object.sha1); } +struct in_pack_object { + off_t offset; + struct object *object; +}; + +struct in_pack { + int alloc; + int nr; + struct in_pack_object *array; +}; + +static void mark_in_pack_object(struct object *object, struct packed_git *p, struct in_pack *in_pack) +{ + in_pack->array[in_pack->nr].offset = find_pack_entry_one(object->sha1, p); + in_pack->array[in_pack->nr].object = object; + in_pack->nr++; +} + +/* + * Compare the objects in the offset order, in order to emulate the + * "git-rev-list --objects" output that produced the pack originally. + */ +static int ofscmp(const void *a_, const void *b_) +{ + struct in_pack_object *a = (struct in_pack_object *)a_; + struct in_pack_object *b = (struct in_pack_object *)b_; + + if (a->offset < b->offset) + return -1; + else if (a->offset > b->offset) + return 1; + else + return hashcmp(a->object->sha1, b->object->sha1); +} + +static void add_objects_in_unpacked_packs(struct rev_info *revs) +{ + struct packed_git *p; + struct in_pack in_pack; + uint32_t i; + + memset(&in_pack, 0, sizeof(in_pack)); + + for (p = packed_git; p; p = p->next) { + const unsigned char *sha1; + struct object *o; + + for (i = 0; i < revs->num_ignore_packed; i++) { + if (matches_pack_name(p, revs->ignore_packed[i])) + break; + } + if (revs->num_ignore_packed <= i) + continue; + if (open_pack_index(p)) + die("cannot open pack index"); + + ALLOC_GROW(in_pack.array, + in_pack.nr + p->num_objects, + in_pack.alloc); + + for (i = 0; i < p->num_objects; i++) { + sha1 = nth_packed_object_sha1(p, i); + o = lookup_unknown_object(sha1); + if (!(o->flags & OBJECT_ADDED)) + mark_in_pack_object(o, p, &in_pack); + o->flags |= OBJECT_ADDED; + } + } + + if (in_pack.nr) { + qsort(in_pack.array, in_pack.nr, sizeof(in_pack.array[0]), + ofscmp); + for (i = 0; i < in_pack.nr; i++) { + struct object *o = in_pack.array[i].object; + add_object_entry(o->sha1, o->type, "", 0); + } + } + free(in_pack.array); +} + static void get_object_list(int ac, const char **av) { struct rev_info revs; @@ -1854,6 +1933,9 @@ static void get_object_list(int ac, const char **av) prepare_revision_walk(&revs); mark_edges_uninteresting(revs.commits, &revs, show_edge); traverse_commit_list(&revs, show_commit, show_object); + + if (keep_unreachable) + add_objects_in_unpacked_packs(&revs); } static int adjust_perm(const char *path, mode_t mode) @@ -1983,6 +2065,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) use_internal_rev_list = 1; continue; } + if (!strcmp("--keep-unreachable", arg)) { + keep_unreachable = 1; + continue; + } if (!strcmp("--unpacked", arg) || !prefixcmp(arg, "--unpacked=") || !strcmp("--reflog", arg) || @@ -2044,23 +2130,17 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) prepare_packed_git(); if (progress) - start_progress(&progress_state, "Generating pack...", - "Counting objects: ", 0); + progress_state = start_progress("Counting objects", 0); if (!use_internal_rev_list) read_object_list_from_stdin(); else { rp_av[rp_ac] = NULL; get_object_list(rp_ac, rp_av); } - if (progress) { - stop_progress(&progress_state); - fprintf(stderr, "Done counting %u objects.\n", nr_objects); - } + stop_progress(&progress_state); if (non_empty && !nr_result) return 0; - if (progress && (nr_objects != nr_result)) - fprintf(stderr, "Result has %u objects.\n", nr_result); if (nr_result) prepare_pack(window, depth); write_pack_file();