object-file: update object_info_extended to reencode objects

oid_object_info_extended is updated to detect an oid encoding that does not match the current repository, use repo_oid_to_algop to find the correspoding oid in the current repository and to return the data for the oid. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Eric W. Biederman committed Oct 1, 2023 at 21:40 UTC 2328ebaa4ef7a921c7021db9e83e122dbe2ac7ad
1 file changed +91
object-file.c
+91
@@ -1662,10 +1662,101 @@ static int do_oid_object_info_extended(struct repository *r,
1662 return 0;
1663 }
1664
1665 +static int oid_object_info_convert(struct repository *r,
1666 + const struct object_id *input_oid,
1667 + struct object_info *input_oi, unsigned flags)
1668 +{
1669 + const struct git_hash_algo *input_algo = &hash_algos[input_oid->algo];
1670 + int do_die = flags & OBJECT_INFO_DIE_IF_CORRUPT;
1671 + struct strbuf type_name = STRBUF_INIT;
1672 + struct object_id oid, delta_base_oid;
1673 + struct object_info new_oi, *oi;
1674 + unsigned long size;
1675 + void *content;
1676 + int ret;
1677 +
1678 + if (repo_oid_to_algop(r, input_oid, the_hash_algo, &oid)) {
1679 + if (do_die)
1680 + die(_("missing mapping of %s to %s"),
1681 + oid_to_hex(input_oid), the_hash_algo->name);
1682 + return -1;
1683 + }
1684 +
1685 + /* Is new_oi needed? */
1686 + oi = input_oi;
1687 + if (input_oi && (input_oi->delta_base_oid || input_oi->sizep ||
1688 + input_oi->contentp)) {
1689 + new_oi = *input_oi;
1690 + /* Does delta_base_oid need to be converted? */
1691 + if (input_oi->delta_base_oid)
1692 + new_oi.delta_base_oid = &delta_base_oid;
1693 + /* Will the attributes differ when converted? */
1694 + if (input_oi->sizep || input_oi->contentp) {
1695 + new_oi.contentp = &content;
1696 + new_oi.sizep = &size;
1697 + new_oi.type_name = &type_name;
1698 + }
1699 + oi = &new_oi;
1700 + }
1701 +
1702 + ret = oid_object_info_extended(r, &oid, oi, flags);
1703 + if (ret)
1704 + return -1;
1705 + if (oi == input_oi)
1706 + return ret;
1707 +
1708 + if (new_oi.contentp) {
1709 + struct strbuf outbuf = STRBUF_INIT;
1710 + enum object_type type;
1711 +
1712 + type = type_from_string_gently(type_name.buf, type_name.len,
1713 + !do_die);
1714 + if (type == -1)
1715 + return -1;
1716 + if (type != OBJ_BLOB) {
1717 + ret = convert_object_file(&outbuf,
1718 + the_hash_algo, input_algo,
1719 + content, size, type, !do_die);
1720 + if (ret == -1)
1721 + return -1;
1722 + free(content);
1723 + size = outbuf.len;
1724 + content = strbuf_detach(&outbuf, NULL);
1725 + }
1726 + if (input_oi->sizep)
1727 + *input_oi->sizep = size;
1728 + if (input_oi->contentp)
1729 + *input_oi->contentp = content;
1730 + else
1731 + free(content);
1732 + if (input_oi->type_name)
1733 + *input_oi->type_name = type_name;
1734 + else
1735 + strbuf_release(&type_name);
1736 + }
1737 + if (new_oi.delta_base_oid == &delta_base_oid) {
1738 + if (repo_oid_to_algop(r, &delta_base_oid, input_algo,
1739 + input_oi->delta_base_oid)) {
1740 + if (do_die)
1741 + die(_("missing mapping of %s to %s"),
1742 + oid_to_hex(&delta_base_oid),
1743 + input_algo->name);
1744 + return -1;
1745 + }
1746 + }
1747 + input_oi->whence = new_oi.whence;
1748 + input_oi->u = new_oi.u;
1749 + return ret;
1750 +}
1751 +
1752 int oid_object_info_extended(struct repository *r, const struct object_id *oid,
1753 struct object_info *oi, unsigned flags)
1754 {
1755 int ret;
1756 +
1757 + if (oid->algo && (hash_algo_by_ptr(r->hash_algo) != oid->algo))
1758 + return oid_object_info_convert(r, oid, oi, flags);
1759 +
1760 obj_read_lock();
1761 ret = do_oid_object_info_extended(r, oid, oi, flags);
1762 obj_read_unlock();