Skip to content

Commit 944b4e3

Browse files
pcloudsgitster
authored andcommitted
files-backend: make reflog iterator go through per-worktree reflog
refs/bisect is unfortunately per-worktree, so we need to look in per-worktree logs/refs/bisect in addition to per-repo logs/refs. The current iterator only goes through per-repo logs/refs. Use merge iterator to walk two ref stores at the same time and pick per-worktree refs from the right iterator. PS. Note the unsorted order of for_each_reflog in the test. This is supposed to be OK, for now. If we enforce order on for_each_reflog() then some more work will be required. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent d0c39a4 commit 944b4e3

2 files changed

Lines changed: 75 additions & 14 deletions

File tree

refs/files-backend.c

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,6 @@ static void files_reflog_path(struct files_ref_store *refs,
106106
struct strbuf *sb,
107107
const char *refname)
108108
{
109-
if (!refname) {
110-
/*
111-
* FIXME: of course this is wrong in multi worktree
112-
* setting. To be fixed real soon.
113-
*/
114-
strbuf_addf(sb, "%s/logs", refs->gitcommondir);
115-
return;
116-
}
117-
118109
switch (ref_type(refname)) {
119110
case REF_TYPE_PER_WORKTREE:
120111
case REF_TYPE_PSEUDOREF:
@@ -2055,23 +2046,63 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {
20552046
files_reflog_iterator_abort
20562047
};
20572048

2058-
static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
2049+
static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store,
2050+
const char *gitdir)
20592051
{
2060-
struct files_ref_store *refs =
2061-
files_downcast(ref_store, REF_STORE_READ,
2062-
"reflog_iterator_begin");
20632052
struct files_reflog_iterator *iter = xcalloc(1, sizeof(*iter));
20642053
struct ref_iterator *ref_iterator = &iter->base;
20652054
struct strbuf sb = STRBUF_INIT;
20662055

20672056
base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable);
2068-
files_reflog_path(refs, &sb, NULL);
2057+
strbuf_addf(&sb, "%s/logs", gitdir);
20692058
iter->dir_iterator = dir_iterator_begin(sb.buf);
20702059
iter->ref_store = ref_store;
20712060
strbuf_release(&sb);
2061+
20722062
return ref_iterator;
20732063
}
20742064

2065+
static enum iterator_selection reflog_iterator_select(
2066+
struct ref_iterator *iter_worktree,
2067+
struct ref_iterator *iter_common,
2068+
void *cb_data)
2069+
{
2070+
if (iter_worktree) {
2071+
/*
2072+
* We're a bit loose here. We probably should ignore
2073+
* common refs if they are accidentally added as
2074+
* per-worktree refs.
2075+
*/
2076+
return ITER_SELECT_0;
2077+
} else if (iter_common) {
2078+
if (ref_type(iter_common->refname) == REF_TYPE_NORMAL)
2079+
return ITER_SELECT_1;
2080+
2081+
/*
2082+
* The main ref store may contain main worktree's
2083+
* per-worktree refs, which should be ignored
2084+
*/
2085+
return ITER_SKIP_1;
2086+
} else
2087+
return ITER_DONE;
2088+
}
2089+
2090+
static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
2091+
{
2092+
struct files_ref_store *refs =
2093+
files_downcast(ref_store, REF_STORE_READ,
2094+
"reflog_iterator_begin");
2095+
2096+
if (!strcmp(refs->gitdir, refs->gitcommondir)) {
2097+
return reflog_iterator_begin(ref_store, refs->gitcommondir);
2098+
} else {
2099+
return merge_ref_iterator_begin(
2100+
reflog_iterator_begin(ref_store, refs->gitdir),
2101+
reflog_iterator_begin(ref_store, refs->gitcommondir),
2102+
reflog_iterator_select, refs);
2103+
}
2104+
}
2105+
20752106
/*
20762107
* If update is a direct update of head_ref (the reference pointed to
20772108
* by HEAD), then add an extra REF_LOG_ONLY update for HEAD.

t/t1407-worktree-ref-store.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,34 @@ test_expect_success 'create_symref(FOO, refs/heads/master)' '
4949
test_cmp expected actual
5050
'
5151

52+
test_expect_success 'for_each_reflog()' '
53+
echo $_z40 > .git/logs/PSEUDO-MAIN &&
54+
mkdir -p .git/logs/refs/bisect &&
55+
echo $_z40 > .git/logs/refs/bisect/random &&
56+
57+
echo $_z40 > .git/worktrees/wt/logs/PSEUDO-WT &&
58+
mkdir -p .git/worktrees/wt/logs/refs/bisect &&
59+
echo $_z40 > .git/worktrees/wt/logs/refs/bisect/wt-random &&
60+
61+
$RWT for-each-reflog | cut -c 42- | sort >actual &&
62+
cat >expected <<-\EOF &&
63+
HEAD 0x1
64+
PSEUDO-WT 0x0
65+
refs/bisect/wt-random 0x0
66+
refs/heads/master 0x0
67+
refs/heads/wt-master 0x0
68+
EOF
69+
test_cmp expected actual &&
70+
71+
$RMAIN for-each-reflog | cut -c 42- | sort >actual &&
72+
cat >expected <<-\EOF &&
73+
HEAD 0x1
74+
PSEUDO-MAIN 0x0
75+
refs/bisect/random 0x0
76+
refs/heads/master 0x0
77+
refs/heads/wt-master 0x0
78+
EOF
79+
test_cmp expected actual
80+
'
81+
5282
test_done

0 commit comments

Comments
 (0)