@@ -101,36 +101,36 @@ struct common_dir {
101
101
/* Not considered garbage for report_linked_checkout_garbage */
102
102
unsigned ignore_garbage :1 ;
103
103
unsigned is_dir :1 ;
104
- /* Not common even though its parent is */
105
- unsigned exclude :1 ;
106
- const char * dirname ;
104
+ /* Belongs to the common dir, though it may contain paths that don't */
105
+ unsigned is_common :1 ;
106
+ const char * path ;
107
107
};
108
108
109
109
static struct common_dir common_list [] = {
110
- { 0 , 1 , 0 , "branches" },
111
- { 0 , 1 , 0 , "common" },
112
- { 0 , 1 , 0 , "hooks" },
113
- { 0 , 1 , 0 , "info" },
114
- { 0 , 0 , 1 , "info/sparse-checkout" },
115
- { 1 , 1 , 0 , "logs" },
116
- { 1 , 1 , 1 , "logs/HEAD" },
117
- { 0 , 1 , 1 , "logs/refs/bisect" },
118
- { 0 , 1 , 1 , "logs/refs/rewritten" },
119
- { 0 , 1 , 1 , "logs/refs/worktree" },
120
- { 0 , 1 , 0 , "lost-found" },
121
- { 0 , 1 , 0 , "objects" },
122
- { 0 , 1 , 0 , "refs" },
123
- { 0 , 1 , 1 , "refs/bisect" },
124
- { 0 , 1 , 1 , "refs/rewritten" },
125
- { 0 , 1 , 1 , "refs/worktree" },
126
- { 0 , 1 , 0 , "remotes" },
127
- { 0 , 1 , 0 , "worktrees" },
128
- { 0 , 1 , 0 , "rr-cache" },
129
- { 0 , 1 , 0 , "svn" },
130
- { 0 , 0 , 0 , "config" },
131
- { 1 , 0 , 0 , "gc.pid" },
132
- { 0 , 0 , 0 , "packed-refs" },
133
- { 0 , 0 , 0 , "shallow" },
110
+ { 0 , 1 , 1 , "branches" },
111
+ { 0 , 1 , 1 , "common" },
112
+ { 0 , 1 , 1 , "hooks" },
113
+ { 0 , 1 , 1 , "info" },
114
+ { 0 , 0 , 0 , "info/sparse-checkout" },
115
+ { 1 , 1 , 1 , "logs" },
116
+ { 1 , 0 , 0 , "logs/HEAD" },
117
+ { 0 , 1 , 0 , "logs/refs/bisect" },
118
+ { 0 , 1 , 0 , "logs/refs/rewritten" },
119
+ { 0 , 1 , 0 , "logs/refs/worktree" },
120
+ { 0 , 1 , 1 , "lost-found" },
121
+ { 0 , 1 , 1 , "objects" },
122
+ { 0 , 1 , 1 , "refs" },
123
+ { 0 , 1 , 0 , "refs/bisect" },
124
+ { 0 , 1 , 0 , "refs/rewritten" },
125
+ { 0 , 1 , 0 , "refs/worktree" },
126
+ { 0 , 1 , 1 , "remotes" },
127
+ { 0 , 1 , 1 , "worktrees" },
128
+ { 0 , 1 , 1 , "rr-cache" },
129
+ { 0 , 1 , 1 , "svn" },
130
+ { 0 , 0 , 1 , "config" },
131
+ { 1 , 0 , 1 , "gc.pid" },
132
+ { 0 , 0 , 1 , "packed-refs" },
133
+ { 0 , 0 , 1 , "shallow" },
134
134
{ 0 , 0 , 0 , NULL }
135
135
};
136
136
@@ -236,30 +236,41 @@ static void *add_to_trie(struct trie *root, const char *key, void *value)
236
236
return old ;
237
237
}
238
238
239
- typedef int (* match_fn )(const char * unmatched , void * data , void * baton );
239
+ typedef int (* match_fn )(const char * unmatched , void * value , void * baton );
240
240
241
241
/*
242
242
* Search a trie for some key. Find the longest /-or-\0-terminated
243
- * prefix of the key for which the trie contains a value. Call fn
244
- * with the unmatched portion of the key and the found value, and
245
- * return its return value. If there is no such prefix, return -1.
243
+ * prefix of the key for which the trie contains a value. If there is
244
+ * no such prefix, return -1. Otherwise call fn with the unmatched
245
+ * portion of the key and the found value. If fn returns 0 or
246
+ * positive, then return its return value. If fn returns negative,
247
+ * then call fn with the next-longest /-terminated prefix of the key
248
+ * (i.e. a parent directory) for which the trie contains a value, and
249
+ * handle its return value the same way. If there is no shorter
250
+ * /-terminated prefix with a value left, then return the negative
251
+ * return value of the most recent fn invocation.
246
252
*
247
253
* The key is partially normalized: consecutive slashes are skipped.
248
254
*
249
- * For example, consider the trie containing only [refs,
250
- * refs/worktree] (both with values).
251
- *
252
- * | key | unmatched | val from node | return value |
253
- * |-----------------|------------|---------------|--------------|
254
- * | a | not called | n/a | -1 |
255
- * | refs | \0 | refs | as per fn |
256
- * | refs/ | / | refs | as per fn |
257
- * | refs/w | /w | refs | as per fn |
258
- * | refs/worktree | \0 | refs/worktree | as per fn |
259
- * | refs/worktree/ | / | refs/worktree | as per fn |
260
- * | refs/worktree/a | /a | refs/worktree | as per fn |
261
- * |-----------------|------------|---------------|--------------|
255
+ * For example, consider the trie containing only [logs,
256
+ * logs/refs/bisect], both with values, but not logs/refs.
262
257
*
258
+ * | key | unmatched | prefix to node | return value |
259
+ * |--------------------|----------------|------------------|--------------|
260
+ * | a | not called | n/a | -1 |
261
+ * | logstore | not called | n/a | -1 |
262
+ * | logs | \0 | logs | as per fn |
263
+ * | logs/ | / | logs | as per fn |
264
+ * | logs/refs | /refs | logs | as per fn |
265
+ * | logs/refs/ | /refs/ | logs | as per fn |
266
+ * | logs/refs/b | /refs/b | logs | as per fn |
267
+ * | logs/refs/bisected | /refs/bisected | logs | as per fn |
268
+ * | logs/refs/bisect | \0 | logs/refs/bisect | as per fn |
269
+ * | logs/refs/bisect/ | / | logs/refs/bisect | as per fn |
270
+ * | logs/refs/bisect/a | /a | logs/refs/bisect | as per fn |
271
+ * | (If fn in the previous line returns -1, then fn is called once more:) |
272
+ * | logs/refs/bisect/a | /refs/bisect/a | logs | as per fn |
273
+ * |--------------------|----------------|------------------|--------------|
263
274
*/
264
275
static int trie_find (struct trie * root , const char * key , match_fn fn ,
265
276
void * baton )
@@ -288,9 +299,13 @@ static int trie_find(struct trie *root, const char *key, match_fn fn,
288
299
289
300
/* Matched the entire compressed section */
290
301
key += i ;
291
- if (!* key )
302
+ if (!* key ) {
292
303
/* End of key */
293
- return fn (key , root -> value , baton );
304
+ if (root -> value )
305
+ return fn (key , root -> value , baton );
306
+ else
307
+ return -1 ;
308
+ }
294
309
295
310
/* Partial path normalization: skip consecutive slashes */
296
311
while (key [0 ] == '/' && key [1 ] == '/' )
@@ -320,8 +335,8 @@ static void init_common_trie(void)
320
335
if (common_trie_done_setup )
321
336
return ;
322
337
323
- for (p = common_list ; p -> dirname ; p ++ )
324
- add_to_trie (& common_trie , p -> dirname , p );
338
+ for (p = common_list ; p -> path ; p ++ )
339
+ add_to_trie (& common_trie , p -> path , p );
325
340
326
341
common_trie_done_setup = 1 ;
327
342
}
@@ -334,14 +349,11 @@ static int check_common(const char *unmatched, void *value, void *baton)
334
349
{
335
350
struct common_dir * dir = value ;
336
351
337
- if (!dir )
338
- return 0 ;
339
-
340
352
if (dir -> is_dir && (unmatched [0 ] == 0 || unmatched [0 ] == '/' ))
341
- return ! dir -> exclude ;
353
+ return dir -> is_common ;
342
354
343
355
if (!dir -> is_dir && unmatched [0 ] == 0 )
344
- return ! dir -> exclude ;
356
+ return dir -> is_common ;
345
357
346
358
return 0 ;
347
359
}
@@ -365,8 +377,8 @@ void report_linked_checkout_garbage(void)
365
377
return ;
366
378
strbuf_addf (& sb , "%s/" , get_git_dir ());
367
379
len = sb .len ;
368
- for (p = common_list ; p -> dirname ; p ++ ) {
369
- const char * path = p -> dirname ;
380
+ for (p = common_list ; p -> path ; p ++ ) {
381
+ const char * path = p -> path ;
370
382
if (p -> ignore_garbage )
371
383
continue ;
372
384
strbuf_setlen (& sb , len );
0 commit comments