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,