Skip to content

Commit

Permalink
[PATCH] Update fsck-cache (take 2)
Browse files Browse the repository at this point in the history
The fsck-cache complains if objects referred to by files in .git/refs/
or objects stored in files under .git/objects/??/ are not found as
stand-alone SHA1 files (i.e.  found in alternate object pools
GIT_ALTERNATE_OBJECT_DIRECTORIES or packed archives stored under
.git/objects/pack).

Although this is a good semantics to maintain consistency of a single
.git/objects directory as a self contained set of objects, it sometimes
is useful to consider it is OK as long as these "outside" objects are
available.

This commit introduces a new flag, --standalone, to git-fsck-cache.
When it is not specified, connectivity checks and .git/refs pointer
checks are taught that it is OK when expected objects do not exist under
.git/objects/?? hierarchy but are available from an packed archive or in
an alternate object pool.

Another new flag, --full, makes git-fsck-cache to check not only the
current GIT_OBJECT_DIRECTORY but also objects found in alternate object
pools and packed GIT archives.a

Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Junio C Hamano authored and Linus Torvalds committed Jun 28, 2005
1 parent 9a217f2 commit 8a498a0
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 13 deletions.
18 changes: 17 additions & 1 deletion Documentation/git-fsck-cache.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ git-fsck-cache - Verifies the connectivity and validity of the objects in the da

SYNOPSIS
--------
'git-fsck-cache' [--tags] [--root] [--unreachable] [--cache] [<object>*]
'git-fsck-cache' [--tags] [--root] [--unreachable] [--cache] [--standalone | --full] [<object>*]

DESCRIPTION
-----------
Expand Down Expand Up @@ -37,6 +37,22 @@ OPTIONS
Consider any object recorded in the cache also as a head node for
an unreachability trace.

--standalone::
Limit checks to the contents of GIT_OBJECT_DIRECTORY
(.git/objects), making sure that it is consistent and
complete without referring to objects found in alternate
object pools listed in GIT_ALTERNATE_OBJECT_DIRECTORIES,
nor packed GIT archives found in .git/objects/pack;
cannot be used with --full.

--full::
Check not just objects in GIT_OBJECT_DIRECTORY
(.git/objects), but also the ones found in alternate
object pools listed in GIT_ALTERNATE_OBJECT_DIRECTORIES,
and in packed GIT archives found in .git/objects/pack
and corresponding pack subdirectories in alternate
object pools; cannot be used with --standalone.

It tests SHA1 and general object sanity, and it does full tracking of
the resulting reachability and everything else. It prints out any
corruption it finds (missing or bad objects), and if you use the
Expand Down
71 changes: 59 additions & 12 deletions fsck-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
static int show_root = 0;
static int show_tags = 0;
static int show_unreachable = 0;
static int standalone = 0;
static int check_full = 0;
static int keep_cache_objects = 0;
static unsigned char head_sha1[20];

Expand All @@ -25,13 +27,17 @@ static void check_connectivity(void)
struct object_list *refs;

if (!obj->parsed) {
printf("missing %s %s\n",
obj->type, sha1_to_hex(obj->sha1));
if (!standalone && has_sha1_file(obj->sha1))
; /* it is in pack */
else
printf("missing %s %s\n",
obj->type, sha1_to_hex(obj->sha1));
continue;
}

for (refs = obj->refs; refs; refs = refs->next) {
if (refs->item->parsed)
if (refs->item->parsed ||
(!standalone && has_sha1_file(refs->item->sha1)))
continue;
printf("broken link from %7s %s\n",
obj->type, sha1_to_hex(obj->sha1));
Expand Down Expand Up @@ -315,8 +321,11 @@ static int read_sha1_reference(const char *path)
return -1;

obj = lookup_object(sha1);
if (!obj)
if (!obj) {
if (!standalone && has_sha1_file(sha1))
return 0; /* it is in pack */
return error("%s: invalid sha1 pointer %.40s", path, hexname);
}

obj->used = 1;
mark_reachable(obj, REACHABLE);
Expand Down Expand Up @@ -366,10 +375,20 @@ static void get_default_heads(void)
die("No default references");
}

static void fsck_object_dir(const char *path)
{
int i;
for (i = 0; i < 256; i++) {
static char dir[4096];
sprintf(dir, "%s/%02x", path, i);
fsck_dir(i, dir);
}
fsck_sha1_list();
}

int main(int argc, char **argv)
{
int i, heads;
char *sha1_dir;

for (i = 1; i < argc; i++) {
const char *arg = argv[i];
Expand All @@ -390,17 +409,45 @@ int main(int argc, char **argv)
keep_cache_objects = 1;
continue;
}
if (!strcmp(arg, "--standalone")) {
standalone = 1;
continue;
}
if (!strcmp(arg, "--full")) {
check_full = 1;
continue;
}
if (*arg == '-')
usage("git-fsck-cache [--tags] [[--unreachable] [--cache] <head-sha1>*]");
usage("git-fsck-cache [--tags] [[--unreachable] [--cache] [--standalone | --full] <head-sha1>*]");
}

sha1_dir = get_object_directory();
for (i = 0; i < 256; i++) {
static char dir[4096];
sprintf(dir, "%s/%02x", sha1_dir, i);
fsck_dir(i, dir);
if (standalone && check_full)
die("Only one of --standalone or --full can be used.");
if (standalone)
unsetenv("GIT_ALTERNATE_OBJECT_DIRECTORIES");

fsck_object_dir(get_object_directory());
if (check_full) {
int j;
struct packed_git *p;
prepare_alt_odb();
for (j = 0; alt_odb[j].base; j++) {
alt_odb[j].name[-1] = 0; /* was slash */
fsck_object_dir(alt_odb[j].base);
alt_odb[j].name[-1] = '/';
}
prepare_packed_git();
for (p = packed_git; p; p = p->next) {
int num = num_packed_objects(p);
for (i = 0; i < num; i++) {
unsigned char sha1[20];
nth_packed_object_sha1(p, i, sha1);
if (fsck_sha1(sha1) < 0)
fprintf(stderr, "bad sha1 entry '%s'\n", sha1_to_hex(sha1));

}
}
}
fsck_sha1_list();

heads = 0;
for (i = 1; i < argc; i++) {
Expand Down

0 comments on commit 8a498a0

Please sign in to comment.