When adding an alternate object store then add entries from its info/alternates files, too. Signed-off-by: Martin Waitz <tali@xxxxxxxxxxxxxx> --- sha1_file.c | 166 +++++++++++++++++++++++++++++++++-------------------------- 1 files changed, 94 insertions(+), 72 deletions(-) 6ef777610f4e314fd93ecf672b9898fb95a7d5af diff --git a/sha1_file.c b/sha1_file.c index f2d33af..fb5778c 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -216,6 +216,8 @@ char *sha1_pack_index_name(const unsigne struct alternate_object_database *alt_odb_list; static struct alternate_object_database **alt_odb_tail; +static void read_info_alternates(const char * alternates); + /* * Prepare alternate object database registry. * @@ -231,13 +233,78 @@ static struct alternate_object_database * SHA1, an extra slash for the first level indirection, and the * terminating NUL. */ +static int link_alt_odb_entry(const char * entry, int len, const char * relative_base) +{ + struct stat st; + const char *objdir = get_object_directory(); + struct alternate_object_database *ent; + struct alternate_object_database *alt; + /* 43 = 40-byte + 2 '/' + terminating NUL */ + int pfxlen = len; + int entlen = pfxlen + 43; + int base_len = -1; + + if (*entry != '/' && relative_base) { + /* Relative alt-odb */ + if (base_len < 0) + base_len = strlen(relative_base) + 1; + entlen += base_len; + pfxlen += base_len; + } + ent = xmalloc(sizeof(*ent) + entlen); + + if (*entry != '/' && relative_base) { + memcpy(ent->base, relative_base, base_len - 1); + ent->base[base_len - 1] = '/'; + memcpy(ent->base + base_len, entry, len); + } + else + memcpy(ent->base, entry, pfxlen); + + ent->name = ent->base + pfxlen + 1; + ent->base[pfxlen + 3] = '/'; + ent->base[pfxlen] = ent->base[entlen-1] = 0; + + /* Detect cases where alternate disappeared */ + if (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) { + error("object directory %s does not exist; " + "check .git/objects/info/alternates.", + ent->base); + free(ent); + return -1; + } + + /* Prevent the common mistake of listing the same + * thing twice, or object directory itself. + */ + for (alt = alt_odb_list; alt; alt = alt->next) { + if (!memcmp(ent->base, alt->base, pfxlen)) { + free(ent); + return -1; + } + } + if (!memcmp(ent->base, objdir, pfxlen)) { + free(ent); + return -1; + } + + /* add the alternate entry */ + *alt_odb_tail = ent; + alt_odb_tail = &(ent->next); + ent->next = NULL; + + /* recursively add alternates */ + read_info_alternates(ent->base); + + ent->base[pfxlen] = '/'; + + return 0; +} + static void link_alt_odb_entries(const char *alt, const char *ep, int sep, const char *relative_base) { const char *cp, *last; - struct alternate_object_database *ent; - const char *objdir = get_object_directory(); - int base_len = -1; last = alt; while (last < ep) { @@ -248,61 +315,10 @@ static void link_alt_odb_entries(const c last = cp + 1; continue; } - for ( ; cp < ep && *cp != sep; cp++) - ; + while (cp < ep && *cp != sep) + cp++; if (last != cp) { - struct stat st; - struct alternate_object_database *alt; - /* 43 = 40-byte + 2 '/' + terminating NUL */ - int pfxlen = cp - last; - int entlen = pfxlen + 43; - - if (*last != '/' && relative_base) { - /* Relative alt-odb */ - if (base_len < 0) - base_len = strlen(relative_base) + 1; - entlen += base_len; - pfxlen += base_len; - } - ent = xmalloc(sizeof(*ent) + entlen); - - if (*last != '/' && relative_base) { - memcpy(ent->base, relative_base, base_len - 1); - ent->base[base_len - 1] = '/'; - memcpy(ent->base + base_len, - last, cp - last); - } - else - memcpy(ent->base, last, pfxlen); - - ent->name = ent->base + pfxlen + 1; - ent->base[pfxlen + 3] = '/'; - ent->base[pfxlen] = ent->base[entlen-1] = 0; - - /* Detect cases where alternate disappeared */ - if (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) { - error("object directory %s does not exist; " - "check .git/objects/info/alternates.", - ent->base); - goto bad; - } - ent->base[pfxlen] = '/'; - - /* Prevent the common mistake of listing the same - * thing twice, or object directory itself. - */ - for (alt = alt_odb_list; alt; alt = alt->next) - if (!memcmp(ent->base, alt->base, pfxlen)) - goto bad; - if (!memcmp(ent->base, objdir, pfxlen)) { - bad: - free(ent); - } - else { - *alt_odb_tail = ent; - alt_odb_tail = &(ent->next); - ent->next = NULL; - } + link_alt_odb_entry(last, cp - last, relative_base); } while (cp < ep && *cp == sep) cp++; @@ -310,23 +326,14 @@ static void link_alt_odb_entries(const c } } -void prepare_alt_odb(void) +static void read_info_alternates(const char * relative_base) { - char path[PATH_MAX]; char *map; - int fd; struct stat st; - char *alt; - - alt = getenv(ALTERNATE_DB_ENVIRONMENT); - if (!alt) alt = ""; - - if (alt_odb_tail) - return; - alt_odb_tail = &alt_odb_list; - link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL); + char path[PATH_MAX]; + int fd; - sprintf(path, "%s/info/alternates", get_object_directory()); + sprintf(path, "%s/info/alternates", relative_base); fd = open(path, O_RDONLY); if (fd < 0) return; @@ -339,11 +346,26 @@ void prepare_alt_odb(void) if (map == MAP_FAILED) return; - link_alt_odb_entries(map, map + st.st_size, '\n', - get_object_directory()); + link_alt_odb_entries(map, map + st.st_size, '\n', relative_base); + munmap(map, st.st_size); } +void prepare_alt_odb(void) +{ + char *alt; + + alt = getenv(ALTERNATE_DB_ENVIRONMENT); + if (!alt) alt = ""; + + if (alt_odb_tail) + return; + alt_odb_tail = &alt_odb_list; + link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL); + + read_info_alternates(get_object_directory()); +} + static char *find_sha1_file(const unsigned char *sha1, struct stat *st) { char *name = sha1_file_name(sha1); -- 1.3.1.g6ef7 -- Martin Waitz - : send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html