sha1_object_info_extended(): expose a bit more info

The original interface for sha1_object_info() takes an object name and gives back a type and its size (the latter is given only when it was asked). The new interface wraps its implementation and exposes a bit more pieces of information that the interface used to discard, namely: - where the object is stored (loose? cached? packed?) - if packed, where in which packfile? Signed-off-by: Junio C Hamano <gitster@pobox.com> --- * In the earlier round, this used u.pack.delta to record the length of the delta chain, but the caller is not necessarily interested in the length of the delta chain per-se, but may only want to know if it is a delta against another object or is stored as a deflated data. Calling packed_object_info_detail() involves walking the reverse index chain to compute the store size of the object and is unnecessarily expensive. We could resurrect the code if a new caller wants to know, but I doubt it.

Junio C Hamano committed May 12, 2011 at 15:51 UTC 9a4905902230c080f0f6a64ed7f0aaa5777d2f5b
2 files changed +59 -11
cache.h
+28
@@ -1022,6 +1022,34 @@ extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsig
1022 extern unsigned long get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
1023 extern int packed_object_info_detail(struct packed_git *, off_t, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
1024
1025 +struct object_info {
1026 + /* Request */
1027 + unsigned long *sizep;
1028 +
1029 + /* Response */
1030 + enum {
1031 + OI_CACHED,
1032 + OI_LOOSE,
1033 + OI_PACKED
1034 + } whence;
1035 + union {
1036 + /*
1037 + * struct {
1038 + * ... Nothing to expose in this case
1039 + * } cached;
1040 + * struct {
1041 + * ... Nothing to expose in this case
1042 + * } loose;
1043 + */
1044 + struct {
1045 + struct packed_git *pack;
1046 + off_t offset;
1047 + unsigned int is_delta;
1048 + } packed;
1049 + } u;
1050 +};
1051 +extern int sha1_object_info_extended(const unsigned char *, struct object_info *);
1052 +
1053 /* Dumb servers support */
1054 extern int update_server_info(int);
1055
sha1_file.c
+31 -11
@@ -1481,7 +1481,7 @@ static off_t get_delta_base(struct packed_git *p,
1481
1482 /* forward declaration for a mutually recursive function */
1483 static int packed_object_info(struct packed_git *p, off_t offset,
1484 - unsigned long *sizep);
1484 + unsigned long *sizep, int *rtype);
1485
1486 static int packed_delta_info(struct packed_git *p,
1487 struct pack_window **w_curs,
@@ -1495,7 +1495,7 @@ static int packed_delta_info(struct packed_git *p,
1495 base_offset = get_delta_base(p, w_curs, &curpos, type, obj_offset);
1496 if (!base_offset)
1497 return OBJ_BAD;
1498 - type = packed_object_info(p, base_offset, NULL);
1498 + type = packed_object_info(p, base_offset, NULL, NULL);
1499 if (type <= OBJ_NONE) {
1500 struct revindex_entry *revidx;
1501 const unsigned char *base_sha1;
@@ -1605,7 +1605,7 @@ int packed_object_info_detail(struct packed_git *p,
1605 }
1606
1607 static int packed_object_info(struct packed_git *p, off_t obj_offset,
1608 - unsigned long *sizep)
1608 + unsigned long *sizep, int *rtype)
1609 {
1610 struct pack_window *w_curs = NULL;
1611 unsigned long size;
@@ -1613,6 +1613,8 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
1613 enum object_type type;
1614
1615 type = unpack_object_header(p, &w_curs, &curpos, &size);
1616 + if (rtype)
1617 + *rtype = type; /* representation type */
1618
1619 switch (type) {
1620 case OBJ_OFS_DELTA:
@@ -2093,24 +2095,28 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
2095 return status;
2096 }
2097
2096 -int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
2098 +/* returns enum object_type or negative */
2099 +int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
2100 {
2101 struct cached_object *co;
2102 struct pack_entry e;
2100 - int status;
2103 + int status, rtype;
2104
2105 co = find_cached_object(sha1);
2106 if (co) {
2104 - if (sizep)
2105 - *sizep = co->size;
2107 + if (oi->sizep)
2108 + *(oi->sizep) = co->size;
2109 + oi->whence = OI_CACHED;
2110 return co->type;
2111 }
2112
2113 if (!find_pack_entry(sha1, &e)) {
2114 /* Most likely it's a loose object. */
2111 - status = sha1_loose_object_info(sha1, sizep);
2112 - if (status >= 0)
2115 + status = sha1_loose_object_info(sha1, oi->sizep);
2116 + if (status >= 0) {
2117 + oi->whence = OI_LOOSE;
2118 return status;
2119 + }
2120
2121 /* Not a loose object; someone else may have just packed it. */
2122 reprepare_packed_git();
@@ -2118,15 +2124,29 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
2124 return status;
2125 }
2126
2121 - status = packed_object_info(e.p, e.offset, sizep);
2127 + status = packed_object_info(e.p, e.offset, oi->sizep, &rtype);
2128 if (status < 0) {
2129 mark_bad_packed_object(e.p, sha1);
2124 - status = sha1_object_info(sha1, sizep);
2130 + status = sha1_object_info_extended(sha1, oi);
2131 + } else {
2132 + oi->whence = OI_PACKED;
2133 + oi->u.packed.offset = e.offset;
2134 + oi->u.packed.pack = e.p;
2135 + oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
2136 + rtype == OBJ_OFS_DELTA);
2137 }
2138
2139 return status;
2140 }
2141
2142 +int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
2143 +{
2144 + struct object_info oi;
2145 +
2146 + oi.sizep = sizep;
2147 + return sha1_object_info_extended(sha1, &oi);
2148 +}
2149 +
2150 static void *read_packed_sha1(const unsigned char *sha1,
2151 enum object_type *type, unsigned long *size)
2152 {