@@ -245,6 +245,7 @@ struct branch
245
245
const char * name ;
246
246
struct tree_entry branch_tree ;
247
247
uintmax_t last_commit ;
248
+ uintmax_t num_notes ;
248
249
unsigned active : 1 ;
249
250
unsigned pack_id : PACK_ID_BITS ;
250
251
unsigned char sha1 [20 ];
@@ -702,6 +703,7 @@ static struct branch *new_branch(const char *name)
702
703
b -> table_next_branch = branch_table [hc ];
703
704
b -> branch_tree .versions [0 ].mode = S_IFDIR ;
704
705
b -> branch_tree .versions [1 ].mode = S_IFDIR ;
706
+ b -> num_notes = 0 ;
705
707
b -> active = 0 ;
706
708
b -> pack_id = MAX_PACK_ID ;
707
709
branch_table [hc ] = b ;
@@ -1911,6 +1913,109 @@ static void load_branch(struct branch *b)
1911
1913
}
1912
1914
}
1913
1915
1916
+ static unsigned char convert_num_notes_to_fanout (uintmax_t num_notes )
1917
+ {
1918
+ unsigned char fanout = 0 ;
1919
+ while ((num_notes >>= 8 ))
1920
+ fanout ++ ;
1921
+ return fanout ;
1922
+ }
1923
+
1924
+ static void construct_path_with_fanout (const char * hex_sha1 ,
1925
+ unsigned char fanout , char * path )
1926
+ {
1927
+ unsigned int i = 0 , j = 0 ;
1928
+ if (fanout >= 20 )
1929
+ die ("Too large fanout (%u)" , fanout );
1930
+ while (fanout ) {
1931
+ path [i ++ ] = hex_sha1 [j ++ ];
1932
+ path [i ++ ] = hex_sha1 [j ++ ];
1933
+ path [i ++ ] = '/' ;
1934
+ fanout -- ;
1935
+ }
1936
+ memcpy (path + i , hex_sha1 + j , 40 - j );
1937
+ path [i + 40 - j ] = '\0' ;
1938
+ }
1939
+
1940
+ static uintmax_t do_change_note_fanout (
1941
+ struct tree_entry * orig_root , struct tree_entry * root ,
1942
+ char * hex_sha1 , unsigned int hex_sha1_len ,
1943
+ char * fullpath , unsigned int fullpath_len ,
1944
+ unsigned char fanout )
1945
+ {
1946
+ struct tree_content * t = root -> tree ;
1947
+ struct tree_entry * e , leaf ;
1948
+ unsigned int i , tmp_hex_sha1_len , tmp_fullpath_len ;
1949
+ uintmax_t num_notes = 0 ;
1950
+ unsigned char sha1 [20 ];
1951
+ char realpath [60 ];
1952
+
1953
+ for (i = 0 ; t && i < t -> entry_count ; i ++ ) {
1954
+ e = t -> entries [i ];
1955
+ tmp_hex_sha1_len = hex_sha1_len + e -> name -> str_len ;
1956
+ tmp_fullpath_len = fullpath_len ;
1957
+
1958
+ /*
1959
+ * We're interested in EITHER existing note entries (entries
1960
+ * with exactly 40 hex chars in path, not including directory
1961
+ * separators), OR directory entries that may contain note
1962
+ * entries (with < 40 hex chars in path).
1963
+ * Also, each path component in a note entry must be a multiple
1964
+ * of 2 chars.
1965
+ */
1966
+ if (!e -> versions [1 ].mode ||
1967
+ tmp_hex_sha1_len > 40 ||
1968
+ e -> name -> str_len % 2 )
1969
+ continue ;
1970
+
1971
+ /* This _may_ be a note entry, or a subdir containing notes */
1972
+ memcpy (hex_sha1 + hex_sha1_len , e -> name -> str_dat ,
1973
+ e -> name -> str_len );
1974
+ if (tmp_fullpath_len )
1975
+ fullpath [tmp_fullpath_len ++ ] = '/' ;
1976
+ memcpy (fullpath + tmp_fullpath_len , e -> name -> str_dat ,
1977
+ e -> name -> str_len );
1978
+ tmp_fullpath_len += e -> name -> str_len ;
1979
+ fullpath [tmp_fullpath_len ] = '\0' ;
1980
+
1981
+ if (tmp_hex_sha1_len == 40 && !get_sha1_hex (hex_sha1 , sha1 )) {
1982
+ /* This is a note entry */
1983
+ construct_path_with_fanout (hex_sha1 , fanout , realpath );
1984
+ if (!strcmp (fullpath , realpath )) {
1985
+ /* Note entry is in correct location */
1986
+ num_notes ++ ;
1987
+ continue ;
1988
+ }
1989
+
1990
+ /* Rename fullpath to realpath */
1991
+ if (!tree_content_remove (orig_root , fullpath , & leaf ))
1992
+ die ("Failed to remove path %s" , fullpath );
1993
+ tree_content_set (orig_root , realpath ,
1994
+ leaf .versions [1 ].sha1 ,
1995
+ leaf .versions [1 ].mode ,
1996
+ leaf .tree );
1997
+ } else if (S_ISDIR (e -> versions [1 ].mode )) {
1998
+ /* This is a subdir that may contain note entries */
1999
+ if (!e -> tree )
2000
+ load_tree (e );
2001
+ num_notes += do_change_note_fanout (orig_root , e ,
2002
+ hex_sha1 , tmp_hex_sha1_len ,
2003
+ fullpath , tmp_fullpath_len , fanout );
2004
+ }
2005
+
2006
+ /* The above may have reallocated the current tree_content */
2007
+ t = root -> tree ;
2008
+ }
2009
+ return num_notes ;
2010
+ }
2011
+
2012
+ static uintmax_t change_note_fanout (struct tree_entry * root ,
2013
+ unsigned char fanout )
2014
+ {
2015
+ char hex_sha1 [40 ], path [60 ];
2016
+ return do_change_note_fanout (root , root , hex_sha1 , 0 , path , 0 , fanout );
2017
+ }
2018
+
1914
2019
static void file_change_m (struct branch * b )
1915
2020
{
1916
2021
const char * p = command_buf .buf + 2 ;
@@ -2061,14 +2166,16 @@ static void file_change_cr(struct branch *b, int rename)
2061
2166
leaf .tree );
2062
2167
}
2063
2168
2064
- static void note_change_n (struct branch * b )
2169
+ static void note_change_n (struct branch * b , unsigned char old_fanout )
2065
2170
{
2066
2171
const char * p = command_buf .buf + 2 ;
2067
2172
static struct strbuf uq = STRBUF_INIT ;
2068
2173
struct object_entry * oe = oe ;
2069
2174
struct branch * s ;
2070
2175
unsigned char sha1 [20 ], commit_sha1 [20 ];
2176
+ char path [60 ];
2071
2177
uint16_t inline_data = 0 ;
2178
+ unsigned char new_fanout ;
2072
2179
2073
2180
/* <dataref> or 'inline' */
2074
2181
if (* p == ':' ) {
@@ -2122,7 +2229,7 @@ static void note_change_n(struct branch *b)
2122
2229
if (oe -> type != OBJ_BLOB )
2123
2230
die ("Not a blob (actually a %s): %s" ,
2124
2231
typename (oe -> type ), command_buf .buf );
2125
- } else {
2232
+ } else if (! is_null_sha1 ( sha1 )) {
2126
2233
enum object_type type = sha1_object_info (sha1 , NULL );
2127
2234
if (type < 0 )
2128
2235
die ("Blob not found: %s" , command_buf .buf );
@@ -2131,8 +2238,17 @@ static void note_change_n(struct branch *b)
2131
2238
typename (type ), command_buf .buf );
2132
2239
}
2133
2240
2134
- tree_content_set (& b -> branch_tree , sha1_to_hex (commit_sha1 ), sha1 ,
2135
- S_IFREG | 0644 , NULL );
2241
+ construct_path_with_fanout (sha1_to_hex (commit_sha1 ), old_fanout , path );
2242
+ if (tree_content_remove (& b -> branch_tree , path , NULL ))
2243
+ b -> num_notes -- ;
2244
+
2245
+ if (is_null_sha1 (sha1 ))
2246
+ return ; /* nothing to insert */
2247
+
2248
+ b -> num_notes ++ ;
2249
+ new_fanout = convert_num_notes_to_fanout (b -> num_notes );
2250
+ construct_path_with_fanout (sha1_to_hex (commit_sha1 ), new_fanout , path );
2251
+ tree_content_set (& b -> branch_tree , path , sha1 , S_IFREG | 0644 , NULL );
2136
2252
}
2137
2253
2138
2254
static void file_change_deleteall (struct branch * b )
@@ -2141,6 +2257,7 @@ static void file_change_deleteall(struct branch *b)
2141
2257
hashclr (b -> branch_tree .versions [0 ].sha1 );
2142
2258
hashclr (b -> branch_tree .versions [1 ].sha1 );
2143
2259
load_tree (& b -> branch_tree );
2260
+ b -> num_notes = 0 ;
2144
2261
}
2145
2262
2146
2263
static void parse_from_commit (struct branch * b , char * buf , unsigned long size )
@@ -2264,6 +2381,7 @@ static void parse_new_commit(void)
2264
2381
char * committer = NULL ;
2265
2382
struct hash_list * merge_list = NULL ;
2266
2383
unsigned int merge_count ;
2384
+ unsigned char prev_fanout , new_fanout ;
2267
2385
2268
2386
/* Obtain the branch name from the rest of our command */
2269
2387
sp = strchr (command_buf .buf , ' ' ) + 1 ;
@@ -2294,6 +2412,8 @@ static void parse_new_commit(void)
2294
2412
load_branch (b );
2295
2413
}
2296
2414
2415
+ prev_fanout = convert_num_notes_to_fanout (b -> num_notes );
2416
+
2297
2417
/* file_change* */
2298
2418
while (command_buf .len > 0 ) {
2299
2419
if (!prefixcmp (command_buf .buf , "M " ))
@@ -2305,7 +2425,7 @@ static void parse_new_commit(void)
2305
2425
else if (!prefixcmp (command_buf .buf , "C " ))
2306
2426
file_change_cr (b , 0 );
2307
2427
else if (!prefixcmp (command_buf .buf , "N " ))
2308
- note_change_n (b );
2428
+ note_change_n (b , prev_fanout );
2309
2429
else if (!strcmp ("deleteall" , command_buf .buf ))
2310
2430
file_change_deleteall (b );
2311
2431
else {
@@ -2316,6 +2436,10 @@ static void parse_new_commit(void)
2316
2436
break ;
2317
2437
}
2318
2438
2439
+ new_fanout = convert_num_notes_to_fanout (b -> num_notes );
2440
+ if (new_fanout != prev_fanout )
2441
+ b -> num_notes = change_note_fanout (& b -> branch_tree , new_fanout );
2442
+
2319
2443
/* build the tree and the commit */
2320
2444
store_tree (& b -> branch_tree );
2321
2445
hashcpy (b -> branch_tree .versions [0 ].sha1 ,
0 commit comments