diff options
-rw-r--r-- | cache.h | 68 | ||||
-rw-r--r-- | http.c | 2 | ||||
-rw-r--r-- | replace_object.c | 17 | ||||
-rw-r--r-- | sha1_file.c | 66 |
4 files changed, 112 insertions, 41 deletions
@@ -660,9 +660,28 @@ extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2) extern char *git_path_submodule(const char *path, const char *fmt, ...) __attribute__((format (printf, 2, 3))); -extern char *sha1_file_name(const unsigned char *sha1); +/* + * Return the name of the file in the local object database that would + * be used to store a loose object with the specified sha1. The + * return value is a pointer to a statically allocated buffer that is + * overwritten each time the function is called. + */ +extern const char *sha1_file_name(const unsigned char *sha1); + +/* + * Return the name of the (local) packfile with the specified sha1 in + * its name. The return value is a pointer to memory that is + * overwritten each time this function is called. + */ extern char *sha1_pack_name(const unsigned char *sha1); + +/* + * Return the name of the (local) pack index file with the specified + * sha1 in its name. The return value is a pointer to memory that is + * overwritten each time this function is called. + */ extern char *sha1_pack_index_name(const unsigned char *sha1); + extern const char *find_unique_abbrev(const unsigned char *sha1, int); extern const unsigned char null_sha1[20]; @@ -822,7 +841,19 @@ extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned l extern int move_temp_to_file(const char *tmpfile, const char *filename); extern int has_sha1_pack(const unsigned char *sha1); + +/* + * Return true iff we have an object named sha1, whether local or in + * an alternate object database, and whether packed or loose. This + * function does not respect replace references. + */ extern int has_sha1_file(const unsigned char *sha1); + +/* + * Return true iff an alternate object database has a loose object + * with the specified name. This function does not respect replace + * references. + */ extern int has_loose_object_nonlocal(const unsigned char *sha1); extern int has_pack_index(const unsigned char *sha1); @@ -1086,17 +1117,46 @@ extern struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs); extern void pack_report(void); + +/* + * mmap the index file for the specified packfile (if it is not + * already mmapped). Return 0 on success. + */ extern int open_pack_index(struct packed_git *); + +/* + * munmap the index file for the specified packfile (if it is + * currently mmapped). + */ extern void close_pack_index(struct packed_git *); + extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *); extern void close_pack_windows(struct packed_git *); extern void unuse_pack(struct pack_window **); extern void free_pack_by_name(const char *); extern void clear_delta_base_cache(void); extern struct packed_git *add_packed_git(const char *, int, int); -extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t); -extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t); -extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *); + +/* + * Return the SHA-1 of the nth object within the specified packfile. + * Open the index if it is not already open. The return value points + * at the SHA-1 within the mmapped index. Return NULL if there is an + * error. + */ +extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t n); + +/* + * Return the offset of the nth object within the specified packfile. + * The index must already be opened. + */ +extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t n); + +/* + * If the object named sha1 is present in the specified packfile, + * return its offset within the packfile; otherwise, return 0. + */ +extern off_t find_pack_entry_one(const unsigned char *sha1, struct packed_git *); + extern int is_pack_valid(struct packed_git *); extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *); extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep); @@ -1390,7 +1390,7 @@ struct http_object_request *new_http_object_request(const char *base_url, unsigned char *sha1) { char *hex = sha1_to_hex(sha1); - char *filename; + const char *filename; char prevfile[PATH_MAX]; int prevlocal; char prev_buf[PREV_BUF_SIZE]; diff --git a/replace_object.c b/replace_object.c index cdcaf8cbe..6fc3ff47b 100644 --- a/replace_object.c +++ b/replace_object.c @@ -3,8 +3,13 @@ #include "refs.h" #include "commit.h" +/* + * An array of replacements. The array is kept sorted by the original + * sha1. + */ static struct replace_object { - unsigned char sha1[2][20]; + unsigned char original[20]; + unsigned char replacement[20]; } **replace_object; static int replace_object_alloc, replace_object_nr; @@ -12,7 +17,7 @@ static int replace_object_alloc, replace_object_nr; static const unsigned char *replace_sha1_access(size_t index, void *table) { struct replace_object **replace = table; - return replace[index]->sha1[0]; + return replace[index]->original; } static int replace_object_pos(const unsigned char *sha1) @@ -24,7 +29,7 @@ static int replace_object_pos(const unsigned char *sha1) static int register_replace_object(struct replace_object *replace, int ignore_dups) { - int pos = replace_object_pos(replace->sha1[0]); + int pos = replace_object_pos(replace->original); if (0 <= pos) { if (ignore_dups) @@ -60,14 +65,14 @@ static int register_replace_ref(const char *refname, const char *hash = slash ? slash + 1 : refname; struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj)); - if (strlen(hash) != 40 || get_sha1_hex(hash, repl_obj->sha1[0])) { + if (strlen(hash) != 40 || get_sha1_hex(hash, repl_obj->original)) { free(repl_obj); warning("bad replace ref name: %s", refname); return 0; } /* Copy sha1 from the read ref */ - hashcpy(repl_obj->sha1[1], sha1); + hashcpy(repl_obj->replacement, sha1); /* Register new object */ if (register_replace_object(repl_obj, 1)) @@ -107,7 +112,7 @@ const unsigned char *do_lookup_replace_object(const unsigned char *sha1) pos = replace_object_pos(cur); if (0 <= pos) - cur = replace_object[pos]->sha1[1]; + cur = replace_object[pos]->replacement; } while (0 <= pos); return cur; diff --git a/sha1_file.c b/sha1_file.c index 019628add..b37c6f67e 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -60,6 +60,12 @@ static struct cached_object empty_tree = { 0 }; +/* + * A pointer to the last packed_git in which an object was found. + * When an object is sought, we look in this packfile first, because + * objects that are looked up at similar times are often in the same + * packfile as one another. + */ static struct packed_git *last_found_pack; static struct cached_object *find_cached_object(const unsigned char *sha1) @@ -178,17 +184,7 @@ static void fill_sha1_path(char *pathbuf, const unsigned char *sha1) } } -/* - * NOTE! This returns a statically allocated buffer, so you have to be - * careful about using it. Do an "xstrdup()" if you need to save the - * filename. - * - * Also note that this returns the location for creating. Reading - * SHA1 file can happen from any alternate directory listed in the - * DB_ENVIRONMENT environment variable if it is not found in - * the primary object database. - */ -char *sha1_file_name(const unsigned char *sha1) +const char *sha1_file_name(const unsigned char *sha1) { static char buf[PATH_MAX]; const char *objdir; @@ -208,6 +204,11 @@ char *sha1_file_name(const unsigned char *sha1) return buf; } +/* + * Return the name of the pack or index file with the specified sha1 + * in its filename. *base and *name are scratch space that must be + * provided by the caller. which should be "pack" or "idx". + */ static char *sha1_get_pack_name(const unsigned char *sha1, char **name, char **base, const char *which) { @@ -436,8 +437,7 @@ void prepare_alt_odb(void) static int has_loose_object_local(const unsigned char *sha1) { - char *name = sha1_file_name(sha1); - return !access(name, F_OK); + return !access(sha1_file_name(sha1), F_OK); } int has_loose_object_nonlocal(const unsigned char *sha1) @@ -489,7 +489,12 @@ void pack_report(void) sz_fmt(pack_mapped), sz_fmt(peak_pack_mapped)); } -static int check_packed_git_idx(const char *path, struct packed_git *p) +/* + * Open and mmap the index file at path, perform a couple of + * consistency checks, then record its information to p. Return 0 on + * success. + */ +static int check_packed_git_idx(const char *path, struct packed_git *p) { void *idx_map; struct pack_idx_header *hdr; @@ -1412,17 +1417,15 @@ int git_open_noatime(const char *name) static int stat_sha1_file(const unsigned char *sha1, struct stat *st) { - char *name = sha1_file_name(sha1); struct alternate_object_database *alt; - if (!lstat(name, st)) + if (!lstat(sha1_file_name(sha1), st)) return 0; prepare_alt_odb(); errno = ENOENT; for (alt = alt_odb_list; alt; alt = alt->next) { - name = alt->name; - fill_sha1_path(name, sha1); + fill_sha1_path(alt->name, sha1); if (!lstat(alt->base, st)) return 0; } @@ -1433,18 +1436,16 @@ static int stat_sha1_file(const unsigned char *sha1, struct stat *st) static int open_sha1_file(const unsigned char *sha1) { int fd; - char *name = sha1_file_name(sha1); struct alternate_object_database *alt; - fd = git_open_noatime(name); + fd = git_open_noatime(sha1_file_name(sha1)); if (fd >= 0) return fd; prepare_alt_odb(); errno = ENOENT; for (alt = alt_odb_list; alt; alt = alt->next) { - name = alt->name; - fill_sha1_path(name, sha1); + fill_sha1_path(alt->name, sha1); fd = git_open_noatime(alt->base); if (fd >= 0) return fd; @@ -2446,6 +2447,10 @@ static int fill_pack_entry(const unsigned char *sha1, return 1; } +/* + * Iff a pack file contains the object named by sha1, return true and + * store its location to e. + */ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e) { struct packed_git *p; @@ -2458,11 +2463,13 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e) return 1; for (p = packed_git; p; p = p->next) { - if (p == last_found_pack || !fill_pack_entry(sha1, e, p)) - continue; + if (p == last_found_pack) + continue; /* we already checked this one */ - last_found_pack = p; - return 1; + if (fill_pack_entry(sha1, e, p)) { + last_found_pack = p; + return 1; + } } return 0; } @@ -2677,7 +2684,6 @@ void *read_sha1_file_extended(const unsigned char *sha1, unsigned flag) { void *data; - char *path; const struct packed_git *p; const unsigned char *repl = lookup_replace_object_extended(sha1, flag); @@ -2695,7 +2701,8 @@ void *read_sha1_file_extended(const unsigned char *sha1, sha1_to_hex(repl), sha1_to_hex(sha1)); if (has_loose_object(repl)) { - path = sha1_file_name(sha1); + const char *path = sha1_file_name(sha1); + die("loose object %s (stored in %s) is corrupt", sha1_to_hex(repl), path); } @@ -2893,10 +2900,9 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen, git_zstream stream; git_SHA_CTX c; unsigned char parano_sha1[20]; - char *filename; static char tmp_file[PATH_MAX]; + const char *filename = sha1_file_name(sha1); - filename = sha1_file_name(sha1); fd = create_tmpfile(tmp_file, sizeof(tmp_file), filename); if (fd < 0) { if (errno == EACCES) |