summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/count-objects.c44
-rw-r--r--builtin/fsck.c46
-rw-r--r--builtin/gc.c26
-rw-r--r--builtin/pack-objects.c188
-rw-r--r--builtin/pack-redundant.c37
-rw-r--r--cache.h18
-rw-r--r--fast-import.c4
-rw-r--r--http-backend.c28
-rw-r--r--http-push.c4
-rw-r--r--http-walker.c2
-rw-r--r--pack-revindex.c20
-rw-r--r--server-info.c35
-rw-r--r--sha1_file.c35
-rw-r--r--sha1_name.c18
14 files changed, 317 insertions, 188 deletions
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index a7f70cb858..c1a6a2c254 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -83,14 +83,32 @@ static char const * const count_objects_usage[] = {
NULL
};
+struct pack_data {
+ unsigned long packed;
+ off_t size_pack;
+ unsigned long num_pack;
+};
+
+static int collect_pack_data(struct packed_git *p, void *data)
+{
+ struct pack_data *pd = (struct pack_data *) data;
+ if (p->pack_local && !open_pack_index(p)) {
+ pd->packed += p->num_objects;
+ pd->size_pack += p->pack_size + p->index_size;
+ pd->num_pack++;
+ }
+ return 0;
+}
+
int cmd_count_objects(int argc, const char **argv, const char *prefix)
{
int i, verbose = 0, human_readable = 0;
const char *objdir = get_object_directory();
int len = strlen(objdir);
char *path = xmalloc(len + 50);
- unsigned long loose = 0, packed = 0, packed_loose = 0;
+ unsigned long loose = 0, packed_loose = 0;
off_t loose_size = 0;
+ struct pack_data pd = {0, 0, 0};
struct option opts[] = {
OPT__VERBOSE(&verbose, N_("be verbose")),
OPT_BOOL('H', "human-readable", &human_readable,
@@ -118,41 +136,29 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
closedir(d);
}
if (verbose) {
- struct packed_git *p;
- unsigned long num_pack = 0;
- off_t size_pack = 0;
struct strbuf loose_buf = STRBUF_INIT;
struct strbuf pack_buf = STRBUF_INIT;
struct strbuf garbage_buf = STRBUF_INIT;
- if (!packed_git)
- prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
- if (!p->pack_local)
- continue;
- if (open_pack_index(p))
- continue;
- packed += p->num_objects;
- size_pack += p->pack_size + p->index_size;
- num_pack++;
- }
+ prepare_packed_git();
+ foreach_packed_git(collect_pack_data, NULL, &pd);
if (human_readable) {
strbuf_humanise_bytes(&loose_buf, loose_size);
- strbuf_humanise_bytes(&pack_buf, size_pack);
+ strbuf_humanise_bytes(&pack_buf, pd.size_pack);
strbuf_humanise_bytes(&garbage_buf, size_garbage);
} else {
strbuf_addf(&loose_buf, "%lu",
(unsigned long)(loose_size / 1024));
strbuf_addf(&pack_buf, "%lu",
- (unsigned long)(size_pack / 1024));
+ (unsigned long)(pd.size_pack / 1024));
strbuf_addf(&garbage_buf, "%lu",
(unsigned long)(size_garbage / 1024));
}
printf("count: %lu\n", loose);
printf("size: %s\n", loose_buf.buf);
- printf("in-pack: %lu\n", packed);
- printf("packs: %lu\n", num_pack);
+ printf("in-pack: %lu\n", pd.packed);
+ printf("packs: %lu\n", pd.num_pack);
printf("size-pack: %s\n", pack_buf.buf);
printf("prune-packable: %lu\n", packed_loose);
printf("garbage: %lu\n", garbage);
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 1affdd5e92..e55f0803a2 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -624,6 +624,29 @@ static struct option fsck_opts[] = {
OPT_END(),
};
+struct verify_packs_data {
+ struct progress *progress;
+ uint32_t total;
+ uint32_t count;
+};
+
+static int count_packs(struct packed_git *p, void *data)
+{
+ struct verify_packs_data *vpd = (struct verify_packs_data *) data;
+ if (!open_pack_index(p))
+ vpd->total++;
+ return 0;
+}
+
+static int verify_packs(struct packed_git *p, void *data)
+{
+ struct verify_packs_data *vpd = (struct verify_packs_data *) data;
+ if (verify_pack(p, fsck_obj_buffer, vpd->progress, vpd->count))
+ errors_found |= ERROR_PACK;
+ vpd->count += p->num_objects;
+ return 0;
+}
+
int cmd_fsck(int argc, const char **argv, const char *prefix)
{
int i, heads;
@@ -657,29 +680,16 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
}
if (check_full) {
- struct packed_git *p;
- uint32_t total = 0, count = 0;
- struct progress *progress = NULL;
+ struct verify_packs_data vpd = {0, 0, 0};
prepare_packed_git();
if (show_progress) {
- for (p = packed_git; p; p = p->next) {
- if (open_pack_index(p))
- continue;
- total += p->num_objects;
- }
-
- progress = start_progress("Checking objects", total);
- }
- for (p = packed_git; p; p = p->next) {
- /* verify gives error messages itself */
- if (verify_pack(p, fsck_obj_buffer,
- progress, count))
- errors_found |= ERROR_PACK;
- count += p->num_objects;
+ foreach_packed_git(count_packs, NULL, &vpd);
+ vpd.progress = start_progress("Checking objects", vpd.total);
}
- stop_progress(&progress);
+ foreach_packed_git(verify_packs, NULL, &vpd);
+ stop_progress(&vpd.progress);
}
heads = 0;
diff --git a/builtin/gc.c b/builtin/gc.c
index c19545d49e..d9fbbd711e 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -125,26 +125,26 @@ static int too_many_loose_objects(void)
return needed;
}
+static int count_packs(struct packed_git *p, void *data)
+{
+ /*
+ * Perhaps check the size of the pack and count only
+ * very small ones here?
+ */
+ if (p->pack_local && !p->pack_keep)
+ (*((int *) data))++;
+ return 0;
+}
+
static int too_many_packs(void)
{
- struct packed_git *p;
- int cnt;
+ int cnt = 0;
if (gc_auto_pack_limit <= 0)
return 0;
prepare_packed_git();
- for (cnt = 0, p = packed_git; p; p = p->next) {
- if (!p->pack_local)
- continue;
- if (p->pack_keep)
- continue;
- /*
- * Perhaps check the size of the pack and count only
- * very small ones here?
- */
- cnt++;
- }
+ foreach_packed_git(count_packs, NULL, &cnt);
return gc_auto_pack_limit <= cnt;
}
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,
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index 649c3aaa93..0a86132af9 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -567,29 +567,42 @@ static struct pack_list * add_pack(struct packed_git *p)
return pack_list_insert(&altodb_packs, &l);
}
+struct add_pack_data {
+ const char *filename;
+ int found;
+ struct pack_list *added_pack;
+};
+
+static int add_pack_fn(struct packed_git *p, void *data)
+{
+ struct add_pack_data *apd = (struct add_pack_data *) data;
+ if (apd->filename && strstr(p->pack_name, apd->filename)) {
+ apd->found = 1;
+ apd->added_pack = add_pack(p);
+ return 1;
+ } else if (!apd->filename) {
+ add_pack(p);
+ }
+ return 0;
+}
+
static struct pack_list * add_pack_file(const char *filename)
{
- struct packed_git *p = packed_git;
+ struct add_pack_data apd = {filename, 0, NULL};
if (strlen(filename) < 40)
die("Bad pack filename: %s", filename);
- while (p) {
- if (strstr(p->pack_name, filename))
- return add_pack(p);
- p = p->next;
- }
+ foreach_packed_git(add_pack_fn, NULL, &apd);
+ if (apd.found)
+ return apd.added_pack;
die("Filename %s not found in packed_git", filename);
}
static void load_all(void)
{
- struct packed_git *p = packed_git;
-
- while (p) {
- add_pack(p);
- p = p->next;
- }
+ struct add_pack_data apd = {NULL, 0, NULL};
+ foreach_packed_git(add_pack_fn, NULL, &apd);
}
int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
diff --git a/cache.h b/cache.h
index c9efe88e9e..0b5040e316 100644
--- a/cache.h
+++ b/cache.h
@@ -1020,7 +1020,7 @@ struct pack_window {
unsigned int inuse_cnt;
};
-extern struct packed_git {
+struct packed_git {
struct packed_git *next;
struct pack_window *windows;
off_t pack_size;
@@ -1038,7 +1038,7 @@ extern struct packed_git {
unsigned char sha1[20];
/* something like ".git/objects/pack/xxxxx.pack" */
char pack_name[FLEX_ARRAY]; /* more */
-} *packed_git;
+};
struct pack_entry {
off_t offset;
@@ -1046,6 +1046,20 @@ struct pack_entry {
struct packed_git *p;
};
+/*
+ * packed_git_foreach_fn implementations should return zero
+ * to continue the traversal, non-zero to halt.
+ */
+typedef int (*packed_git_foreach_fn)(struct packed_git *, void *);
+
+/*
+ * The 'hint' argument is for the commonly-used 'last found pack' optimization.
+ * It can be NULL.
+ */
+extern void foreach_packed_git(packed_git_foreach_fn fn, struct packed_git *hint, void *data);
+
+extern size_t packed_git_count(void);
+extern size_t packed_git_local_count(void);
extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
/* A hook for count-objects to report invalid files in pack directory */
diff --git a/fast-import.c b/fast-import.c
index 4fd18a3574..11d1f227b7 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1037,7 +1037,7 @@ static int store_object(
if (e->idx.offset) {
duplicate_count_by_type[type]++;
return 1;
- } else if (find_sha1_pack(sha1, packed_git)) {
+ } else if (find_sha1_pack(sha1, NULL)) {
e->type = type;
e->pack_id = MAX_PACK_ID;
e->idx.offset = 1; /* just not zero! */
@@ -1238,7 +1238,7 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark)
duplicate_count_by_type[OBJ_BLOB]++;
truncate_pack(&checkpoint);
- } else if (find_sha1_pack(sha1, packed_git)) {
+ } else if (find_sha1_pack(sha1, NULL)) {
e->type = OBJ_BLOB;
e->pack_id = MAX_PACK_ID;
e->idx.offset = 1; /* just not zero! */
diff --git a/http-backend.c b/http-backend.c
index d2c0a625ce..cf1f2a4372 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -438,25 +438,29 @@ static void get_head(char *arg)
strbuf_release(&buf);
}
+struct pack_info_data {
+ struct strbuf *buf;
+ size_t objdirlen;
+};
+
+static int append_pack_info_fn(struct packed_git *p, void *data)
+{
+ struct pack_info_data *d = (struct pack_info_data *) data;
+ if (p->pack_local)
+ strbuf_addf(d->buf, "P %s\n", p->pack_name + d->objdirlen + 6);
+ return 0;
+}
+
static void get_info_packs(char *arg)
{
size_t objdirlen = strlen(get_object_directory());
struct strbuf buf = STRBUF_INIT;
- struct packed_git *p;
- size_t cnt = 0;
+ struct pack_info_data d = {&buf, objdirlen};
select_getanyfile();
prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
- if (p->pack_local)
- cnt++;
- }
-
- strbuf_grow(&buf, cnt * 53 + 2);
- for (p = packed_git; p; p = p->next) {
- if (p->pack_local)
- strbuf_addf(&buf, "P %s\n", p->pack_name + objdirlen + 6);
- }
+ strbuf_grow(&buf, packed_git_local_count() * 53 + 2);
+ foreach_packed_git(append_pack_info_fn, NULL, &d);
strbuf_addch(&buf, '\n');
hdr_nocache();
diff --git a/http-push.c b/http-push.c
index d4b40c9c60..f2c4256312 100644
--- a/http-push.c
+++ b/http-push.c
@@ -304,7 +304,7 @@ static void start_fetch_packed(struct transfer_request *request)
struct transfer_request *check_request = request_queue_head;
struct http_pack_request *preq;
- target = find_sha1_pack(request->obj->sha1, repo->packs);
+ target = repo->packs ? find_sha1_pack(request->obj->sha1, repo->packs) : NULL;
if (!target) {
fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1));
repo->can_update_info_refs = 0;
@@ -677,7 +677,7 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
get_remote_object_list(obj->sha1[0]);
if (obj->flags & (REMOTE | PUSHING))
return 0;
- target = find_sha1_pack(obj->sha1, repo->packs);
+ target = repo->packs ? find_sha1_pack(obj->sha1, repo->packs) : NULL;
if (target) {
obj->flags |= REMOTE;
return 0;
diff --git a/http-walker.c b/http-walker.c
index 1516c5eb29..d9d758ad95 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -405,7 +405,7 @@ static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigne
if (fetch_indices(walker, repo))
return -1;
- target = find_sha1_pack(sha1, repo->packs);
+ target = repo->packs ? find_sha1_pack(sha1, repo->packs) : NULL;
if (!target)
return -1;
diff --git a/pack-revindex.c b/pack-revindex.c
index b4d2b35bb3..40785f754d 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -40,23 +40,25 @@ static int pack_revindex_ix(struct packed_git *p)
return -1 - i;
}
+static int init_pack_revindex_fn(struct packed_git *p, void *data)
+{
+ /* revindex elements are lazily initialized */
+ int num = pack_revindex_ix(p);
+ num = -1 - num;
+ pack_revindex[num].p = p;
+ return 0;
+}
+
static void init_pack_revindex(void)
{
int num;
- struct packed_git *p;
- for (num = 0, p = packed_git; p; p = p->next)
- num++;
+ num = packed_git_count();
if (!num)
return;
pack_revindex_hashsz = num * 11;
pack_revindex = xcalloc(sizeof(*pack_revindex), pack_revindex_hashsz);
- for (p = packed_git; p; p = p->next) {
- num = pack_revindex_ix(p);
- num = - 1 - num;
- pack_revindex[num].p = p;
- }
- /* revindex elements are lazily initialized */
+ foreach_packed_git(init_pack_revindex_fn, NULL, NULL);
}
/*
diff --git a/server-info.c b/server-info.c
index 9ec744e9f2..70e5a26177 100644
--- a/server-info.c
+++ b/server-info.c
@@ -151,9 +151,20 @@ static int compare_info(const void *a_, const void *b_)
return 1;
}
+static int init_pack_info_fn(struct packed_git *p, void *data)
+{
+ int *idx = (int *) data;
+ if (p->pack_local) {
+ info[*idx] = xcalloc(1, sizeof(struct pack_info));
+ info[*idx]->p = p;
+ info[*idx]->old_num = -1;
+ (*idx)++;
+ }
+ return 0;
+}
+
static void init_pack_info(const char *infofile, int force)
{
- struct packed_git *p;
int stale;
int i = 0;
@@ -161,24 +172,12 @@ static void init_pack_info(const char *infofile, int force)
objdirlen = strlen(objdir);
prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
- /* we ignore things on alternate path since they are
- * not available to the pullers in general.
- */
- if (!p->pack_local)
- continue;
- i++;
- }
- num_pack = i;
+ /* we ignore things on alternate path since they are
+ * not available to the pullers in general.
+ */
+ num_pack = packed_git_local_count();
info = xcalloc(num_pack, sizeof(struct pack_info *));
- for (i = 0, p = packed_git; p; p = p->next) {
- if (!p->pack_local)
- continue;
- info[i] = xcalloc(1, sizeof(struct pack_info));
- info[i]->p = p;
- info[i]->old_num = -1;
- i++;
- }
+ foreach_packed_git(init_pack_info_fn, NULL, &i);
if (infofile && !force)
stale = read_pack_info_file(infofile);
diff --git a/sha1_file.c b/sha1_file.c
index e13bd2c3ee..6bca45c9f6 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -60,6 +60,7 @@ static struct cached_object empty_tree = {
0
};
+static struct packed_git *packed_git;
static struct packed_git *last_found_pack;
static struct cached_object *find_cached_object(const unsigned char *sha1)
@@ -455,7 +456,6 @@ static unsigned int pack_open_fds;
static unsigned int pack_max_fds;
static size_t peak_pack_mapped;
static size_t pack_mapped;
-struct packed_git *packed_git;
void pack_report(void)
{
@@ -1078,6 +1078,37 @@ struct packed_git *add_packed_git(const char *path, int path_len, int local)
return p;
}
+void foreach_packed_git(packed_git_foreach_fn fn, struct packed_git *hint, void *data)
+{
+ struct packed_git *p;
+ if (hint && ((*fn)(hint, data)))
+ return;
+ for (p = packed_git; p; p = p->next)
+ if (p != hint && (*fn)(p, data))
+ return;
+}
+
+size_t packed_git_count(void)
+{
+ size_t res = 0;
+ struct packed_git *p;
+
+ for (p = packed_git; p; p = p->next)
+ ++res;
+ return res;
+}
+
+size_t packed_git_local_count(void)
+{
+ size_t res = 0;
+ struct packed_git *p;
+
+ for (p = packed_git; p; p = p->next)
+ if (p->pack_local)
+ ++res;
+ return res;
+}
+
struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
{
const char *path = sha1_pack_name(sha1);
@@ -2461,6 +2492,8 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,
{
struct packed_git *p;
+ if (!packs)
+ packs = packed_git;
for (p = packs; p; p = p->next) {
if (find_pack_entry_one(sha1, p))
return p;
diff --git a/sha1_name.c b/sha1_name.c
index a5578f718e..c1f24a1b43 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -176,14 +176,26 @@ static void unique_in_pack(int len,
}
}
+struct disambiguate_data {
+ int len;
+ const unsigned char *bin_pfx;
+ struct disambiguate_state *ds;
+};
+
+static int find_short_packed_object_fn(struct packed_git *p, void *data)
+{
+ struct disambiguate_data *d = (struct disambiguate_data *) data;
+ unique_in_pack(d->len, d->bin_pfx, p, d->ds);
+ return 0;
+}
+
static void find_short_packed_object(int len, const unsigned char *bin_pfx,
struct disambiguate_state *ds)
{
- struct packed_git *p;
+ struct disambiguate_data d = {len, bin_pfx, ds};
prepare_packed_git();
- for (p = packed_git; p && !ds->ambiguous; p = p->next)
- unique_in_pack(len, bin_pfx, p, ds);
+ foreach_packed_git(find_short_packed_object_fn, NULL, &d);
}
#define SHORT_NAME_NOT_FOUND (-1)