@@ -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 )
@@ -2522,13 +2579,15 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,
2522
2579
}
2523
2580
2524
2581
static int sha1_loose_object_info (const unsigned char * sha1 ,
2525
- struct object_info * oi )
2582
+ struct object_info * oi ,
2583
+ int flags )
2526
2584
{
2527
- int status ;
2528
- unsigned long mapsize , size ;
2585
+ int status = 0 ;
2586
+ unsigned long mapsize ;
2529
2587
void * map ;
2530
2588
git_zstream stream ;
2531
2589
char hdr [32 ];
2590
+ struct strbuf hdrbuf = STRBUF_INIT ;
2532
2591
2533
2592
if (oi -> delta_base_sha1 )
2534
2593
hashclr (oi -> delta_base_sha1 );
@@ -2541,7 +2600,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
2541
2600
* return value implicitly indicates whether the
2542
2601
* object even exists.
2543
2602
*/
2544
- if (!oi -> typep && !oi -> sizep ) {
2603
+ if (!oi -> typep && !oi -> typename && ! oi -> sizep ) {
2545
2604
struct stat st ;
2546
2605
if (stat_sha1_file (sha1 , & st ) < 0 )
2547
2606
return -1 ;
@@ -2555,17 +2614,26 @@ static int sha1_loose_object_info(const unsigned char *sha1,
2555
2614
return -1 ;
2556
2615
if (oi -> disk_sizep )
2557
2616
* oi -> disk_sizep = mapsize ;
2558
- if (unpack_sha1_header (& stream , map , mapsize , hdr , sizeof (hdr )) < 0 )
2617
+ if ((flags & LOOKUP_UNKNOWN_OBJECT )) {
2618
+ if (unpack_sha1_header_to_strbuf (& stream , map , mapsize , hdr , sizeof (hdr ), & hdrbuf ) < 0 )
2619
+ status = error ("unable to unpack %s header with --allow-unknown-type" ,
2620
+ sha1_to_hex (sha1 ));
2621
+ } else if (unpack_sha1_header (& stream , map , mapsize , hdr , sizeof (hdr )) < 0 )
2559
2622
status = error ("unable to unpack %s header" ,
2560
2623
sha1_to_hex (sha1 ));
2561
- else if ((status = parse_sha1_header (hdr , & size )) < 0 )
2624
+ if (status < 0 )
2625
+ ; /* Do nothing */
2626
+ else if (hdrbuf .len ) {
2627
+ if ((status = parse_sha1_header_extended (hdrbuf .buf , oi , flags )) < 0 )
2628
+ status = error ("unable to parse %s header with --allow-unknown-type" ,
2629
+ sha1_to_hex (sha1 ));
2630
+ } else if ((status = parse_sha1_header_extended (hdr , oi , flags )) < 0 )
2562
2631
status = error ("unable to parse %s header" , sha1_to_hex (sha1 ));
2563
- else if (oi -> sizep )
2564
- * oi -> sizep = size ;
2565
2632
git_inflate_end (& stream );
2566
2633
munmap (map , mapsize );
2567
- if (oi -> typep )
2634
+ if (status && oi -> typep )
2568
2635
* oi -> typep = status ;
2636
+ strbuf_release (& hdrbuf );
2569
2637
return 0 ;
2570
2638
}
2571
2639
@@ -2574,6 +2642,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
2574
2642
struct cached_object * co ;
2575
2643
struct pack_entry e ;
2576
2644
int rtype ;
2645
+ enum object_type real_type ;
2577
2646
const unsigned char * real = lookup_replace_object_extended (sha1 , flags );
2578
2647
2579
2648
co = find_cached_object (real );
@@ -2586,13 +2655,15 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
2586
2655
* (oi -> disk_sizep ) = 0 ;
2587
2656
if (oi -> delta_base_sha1 )
2588
2657
hashclr (oi -> delta_base_sha1 );
2658
+ if (oi -> typename )
2659
+ strbuf_addstr (oi -> typename , typename (co -> type ));
2589
2660
oi -> whence = OI_CACHED ;
2590
2661
return 0 ;
2591
2662
}
2592
2663
2593
2664
if (!find_pack_entry (real , & e )) {
2594
2665
/* Most likely it's a loose object. */
2595
- if (!sha1_loose_object_info (real , oi )) {
2666
+ if (!sha1_loose_object_info (real , oi , flags )) {
2596
2667
oi -> whence = OI_LOOSE ;
2597
2668
return 0 ;
2598
2669
}
@@ -2603,9 +2674,18 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
2603
2674
return -1 ;
2604
2675
}
2605
2676
2677
+ /*
2678
+ * packed_object_info() does not follow the delta chain to
2679
+ * find out the real type, unless it is given oi->typep.
2680
+ */
2681
+ if (oi -> typename && !oi -> typep )
2682
+ oi -> typep = & real_type ;
2683
+
2606
2684
rtype = packed_object_info (e .p , e .offset , oi );
2607
2685
if (rtype < 0 ) {
2608
2686
mark_bad_packed_object (e .p , real );
2687
+ if (oi -> typep == & real_type )
2688
+ oi -> typep = NULL ;
2609
2689
return sha1_object_info_extended (real , oi , 0 );
2610
2690
} else if (in_delta_base_cache (e .p , e .offset )) {
2611
2691
oi -> whence = OI_DBCACHED ;
@@ -2616,6 +2696,10 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
2616
2696
oi -> u .packed .is_delta = (rtype == OBJ_REF_DELTA ||
2617
2697
rtype == OBJ_OFS_DELTA );
2618
2698
}
2699
+ if (oi -> typename )
2700
+ strbuf_addstr (oi -> typename , typename (* oi -> typep ));
2701
+ if (oi -> typep == & real_type )
2702
+ oi -> typep = NULL ;
2619
2703
2620
2704
return 0 ;
2621
2705
}
0 commit comments