@@ -1568,7 +1568,8 @@ static int tree_content_set(
1568
1568
static int tree_content_remove (
1569
1569
struct tree_entry * root ,
1570
1570
const char * p ,
1571
- struct tree_entry * backup_leaf )
1571
+ struct tree_entry * backup_leaf ,
1572
+ int allow_root )
1572
1573
{
1573
1574
struct tree_content * t ;
1574
1575
const char * slash1 ;
@@ -1583,6 +1584,12 @@ static int tree_content_remove(
1583
1584
1584
1585
if (!root -> tree )
1585
1586
load_tree (root );
1587
+
1588
+ if (!* p && allow_root ) {
1589
+ e = root ;
1590
+ goto del_entry ;
1591
+ }
1592
+
1586
1593
t = root -> tree ;
1587
1594
for (i = 0 ; i < t -> entry_count ; i ++ ) {
1588
1595
e = t -> entries [i ];
@@ -1599,7 +1606,7 @@ static int tree_content_remove(
1599
1606
goto del_entry ;
1600
1607
if (!e -> tree )
1601
1608
load_tree (e );
1602
- if (tree_content_remove (e , slash1 + 1 , backup_leaf )) {
1609
+ if (tree_content_remove (e , slash1 + 1 , backup_leaf , 0 )) {
1603
1610
for (n = 0 ; n < e -> tree -> entry_count ; n ++ ) {
1604
1611
if (e -> tree -> entries [n ]-> versions [1 ].mode ) {
1605
1612
hashclr (root -> versions [1 ].sha1 );
@@ -1629,7 +1636,8 @@ static int tree_content_remove(
1629
1636
static int tree_content_get (
1630
1637
struct tree_entry * root ,
1631
1638
const char * p ,
1632
- struct tree_entry * leaf )
1639
+ struct tree_entry * leaf ,
1640
+ int allow_root )
1633
1641
{
1634
1642
struct tree_content * t ;
1635
1643
const char * slash1 ;
@@ -1641,31 +1649,39 @@ static int tree_content_get(
1641
1649
n = slash1 - p ;
1642
1650
else
1643
1651
n = strlen (p );
1644
- if (!n )
1652
+ if (!n && ! allow_root )
1645
1653
die ("Empty path component found in input" );
1646
1654
1647
1655
if (!root -> tree )
1648
1656
load_tree (root );
1657
+
1658
+ if (!n ) {
1659
+ e = root ;
1660
+ goto found_entry ;
1661
+ }
1662
+
1649
1663
t = root -> tree ;
1650
1664
for (i = 0 ; i < t -> entry_count ; i ++ ) {
1651
1665
e = t -> entries [i ];
1652
1666
if (e -> name -> str_len == n && !strncmp_icase (p , e -> name -> str_dat , n )) {
1653
- if (!slash1 ) {
1654
- memcpy (leaf , e , sizeof (* leaf ));
1655
- if (e -> tree && is_null_sha1 (e -> versions [1 ].sha1 ))
1656
- leaf -> tree = dup_tree_content (e -> tree );
1657
- else
1658
- leaf -> tree = NULL ;
1659
- return 1 ;
1660
- }
1667
+ if (!slash1 )
1668
+ goto found_entry ;
1661
1669
if (!S_ISDIR (e -> versions [1 ].mode ))
1662
1670
return 0 ;
1663
1671
if (!e -> tree )
1664
1672
load_tree (e );
1665
- return tree_content_get (e , slash1 + 1 , leaf );
1673
+ return tree_content_get (e , slash1 + 1 , leaf , 0 );
1666
1674
}
1667
1675
}
1668
1676
return 0 ;
1677
+
1678
+ found_entry :
1679
+ memcpy (leaf , e , sizeof (* leaf ));
1680
+ if (e -> tree && is_null_sha1 (e -> versions [1 ].sha1 ))
1681
+ leaf -> tree = dup_tree_content (e -> tree );
1682
+ else
1683
+ leaf -> tree = NULL ;
1684
+ return 1 ;
1669
1685
}
1670
1686
1671
1687
static int update_branch (struct branch * b )
@@ -2179,7 +2195,7 @@ static uintmax_t do_change_note_fanout(
2179
2195
}
2180
2196
2181
2197
/* Rename fullpath to realpath */
2182
- if (!tree_content_remove (orig_root , fullpath , & leaf ))
2198
+ if (!tree_content_remove (orig_root , fullpath , & leaf , 0 ))
2183
2199
die ("Failed to remove path %s" , fullpath );
2184
2200
tree_content_set (orig_root , realpath ,
2185
2201
leaf .versions [1 ].sha1 ,
@@ -2314,7 +2330,7 @@ static void file_change_m(struct branch *b)
2314
2330
2315
2331
/* Git does not track empty, non-toplevel directories. */
2316
2332
if (S_ISDIR (mode ) && !memcmp (sha1 , EMPTY_TREE_SHA1_BIN , 20 ) && * p ) {
2317
- tree_content_remove (& b -> branch_tree , p , NULL );
2333
+ tree_content_remove (& b -> branch_tree , p , NULL , 0 );
2318
2334
return ;
2319
2335
}
2320
2336
@@ -2375,7 +2391,7 @@ static void file_change_d(struct branch *b)
2375
2391
die ("Garbage after path in: %s" , command_buf .buf );
2376
2392
p = uq .buf ;
2377
2393
}
2378
- tree_content_remove (& b -> branch_tree , p , NULL );
2394
+ tree_content_remove (& b -> branch_tree , p , NULL , 1 );
2379
2395
}
2380
2396
2381
2397
static void file_change_cr (struct branch * b , int rename )
@@ -2413,9 +2429,9 @@ static void file_change_cr(struct branch *b, int rename)
2413
2429
2414
2430
memset (& leaf , 0 , sizeof (leaf ));
2415
2431
if (rename )
2416
- tree_content_remove (& b -> branch_tree , s , & leaf );
2432
+ tree_content_remove (& b -> branch_tree , s , & leaf , 1 );
2417
2433
else
2418
- tree_content_get (& b -> branch_tree , s , & leaf );
2434
+ tree_content_get (& b -> branch_tree , s , & leaf , 1 );
2419
2435
if (!leaf .versions [1 ].mode )
2420
2436
die ("Path %s not in branch" , s );
2421
2437
if (!* d ) { /* C "path/to/subdir" "" */
@@ -2521,7 +2537,7 @@ static void note_change_n(struct branch *b, unsigned char *old_fanout)
2521
2537
}
2522
2538
2523
2539
construct_path_with_fanout (sha1_to_hex (commit_sha1 ), * old_fanout , path );
2524
- if (tree_content_remove (& b -> branch_tree , path , NULL ))
2540
+ if (tree_content_remove (& b -> branch_tree , path , NULL , 0 ))
2525
2541
b -> num_notes -- ;
2526
2542
2527
2543
if (is_null_sha1 (sha1 ))
@@ -3051,6 +3067,8 @@ static void parse_ls(struct branch *b)
3051
3067
struct object_entry * e = parse_treeish_dataref (& p );
3052
3068
root = new_tree_entry ();
3053
3069
hashcpy (root -> versions [1 ].sha1 , e -> idx .sha1 );
3070
+ if (!is_null_sha1 (root -> versions [1 ].sha1 ))
3071
+ root -> versions [1 ].mode = S_IFDIR ;
3054
3072
load_tree (root );
3055
3073
if (* p ++ != ' ' )
3056
3074
die ("Missing space after tree-ish: %s" , command_buf .buf );
@@ -3065,7 +3083,7 @@ static void parse_ls(struct branch *b)
3065
3083
die ("Garbage after path in: %s" , command_buf .buf );
3066
3084
p = uq .buf ;
3067
3085
}
3068
- tree_content_get (root , p , & leaf );
3086
+ tree_content_get (root , p , & leaf , 1 );
3069
3087
/*
3070
3088
* A directory in preparation would have a sha1 of zero
3071
3089
* until it is saved. Save, for simplicity.
0 commit comments