Browse Source

Add connectivity tracking to fsck.

This shows that I've lost track of one commit already. Most likely
because I forgot to update the .dircache/HEAD file when doing a
commit, so that the next commit referenced not the top-of-tree, but
the one older commit.

Having dangling commits is fine (in fact, you should always have
at least _one_ dangling commit in the top-of-tree). But it's
good to know about them.
maint
Linus Torvalds 20 years ago
parent
commit
8ba0bbb237
  1. 104
      fsck-cache.c

104
fsck-cache.c

@ -3,18 +3,113 @@ @@ -3,18 +3,113 @@
#include <sys/types.h>
#include <dirent.h>

struct needs {
unsigned char parent[20];
unsigned char needs[20];
char tag[10];
};

struct seen {
unsigned char sha1[20];
char tag[10];
unsigned needed;
};

static struct needs *needs;
static struct seen *seen;

static int nr_seen, alloc_seen, nr_needs, alloc_needs;

/*
* These two functions should build up a graph in memory about
* These two functions build up a graph in memory about
* what objects we've referenced, and found, and types..
*
* Right now we don't do that kind of reachability checking. Yet.
*/
static void mark_needs_sha1(unsigned char *parent, const char * type, unsigned char *child)
static int compare_seen(const void *s1, const void *s2)
{
return memcmp(s1, s2, 20);
}

static int lookup_seen(unsigned char *sha1, char *tag)
{
int first = 0, last = nr_seen;

while (last > first) {
int next = (last + first) / 2;
struct seen *s = seen + next;
int cmp = memcmp(sha1, s->sha1, 20);

if (cmp < 0) {
last = next;
continue;
}
if (cmp > 0) {
first = next+1;
continue;
}
if (strcmp(tag, s->tag))
break;
s->needed++;
return 1;
}
return 0;
}

static void check_connectivity(void)
{
int i;

/* Sort the "seen" tags for quicker lookup */
qsort(seen, nr_seen, sizeof(struct seen), compare_seen);

/* Look up all the requirements, warn about missing objects.. */
for (i = 0; i < nr_needs; i++) {
struct needs *n = needs + i;
char hex[60];

if (lookup_seen(n->needs, n->tag))
continue;
strcpy(hex, sha1_to_hex(n->parent));
}

/* Tell the user about things not referenced.. */
for (i = 0; i < nr_seen; i++) {
struct seen *s = seen + i;

if (s->needed)
continue;
printf("unreferenced %s: %s\n", s->tag, sha1_to_hex(s->sha1));
}
}

static void mark_needs_sha1(unsigned char *parent, const char * tag, unsigned char *child)
{
struct needs *n;

if (nr_needs == alloc_needs) {
alloc_needs = alloc_nr(alloc_needs);
needs = realloc(needs, alloc_needs*sizeof(struct needs));
}
n = needs + nr_needs;
nr_needs++;
memcpy(n->parent, parent, 20);
memcpy(n->needs, child, 20);
strncpy(n->tag, tag, sizeof(n->tag));
}

static int mark_sha1_seen(unsigned char *sha1, char *tag)
{
struct seen *s;

if (nr_seen == alloc_seen) {
alloc_seen = alloc_nr(alloc_seen);
seen = realloc(seen, alloc_seen*sizeof(struct seen));
}
s = seen + nr_seen;
memset(s, 0, sizeof(s));
nr_seen++;
memcpy(s->sha1, sha1, 20);
strncpy(s->tag, tag, sizeof(s->tag));
return 0;
}

@ -150,5 +245,6 @@ int main(int argc, char **argv) @@ -150,5 +245,6 @@ int main(int argc, char **argv)
sprintf(dir, "%s/%02x", sha1_dir, i);
fsck_dir(i, dir);
}
check_connectivity();
return 0;
}
Loading…
Cancel
Save