packed_object_info: hoist delta type resolution to helper
To calculate the type of a packed object, we must walk down its delta chain until we hit a true base object with a real type. Most of the code in packed_object_info is for handling this case. Let's hoist it out into a separate helper function, which will make it easier to make the type-lookup optional in the future (and keep our indentation level sane). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Jul 12, 2013 at 02:31 UTC
90191d37ab08f7c6810fa22804dedb23bade02a1
1 file changed
+53
-40
sha1_file.c
+53
-40
@@ -1710,52 +1710,21 @@ static int retry_bad_packed_offset(struct packed_git *p, off_t obj_offset)
1710
return type;
1711
}
1712
1713
-
1713
#define POI_STACK_PREALLOC 64
1714
1716
-static int packed_object_info(struct packed_git *p, off_t obj_offset,
1717
- unsigned long *sizep, int *rtype,
1718
- unsigned long *disk_sizep)
1715
+static enum object_type packed_to_object_type(struct packed_git *p,
1716
+ off_t obj_offset,
1717
+ enum object_type type,
1718
+ struct pack_window **w_curs,
1719
+ off_t curpos)
1720
{
1720
- struct pack_window *w_curs = NULL;
1721
- unsigned long size;
1722
- off_t curpos = obj_offset;
1723
- enum object_type type;
1721
off_t small_poi_stack[POI_STACK_PREALLOC];
1722
off_t *poi_stack = small_poi_stack;
1723
int poi_stack_nr = 0, poi_stack_alloc = POI_STACK_PREALLOC;
1724
1728
- type = unpack_object_header(p, &w_curs, &curpos, &size);
1729
-
1730
- if (rtype)
1731
- *rtype = type; /* representation type */
1732
-
1733
- if (sizep) {
1734
- if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
1735
- off_t tmp_pos = curpos;
1736
- off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
1737
- type, obj_offset);
1738
- if (!base_offset) {
1739
- type = OBJ_BAD;
1740
- goto out;
1741
- }
1742
- *sizep = get_size_from_delta(p, &w_curs, tmp_pos);
1743
- if (*sizep == 0) {
1744
- type = OBJ_BAD;
1745
- goto out;
1746
- }
1747
- } else {
1748
- *sizep = size;
1749
- }
1750
- }
1751
-
1752
- if (disk_sizep) {
1753
- struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
1754
- *disk_sizep = revidx[1].offset - obj_offset;
1755
- }
1756
-
1725
while (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
1726
off_t base_offset;
1727
+ unsigned long size;
1728
/* Push the object we're going to leave behind */
1729
if (poi_stack_nr >= poi_stack_alloc && poi_stack == small_poi_stack) {
1730
poi_stack_alloc = alloc_nr(poi_stack_nr);
@@ -1766,11 +1735,11 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
1735
}
1736
poi_stack[poi_stack_nr++] = obj_offset;
1737
/* If parsing the base offset fails, just unwind */
1769
- base_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
1738
+ base_offset = get_delta_base(p, w_curs, &curpos, type, obj_offset);
1739
if (!base_offset)
1740
goto unwind;
1741
curpos = obj_offset = base_offset;
1773
- type = unpack_object_header(p, &w_curs, &curpos, &size);
1742
+ type = unpack_object_header(p, w_curs, &curpos, &size);
1743
if (type <= OBJ_NONE) {
1744
/* If getting the base itself fails, we first
1745
* retry the base, otherwise unwind */
@@ -1797,7 +1766,6 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
1766
out:
1767
if (poi_stack != small_poi_stack)
1768
free(poi_stack);
1800
- unuse_pack(&w_curs);
1769
return type;
1770
1771
unwind:
@@ -1811,6 +1779,51 @@ unwind:
1779
goto out;
1780
}
1781
1782
+static int packed_object_info(struct packed_git *p, off_t obj_offset,
1783
+ unsigned long *sizep, int *rtype,
1784
+ unsigned long *disk_sizep)
1785
+{
1786
+ struct pack_window *w_curs = NULL;
1787
+ unsigned long size;
1788
+ off_t curpos = obj_offset;
1789
+ enum object_type type;
1790
+
1791
+ type = unpack_object_header(p, &w_curs, &curpos, &size);
1792
+
1793
+ if (rtype)
1794
+ *rtype = type; /* representation type */
1795
+
1796
+ if (sizep) {
1797
+ if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
1798
+ off_t tmp_pos = curpos;
1799
+ off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
1800
+ type, obj_offset);
1801
+ if (!base_offset) {
1802
+ type = OBJ_BAD;
1803
+ goto out;
1804
+ }
1805
+ *sizep = get_size_from_delta(p, &w_curs, tmp_pos);
1806
+ if (*sizep == 0) {
1807
+ type = OBJ_BAD;
1808
+ goto out;
1809
+ }
1810
+ } else {
1811
+ *sizep = size;
1812
+ }
1813
+ }
1814
+
1815
+ if (disk_sizep) {
1816
+ struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
1817
+ *disk_sizep = revidx[1].offset - obj_offset;
1818
+ }
1819
+
1820
+ type = packed_to_object_type(p, obj_offset, type, &w_curs, curpos);
1821
+
1822
+out:
1823
+ unuse_pack(&w_curs);
1824
+ return type;
1825
+}
1826
+
1827
static void *unpack_compressed_entry(struct packed_git *p,
1828
struct pack_window **w_curs,
1829
off_t curpos,