diff options
Diffstat (limited to 'object-file.c')
| -rw-r--r-- | object-file.c | 159 |
1 files changed, 67 insertions, 92 deletions
diff --git a/object-file.c b/object-file.c index 26290554bb..ce9efae994 100644 --- a/object-file.c +++ b/object-file.c @@ -1211,35 +1211,25 @@ static int quick_has_loose(struct repository *r, } /* - * Map the loose object at "path" if it is not NULL, or the path found by - * searching for a loose object named "oid". + * Map and close the given loose object fd. The path argument is used for + * error reporting. */ -static void *map_loose_object_1(struct repository *r, const char *path, - const struct object_id *oid, unsigned long *size) +static void *map_fd(int fd, const char *path, unsigned long *size) { - void *map; - int fd; - - if (path) - fd = git_open(path); - else - fd = open_loose_object(r, oid, &path); - map = NULL; - if (fd >= 0) { - struct stat st; + void *map = NULL; + struct stat st; - if (!fstat(fd, &st)) { - *size = xsize_t(st.st_size); - if (!*size) { - /* mmap() is forbidden on empty files */ - error(_("object file %s is empty"), path); - close(fd); - return NULL; - } - map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0); + if (!fstat(fd, &st)) { + *size = xsize_t(st.st_size); + if (!*size) { + /* mmap() is forbidden on empty files */ + error(_("object file %s is empty"), path); + close(fd); + return NULL; } - close(fd); + map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0); } + close(fd); return map; } @@ -1247,7 +1237,12 @@ void *map_loose_object(struct repository *r, const struct object_id *oid, unsigned long *size) { - return map_loose_object_1(r, NULL, oid, size); + const char *p; + int fd = open_loose_object(r, oid, &p); + + if (fd < 0) + return NULL; + return map_fd(fd, p, size); } enum unpack_loose_header_result unpack_loose_header(git_zstream *stream, @@ -1427,7 +1422,9 @@ static int loose_object_info(struct repository *r, struct object_info *oi, int flags) { int status = 0; + int fd; unsigned long mapsize; + const char *path; void *map; git_zstream stream; char hdr[MAX_HEADER_LEN]; @@ -1448,7 +1445,6 @@ static int loose_object_info(struct repository *r, * object even exists. */ if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) { - const char *path; struct stat st; if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK)) return quick_has_loose(r, oid) ? 0 : -1; @@ -1459,7 +1455,13 @@ static int loose_object_info(struct repository *r, return 0; } - map = map_loose_object(r, oid, &mapsize); + fd = open_loose_object(r, oid, &path); + if (fd < 0) { + if (errno != ENOENT) + error_errno(_("unable to open loose object %s"), oid_to_hex(oid)); + return -1; + } + map = map_fd(fd, path, &mapsize); if (!map) return -1; @@ -1497,6 +1499,10 @@ static int loose_object_info(struct repository *r, break; } + if (status && (flags & OBJECT_INFO_DIE_IF_CORRUPT)) + die(_("loose object %s (stored in %s) is corrupt"), + oid_to_hex(oid), path); + git_inflate_end(&stream); cleanup: munmap(map, mapsize); @@ -1575,9 +1581,6 @@ static int do_oid_object_info_extended(struct repository *r, if (find_pack_entry(r, real, &e)) break; - if (flags & OBJECT_INFO_IGNORE_LOOSE) - return -1; - /* Most likely it's a loose object. */ if (!loose_object_info(r, real, oi, flags)) return 0; @@ -1609,6 +1612,15 @@ static int do_oid_object_info_extended(struct repository *r, continue; } + if (flags & OBJECT_INFO_DIE_IF_CORRUPT) { + const struct packed_git *p; + if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid)) + die(_("replacement %s not found for %s"), + oid_to_hex(real), oid_to_hex(oid)); + if ((p = has_packed_and_bad(r, real))) + die(_("packed object %s (stored in %s) is corrupt"), + oid_to_hex(real), p->pack_name); + } return -1; } @@ -1659,21 +1671,6 @@ int oid_object_info(struct repository *r, return type; } -static void *read_object(struct repository *r, - const struct object_id *oid, enum object_type *type, - unsigned long *size) -{ - struct object_info oi = OBJECT_INFO_INIT; - void *content; - oi.typep = type; - oi.sizep = size; - oi.contentp = &content; - - if (oid_object_info_extended(r, oid, &oi, 0) < 0) - return NULL; - return content; -} - int pretend_object_file(void *buf, unsigned long len, enum object_type type, struct object_id *oid) { @@ -1695,46 +1692,25 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type, /* * This function dies on corrupt objects; the callers who want to - * deal with them should arrange to call read_object() and give error - * messages themselves. + * deal with them should arrange to call oid_object_info_extended() and give + * error messages themselves. */ -void *read_object_file_extended(struct repository *r, - const struct object_id *oid, - enum object_type *type, - unsigned long *size, - int lookup_replace) +void *repo_read_object_file(struct repository *r, + const struct object_id *oid, + enum object_type *type, + unsigned long *size) { + struct object_info oi = OBJECT_INFO_INIT; + unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE; void *data; - const struct packed_git *p; - const char *path; - struct stat st; - const struct object_id *repl = lookup_replace ? - lookup_replace_object(r, oid) : oid; - - errno = 0; - data = read_object(r, repl, type, size); - if (data) - return data; - - obj_read_lock(); - if (errno && errno != ENOENT) - die_errno(_("failed to read object %s"), oid_to_hex(oid)); - - /* die if we replaced an object with one that does not exist */ - if (repl != oid) - die(_("replacement %s not found for %s"), - oid_to_hex(repl), oid_to_hex(oid)); - - if (!stat_loose_object(r, repl, &st, &path)) - die(_("loose object %s (stored in %s) is corrupt"), - oid_to_hex(repl), path); - if ((p = has_packed_and_bad(r, repl))) - die(_("packed object %s (stored in %s) is corrupt"), - oid_to_hex(repl), p->pack_name); - obj_read_unlock(); + oi.typep = type; + oi.sizep = size; + oi.contentp = &data; + if (oid_object_info_extended(r, oid, &oi, flags)) + return NULL; - return NULL; + return data; } void *read_object_with_reference(struct repository *r, @@ -1864,13 +1840,6 @@ out: return 0; } -static int write_buffer(int fd, const void *buf, size_t len) -{ - if (write_in_full(fd, buf, len) < 0) - return error_errno(_("file write error")); - return 0; -} - static void hash_object_file_literally(const struct git_hash_algo *algo, const void *buf, unsigned long len, const char *type, struct object_id *oid) @@ -2015,8 +1984,8 @@ static int write_loose_object_common(git_hash_ctx *c, ret = git_deflate(stream, flush ? Z_FINISH : 0); the_hash_algo->update_fn(c, in0, stream->next_in - in0); - if (write_buffer(fd, compressed, stream->next_out - compressed) < 0) - die(_("unable to write loose object file")); + if (write_in_full(fd, compressed, stream->next_out - compressed) < 0) + die_errno(_("unable to write loose object file")); stream->next_out = compressed; stream->avail_out = compressed_len; @@ -2269,6 +2238,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime) { void *buf; unsigned long len; + struct object_info oi = OBJECT_INFO_INIT; enum object_type type; char hdr[MAX_HEADER_LEN]; int hdrlen; @@ -2276,8 +2246,10 @@ int force_object_loose(const struct object_id *oid, time_t mtime) if (has_loose_object(oid)) return 0; - buf = read_object(the_repository, oid, &type, &len); - if (!buf) + oi.typep = &type; + oi.sizep = &len; + oi.contentp = &buf; + if (oid_object_info_extended(the_repository, oid, &oi, 0)) return error(_("cannot read object for %s"), oid_to_hex(oid)); hdrlen = format_object_header(hdr, sizeof(hdr), type, len); ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0); @@ -2792,13 +2764,16 @@ int read_loose_object(const char *path, struct object_info *oi) { int ret = -1; + int fd; void *map = NULL; unsigned long mapsize; git_zstream stream; char hdr[MAX_HEADER_LEN]; unsigned long *size = oi->sizep; - map = map_loose_object_1(the_repository, path, NULL, &mapsize); + fd = git_open(path); + if (fd >= 0) + map = map_fd(fd, path, &mapsize); if (!map) { error_errno(_("unable to mmap %s"), path); goto out; |
