diff options
Diffstat (limited to 'sha1-file.c')
-rw-r--r-- | sha1-file.c | 123 |
1 files changed, 75 insertions, 48 deletions
diff --git a/sha1-file.c b/sha1-file.c index 77ccaab928..555e780f4b 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -23,6 +23,7 @@ #include "sha1-lookup.h" #include "bulk-checkin.h" #include "repository.h" +#include "replace-object.h" #include "streaming.h" #include "dir.h" #include "list.h" @@ -35,12 +36,21 @@ /* The maximum size for an object header. */ #define MAX_HEADER_LEN 32 + +#define EMPTY_TREE_SHA1_BIN_LITERAL \ + "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \ + "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04" + +#define EMPTY_BLOB_SHA1_BIN_LITERAL \ + "\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b" \ + "\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91" + const unsigned char null_sha1[GIT_MAX_RAWSZ]; const struct object_id null_oid; -const struct object_id empty_tree_oid = { +static const struct object_id empty_tree_oid = { EMPTY_TREE_SHA1_BIN_LITERAL }; -const struct object_id empty_blob_oid = { +static const struct object_id empty_blob_oid = { EMPTY_BLOB_SHA1_BIN_LITERAL }; @@ -100,6 +110,18 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { }, }; +const char *empty_tree_oid_hex(void) +{ + static char buf[GIT_MAX_HEXSZ + 1]; + return oid_to_hex_r(buf, the_hash_algo->empty_tree); +} + +const char *empty_blob_oid_hex(void) +{ + static char buf[GIT_MAX_HEXSZ + 1]; + return oid_to_hex_r(buf, the_hash_algo->empty_blob); +} + /* * This is meant to hold a *small* number of objects that you would * want read_sha1_file() to be able to return, but yet you do not want @@ -107,7 +129,7 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { * application). */ static struct cached_object { - unsigned char sha1[20]; + struct object_id oid; enum object_type type; void *buf; unsigned long size; @@ -115,22 +137,22 @@ static struct cached_object { static int cached_object_nr, cached_object_alloc; static struct cached_object empty_tree = { - EMPTY_TREE_SHA1_BIN_LITERAL, + { EMPTY_TREE_SHA1_BIN_LITERAL }, OBJ_TREE, "", 0 }; -static struct cached_object *find_cached_object(const unsigned char *sha1) +static struct cached_object *find_cached_object(const struct object_id *oid) { int i; struct cached_object *co = cached_objects; for (i = 0; i < cached_object_nr; i++, co++) { - if (!hashcmp(co->sha1, sha1)) + if (!oidcmp(&co->oid, oid)) return co; } - if (!hashcmp(sha1, empty_tree.sha1)) + if (!oidcmp(oid, the_hash_algo->empty_tree)) return &empty_tree; return NULL; } @@ -141,7 +163,7 @@ static int get_conv_flags(unsigned flags) if (flags & HASH_RENORMALIZE) return CONV_EOL_RENORMALIZE; else if (flags & HASH_WRITE_OBJECT) - return global_conv_flags_eol; + return global_conv_flags_eol | CONV_WRITE_OBJECT; else return 0; } @@ -709,42 +731,42 @@ int check_and_freshen_file(const char *fn, int freshen) return 1; } -static int check_and_freshen_local(const unsigned char *sha1, int freshen) +static int check_and_freshen_local(const struct object_id *oid, int freshen) { static struct strbuf buf = STRBUF_INIT; strbuf_reset(&buf); - sha1_file_name(the_repository, &buf, sha1); + sha1_file_name(the_repository, &buf, oid->hash); return check_and_freshen_file(buf.buf, freshen); } -static int check_and_freshen_nonlocal(const unsigned char *sha1, int freshen) +static int check_and_freshen_nonlocal(const struct object_id *oid, int freshen) { struct alternate_object_database *alt; prepare_alt_odb(the_repository); for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) { - const char *path = alt_sha1_path(alt, sha1); + const char *path = alt_sha1_path(alt, oid->hash); if (check_and_freshen_file(path, freshen)) return 1; } return 0; } -static int check_and_freshen(const unsigned char *sha1, int freshen) +static int check_and_freshen(const struct object_id *oid, int freshen) { - return check_and_freshen_local(sha1, freshen) || - check_and_freshen_nonlocal(sha1, freshen); + return check_and_freshen_local(oid, freshen) || + check_and_freshen_nonlocal(oid, freshen); } -int has_loose_object_nonlocal(const unsigned char *sha1) +int has_loose_object_nonlocal(const struct object_id *oid) { - return check_and_freshen_nonlocal(sha1, 0); + return check_and_freshen_nonlocal(oid, 0); } -static int has_loose_object(const unsigned char *sha1) +static int has_loose_object(const struct object_id *oid) { - return check_and_freshen(sha1, 0); + return check_and_freshen(oid, 0); } static void mmap_limit_check(size_t length) @@ -1230,7 +1252,8 @@ static int sha1_loose_object_info(struct repository *r, int fetch_if_missing = 1; -int oid_object_info_extended(const struct object_id *oid, struct object_info *oi, unsigned flags) +int oid_object_info_extended(struct repository *r, const struct object_id *oid, + struct object_info *oi, unsigned flags) { static struct object_info blank_oi = OBJECT_INFO_INIT; struct pack_entry e; @@ -1239,7 +1262,7 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi int already_retried = 0; if (flags & OBJECT_INFO_LOOKUP_REPLACE) - real = lookup_replace_object(oid); + real = lookup_replace_object(r, oid); if (is_null_oid(real)) return -1; @@ -1248,7 +1271,7 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi oi = &blank_oi; if (!(flags & OBJECT_INFO_SKIP_CACHED)) { - struct cached_object *co = find_cached_object(real->hash); + struct cached_object *co = find_cached_object(real); if (co) { if (oi->typep) *(oi->typep) = co->type; @@ -1268,29 +1291,31 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi } while (1) { - if (find_pack_entry(the_repository, real->hash, &e)) + if (find_pack_entry(r, real, &e)) break; if (flags & OBJECT_INFO_IGNORE_LOOSE) return -1; /* Most likely it's a loose object. */ - if (!sha1_loose_object_info(the_repository, real->hash, oi, flags)) + if (!sha1_loose_object_info(r, real->hash, oi, flags)) return 0; /* Not a loose object; someone else may have just packed it. */ if (!(flags & OBJECT_INFO_QUICK)) { - reprepare_packed_git(the_repository); - if (find_pack_entry(the_repository, real->hash, &e)) + reprepare_packed_git(r); + if (find_pack_entry(r, real, &e)) break; } /* Check if it is a missing object */ if (fetch_if_missing && repository_format_partial_clone && - !already_retried) { + !already_retried && r == the_repository) { /* - * TODO Investigate haveing fetch_object() return + * TODO Investigate having fetch_object() return * TODO error/success and stopping the music here. + * TODO Pass a repository struct through fetch_object, + * such that arbitrary repositories work. */ fetch_object(repository_format_partial_clone, real->hash); already_retried = 1; @@ -1306,10 +1331,10 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi * information below, so return early. */ return 0; - rtype = packed_object_info(e.p, e.offset, oi); + rtype = packed_object_info(r, e.p, e.offset, oi); if (rtype < 0) { mark_bad_packed_object(e.p, real->hash); - return oid_object_info_extended(real, oi, 0); + return oid_object_info_extended(r, real, oi, 0); } else if (oi->whence == OI_PACKED) { oi->u.packed.offset = e.offset; oi->u.packed.pack = e.p; @@ -1321,15 +1346,17 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi } /* returns enum object_type or negative */ -int oid_object_info(const struct object_id *oid, unsigned long *sizep) +int oid_object_info(struct repository *r, + const struct object_id *oid, + unsigned long *sizep) { enum object_type type; struct object_info oi = OBJECT_INFO_INIT; oi.typep = &type; oi.sizep = sizep; - if (oid_object_info_extended(oid, &oi, - OBJECT_INFO_LOOKUP_REPLACE) < 0) + if (oid_object_info_extended(r, oid, &oi, + OBJECT_INFO_LOOKUP_REPLACE) < 0) return -1; return type; } @@ -1346,7 +1373,7 @@ static void *read_object(const unsigned char *sha1, enum object_type *type, hashcpy(oid.hash, sha1); - if (oid_object_info_extended(&oid, &oi, 0) < 0) + if (oid_object_info_extended(the_repository, &oid, &oi, 0) < 0) return NULL; return content; } @@ -1357,7 +1384,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type, struct cached_object *co; hash_object_file(buf, len, type_name(type), oid); - if (has_sha1_file(oid->hash) || find_cached_object(oid->hash)) + if (has_sha1_file(oid->hash) || find_cached_object(oid)) return 0; ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc); co = &cached_objects[cached_object_nr++]; @@ -1365,7 +1392,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type, co->type = type; co->buf = xmalloc(len); memcpy(co->buf, buf, len); - hashcpy(co->sha1, oid->hash); + oidcpy(&co->oid, oid); return 0; } @@ -1383,8 +1410,8 @@ void *read_object_file_extended(const struct object_id *oid, const struct packed_git *p; const char *path; struct stat st; - const struct object_id *repl = lookup_replace ? lookup_replace_object(oid) - : oid; + const struct object_id *repl = lookup_replace ? + lookup_replace_object(the_repository, oid) : oid; errno = 0; data = read_object(repl->hash, type, size); @@ -1661,15 +1688,15 @@ static int write_loose_object(const struct object_id *oid, char *hdr, return finalize_object_file(tmp_file.buf, filename.buf); } -static int freshen_loose_object(const unsigned char *sha1) +static int freshen_loose_object(const struct object_id *oid) { - return check_and_freshen(sha1, 1); + return check_and_freshen(oid, 1); } -static int freshen_packed_object(const unsigned char *sha1) +static int freshen_packed_object(const struct object_id *oid) { struct pack_entry e; - if (!find_pack_entry(the_repository, sha1, &e)) + if (!find_pack_entry(the_repository, oid, &e)) return 0; if (e.p->freshened) return 1; @@ -1689,7 +1716,7 @@ int write_object_file(const void *buf, unsigned long len, const char *type, * it out into .git/objects/??/?{38} file. */ write_object_file_prepare(buf, len, type, oid, hdr, &hdrlen); - if (freshen_packed_object(oid->hash) || freshen_loose_object(oid->hash)) + if (freshen_packed_object(oid) || freshen_loose_object(oid)) return 0; return write_loose_object(oid, hdr, hdrlen, buf, len, 0); } @@ -1708,7 +1735,7 @@ int hash_object_file_literally(const void *buf, unsigned long len, if (!(flags & HASH_WRITE_OBJECT)) goto cleanup; - if (freshen_packed_object(oid->hash) || freshen_loose_object(oid->hash)) + if (freshen_packed_object(oid) || freshen_loose_object(oid)) goto cleanup; status = write_loose_object(oid, header, hdrlen, buf, len, 0); @@ -1726,7 +1753,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime) int hdrlen; int ret; - if (has_loose_object(oid->hash)) + if (has_loose_object(oid)) return 0; buf = read_object(oid->hash, &type, &len); if (!buf) @@ -1744,7 +1771,7 @@ int has_sha1_file_with_flags(const unsigned char *sha1, int flags) if (!startup_info->have_repository) return 0; hashcpy(oid.hash, sha1); - return oid_object_info_extended(&oid, NULL, + return oid_object_info_extended(the_repository, &oid, NULL, flags | OBJECT_INFO_SKIP_CACHED) >= 0; } @@ -1987,7 +2014,7 @@ int read_pack_header(int fd, struct pack_header *header) void assert_oid_type(const struct object_id *oid, enum object_type expect) { - enum object_type type = oid_object_info(oid, NULL); + enum object_type type = oid_object_info(the_repository, oid, NULL); if (type < 0) die("%s is not a valid object", oid_to_hex(oid)); if (type != expect) @@ -2226,7 +2253,7 @@ int read_loose_object(const char *path, goto out; } - if (*type == OBJ_BLOB) { + if (*type == OBJ_BLOB && *size > big_file_threshold) { if (check_stream_sha1(&stream, hdr, *size, path, expected_oid->hash) < 0) goto out; } else { |