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>

Jonathan Tan committed Jun 21, 2017 at 17:40 UTC c84a1f3ed4d5314d2acc2bdca71b0bc5088423f9
2 files changed +43 -42
cache.h
+1
@@ -1827,6 +1827,7 @@ struct object_info {
1827 off_t *disk_sizep;
1828 unsigned char *delta_base_sha1;
1829 struct strbuf *typename;
1830 + void **contentp;
1831
1832 /* Response */
1833 enum {
sha1_file.c
+42 -42
@@ -2005,19 +2005,6 @@ int parse_sha1_header(const char *hdr, unsigned long *sizep)
2005 return parse_sha1_header_extended(hdr, &oi, 0);
2006 }
2007
2008 -static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1)
2009 -{
2010 - int ret;
2011 - git_zstream stream;
2012 - char hdr[8192];
2013 -
2014 - ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr));
2015 - if (ret < Z_OK || (*type = parse_sha1_header(hdr, size)) < 0)
2016 - return NULL;
2017 -
2018 - return unpack_sha1_rest(&stream, hdr, *size, sha1);
2019 -}
2020 -
2008 unsigned long get_size_from_delta(struct packed_git *p,
2009 struct pack_window **w_curs,
2010 off_t curpos)
@@ -2326,8 +2313,10 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
2313 if (!ent)
2314 return unpack_entry(p, base_offset, type, base_size);
2315
2329 - *type = ent->type;
2330 - *base_size = ent->size;
2316 + if (type)
2317 + *type = ent->type;
2318 + if (base_size)
2319 + *base_size = ent->size;
2320 return xmemdupz(ent->data, ent->size);
2321 }
2322
@@ -2388,9 +2377,16 @@ int packed_object_info(struct packed_git *p, off_t obj_offset,
2377 * We always get the representation type, but only convert it to
2378 * a "real" type later if the caller is interested.
2379 */
2391 - type = unpack_object_header(p, &w_curs, &curpos, &size);
2380 + if (oi->contentp) {
2381 + *oi->contentp = cache_or_unpack_entry(p, obj_offset, oi->sizep,
2382 + &type);
2383 + if (!*oi->contentp)
2384 + type = OBJ_BAD;
2385 + } else {
2386 + type = unpack_object_header(p, &w_curs, &curpos, &size);
2387 + }
2388
2393 - if (oi->sizep) {
2389 + if (!oi->contentp && oi->sizep) {
2390 if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
2391 off_t tmp_pos = curpos;
2392 off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
@@ -2679,8 +2675,10 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
2675 free(external_base);
2676 }
2677
2682 - *final_type = type;
2683 - *final_size = size;
2678 + if (final_type)
2679 + *final_type = type;
2680 + if (final_size)
2681 + *final_size = size;
2682
2683 unuse_pack(&w_curs);
2684
@@ -2914,6 +2912,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
2912 git_zstream stream;
2913 char hdr[32];
2914 struct strbuf hdrbuf = STRBUF_INIT;
2915 + unsigned long size_scratch;
2916
2917 if (oi->delta_base_sha1)
2918 hashclr(oi->delta_base_sha1);
@@ -2926,7 +2925,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
2925 * return value implicitly indicates whether the
2926 * object even exists.
2927 */
2929 - if (!oi->typep && !oi->typename && !oi->sizep) {
2928 + if (!oi->typep && !oi->typename && !oi->sizep && !oi->contentp) {
2929 const char *path;
2930 struct stat st;
2931 if (stat_sha1_file(sha1, &st, &path) < 0)
@@ -2939,6 +2938,10 @@ static int sha1_loose_object_info(const unsigned char *sha1,
2938 map = map_sha1_file(sha1, &mapsize);
2939 if (!map)
2940 return -1;
2941 +
2942 + if (!oi->sizep)
2943 + oi->sizep = &size_scratch;
2944 +
2945 if (oi->disk_sizep)
2946 *oi->disk_sizep = mapsize;
2947 if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE)) {
@@ -2956,10 +2959,18 @@ static int sha1_loose_object_info(const unsigned char *sha1,
2959 sha1_to_hex(sha1));
2960 } else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)
2961 status = error("unable to parse %s header", sha1_to_hex(sha1));
2959 - git_inflate_end(&stream);
2962 +
2963 + if (status >= 0 && oi->contentp)
2964 + *oi->contentp = unpack_sha1_rest(&stream, hdr,
2965 + *oi->sizep, sha1);
2966 + else
2967 + git_inflate_end(&stream);
2968 +
2969 munmap(map, mapsize);
2970 if (status && oi->typep)
2971 *oi->typep = status;
2972 + if (oi->sizep == &size_scratch)
2973 + oi->sizep = NULL;
2974 strbuf_release(&hdrbuf);
2975 return (status < 0) ? status : 0;
2976 }
@@ -2985,6 +2996,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
2996 hashclr(oi->delta_base_sha1);
2997 if (oi->typename)
2998 strbuf_addstr(oi->typename, typename(co->type));
2999 + if (oi->contentp)
3000 + *oi->contentp = xmemdupz(co->buf, co->size);
3001 oi->whence = OI_CACHED;
3002 return 0;
3003 }
@@ -3078,28 +3091,15 @@ int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
3091 static void *read_object(const unsigned char *sha1, enum object_type *type,
3092 unsigned long *size)
3093 {
3081 - unsigned long mapsize;
3082 - void *map, *buf;
3083 - struct cached_object *co;
3084 -
3085 - co = find_cached_object(sha1);
3086 - if (co) {
3087 - *type = co->type;
3088 - *size = co->size;
3089 - return xmemdupz(co->buf, co->size);
3090 - }
3094 + struct object_info oi = OBJECT_INFO_INIT;
3095 + void *content;
3096 + oi.typep = type;
3097 + oi.sizep = size;
3098 + oi.contentp = &content;
3099
3092 - buf = read_packed_sha1(sha1, type, size);
3093 - if (buf)
3094 - return buf;
3095 - map = map_sha1_file(sha1, &mapsize);
3096 - if (map) {
3097 - buf = unpack_sha1_file(map, mapsize, type, size, sha1);
3098 - munmap(map, mapsize);
3099 - return buf;
3100 - }
3101 - reprepare_packed_git();
3102 - return read_packed_sha1(sha1, type, size);
3100 + if (sha1_object_info_extended(sha1, &oi, 0) < 0)
3101 + return NULL;
3102 + return content;
3103 }
3104
3105 /*