X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=sha1_file.c;h=111a71de6b3bb33b7e2ca1879613a70bc3a6ed81;hb=5e80092f7e6db09a40a62e837ca3f74f0bc5ad73;hp=baaa4c00da50342a7db8064dadf7f963b0e2e679;hpb=b12bbd5986e1fae4120d7a415c1271c0273cad7e;p=git.git diff --git a/sha1_file.c b/sha1_file.c index baaa4c00..111a71de 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -48,68 +48,11 @@ int get_sha1_hex(const char *hex, unsigned char *sha1) return 0; } -static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir, - *git_graft_file; -static void setup_git_env(void) -{ - git_dir = getenv(GIT_DIR_ENVIRONMENT); - if (!git_dir) - git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; - git_object_dir = getenv(DB_ENVIRONMENT); - if (!git_object_dir) { - git_object_dir = xmalloc(strlen(git_dir) + 9); - sprintf(git_object_dir, "%s/objects", git_dir); - } - git_refs_dir = xmalloc(strlen(git_dir) + 6); - sprintf(git_refs_dir, "%s/refs", git_dir); - git_index_file = getenv(INDEX_ENVIRONMENT); - if (!git_index_file) { - git_index_file = xmalloc(strlen(git_dir) + 7); - sprintf(git_index_file, "%s/index", git_dir); - } - git_graft_file = getenv(GRAFT_ENVIRONMENT); - if (!git_graft_file) - git_graft_file = strdup(git_path("info/grafts")); -} - -char *get_git_dir(void) -{ - if (!git_dir) - setup_git_env(); - return git_dir; -} - -char *get_object_directory(void) -{ - if (!git_object_dir) - setup_git_env(); - return git_object_dir; -} - -char *get_refs_directory(void) -{ - if (!git_refs_dir) - setup_git_env(); - return git_refs_dir; -} - -char *get_index_file(void) -{ - if (!git_index_file) - setup_git_env(); - return git_index_file; -} - -char *get_graft_file(void) -{ - if (!git_graft_file) - setup_git_env(); - return git_graft_file; -} - int safe_create_leading_directories(char *path) { char *pos = path; + if (*pos == '/') + pos++; while (pos) { pos = strchr(pos, '/'); @@ -241,8 +184,8 @@ static struct alternate_object_database **alt_odb_tail; * 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 + * whose contents is similar to that environment variable but can be + * LF separated. 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 @@ -254,6 +197,7 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep, { const char *cp, *last; struct alternate_object_database *ent; + const char *objdir = get_object_directory(); int base_len = -1; last = alt; @@ -268,6 +212,7 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep, for ( ; cp < ep && *cp != sep; cp++) ; if (last != cp) { + struct alternate_object_database *alt; /* 43 = 40-byte + 2 '/' + terminating NUL */ int pfxlen = cp - last; int entlen = pfxlen + 43; @@ -280,9 +225,7 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep, pfxlen += base_len; } ent = xmalloc(sizeof(*ent) + entlen); - *alt_odb_tail = ent; - alt_odb_tail = &(ent->next); - ent->next = NULL; + if (*last != '/' && relative_base) { memcpy(ent->base, relative_base, base_len - 1); ent->base[base_len - 1] = '/'; @@ -294,6 +237,22 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep, ent->name = ent->base + pfxlen + 1; ent->base[pfxlen] = ent->base[pfxlen + 3] = '/'; ent->base[entlen-1] = 0; + + /* 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; + } } while (cp < ep && *cp == sep) cp++; @@ -475,12 +434,13 @@ int use_packed_git(struct packed_git *p) return 0; } -struct packed_git *add_packed_git(char *path, int path_len) +struct packed_git *add_packed_git(char *path, int path_len, int local) { struct stat st; struct packed_git *p; unsigned long idx_size; void *idx_map; + unsigned char sha1[20]; if (check_packed_git_idx(path, &idx_size, &idx_map)) return NULL; @@ -503,6 +463,9 @@ struct packed_git *add_packed_git(char *path, int path_len) p->pack_base = NULL; p->pack_last_used = 0; p->pack_use_cnt = 0; + p->pack_local = local; + if (!get_sha1_hex(path + path_len - 40 - 4, sha1)) + memcpy(p->sha1, sha1, 20); return p; } @@ -543,7 +506,7 @@ void install_packed_git(struct packed_git *pack) packed_git = pack; } -static void prepare_packed_git_one(char *objdir) +static void prepare_packed_git_one(char *objdir, int local) { char path[PATH_MAX]; int len; @@ -565,7 +528,7 @@ static void prepare_packed_git_one(char *objdir) /* we have .idx. Is it a file we can map? */ strcpy(path + len, de->d_name); - p = add_packed_git(path, len + namelen); + p = add_packed_git(path, len + namelen, local); if (!p) continue; p->next = packed_git; @@ -581,11 +544,12 @@ void prepare_packed_git(void) if (run_once) return; - prepare_packed_git_one(get_object_directory()); + prepare_packed_git_one(get_object_directory(), 1); prepare_alt_odb(); for (alt = alt_odb_list; alt; alt = alt->next) { - alt->name[0] = 0; - prepare_packed_git_one(alt->base); + alt->name[-1] = 0; + prepare_packed_git_one(alt->base, 0); + alt->name[-1] = '/'; } run_once = 1; } @@ -1287,21 +1251,25 @@ static int link_temp_to_file(const char *tmpfile, char *filename) /* * Move the just written object into its final resting place */ -static int move_temp_to_file(const char *tmpfile, char *filename) +int move_temp_to_file(const char *tmpfile, char *filename) { int ret = link_temp_to_file(tmpfile, filename); - if (ret) { - /* - * Coda hack - coda doesn't like cross-directory links, - * so we fall back to a rename, which will mean that it - * won't be able to check collisions, but that's not a - * big deal. - * - * When this succeeds, we just return 0. We have nothing - * left to unlink. - */ - if (ret == EXDEV && !rename(tmpfile, filename)) + + /* + * Coda hack - coda doesn't like cross-directory links, + * so we fall back to a rename, which will mean that it + * won't be able to check collisions, but that's not a + * big deal. + * + * The same holds for FAT formatted media. + * + * When this succeeds, we just return 0. We have nothing + * left to unlink. + */ + if (ret && ret != EEXIST) { + if (!rename(tmpfile, filename)) return 0; + ret = errno; } unlink(tmpfile); if (ret) {