diff options
Diffstat (limited to 'builtin/pack-objects.c')
-rw-r--r-- | builtin/pack-objects.c | 188 |
1 files changed, 112 insertions, 76 deletions
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 541667f102..bc3074b30c 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -900,14 +900,45 @@ static int no_try_delta(const char *path) return 0; } +struct find_pack_data { + const unsigned char *sha1; + off_t offset; + struct packed_git *found_pack; + int exclude; + int found_non_local_pack; + int found_pack_keep; +}; + +static int find_pack_fn(struct packed_git *p, void *data) +{ + struct find_pack_data *fpd = (struct find_pack_data *) data; + off_t offset = find_pack_entry_one(fpd->sha1, p); + if (offset) { + if (!fpd->found_pack) { + if (!is_pack_valid(p)) { + warning("packfile %s cannot be accessed", p->pack_name); + return 0; + } + fpd->offset = offset; + fpd->found_pack = p; + } + if (fpd->exclude) + return 1; + if (!p->pack_local) + fpd->found_non_local_pack = 1; + else if (p->pack_keep) + fpd->found_pack_keep = 1; + } + return 0; +} + static int add_object_entry(const unsigned char *sha1, enum object_type type, const char *name, int exclude) { struct object_entry *entry; - struct packed_git *p, *found_pack = NULL; - off_t found_offset = 0; int ix; uint32_t hash = name_hash(name); + struct find_pack_data fpd; ix = nr_objects ? locate_object_entry_hash(sha1) : -1; if (ix >= 0) { @@ -923,27 +954,18 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type, 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) { - if (!found_pack) { - if (!is_pack_valid(p)) { - warning("packfile %s cannot be accessed", p->pack_name); - continue; - } - found_offset = offset; - found_pack = p; - } - if (exclude) - break; - if (incremental) - return 0; - if (local && !p->pack_local) - return 0; - if (ignore_packed_keep && p->pack_local && p->pack_keep) - return 0; - } - } + fpd.sha1 = sha1; + fpd.offset = 0; + fpd.found_pack = NULL; + fpd.exclude = exclude; + fpd.found_non_local_pack = fpd.found_pack_keep = 0; + + foreach_packed_git(find_pack_fn, NULL, &fpd); + if (fpd.found_pack && !exclude && + (incremental || + (local && fpd.found_non_local_pack) || + (ignore_packed_keep && fpd.found_pack_keep))) + return 0; if (nr_objects >= nr_alloc) { nr_alloc = (nr_alloc + 1024) * 3 / 2; @@ -960,9 +982,9 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type, entry->preferred_base = 1; else nr_result++; - if (found_pack) { - entry->in_pack = found_pack; - entry->in_pack_offset = found_offset; + if (fpd.found_pack) { + entry->in_pack = fpd.found_pack; + entry->in_pack_offset = fpd.offset; } if (object_ix_hashsz * 3 <= nr_objects * 4) @@ -2257,35 +2279,40 @@ static int ofscmp(const void *a_, const void *b_) return hashcmp(a->object->sha1, b->object->sha1); } -static void add_objects_in_unpacked_packs(struct rev_info *revs) +static int add_objects_fn(struct packed_git *p, void *data) { - struct packed_git *p; - struct in_pack in_pack; + struct in_pack *ip = (struct in_pack *) data; uint32_t i; + const unsigned char *sha1; + struct object *o; - memset(&in_pack, 0, sizeof(in_pack)); - - for (p = packed_git; p; p = p->next) { - const unsigned char *sha1; - struct object *o; - - if (!p->pack_local || p->pack_keep) - continue; + if (p->pack_local && !p->pack_keep) { if (open_pack_index(p)) die("cannot open pack index"); - ALLOC_GROW(in_pack.array, - in_pack.nr + p->num_objects, - in_pack.alloc); + ALLOC_GROW(ip->array, + ip->nr + p->num_objects, + ip->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); + mark_in_pack_object(o, p, ip); o->flags |= OBJECT_ADDED; } } + return 0; +} + +static void add_objects_in_unpacked_packs(struct rev_info *revs) +{ + struct in_pack in_pack; + uint32_t i; + + memset(&in_pack, 0, sizeof(in_pack)); + + foreach_packed_git(add_objects_fn, NULL, &in_pack); if (in_pack.nr) { qsort(in_pack.array, in_pack.nr, sizeof(in_pack.array[0]), @@ -2298,54 +2325,63 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs) free(in_pack.array); } +struct nonlocal_or_keep_data { + struct packed_git **last_found; + const unsigned char *sha1; + int found; +}; + +static int find_nonlocal_or_keep_fn(struct packed_git *p, void *data) +{ + struct nonlocal_or_keep_data *d = (struct nonlocal_or_keep_data *) data; + if ((!p->pack_local || p->pack_keep) && + find_pack_entry_one(d->sha1, p)) { + *d->last_found = p; + d->found = 1; + return 1; + } + return 0; +} + static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1) { static struct packed_git *last_found = (void *)1; - struct packed_git *p; + struct nonlocal_or_keep_data d; + struct packed_git *hint; - p = (last_found != (void *)1) ? last_found : packed_git; + d.last_found = &last_found; + d.sha1 = sha1; + d.found = 0; - while (p) { - if ((!p->pack_local || p->pack_keep) && - find_pack_entry_one(sha1, p)) { - last_found = p; - return 1; - } - if (p == last_found) - p = packed_git; - else - p = p->next; - if (p == last_found) - p = p->next; - } - return 0; + hint = (last_found != (void *)1) ? last_found : NULL; + + foreach_packed_git(find_nonlocal_or_keep_fn, hint, &d); + return d.found; } -static void loosen_unused_packed_objects(struct rev_info *revs) +static int loosen_unused_objects_fn(struct packed_git *p, void *data) { - struct packed_git *p; + const unsigned char *sha1 = (const unsigned char *) data; uint32_t i; - const unsigned char *sha1; - for (p = packed_git; p; p = p->next) { - if (!p->pack_local || p->pack_keep) - continue; + if (!p->pack_local || p->pack_keep) + return 0; - if (unpack_unreachable_expiration && - p->mtime < unpack_unreachable_expiration) - continue; + if (unpack_unreachable_expiration && + p->mtime < unpack_unreachable_expiration) + return 0; - if (open_pack_index(p)) - die("cannot open pack index"); + if (open_pack_index(p)) + die("cannot open pack index"); - for (i = 0; i < p->num_objects; i++) { - sha1 = nth_packed_object_sha1(p, i); - if (!locate_object_entry(sha1) && - !has_sha1_pack_kept_or_nonlocal(sha1)) - if (force_object_loose(sha1, p->mtime)) - die("unable to force loose object"); - } + for (i = 0; i < p->num_objects; i++) { + sha1 = nth_packed_object_sha1(p, i); + if (!locate_object_entry(sha1) && + !has_sha1_pack_kept_or_nonlocal(sha1)) + if (force_object_loose(sha1, p->mtime)) + die("unable to force loose object"); } + return 0; } static void get_object_list(int ac, const char **av) @@ -2383,7 +2419,7 @@ static void get_object_list(int ac, const char **av) if (keep_unreachable) add_objects_in_unpacked_packs(&revs); if (unpack_unreachable) - loosen_unused_packed_objects(&revs); + foreach_packed_git(loosen_unused_objects_fn, NULL, NULL); } static int option_parse_index_version(const struct option *opt, |