@@ -1306,6 +1306,26 @@ static int git_open_noatime(const char *name)
1306
1306
}
1307
1307
}
1308
1308
1309
+ static int stat_sha1_file (const unsigned char * sha1 , struct stat * st )
1310
+ {
1311
+ char * name = sha1_file_name (sha1 );
1312
+ struct alternate_object_database * alt ;
1313
+
1314
+ if (!lstat (name , st ))
1315
+ return 0 ;
1316
+
1317
+ prepare_alt_odb ();
1318
+ errno = ENOENT ;
1319
+ for (alt = alt_odb_list ; alt ; alt = alt -> next ) {
1320
+ name = alt -> name ;
1321
+ fill_sha1_path (name , sha1 );
1322
+ if (!lstat (alt -> base , st ))
1323
+ return 0 ;
1324
+ }
1325
+
1326
+ return -1 ;
1327
+ }
1328
+
1309
1329
static int open_sha1_file (const unsigned char * sha1 )
1310
1330
{
1311
1331
int fd ;
@@ -1693,52 +1713,21 @@ static int retry_bad_packed_offset(struct packed_git *p, off_t obj_offset)
1693
1713
return type ;
1694
1714
}
1695
1715
1696
-
1697
1716
#define POI_STACK_PREALLOC 64
1698
1717
1699
- static int packed_object_info (struct packed_git * p , off_t obj_offset ,
1700
- unsigned long * sizep , int * rtype ,
1701
- unsigned long * disk_sizep )
1718
+ static enum object_type packed_to_object_type (struct packed_git * p ,
1719
+ off_t obj_offset ,
1720
+ enum object_type type ,
1721
+ struct pack_window * * w_curs ,
1722
+ off_t curpos )
1702
1723
{
1703
- struct pack_window * w_curs = NULL ;
1704
- unsigned long size ;
1705
- off_t curpos = obj_offset ;
1706
- enum object_type type ;
1707
1724
off_t small_poi_stack [POI_STACK_PREALLOC ];
1708
1725
off_t * poi_stack = small_poi_stack ;
1709
1726
int poi_stack_nr = 0 , poi_stack_alloc = POI_STACK_PREALLOC ;
1710
1727
1711
- type = unpack_object_header (p , & w_curs , & curpos , & size );
1712
-
1713
- if (rtype )
1714
- * rtype = type ; /* representation type */
1715
-
1716
- if (sizep ) {
1717
- if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA ) {
1718
- off_t tmp_pos = curpos ;
1719
- off_t base_offset = get_delta_base (p , & w_curs , & tmp_pos ,
1720
- type , obj_offset );
1721
- if (!base_offset ) {
1722
- type = OBJ_BAD ;
1723
- goto out ;
1724
- }
1725
- * sizep = get_size_from_delta (p , & w_curs , tmp_pos );
1726
- if (* sizep == 0 ) {
1727
- type = OBJ_BAD ;
1728
- goto out ;
1729
- }
1730
- } else {
1731
- * sizep = size ;
1732
- }
1733
- }
1734
-
1735
- if (disk_sizep ) {
1736
- struct revindex_entry * revidx = find_pack_revindex (p , obj_offset );
1737
- * disk_sizep = revidx [1 ].offset - obj_offset ;
1738
- }
1739
-
1740
1728
while (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA ) {
1741
1729
off_t base_offset ;
1730
+ unsigned long size ;
1742
1731
/* Push the object we're going to leave behind */
1743
1732
if (poi_stack_nr >= poi_stack_alloc && poi_stack == small_poi_stack ) {
1744
1733
poi_stack_alloc = alloc_nr (poi_stack_nr );
@@ -1749,11 +1738,11 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
1749
1738
}
1750
1739
poi_stack [poi_stack_nr ++ ] = obj_offset ;
1751
1740
/* If parsing the base offset fails, just unwind */
1752
- base_offset = get_delta_base (p , & w_curs , & curpos , type , obj_offset );
1741
+ base_offset = get_delta_base (p , w_curs , & curpos , type , obj_offset );
1753
1742
if (!base_offset )
1754
1743
goto unwind ;
1755
1744
curpos = obj_offset = base_offset ;
1756
- type = unpack_object_header (p , & w_curs , & curpos , & size );
1745
+ type = unpack_object_header (p , w_curs , & curpos , & size );
1757
1746
if (type <= OBJ_NONE ) {
1758
1747
/* If getting the base itself fails, we first
1759
1748
* retry the base, otherwise unwind */
@@ -1780,7 +1769,6 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
1780
1769
out :
1781
1770
if (poi_stack != small_poi_stack )
1782
1771
free (poi_stack );
1783
- unuse_pack (& w_curs );
1784
1772
return type ;
1785
1773
1786
1774
unwind :
@@ -1794,6 +1782,57 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
1794
1782
goto out ;
1795
1783
}
1796
1784
1785
+ static int packed_object_info (struct packed_git * p , off_t obj_offset ,
1786
+ struct object_info * oi )
1787
+ {
1788
+ struct pack_window * w_curs = NULL ;
1789
+ unsigned long size ;
1790
+ off_t curpos = obj_offset ;
1791
+ enum object_type type ;
1792
+
1793
+ /*
1794
+ * We always get the representation type, but only convert it to
1795
+ * a "real" type later if the caller is interested.
1796
+ */
1797
+ type = unpack_object_header (p , & w_curs , & curpos , & size );
1798
+
1799
+ if (oi -> sizep ) {
1800
+ if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA ) {
1801
+ off_t tmp_pos = curpos ;
1802
+ off_t base_offset = get_delta_base (p , & w_curs , & tmp_pos ,
1803
+ type , obj_offset );
1804
+ if (!base_offset ) {
1805
+ type = OBJ_BAD ;
1806
+ goto out ;
1807
+ }
1808
+ * oi -> sizep = get_size_from_delta (p , & w_curs , tmp_pos );
1809
+ if (* oi -> sizep == 0 ) {
1810
+ type = OBJ_BAD ;
1811
+ goto out ;
1812
+ }
1813
+ } else {
1814
+ * oi -> sizep = size ;
1815
+ }
1816
+ }
1817
+
1818
+ if (oi -> disk_sizep ) {
1819
+ struct revindex_entry * revidx = find_pack_revindex (p , obj_offset );
1820
+ * oi -> disk_sizep = revidx [1 ].offset - obj_offset ;
1821
+ }
1822
+
1823
+ if (oi -> typep ) {
1824
+ * oi -> typep = packed_to_object_type (p , obj_offset , type , & w_curs , curpos );
1825
+ if (* oi -> typep < 0 ) {
1826
+ type = OBJ_BAD ;
1827
+ goto out ;
1828
+ }
1829
+ }
1830
+
1831
+ out :
1832
+ unuse_pack (& w_curs );
1833
+ return type ;
1834
+ }
1835
+
1797
1836
static void * unpack_compressed_entry (struct packed_git * p ,
1798
1837
struct pack_window * * w_curs ,
1799
1838
off_t curpos ,
@@ -2363,68 +2402,84 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,
2363
2402
2364
2403
}
2365
2404
2366
- static int sha1_loose_object_info (const unsigned char * sha1 , unsigned long * sizep ,
2367
- unsigned long * disk_sizep )
2405
+ static int sha1_loose_object_info (const unsigned char * sha1 ,
2406
+ struct object_info * oi )
2368
2407
{
2369
2408
int status ;
2370
2409
unsigned long mapsize , size ;
2371
2410
void * map ;
2372
2411
git_zstream stream ;
2373
2412
char hdr [32 ];
2374
2413
2414
+ /*
2415
+ * If we don't care about type or size, then we don't
2416
+ * need to look inside the object at all.
2417
+ */
2418
+ if (!oi -> typep && !oi -> sizep ) {
2419
+ if (oi -> disk_sizep ) {
2420
+ struct stat st ;
2421
+ if (stat_sha1_file (sha1 , & st ) < 0 )
2422
+ return -1 ;
2423
+ * oi -> disk_sizep = st .st_size ;
2424
+ }
2425
+ return 0 ;
2426
+ }
2427
+
2375
2428
map = map_sha1_file (sha1 , & mapsize );
2376
2429
if (!map )
2377
2430
return -1 ;
2378
- if (disk_sizep )
2379
- * disk_sizep = mapsize ;
2431
+ if (oi -> disk_sizep )
2432
+ * oi -> disk_sizep = mapsize ;
2380
2433
if (unpack_sha1_header (& stream , map , mapsize , hdr , sizeof (hdr )) < 0 )
2381
2434
status = error ("unable to unpack %s header" ,
2382
2435
sha1_to_hex (sha1 ));
2383
2436
else if ((status = parse_sha1_header (hdr , & size )) < 0 )
2384
2437
status = error ("unable to parse %s header" , sha1_to_hex (sha1 ));
2385
- else if (sizep )
2386
- * sizep = size ;
2438
+ else if (oi -> sizep )
2439
+ * oi -> sizep = size ;
2387
2440
git_inflate_end (& stream );
2388
2441
munmap (map , mapsize );
2389
- return status ;
2442
+ if (oi -> typep )
2443
+ * oi -> typep = status ;
2444
+ return 0 ;
2390
2445
}
2391
2446
2392
2447
/* returns enum object_type or negative */
2393
2448
int sha1_object_info_extended (const unsigned char * sha1 , struct object_info * oi )
2394
2449
{
2395
2450
struct cached_object * co ;
2396
2451
struct pack_entry e ;
2397
- int status , rtype ;
2452
+ int rtype ;
2398
2453
2399
2454
co = find_cached_object (sha1 );
2400
2455
if (co ) {
2456
+ if (oi -> typep )
2457
+ * (oi -> typep ) = co -> type ;
2401
2458
if (oi -> sizep )
2402
2459
* (oi -> sizep ) = co -> size ;
2403
2460
if (oi -> disk_sizep )
2404
2461
* (oi -> disk_sizep ) = 0 ;
2405
2462
oi -> whence = OI_CACHED ;
2406
- return co -> type ;
2463
+ return 0 ;
2407
2464
}
2408
2465
2409
2466
if (!find_pack_entry (sha1 , & e )) {
2410
2467
/* Most likely it's a loose object. */
2411
- status = sha1_loose_object_info (sha1 , oi -> sizep , oi -> disk_sizep );
2412
- if (status >= 0 ) {
2468
+ if (!sha1_loose_object_info (sha1 , oi )) {
2413
2469
oi -> whence = OI_LOOSE ;
2414
- return status ;
2470
+ return 0 ;
2415
2471
}
2416
2472
2417
2473
/* Not a loose object; someone else may have just packed it. */
2418
2474
reprepare_packed_git ();
2419
2475
if (!find_pack_entry (sha1 , & e ))
2420
- return status ;
2476
+ return -1 ;
2421
2477
}
2422
2478
2423
- status = packed_object_info (e .p , e .offset , oi -> sizep , & rtype ,
2424
- oi -> disk_sizep );
2425
- if (status < 0 ) {
2479
+ rtype = packed_object_info (e .p , e .offset , oi );
2480
+ if (rtype < 0 ) {
2426
2481
mark_bad_packed_object (e .p , sha1 );
2427
- status = sha1_object_info_extended (sha1 , oi );
2482
+ return sha1_object_info_extended (sha1 , oi );
2428
2483
} else if (in_delta_base_cache (e .p , e .offset )) {
2429
2484
oi -> whence = OI_DBCACHED ;
2430
2485
} else {
@@ -2435,15 +2490,19 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
2435
2490
rtype == OBJ_OFS_DELTA );
2436
2491
}
2437
2492
2438
- return status ;
2493
+ return 0 ;
2439
2494
}
2440
2495
2441
2496
int sha1_object_info (const unsigned char * sha1 , unsigned long * sizep )
2442
2497
{
2443
- struct object_info oi = {0 };
2498
+ enum object_type type ;
2499
+ struct object_info oi = {NULL };
2444
2500
2501
+ oi .typep = & type ;
2445
2502
oi .sizep = sizep ;
2446
- return sha1_object_info_extended (sha1 , & oi );
2503
+ if (sha1_object_info_extended (sha1 , & oi ) < 0 )
2504
+ return -1 ;
2505
+ return type ;
2447
2506
}
2448
2507
2449
2508
static void * read_packed_sha1 (const unsigned char * sha1 ,
0 commit comments