Alternate object pool mechanism updates.
It was a mistake to use GIT_ALTERNATE_OBJECT_DIRECTORIES environment variable to specify what alternate object pools to look for missing objects when working with an object database. It is not a property of the process running the git commands, but a property of the object database that is partial and needs other object pools to complete the set of objects it lacks. This patch allows you to have $GIT_OBJECT_DIRECTORY/info/alternates whose contents is in exactly the same format as the environment variable, to let an object database name alternate object pools it depends on. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
3f971fc425
commit
d5a63b9983
5
cache.h
5
cache.h
@ -278,9 +278,10 @@ struct checkout {
|
||||
extern int checkout_entry(struct cache_entry *ce, struct checkout *state);
|
||||
|
||||
extern struct alternate_object_database {
|
||||
char *base;
|
||||
struct alternate_object_database *next;
|
||||
char *name;
|
||||
} *alt_odb;
|
||||
char base[0]; /* more */
|
||||
} *alt_odb_list;
|
||||
extern void prepare_alt_odb(void);
|
||||
|
||||
extern struct packed_git {
|
||||
|
@ -456,13 +456,13 @@ int main(int argc, char **argv)
|
||||
fsck_head_link();
|
||||
fsck_object_dir(get_object_directory());
|
||||
if (check_full) {
|
||||
int j;
|
||||
struct alternate_object_database *alt;
|
||||
struct packed_git *p;
|
||||
prepare_alt_odb();
|
||||
for (j = 0; alt_odb[j].base; j++) {
|
||||
for (alt = alt_odb_list; alt; alt = alt->next) {
|
||||
char namebuf[PATH_MAX];
|
||||
int namelen = alt_odb[j].name - alt_odb[j].base;
|
||||
memcpy(namebuf, alt_odb[j].base, namelen);
|
||||
int namelen = alt->name - alt->base;
|
||||
memcpy(namebuf, alt->base, namelen);
|
||||
namebuf[namelen - 1] = 0;
|
||||
fsck_object_dir(namebuf);
|
||||
}
|
||||
|
146
sha1_file.c
146
sha1_file.c
@ -222,84 +222,100 @@ char *sha1_pack_index_name(const unsigned char *sha1)
|
||||
return base;
|
||||
}
|
||||
|
||||
struct alternate_object_database *alt_odb;
|
||||
struct alternate_object_database *alt_odb_list;
|
||||
static struct alternate_object_database **alt_odb_tail;
|
||||
|
||||
/*
|
||||
* Prepare alternate object database registry.
|
||||
* alt_odb points at an array of struct alternate_object_database.
|
||||
* This array is terminated with an element that has both its base
|
||||
* and name set to NULL. alt_odb[n] comes from n'th non-empty
|
||||
* element from colon separated ALTERNATE_DB_ENVIRONMENT environment
|
||||
* variable, and its base points at a statically allocated buffer
|
||||
* that contains "/the/directory/corresponding/to/.git/objects/...",
|
||||
* while its name points just after the slash at the end of
|
||||
* ".git/objects/" in the example above, and has enough space to hold
|
||||
* 40-byte hex SHA1, an extra slash for the first level indirection,
|
||||
* and the terminating NUL.
|
||||
* This function allocates the alt_odb array and all the strings
|
||||
* pointed by base fields of the array elements with one xmalloc();
|
||||
* the string pool immediately follows the array.
|
||||
*
|
||||
* The variable alt_odb_list points at the list of struct
|
||||
* alternate_object_database. The elements on this list come from
|
||||
* non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT
|
||||
* environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates,
|
||||
* whose contents is exactly in the same format as that environment
|
||||
* variable. Its base points at a statically allocated buffer that
|
||||
* contains "/the/directory/corresponding/to/.git/objects/...", while
|
||||
* its name points just after the slash at the end of ".git/objects/"
|
||||
* in the example above, and has enough space to hold 40-byte hex
|
||||
* SHA1, an extra slash for the first level indirection, and the
|
||||
* terminating NUL.
|
||||
*/
|
||||
static void link_alt_odb_entries(const char *alt, const char *ep)
|
||||
{
|
||||
const char *cp, *last;
|
||||
struct alternate_object_database *ent;
|
||||
|
||||
last = alt;
|
||||
do {
|
||||
for (cp = last; cp < ep && *cp != ':'; cp++)
|
||||
;
|
||||
if (last != cp) {
|
||||
/* 43 = 40-byte + 2 '/' + terminating NUL */
|
||||
int pfxlen = cp - last;
|
||||
int entlen = pfxlen + 43;
|
||||
|
||||
ent = xmalloc(sizeof(*ent) + entlen);
|
||||
*alt_odb_tail = ent;
|
||||
alt_odb_tail = &(ent->next);
|
||||
ent->next = NULL;
|
||||
|
||||
memcpy(ent->base, last, pfxlen);
|
||||
ent->name = ent->base + pfxlen + 1;
|
||||
ent->base[pfxlen] = ent->base[pfxlen + 3] = '/';
|
||||
ent->base[entlen-1] = 0;
|
||||
}
|
||||
while (cp < ep && *cp == ':')
|
||||
cp++;
|
||||
last = cp;
|
||||
} while (cp < ep);
|
||||
}
|
||||
|
||||
void prepare_alt_odb(void)
|
||||
{
|
||||
int pass, totlen, i;
|
||||
const char *cp, *last;
|
||||
char *op = NULL;
|
||||
const char *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : "";
|
||||
char path[PATH_MAX];
|
||||
char *map, *ep;
|
||||
int fd;
|
||||
struct stat st;
|
||||
char *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : "";
|
||||
|
||||
if (alt_odb)
|
||||
sprintf(path, "%s/info/alternates", get_object_directory());
|
||||
if (alt_odb_tail)
|
||||
return;
|
||||
alt_odb_tail = &alt_odb_list;
|
||||
link_alt_odb_entries(alt, alt + strlen(alt));
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return;
|
||||
if (fstat(fd, &st) || (st.st_size == 0)) {
|
||||
close(fd);
|
||||
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
|
||||
* the structure and prepares the path buffers for use by
|
||||
* fill_sha1_path().
|
||||
*/
|
||||
for (totlen = pass = 0; pass < 2; pass++) {
|
||||
last = alt;
|
||||
i = 0;
|
||||
do {
|
||||
cp = strchr(last, ':') ? : last + strlen(last);
|
||||
if (last != cp) {
|
||||
/* 43 = 40-byte + 2 '/' + terminating NUL */
|
||||
int pfxlen = cp - last;
|
||||
int entlen = pfxlen + 43;
|
||||
if (pass == 0)
|
||||
totlen += entlen;
|
||||
else {
|
||||
alt_odb[i].base = op;
|
||||
alt_odb[i].name = op + pfxlen + 1;
|
||||
memcpy(op, last, pfxlen);
|
||||
op[pfxlen] = op[pfxlen + 3] = '/';
|
||||
op[entlen-1] = 0;
|
||||
op += entlen;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
while (*cp && *cp == ':')
|
||||
cp++;
|
||||
last = cp;
|
||||
} while (*cp);
|
||||
if (pass)
|
||||
break;
|
||||
alt_odb = xmalloc(sizeof(*alt_odb) * (i + 1) + totlen);
|
||||
alt_odb[i].base = alt_odb[i].name = NULL;
|
||||
op = (char*)(&alt_odb[i+1]);
|
||||
}
|
||||
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
close(fd);
|
||||
if (map == MAP_FAILED)
|
||||
return;
|
||||
|
||||
/* Remove the trailing newline */
|
||||
for (ep = map + st.st_size - 1; map < ep && ep[-1] == '\n'; ep--)
|
||||
;
|
||||
link_alt_odb_entries(map, ep);
|
||||
munmap(map, st.st_size);
|
||||
}
|
||||
|
||||
static char *find_sha1_file(const unsigned char *sha1, struct stat *st)
|
||||
{
|
||||
int i;
|
||||
char *name = sha1_file_name(sha1);
|
||||
struct alternate_object_database *alt;
|
||||
|
||||
if (!stat(name, st))
|
||||
return name;
|
||||
prepare_alt_odb();
|
||||
for (i = 0; (name = alt_odb[i].name) != NULL; i++) {
|
||||
for (alt = alt_odb_list; alt; alt = alt->next) {
|
||||
name = alt->name;
|
||||
fill_sha1_path(name, sha1);
|
||||
if (!stat(alt_odb[i].base, st))
|
||||
return alt_odb[i].base;
|
||||
if (!stat(alt->base, st))
|
||||
return alt->base;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -522,18 +538,18 @@ static void prepare_packed_git_one(char *objdir)
|
||||
|
||||
void prepare_packed_git(void)
|
||||
{
|
||||
int i;
|
||||
static int run_once = 0;
|
||||
struct alternate_object_database *alt;
|
||||
|
||||
if (run_once++)
|
||||
if (run_once)
|
||||
return;
|
||||
|
||||
prepare_packed_git_one(get_object_directory());
|
||||
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);
|
||||
for (alt = alt_odb_list; alt; alt = alt->next) {
|
||||
alt->name[0] = 0;
|
||||
prepare_packed_git_one(alt->base);
|
||||
}
|
||||
run_once = 1;
|
||||
}
|
||||
|
||||
int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type)
|
||||
|
Loading…
Reference in New Issue
Block a user