1564
return git_inflate(stream, 0);
1565
}
1566
1567
+static int unpack_sha1_header_to_strbuf(git_zstream *stream, unsigned char *map,
1568
+ unsigned long mapsize, void *buffer,
1569
+ unsigned long bufsiz, struct strbuf *header)
1570
+{
1571
+ int status;
1572
+
1573
+ status = unpack_sha1_header(stream, map, mapsize, buffer, bufsiz);
1574
+
1575
+ /*
1576
+ * Check if entire header is unpacked in the first iteration.
1577
+ */
1578
+ if (memchr(buffer, '\0', stream->next_out - (unsigned char *)buffer))
1579
+ return 0;
1580
+
1581
+ /*
1582
+ * buffer[0..bufsiz] was not large enough. Copy the partial
1583
+ * result out to header, and then append the result of further
1584
+ * reading the stream.
1585
+ */
1586
+ strbuf_add(header, buffer, stream->next_out - (unsigned char *)buffer);
1587
+ stream->next_out = buffer;
1588
+ stream->avail_out = bufsiz;
1589
+
1590
+ do {
1591
+ status = git_inflate(stream, 0);
1592
+ strbuf_add(header, buffer, stream->next_out - (unsigned char *)buffer);
1593
+ if (memchr(buffer, '\0', stream->next_out - (unsigned char *)buffer))
1594
+ return 0;
1595
+ stream->next_out = buffer;
1596
+ stream->avail_out = bufsiz;
1597
+ } while (status != Z_STREAM_END);
1598
+ return -1;
1599
+}
1600
+
1601
static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long size, const unsigned char *sha1)
1602
{
1603
int bytes = strlen(buffer) + 1;
1648
* too permissive for what we want to check. So do an anal
1649
* object header parse by hand.
1650
*/
1617
-int parse_sha1_header(const char *hdr, unsigned long *sizep)
1651
+static int parse_sha1_header_extended(const char *hdr, struct object_info *oi,
1652
+ unsigned int flags)
1653
{
1619
- char type[10];
1620
- int i;
1654
+ const char *type_buf = hdr;
1655
unsigned long size;
1656
+ int type, type_len = 0;
1657
1658
/*
1624
- * The type can be at most ten bytes (including the
1625
- * terminating '\0' that we add), and is followed by
1659
+ * The type can be of any size but is followed by
1660
* a space.
1661
*/
1628
- i = 0;
1662
for (;;) {
1663
char c = *hdr++;
1664
if (c == ' ')
1665
break;
1633
- type[i++] = c;
1634
- if (i >= sizeof(type))
1635
- return -1;
1666
+ type_len++;
1667
}
1637
- type[i] = 0;
1668
+
1669
+ type = type_from_string_gently(type_buf, type_len, 1);
1670
+ if (oi->typename)
1671
+ strbuf_add(oi->typename, type_buf, type_len);
1672
+ /*
1673
+ * Set type to 0 if its an unknown object and
1674
+ * we're obtaining the type using '--allow-unkown-type'
1675
+ * option.
1676
+ */
1677
+ if ((flags & LOOKUP_UNKNOWN_OBJECT) && (type < 0))
1678
+ type = 0;
1679
+ else if (type < 0)
1680
+ die("invalid object type");
1681
+ if (oi->typep)
1682
+ *oi->typep = type;
1683
1684
/*
1685
* The length must follow immediately, and be in canonical
1697
size = size * 10 + c;
1698
}
1699
}
1655
- *sizep = size;
1700
+
1701
+ if (oi->sizep)
1702
+ *oi->sizep = size;
1703
1704
/*
1705
* The length must be followed by a zero byte
1706
*/
1660
- return *hdr ? -1 : type_from_string(type);
1707
+ return *hdr ? -1 : type;
1708
+}
1709
+
1710
+int parse_sha1_header(const char *hdr, unsigned long *sizep)
1711
+{
1712
+ struct object_info oi;
1713
+
1714
+ oi.sizep = sizep;
1715
+ oi.typename = NULL;
1716
+ oi.typep = NULL;
1717
+ return parse_sha1_header_extended(hdr, &oi, LOOKUP_REPLACE_OBJECT);
1718
}
1719
1720
static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1)
2581
}
2582
2583
static int sha1_loose_object_info(const unsigned char *sha1,
2527
- struct object_info *oi)
2584
+ struct object_info *oi,
2585
+ int flags)
2586
{
2529
- int status;
2530
- unsigned long mapsize, size;
2587
+ int status = 0;
2588
+ unsigned long mapsize;
2589
void *map;
2590
git_zstream stream;
2591
char hdr[32];
2592
+ struct strbuf hdrbuf = STRBUF_INIT;
2593
2594
if (oi->delta_base_sha1)
2595
hashclr(oi->delta_base_sha1);
2602
* return value implicitly indicates whether the
2603
* object even exists.
2604
*/
2546
- if (!oi->typep && !oi->sizep) {
2605
+ if (!oi->typep && !oi->typename && !oi->sizep) {
2606
struct stat st;
2607
if (stat_sha1_file(sha1, &st) < 0)
2608
return -1;
2616
return -1;
2617
if (oi->disk_sizep)
2618
*oi->disk_sizep = mapsize;
2560
- if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
2619
+ if ((flags & LOOKUP_UNKNOWN_OBJECT)) {
2620
+ if (unpack_sha1_header_to_strbuf(&stream, map, mapsize, hdr, sizeof(hdr), &hdrbuf) < 0)
2621
+ status = error("unable to unpack %s header with --allow-unknown-type",
2622
+ sha1_to_hex(sha1));
2623
+ } else if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
2624
status = error("unable to unpack %s header",
2625
sha1_to_hex(sha1));
2563
- else if ((status = parse_sha1_header(hdr, &size)) < 0)
2626
+ if (status < 0)
2627
+ ; /* Do nothing */
2628
+ else if (hdrbuf.len) {
2629
+ if ((status = parse_sha1_header_extended(hdrbuf.buf, oi, flags)) < 0)
2630
+ status = error("unable to parse %s header with --allow-unknown-type",
2631
+ sha1_to_hex(sha1));
2632
+ } else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)
2633
status = error("unable to parse %s header", sha1_to_hex(sha1));
2565
- else if (oi->sizep)
2566
- *oi->sizep = size;
2634
git_inflate_end(&stream);
2635
munmap(map, mapsize);
2569
- if (oi->typep)
2636
+ if (status && oi->typep)
2637
*oi->typep = status;
2638
+ strbuf_release(&hdrbuf);
2639
return 0;
2640
}
2641
2644
struct cached_object *co;
2645
struct pack_entry e;
2646
int rtype;
2647
+ enum object_type real_type;
2648
const unsigned char *real = lookup_replace_object_extended(sha1, flags);
2649
2650
co = find_cached_object(real);
2657
*(oi->disk_sizep) = 0;
2658
if (oi->delta_base_sha1)
2659
hashclr(oi->delta_base_sha1);
2660
+ if (oi->typename)
2661
+ strbuf_addstr(oi->typename, typename(co->type));
2662
oi->whence = OI_CACHED;
2663
return 0;
2664
}
2665
2666
if (!find_pack_entry(real, &e)) {
2667
/* Most likely it's a loose object. */
2597
- if (!sha1_loose_object_info(real, oi)) {
2668
+ if (!sha1_loose_object_info(real, oi, flags)) {
2669
oi->whence = OI_LOOSE;
2670
return 0;
2671
}
2676
return -1;
2677
}
2678
2679
+ /*
2680
+ * packed_object_info() does not follow the delta chain to
2681
+ * find out the real type, unless it is given oi->typep.
2682
+ */
2683
+ if (oi->typename && !oi->typep)
2684
+ oi->typep = &real_type;
2685
+
2686
rtype = packed_object_info(e.p, e.offset, oi);
2687
if (rtype < 0) {
2688
mark_bad_packed_object(e.p, real);
2689
+ if (oi->typep == &real_type)
2690
+ oi->typep = NULL;
2691
return sha1_object_info_extended(real, oi, 0);
2692
} else if (in_delta_base_cache(e.p, e.offset)) {
2693
oi->whence = OI_DBCACHED;
2698
oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
2699
rtype == OBJ_OFS_DELTA);
2700
}
2701
+ if (oi->typename)
2702
+ strbuf_addstr(oi->typename, typename(*oi->typep));
2703
+ if (oi->typep == &real_type)
2704
+ oi->typep = NULL;
2705
2706
return 0;
2707
}