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>
This commit is contained in:
parent
95143f9e68
commit
17815501a8
@ -446,6 +446,12 @@ gc.auto::
|
||||
light-weight garbage collection from time to time. Setting
|
||||
this to 0 disables it.
|
||||
|
||||
gc.autopacklimit::
|
||||
When there are more than this many packs that are not
|
||||
marked with `*.keep` file in the repository, `git gc
|
||||
--auto` consolidates them into one larger pack. Setting
|
||||
this to 0 disables this.
|
||||
|
||||
gc.packrefs::
|
||||
`git gc` does not run `git pack-refs` in a bare repository by
|
||||
default so that older dumb-transport clients can still fetch
|
||||
|
@ -47,10 +47,15 @@ OPTIONS
|
||||
With this option, `git gc` checks if there are too many
|
||||
loose objects in the repository and runs
|
||||
gitlink:git-repack[1] with `-d -l` option to pack them.
|
||||
The threshold is set with `gc.auto` configuration
|
||||
The threshold for loose objects is set with `gc.auto` configuration
|
||||
variable, and can be disabled by setting it to 0. Some
|
||||
Porcelain commands use this after they perform operation
|
||||
that could create many loose objects automatically.
|
||||
Additionally, when there are too many packs are present,
|
||||
they are consolidated into one larger pack by running
|
||||
the `git-repack` command with `-A` option. The
|
||||
threshold for number of packs is set with
|
||||
`gc.autopacklimit` configuration variable.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
60
builtin-gc.c
60
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;
|
||||
|
Loading…
Reference in New Issue
Block a user