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
/*