|
7 | 7 | #include "delta.h" |
8 | 8 | #include "list.h" |
9 | 9 | #include "streaming.h" |
| 10 | +#include "sha1-lookup.h" |
10 | 11 |
|
11 | 12 | char *odb_pack_name(struct strbuf *buf, |
12 | 13 | const unsigned char *sha1, |
@@ -509,7 +510,7 @@ static int open_packed_git_1(struct packed_git *p) |
509 | 510 | return 0; |
510 | 511 | } |
511 | 512 |
|
512 | | -int open_packed_git(struct packed_git *p) |
| 513 | +static int open_packed_git(struct packed_git *p) |
513 | 514 | { |
514 | 515 | if (!open_packed_git_1(p)) |
515 | 516 | return 0; |
@@ -1700,3 +1701,76 @@ off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n) |
1700 | 1701 | ntohl(*((uint32_t *)(index + 4))); |
1701 | 1702 | } |
1702 | 1703 | } |
| 1704 | + |
| 1705 | +off_t find_pack_entry_one(const unsigned char *sha1, |
| 1706 | + struct packed_git *p) |
| 1707 | +{ |
| 1708 | + const uint32_t *level1_ofs = p->index_data; |
| 1709 | + const unsigned char *index = p->index_data; |
| 1710 | + unsigned hi, lo, stride; |
| 1711 | + static int debug_lookup = -1; |
| 1712 | + |
| 1713 | + if (debug_lookup < 0) |
| 1714 | + debug_lookup = !!getenv("GIT_DEBUG_LOOKUP"); |
| 1715 | + |
| 1716 | + if (!index) { |
| 1717 | + if (open_pack_index(p)) |
| 1718 | + return 0; |
| 1719 | + level1_ofs = p->index_data; |
| 1720 | + index = p->index_data; |
| 1721 | + } |
| 1722 | + if (p->index_version > 1) { |
| 1723 | + level1_ofs += 2; |
| 1724 | + index += 8; |
| 1725 | + } |
| 1726 | + index += 4 * 256; |
| 1727 | + hi = ntohl(level1_ofs[*sha1]); |
| 1728 | + lo = ((*sha1 == 0x0) ? 0 : ntohl(level1_ofs[*sha1 - 1])); |
| 1729 | + if (p->index_version > 1) { |
| 1730 | + stride = 20; |
| 1731 | + } else { |
| 1732 | + stride = 24; |
| 1733 | + index += 4; |
| 1734 | + } |
| 1735 | + |
| 1736 | + if (debug_lookup) |
| 1737 | + printf("%02x%02x%02x... lo %u hi %u nr %"PRIu32"\n", |
| 1738 | + sha1[0], sha1[1], sha1[2], lo, hi, p->num_objects); |
| 1739 | + |
| 1740 | + while (lo < hi) { |
| 1741 | + unsigned mi = (lo + hi) / 2; |
| 1742 | + int cmp = hashcmp(index + mi * stride, sha1); |
| 1743 | + |
| 1744 | + if (debug_lookup) |
| 1745 | + printf("lo %u hi %u rg %u mi %u\n", |
| 1746 | + lo, hi, hi - lo, mi); |
| 1747 | + if (!cmp) |
| 1748 | + return nth_packed_object_offset(p, mi); |
| 1749 | + if (cmp > 0) |
| 1750 | + hi = mi; |
| 1751 | + else |
| 1752 | + lo = mi+1; |
| 1753 | + } |
| 1754 | + return 0; |
| 1755 | +} |
| 1756 | + |
| 1757 | +int is_pack_valid(struct packed_git *p) |
| 1758 | +{ |
| 1759 | + /* An already open pack is known to be valid. */ |
| 1760 | + if (p->pack_fd != -1) |
| 1761 | + return 1; |
| 1762 | + |
| 1763 | + /* If the pack has one window completely covering the |
| 1764 | + * file size, the pack is known to be valid even if |
| 1765 | + * the descriptor is not currently open. |
| 1766 | + */ |
| 1767 | + if (p->windows) { |
| 1768 | + struct pack_window *w = p->windows; |
| 1769 | + |
| 1770 | + if (!w->offset && w->len == p->pack_size) |
| 1771 | + return 1; |
| 1772 | + } |
| 1773 | + |
| 1774 | + /* Force the pack to open to prove its valid. */ |
| 1775 | + return !open_packed_git(p); |
| 1776 | +} |
0 commit comments