diff options
author | Junio C Hamano <gitster@pobox.com> | 2007-09-17 00:55:13 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2007-09-17 23:12:16 -0700 |
commit | 17815501a8f95c080891acd9537514adfe17c80e (patch) | |
tree | 24a58abb997d75c363997883ebde4032ea0ebbc7 /builtin-gc.c | |
parent | 95143f9e686dee144e0ff4a20190b923e20e1b64 (diff) | |
download | git-17815501a8f95c080891acd9537514adfe17c80e.tar.gz |
git-gc --auto: run "repack -A -d -l" as necessary.
This teaches "git-gc --auto" to consolidate many packs into one
without losing unreachable objects in them by using "repack -A"
when there are too many packfiles that are not marked with *.keep
in the repository. gc.autopacklimit configuration can be used
to set the maximum number of packs a repository is allowed to
have before this mechanism kicks in.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin-gc.c')
-rw-r--r-- | builtin-gc.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/builtin-gc.c b/builtin-gc.c index 34ce35befb..23ad2b6a21 100644 --- a/builtin-gc.c +++ b/builtin-gc.c @@ -21,6 +21,7 @@ static const char builtin_gc_usage[] = "git-gc [--prune] [--aggressive]"; static int pack_refs = 1; static int aggressive_window = -1; static int gc_auto_threshold = 6700; +static int gc_auto_pack_limit = 20; #define MAX_ADD 10 static const char *argv_pack_refs[] = {"pack-refs", "--all", "--prune", NULL}; @@ -46,6 +47,10 @@ static int gc_config(const char *var, const char *value) gc_auto_threshold = git_config_int(var, value); return 0; } + if (!strcmp(var, "gc.autopacklimit")) { + gc_auto_pack_limit = git_config_int(var, value); + return 0; + } return git_default_config(var, value); } @@ -78,6 +83,9 @@ static int too_many_loose_objects(void) int num_loose = 0; int needed = 0; + if (gc_auto_threshold <= 0) + return 0; + if (sizeof(path) <= snprintf(path, sizeof(path), "%s/17", objdir)) { warning("insanely long object directory %.*s", 50, objdir); return 0; @@ -100,21 +108,61 @@ static int too_many_loose_objects(void) return needed; } +static int too_many_packs(void) +{ + struct packed_git *p; + int cnt; + + if (gc_auto_pack_limit <= 0) + return 0; + + prepare_packed_git(); + for (cnt = 0, p = packed_git; p; p = p->next) { + char path[PATH_MAX]; + size_t len; + int keep; + + if (!p->pack_local) + continue; + len = strlen(p->pack_name); + if (PATH_MAX <= len + 1) + continue; /* oops, give up */ + memcpy(path, p->pack_name, len-5); + memcpy(path + len - 5, ".keep", 6); + keep = access(p->pack_name, F_OK) && (errno == ENOENT); + if (keep) + continue; + /* + * Perhaps check the size of the pack and count only + * very small ones here? + */ + cnt++; + } + return gc_auto_pack_limit <= cnt; +} + static int need_to_gc(void) { int ac = 0; /* - * Setting gc.auto to 0 or negative can disable the - * automatic gc + * Setting gc.auto and gc.autopacklimit to 0 or negative can + * disable the automatic gc. */ - if (gc_auto_threshold <= 0) - return 0; - - if (!too_many_loose_objects()) + if (gc_auto_threshold <= 0 && gc_auto_pack_limit <= 0) return 0; + /* + * If there are too many loose objects, but not too many + * packs, we run "repack -d -l". If there are too many packs, + * we run "repack -A -d -l". Otherwise we tell the caller + * there is no need. + */ argv_repack[ac++] = "repack"; + if (too_many_packs()) + argv_repack[ac++] = "-A"; + else if (!too_many_loose_objects()) + return 0; argv_repack[ac++] = "-d"; argv_repack[ac++] = "-l"; argv_repack[ac++] = NULL; |