@@ -1568,7 +1568,8 @@ static int tree_content_set(
15681568static int tree_content_remove (
15691569 struct tree_entry * root ,
15701570 const char * p ,
1571- struct tree_entry * backup_leaf )
1571+ struct tree_entry * backup_leaf ,
1572+ int allow_root )
15721573{
15731574 struct tree_content * t ;
15741575 const char * slash1 ;
@@ -1583,6 +1584,12 @@ static int tree_content_remove(
15831584
15841585 if (!root -> tree )
15851586 load_tree (root );
1587+
1588+ if (!* p && allow_root ) {
1589+ e = root ;
1590+ goto del_entry ;
1591+ }
1592+
15861593 t = root -> tree ;
15871594 for (i = 0 ; i < t -> entry_count ; i ++ ) {
15881595 e = t -> entries [i ];
@@ -1599,7 +1606,7 @@ static int tree_content_remove(
15991606 goto del_entry ;
16001607 if (!e -> tree )
16011608 load_tree (e );
1602- if (tree_content_remove (e , slash1 + 1 , backup_leaf )) {
1609+ if (tree_content_remove (e , slash1 + 1 , backup_leaf , 0 )) {
16031610 for (n = 0 ; n < e -> tree -> entry_count ; n ++ ) {
16041611 if (e -> tree -> entries [n ]-> versions [1 ].mode ) {
16051612 hashclr (root -> versions [1 ].sha1 );
@@ -1629,7 +1636,8 @@ static int tree_content_remove(
16291636static int tree_content_get (
16301637 struct tree_entry * root ,
16311638 const char * p ,
1632- struct tree_entry * leaf )
1639+ struct tree_entry * leaf ,
1640+ int allow_root )
16331641{
16341642 struct tree_content * t ;
16351643 const char * slash1 ;
@@ -1641,31 +1649,39 @@ static int tree_content_get(
16411649 n = slash1 - p ;
16421650 else
16431651 n = strlen (p );
1644- if (!n )
1652+ if (!n && ! allow_root )
16451653 die ("Empty path component found in input" );
16461654
16471655 if (!root -> tree )
16481656 load_tree (root );
1657+
1658+ if (!n ) {
1659+ e = root ;
1660+ goto found_entry ;
1661+ }
1662+
16491663 t = root -> tree ;
16501664 for (i = 0 ; i < t -> entry_count ; i ++ ) {
16511665 e = t -> entries [i ];
16521666 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 ;
16611669 if (!S_ISDIR (e -> versions [1 ].mode ))
16621670 return 0 ;
16631671 if (!e -> tree )
16641672 load_tree (e );
1665- return tree_content_get (e , slash1 + 1 , leaf );
1673+ return tree_content_get (e , slash1 + 1 , leaf , 0 );
16661674 }
16671675 }
16681676 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 ;
16691685}
16701686
16711687static int update_branch (struct branch * b )
@@ -2179,7 +2195,7 @@ static uintmax_t do_change_note_fanout(
21792195 }
21802196
21812197 /* Rename fullpath to realpath */
2182- if (!tree_content_remove (orig_root , fullpath , & leaf ))
2198+ if (!tree_content_remove (orig_root , fullpath , & leaf , 0 ))
21832199 die ("Failed to remove path %s" , fullpath );
21842200 tree_content_set (orig_root , realpath ,
21852201 leaf .versions [1 ].sha1 ,
@@ -2314,7 +2330,7 @@ static void file_change_m(struct branch *b)
23142330
23152331 /* Git does not track empty, non-toplevel directories. */
23162332 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 );
23182334 return ;
23192335 }
23202336
@@ -2375,7 +2391,7 @@ static void file_change_d(struct branch *b)
23752391 die ("Garbage after path in: %s" , command_buf .buf );
23762392 p = uq .buf ;
23772393 }
2378- tree_content_remove (& b -> branch_tree , p , NULL );
2394+ tree_content_remove (& b -> branch_tree , p , NULL , 1 );
23792395}
23802396
23812397static void file_change_cr (struct branch * b , int rename )
@@ -2413,9 +2429,9 @@ static void file_change_cr(struct branch *b, int rename)
24132429
24142430 memset (& leaf , 0 , sizeof (leaf ));
24152431 if (rename )
2416- tree_content_remove (& b -> branch_tree , s , & leaf );
2432+ tree_content_remove (& b -> branch_tree , s , & leaf , 1 );
24172433 else
2418- tree_content_get (& b -> branch_tree , s , & leaf );
2434+ tree_content_get (& b -> branch_tree , s , & leaf , 1 );
24192435 if (!leaf .versions [1 ].mode )
24202436 die ("Path %s not in branch" , s );
24212437 if (!* d ) { /* C "path/to/subdir" "" */
@@ -2521,7 +2537,7 @@ static void note_change_n(struct branch *b, unsigned char *old_fanout)
25212537 }
25222538
25232539 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 ))
25252541 b -> num_notes -- ;
25262542
25272543 if (is_null_sha1 (sha1 ))
@@ -3051,6 +3067,8 @@ static void parse_ls(struct branch *b)
30513067 struct object_entry * e = parse_treeish_dataref (& p );
30523068 root = new_tree_entry ();
30533069 hashcpy (root -> versions [1 ].sha1 , e -> idx .sha1 );
3070+ if (!is_null_sha1 (root -> versions [1 ].sha1 ))
3071+ root -> versions [1 ].mode = S_IFDIR ;
30543072 load_tree (root );
30553073 if (* p ++ != ' ' )
30563074 die ("Missing space after tree-ish: %s" , command_buf .buf );
@@ -3065,7 +3083,7 @@ static void parse_ls(struct branch *b)
30653083 die ("Garbage after path in: %s" , command_buf .buf );
30663084 p = uq .buf ;
30673085 }
3068- tree_content_get (root , p , & leaf );
3086+ tree_content_get (root , p , & leaf , 1 );
30693087 /*
30703088 * A directory in preparation would have a sha1 of zero
30713089 * until it is saved. Save, for simplicity.
0 commit comments