X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=sha1_file.c;h=6d6073da85d297b4b0a59c0548720b21fc23129d;hb=f5ab6ccae3063725e0a6bfacffaffb245d6df83c;hp=af39e8860ec55d420c724a079be02379288e3f61;hpb=5180cacc202bb20b15981469487eb8d6b0509997;p=git.git diff --git a/sha1_file.c b/sha1_file.c index af39e886..6d6073da 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -58,7 +58,7 @@ static int get_sha1_file(const char *path, unsigned char *result) return get_sha1_hex(buffer, result); } -static char *git_dir, *git_object_dir, *git_index_file; +static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir; static void setup_git_env(void) { git_dir = gitenv(GIT_DIR_ENVIRONMENT); @@ -69,6 +69,8 @@ static void setup_git_env(void) 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 = gitenv(INDEX_ENVIRONMENT); if (!git_index_file) { git_index_file = xmalloc(strlen(git_dir) + 7); @@ -83,6 +85,13 @@ char *get_object_directory(void) 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) @@ -257,7 +266,7 @@ static char *find_sha1_file(const unsigned char *sha1, struct stat *st) return NULL; } -int check_sha1_signature(unsigned char *sha1, void *map, unsigned long size, const char *type) +int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type) { char header[100]; unsigned char real_sha1[20]; @@ -323,7 +332,7 @@ int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size) { int bytes = strlen(buffer) + 1; - char *buf = xmalloc(1+size); + unsigned char *buf = xmalloc(1+size); memcpy(buf, buffer + bytes, stream->total_out - bytes); bytes = stream->total_out - bytes; @@ -401,6 +410,97 @@ void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned l return unpack_sha1_rest(&stream, hdr, *size); } +int sha1_delta_base(const unsigned char *sha1, unsigned char *base_sha1) +{ + int ret; + unsigned long mapsize, size; + void *map; + z_stream stream; + char hdr[64], type[20]; + void *delta_data_head; + + map = map_sha1_file(sha1, &mapsize); + if (!map) + return -1; + ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)); + if (ret < Z_OK || parse_sha1_header(hdr, type, &size) < 0) { + ret = -1; + goto out; + } + if (strcmp(type, "delta")) { + ret = 0; + goto out; + } + + delta_data_head = hdr + strlen(hdr) + 1; + ret = 1; + memcpy(base_sha1, delta_data_head, 20); + out: + inflateEnd(&stream); + munmap(map, mapsize); + return ret; +} + +int sha1_file_size(const unsigned char *sha1, unsigned long *sizep) +{ + int ret, status; + unsigned long mapsize, size; + void *map; + z_stream stream; + char hdr[64], type[20]; + const unsigned char *data; + unsigned char cmd; + int i; + + map = map_sha1_file(sha1, &mapsize); + if (!map) + return -1; + ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)); + status = -1; + if (ret < Z_OK || parse_sha1_header(hdr, type, &size) < 0) + goto out; + if (strcmp(type, "delta")) { + *sizep = size; + status = 0; + goto out; + } + + /* We are dealing with a delta object. Inflated, the first + * 20 bytes hold the base object SHA1, and delta data follows + * immediately after it. + * + * The initial part of the delta starts at delta_data_head + + * 20. Borrow code from patch-delta to read the result size. + */ + data = (unsigned char *)(hdr + strlen(hdr) + 1 + 20); + + /* Skip over the source size; we are not interested in + * it and we cannot verify it because we do not want + * to read the base object. + */ + cmd = *data++; + while (cmd) { + if (cmd & 1) + data++; + cmd >>= 1; + } + /* Read the result size */ + size = i = 0; + cmd = *data++; + while (cmd) { + if (cmd & 1) + size |= *data++ << i; + i += 8; + cmd >>= 1; + } + *sizep = size; + status = 0; + out: + inflateEnd(&stream); + munmap(map, mapsize); + return status; +} + void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size) { unsigned long mapsize;