summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-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
5 files changed, 203 insertions, 138 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)