зеркало из https://github.com/microsoft/git.git
sha1_file: refactor read_object
read_object() and sha1_object_info_extended() both implement mechanisms such as object replacement, retrying the packed store after failing to find the object in the packed store then the loose store, and being able to mark a packed object as bad and then retrying the whole process. Consolidating these mechanisms would be a great help to maintainability. Therefore, consolidate them by extending sha1_object_info_extended() to support the functionality needed, and then modifying read_object() to use sha1_object_info_extended(). Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
845b102b99
Коммит
c84a1f3ed4
1
cache.h
1
cache.h
|
@ -1827,6 +1827,7 @@ struct object_info {
|
||||||
off_t *disk_sizep;
|
off_t *disk_sizep;
|
||||||
unsigned char *delta_base_sha1;
|
unsigned char *delta_base_sha1;
|
||||||
struct strbuf *typename;
|
struct strbuf *typename;
|
||||||
|
void **contentp;
|
||||||
|
|
||||||
/* Response */
|
/* Response */
|
||||||
enum {
|
enum {
|
||||||
|
|
72
sha1_file.c
72
sha1_file.c
|
@ -2005,19 +2005,6 @@ int parse_sha1_header(const char *hdr, unsigned long *sizep)
|
||||||
return parse_sha1_header_extended(hdr, &oi, 0);
|
return parse_sha1_header_extended(hdr, &oi, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
git_zstream stream;
|
|
||||||
char hdr[8192];
|
|
||||||
|
|
||||||
ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr));
|
|
||||||
if (ret < Z_OK || (*type = parse_sha1_header(hdr, size)) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return unpack_sha1_rest(&stream, hdr, *size, sha1);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long get_size_from_delta(struct packed_git *p,
|
unsigned long get_size_from_delta(struct packed_git *p,
|
||||||
struct pack_window **w_curs,
|
struct pack_window **w_curs,
|
||||||
off_t curpos)
|
off_t curpos)
|
||||||
|
@ -2326,7 +2313,9 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
|
||||||
if (!ent)
|
if (!ent)
|
||||||
return unpack_entry(p, base_offset, type, base_size);
|
return unpack_entry(p, base_offset, type, base_size);
|
||||||
|
|
||||||
|
if (type)
|
||||||
*type = ent->type;
|
*type = ent->type;
|
||||||
|
if (base_size)
|
||||||
*base_size = ent->size;
|
*base_size = ent->size;
|
||||||
return xmemdupz(ent->data, ent->size);
|
return xmemdupz(ent->data, ent->size);
|
||||||
}
|
}
|
||||||
|
@ -2388,9 +2377,16 @@ int packed_object_info(struct packed_git *p, off_t obj_offset,
|
||||||
* We always get the representation type, but only convert it to
|
* We always get the representation type, but only convert it to
|
||||||
* a "real" type later if the caller is interested.
|
* a "real" type later if the caller is interested.
|
||||||
*/
|
*/
|
||||||
|
if (oi->contentp) {
|
||||||
|
*oi->contentp = cache_or_unpack_entry(p, obj_offset, oi->sizep,
|
||||||
|
&type);
|
||||||
|
if (!*oi->contentp)
|
||||||
|
type = OBJ_BAD;
|
||||||
|
} else {
|
||||||
type = unpack_object_header(p, &w_curs, &curpos, &size);
|
type = unpack_object_header(p, &w_curs, &curpos, &size);
|
||||||
|
}
|
||||||
|
|
||||||
if (oi->sizep) {
|
if (!oi->contentp && oi->sizep) {
|
||||||
if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
|
if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
|
||||||
off_t tmp_pos = curpos;
|
off_t tmp_pos = curpos;
|
||||||
off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
|
off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
|
||||||
|
@ -2679,7 +2675,9 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
|
||||||
free(external_base);
|
free(external_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (final_type)
|
||||||
*final_type = type;
|
*final_type = type;
|
||||||
|
if (final_size)
|
||||||
*final_size = size;
|
*final_size = size;
|
||||||
|
|
||||||
unuse_pack(&w_curs);
|
unuse_pack(&w_curs);
|
||||||
|
@ -2914,6 +2912,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
|
||||||
git_zstream stream;
|
git_zstream stream;
|
||||||
char hdr[32];
|
char hdr[32];
|
||||||
struct strbuf hdrbuf = STRBUF_INIT;
|
struct strbuf hdrbuf = STRBUF_INIT;
|
||||||
|
unsigned long size_scratch;
|
||||||
|
|
||||||
if (oi->delta_base_sha1)
|
if (oi->delta_base_sha1)
|
||||||
hashclr(oi->delta_base_sha1);
|
hashclr(oi->delta_base_sha1);
|
||||||
|
@ -2926,7 +2925,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
|
||||||
* return value implicitly indicates whether the
|
* return value implicitly indicates whether the
|
||||||
* object even exists.
|
* object even exists.
|
||||||
*/
|
*/
|
||||||
if (!oi->typep && !oi->typename && !oi->sizep) {
|
if (!oi->typep && !oi->typename && !oi->sizep && !oi->contentp) {
|
||||||
const char *path;
|
const char *path;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat_sha1_file(sha1, &st, &path) < 0)
|
if (stat_sha1_file(sha1, &st, &path) < 0)
|
||||||
|
@ -2939,6 +2938,10 @@ static int sha1_loose_object_info(const unsigned char *sha1,
|
||||||
map = map_sha1_file(sha1, &mapsize);
|
map = map_sha1_file(sha1, &mapsize);
|
||||||
if (!map)
|
if (!map)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!oi->sizep)
|
||||||
|
oi->sizep = &size_scratch;
|
||||||
|
|
||||||
if (oi->disk_sizep)
|
if (oi->disk_sizep)
|
||||||
*oi->disk_sizep = mapsize;
|
*oi->disk_sizep = mapsize;
|
||||||
if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE)) {
|
if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE)) {
|
||||||
|
@ -2956,10 +2959,18 @@ static int sha1_loose_object_info(const unsigned char *sha1,
|
||||||
sha1_to_hex(sha1));
|
sha1_to_hex(sha1));
|
||||||
} else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)
|
} else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)
|
||||||
status = error("unable to parse %s header", sha1_to_hex(sha1));
|
status = error("unable to parse %s header", sha1_to_hex(sha1));
|
||||||
|
|
||||||
|
if (status >= 0 && oi->contentp)
|
||||||
|
*oi->contentp = unpack_sha1_rest(&stream, hdr,
|
||||||
|
*oi->sizep, sha1);
|
||||||
|
else
|
||||||
git_inflate_end(&stream);
|
git_inflate_end(&stream);
|
||||||
|
|
||||||
munmap(map, mapsize);
|
munmap(map, mapsize);
|
||||||
if (status && oi->typep)
|
if (status && oi->typep)
|
||||||
*oi->typep = status;
|
*oi->typep = status;
|
||||||
|
if (oi->sizep == &size_scratch)
|
||||||
|
oi->sizep = NULL;
|
||||||
strbuf_release(&hdrbuf);
|
strbuf_release(&hdrbuf);
|
||||||
return (status < 0) ? status : 0;
|
return (status < 0) ? status : 0;
|
||||||
}
|
}
|
||||||
|
@ -2985,6 +2996,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
|
||||||
hashclr(oi->delta_base_sha1);
|
hashclr(oi->delta_base_sha1);
|
||||||
if (oi->typename)
|
if (oi->typename)
|
||||||
strbuf_addstr(oi->typename, typename(co->type));
|
strbuf_addstr(oi->typename, typename(co->type));
|
||||||
|
if (oi->contentp)
|
||||||
|
*oi->contentp = xmemdupz(co->buf, co->size);
|
||||||
oi->whence = OI_CACHED;
|
oi->whence = OI_CACHED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3078,28 +3091,15 @@ int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
|
||||||
static void *read_object(const unsigned char *sha1, enum object_type *type,
|
static void *read_object(const unsigned char *sha1, enum object_type *type,
|
||||||
unsigned long *size)
|
unsigned long *size)
|
||||||
{
|
{
|
||||||
unsigned long mapsize;
|
struct object_info oi = OBJECT_INFO_INIT;
|
||||||
void *map, *buf;
|
void *content;
|
||||||
struct cached_object *co;
|
oi.typep = type;
|
||||||
|
oi.sizep = size;
|
||||||
|
oi.contentp = &content;
|
||||||
|
|
||||||
co = find_cached_object(sha1);
|
if (sha1_object_info_extended(sha1, &oi, 0) < 0)
|
||||||
if (co) {
|
return NULL;
|
||||||
*type = co->type;
|
return content;
|
||||||
*size = co->size;
|
|
||||||
return xmemdupz(co->buf, co->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = read_packed_sha1(sha1, type, size);
|
|
||||||
if (buf)
|
|
||||||
return buf;
|
|
||||||
map = map_sha1_file(sha1, &mapsize);
|
|
||||||
if (map) {
|
|
||||||
buf = unpack_sha1_file(map, mapsize, type, size, sha1);
|
|
||||||
munmap(map, mapsize);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
reprepare_packed_git();
|
|
||||||
return read_packed_sha1(sha1, type, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче