@@ -1564,6 +1564,40 @@ int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long ma
1564
1564
return git_inflate (stream , 0 );
1565
1565
}
1566
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
+
1567
1601
static void * unpack_sha1_rest (git_zstream * stream , void * buffer , unsigned long size , const unsigned char * sha1 )
1568
1602
{
1569
1603
int bytes = strlen (buffer ) + 1 ;
@@ -1614,27 +1648,38 @@ static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long s
1614
1648
* too permissive for what we want to check. So do an anal
1615
1649
* object header parse by hand.
1616
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 )
1618
1653
{
1619
- char type [10 ];
1620
- int i ;
1654
+ const char * type_buf = hdr ;
1621
1655
unsigned long size ;
1656
+ int type , type_len = 0 ;
1622
1657
1623
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
1626
1660
* a space.
1627
1661
*/
1628
- i = 0 ;
1629
1662
for (;;) {
1630
1663
char c = * hdr ++ ;
1631
1664
if (c == ' ' )
1632
1665
break ;
1633
- type [i ++ ] = c ;
1634
- if (i >= sizeof (type ))
1635
- return -1 ;
1666
+ type_len ++ ;
1636
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 ;
1638
1683
1639
1684
/*
1640
1685
* The length must follow immediately, and be in canonical
@@ -1652,12 +1697,24 @@ int parse_sha1_header(const char *hdr, unsigned long *sizep)
1652
1697
size = size * 10 + c ;
1653
1698
}
1654
1699
}
1655
- * sizep = size ;
1700
+
1701
+ if (oi -> sizep )
1702
+ * oi -> sizep = size ;
1656
1703
1657
1704
/*
1658
1705
* The length must be followed by a zero byte
1659
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 );
1661
1718
}
1662
1719
1663
1720
static void * unpack_sha1_file (void * map , unsigned long mapsize , enum object_type * type , unsigned long * size , const unsigned char * sha1 )
@@ -2524,13 +2581,15 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,
2524
2581
}
2525
2582
2526
2583
static int sha1_loose_object_info (const unsigned char * sha1 ,
2527
- struct object_info * oi )
2584
+ struct object_info * oi ,
2585
+ int flags )
2528
2586
{
2529
- int status ;
2530
- unsigned long mapsize , size ;
2587
+ int status = 0 ;
2588
+ unsigned long mapsize ;
2531
2589
void * map ;
2532
2590
git_zstream stream ;
2533
2591
char hdr [32 ];
2592
+ struct strbuf hdrbuf = STRBUF_INIT ;
2534
2593
2535
2594
if (oi -> delta_base_sha1 )
2536
2595
hashclr (oi -> delta_base_sha1 );
@@ -2543,7 +2602,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
2543
2602
* return value implicitly indicates whether the
2544
2603
* object even exists.
2545
2604
*/
2546
- if (!oi -> typep && !oi -> sizep ) {
2605
+ if (!oi -> typep && !oi -> typename && ! oi -> sizep ) {
2547
2606
struct stat st ;
2548
2607
if (stat_sha1_file (sha1 , & st ) < 0 )
2549
2608
return -1 ;
@@ -2557,17 +2616,26 @@ static int sha1_loose_object_info(const unsigned char *sha1,
2557
2616
return -1 ;
2558
2617
if (oi -> disk_sizep )
2559
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 )
2561
2624
status = error ("unable to unpack %s header" ,
2562
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 )
2564
2633
status = error ("unable to parse %s header" , sha1_to_hex (sha1 ));
2565
- else if (oi -> sizep )
2566
- * oi -> sizep = size ;
2567
2634
git_inflate_end (& stream );
2568
2635
munmap (map , mapsize );
2569
- if (oi -> typep )
2636
+ if (status && oi -> typep )
2570
2637
* oi -> typep = status ;
2638
+ strbuf_release (& hdrbuf );
2571
2639
return 0 ;
2572
2640
}
2573
2641
@@ -2576,6 +2644,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
2576
2644
struct cached_object * co ;
2577
2645
struct pack_entry e ;
2578
2646
int rtype ;
2647
+ enum object_type real_type ;
2579
2648
const unsigned char * real = lookup_replace_object_extended (sha1 , flags );
2580
2649
2581
2650
co = find_cached_object (real );
@@ -2588,13 +2657,15 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
2588
2657
* (oi -> disk_sizep ) = 0 ;
2589
2658
if (oi -> delta_base_sha1 )
2590
2659
hashclr (oi -> delta_base_sha1 );
2660
+ if (oi -> typename )
2661
+ strbuf_addstr (oi -> typename , typename (co -> type ));
2591
2662
oi -> whence = OI_CACHED ;
2592
2663
return 0 ;
2593
2664
}
2594
2665
2595
2666
if (!find_pack_entry (real , & e )) {
2596
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 )) {
2598
2669
oi -> whence = OI_LOOSE ;
2599
2670
return 0 ;
2600
2671
}
@@ -2605,9 +2676,18 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
2605
2676
return -1 ;
2606
2677
}
2607
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
+
2608
2686
rtype = packed_object_info (e .p , e .offset , oi );
2609
2687
if (rtype < 0 ) {
2610
2688
mark_bad_packed_object (e .p , real );
2689
+ if (oi -> typep == & real_type )
2690
+ oi -> typep = NULL ;
2611
2691
return sha1_object_info_extended (real , oi , 0 );
2612
2692
} else if (in_delta_base_cache (e .p , e .offset )) {
2613
2693
oi -> whence = OI_DBCACHED ;
@@ -2618,6 +2698,10 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
2618
2698
oi -> u .packed .is_delta = (rtype == OBJ_REF_DELTA ||
2619
2699
rtype == OBJ_OFS_DELTA );
2620
2700
}
2701
+ if (oi -> typename )
2702
+ strbuf_addstr (oi -> typename , typename (* oi -> typep ));
2703
+ if (oi -> typep == & real_type )
2704
+ oi -> typep = NULL ;
2621
2705
2622
2706
return 0 ;
2623
2707
}
0 commit comments