Skip to content

Commit

Permalink
Merge fighting fsck-cache updates from Junio
Browse files Browse the repository at this point in the history
It's just easier to let git help out with the merge than it is to try to
fix up the diffs.
  • Loading branch information
Linus Torvalds committed Jun 28, 2005
2 parents d85a4fe + 8a498a0 commit fead283
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 28 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
19 changes: 19 additions & 0 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,23 @@ struct checkout {

extern int checkout_entry(struct cache_entry *ce, struct checkout *state);

extern struct alternate_object_database {
char *base;
char *name;
} *alt_odb;
extern void prepare_alt_odb(void);

extern struct packed_git {
struct packed_git *next;
unsigned long index_size;
unsigned long pack_size;
unsigned int *index_base;
void *pack_base;
unsigned int pack_last_used;
char pack_name[0]; /* something like ".git/objects/pack/xxxxx.pack" */
} *packed_git;
extern void prepare_packed_git(void);
extern int num_packed_objects(const struct packed_git *p);
extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*);

#endif /* CACHE_H */
51 changes: 43 additions & 8 deletions fsck-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ 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 Down Expand Up @@ -374,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 @@ -402,17 +413,41 @@ int main(int argc, char **argv)
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
43 changes: 24 additions & 19 deletions sha1_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,7 @@ char *sha1_file_name(const unsigned char *sha1)
return base;
}

static struct alternate_object_database {
char *base;
char *name;
} *alt_odb;
struct alternate_object_database *alt_odb;

/*
* Prepare alternate object database registry.
Expand All @@ -206,13 +203,15 @@ static struct alternate_object_database {
* pointed by base fields of the array elements with one xmalloc();
* the string pool immediately follows the array.
*/
static void prepare_alt_odb(void)
void prepare_alt_odb(void)
{
int pass, totlen, i;
const char *cp, *last;
char *op = NULL;
const char *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : "";

if (alt_odb)
return;
/* The first pass counts how large an area to allocate to
* hold the entire alt_odb structure, including array of
* structs and path buffers for them. The second pass fills
Expand Down Expand Up @@ -259,8 +258,7 @@ static char *find_sha1_file(const unsigned char *sha1, struct stat *st)

if (!stat(name, st))
return name;
if (!alt_odb)
prepare_alt_odb();
prepare_alt_odb();
for (i = 0; (name = alt_odb[i].name) != NULL; i++) {
fill_sha1_path(name, sha1);
if (!stat(alt_odb[i].base, st))
Expand All @@ -272,15 +270,7 @@ static char *find_sha1_file(const unsigned char *sha1, struct stat *st)
#define PACK_MAX_SZ (1<<26)
static int pack_used_ctr;
static unsigned long pack_mapped;
static struct packed_git {
struct packed_git *next;
unsigned long index_size;
unsigned long pack_size;
unsigned int *index_base;
void *pack_base;
unsigned int pack_last_used;
char pack_name[0]; /* something like ".git/objects/pack/xxxxx.pack" */
} *packed_git;
struct packed_git *packed_git;

struct pack_entry {
unsigned int offset;
Expand Down Expand Up @@ -431,7 +421,7 @@ static void prepare_packed_git_one(char *objdir)
}
}

static void prepare_packed_git(void)
void prepare_packed_git(void)
{
int i;
static int run_once = 0;
Expand All @@ -440,8 +430,7 @@ static void prepare_packed_git(void)
return;

prepare_packed_git_one(get_object_directory());
if (!alt_odb)
prepare_alt_odb();
prepare_alt_odb();
for (i = 0; alt_odb[i].base != NULL; i++) {
alt_odb[i].name[0] = 0;
prepare_packed_git_one(alt_odb[i].base);
Expand Down Expand Up @@ -842,6 +831,22 @@ static void *unpack_entry(struct pack_entry *entry,
return unpack_non_delta_entry(pack, size, left);
}

int num_packed_objects(const struct packed_git *p)
{
/* See check_packed_git_idx and pack-objects.c */
return (p->index_size - 20 - 20 - 4*256) / 24;
}

int nth_packed_object_sha1(const struct packed_git *p, int n,
unsigned char* sha1)
{
void *index = p->index_base + 256;
if (n < 0 || num_packed_objects(p) <= n)
return -1;
memcpy(sha1, (index + 24 * n + 4), 20);
return 0;
}

static int find_pack_entry_1(const unsigned char *sha1,
struct pack_entry *e, struct packed_git *p)
{
Expand Down

0 comments on commit fead283

Please sign in to comment.