Skip to content

Commit db806d7

Browse files
committed
Merge branch 'sg/dir-trie-fixes'
Code clean-up and a bugfix in the logic used to tell worktree local and repository global refs apart. * sg/dir-trie-fixes: path.c: don't call the match function without value in trie_find() path.c: clarify two field names in 'struct common_dir' path.c: mark 'logs/HEAD' in 'common_list' as file path.c: clarify trie_find()'s in-code comment Documentation: mention more worktree-specific exceptions
2 parents f1e2666 + f45f88b commit db806d7

File tree

3 files changed

+74
-60
lines changed

3 files changed

+74
-60
lines changed

Documentation/gitrepository-layout.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ refs::
9696
directory. The 'git prune' command knows to preserve
9797
objects reachable from refs found in this directory and
9898
its subdirectories.
99-
This directory is ignored (except refs/bisect and
100-
refs/worktree) if $GIT_COMMON_DIR is set and
101-
"$GIT_COMMON_DIR/refs" will be used instead.
99+
This directory is ignored (except refs/bisect,
100+
refs/rewritten and refs/worktree) if $GIT_COMMON_DIR is
101+
set and "$GIT_COMMON_DIR/refs" will be used instead.
102102

103103
refs/heads/`name`::
104104
records tip-of-the-tree commit objects of branch `name`
@@ -240,8 +240,8 @@ remotes::
240240
logs::
241241
Records of changes made to refs are stored in this directory.
242242
See linkgit:git-update-ref[1] for more information. This
243-
directory is ignored if $GIT_COMMON_DIR is set and
244-
"$GIT_COMMON_DIR/logs" will be used instead.
243+
directory is ignored (except logs/HEAD) if $GIT_COMMON_DIR is
244+
set and "$GIT_COMMON_DIR/logs" will be used instead.
245245

246246
logs/refs/heads/`name`::
247247
Records all changes made to the branch tip named `name`.

path.c

Lines changed: 67 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -101,36 +101,36 @@ struct common_dir {
101101
/* Not considered garbage for report_linked_checkout_garbage */
102102
unsigned ignore_garbage:1;
103103
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;
107107
};
108108

109109
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" },
134134
{ 0, 0, 0, NULL }
135135
};
136136

@@ -236,30 +236,41 @@ static void *add_to_trie(struct trie *root, const char *key, void *value)
236236
return old;
237237
}
238238

239-
typedef int (*match_fn)(const char *unmatched, void *data, void *baton);
239+
typedef int (*match_fn)(const char *unmatched, void *value, void *baton);
240240

241241
/*
242242
* 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.
246252
*
247253
* The key is partially normalized: consecutive slashes are skipped.
248254
*
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.
262257
*
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+
* |--------------------|----------------|------------------|--------------|
263274
*/
264275
static int trie_find(struct trie *root, const char *key, match_fn fn,
265276
void *baton)
@@ -288,9 +299,13 @@ static int trie_find(struct trie *root, const char *key, match_fn fn,
288299

289300
/* Matched the entire compressed section */
290301
key += i;
291-
if (!*key)
302+
if (!*key) {
292303
/* 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+
}
294309

295310
/* Partial path normalization: skip consecutive slashes */
296311
while (key[0] == '/' && key[1] == '/')
@@ -320,8 +335,8 @@ static void init_common_trie(void)
320335
if (common_trie_done_setup)
321336
return;
322337

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);
325340

326341
common_trie_done_setup = 1;
327342
}
@@ -334,14 +349,11 @@ static int check_common(const char *unmatched, void *value, void *baton)
334349
{
335350
struct common_dir *dir = value;
336351

337-
if (!dir)
338-
return 0;
339-
340352
if (dir->is_dir && (unmatched[0] == 0 || unmatched[0] == '/'))
341-
return !dir->exclude;
353+
return dir->is_common;
342354

343355
if (!dir->is_dir && unmatched[0] == 0)
344-
return !dir->exclude;
356+
return dir->is_common;
345357

346358
return 0;
347359
}
@@ -365,8 +377,8 @@ void report_linked_checkout_garbage(void)
365377
return;
366378
strbuf_addf(&sb, "%s/", get_git_dir());
367379
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;
370382
if (p->ignore_garbage)
371383
continue;
372384
strbuf_setlen(&sb, len);

t/t0060-path-utils.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ test_git_path GIT_COMMON_DIR=bar index .git/index
288288
test_git_path GIT_COMMON_DIR=bar HEAD .git/HEAD
289289
test_git_path GIT_COMMON_DIR=bar logs/HEAD .git/logs/HEAD
290290
test_git_path GIT_COMMON_DIR=bar logs/refs/bisect/foo .git/logs/refs/bisect/foo
291+
test_git_path GIT_COMMON_DIR=bar logs/refs bar/logs/refs
292+
test_git_path GIT_COMMON_DIR=bar logs/refs/ bar/logs/refs/
291293
test_git_path GIT_COMMON_DIR=bar logs/refs/bisec/foo bar/logs/refs/bisec/foo
292294
test_git_path GIT_COMMON_DIR=bar logs/refs/bisec bar/logs/refs/bisec
293295
test_git_path GIT_COMMON_DIR=bar logs/refs/bisectfoo bar/logs/refs/bisectfoo

0 commit comments

Comments
 (0)