revision.c: --reflog add HEAD reflog from all worktrees

Note that add_other_reflogs_to_pending() is a bit inefficient, since
it scans reflog for all refs of each worktree, including shared refs,
so the shared ref's reflog is scanned over and over again.

We could update refs API to pass "per-worktree only" flag to avoid
that. But long term we should be able to obtain a "per-worktree only"
ref store and would need to revert the changes in reflog iteration
API. So let's just wait until then.

add_reflogs_to_pending() is called by reachable.c so by default "git
prune" will examine reflog from all worktrees.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy 2017-08-23 19:37:01 +07:00 коммит произвёл Junio C Hamano
Родитель 944b4e3013
Коммит acd9544a8f
2 изменённых файлов: 43 добавлений и 1 удалений

Просмотреть файл

@ -1132,6 +1132,7 @@ struct all_refs_cb {
int warned_bad_reflog;
struct rev_info *all_revs;
const char *name_for_errormsg;
struct ref_store *refs;
};
int ref_excluded(struct string_list *ref_excludes, const char *path)
@ -1168,6 +1169,7 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
cb->all_revs = revs;
cb->all_flags = flags;
revs->rev_input_given = 1;
cb->refs = NULL;
}
void clear_ref_exclusion(struct string_list **ref_excludes_p)
@ -1236,17 +1238,41 @@ static int handle_one_reflog(const char *path, const struct object_id *oid,
struct all_refs_cb *cb = cb_data;
cb->warned_bad_reflog = 0;
cb->name_for_errormsg = path;
for_each_reflog_ent(path, handle_one_reflog_ent, cb_data);
refs_for_each_reflog_ent(cb->refs, path,
handle_one_reflog_ent, cb_data);
return 0;
}
static void add_other_reflogs_to_pending(struct all_refs_cb *cb)
{
struct worktree **worktrees, **p;
worktrees = get_worktrees(0);
for (p = worktrees; *p; p++) {
struct worktree *wt = *p;
if (wt->is_current)
continue;
cb->refs = get_worktree_ref_store(wt);
refs_for_each_reflog(cb->refs,
handle_one_reflog,
cb);
}
free_worktrees(worktrees);
}
void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
{
struct all_refs_cb cb;
cb.all_revs = revs;
cb.all_flags = flags;
cb.refs = get_main_ref_store();
for_each_reflog(handle_one_reflog, &cb);
if (!revs->single_worktree)
add_other_reflogs_to_pending(&cb);
}
static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,

Просмотреть файл

@ -304,4 +304,20 @@ test_expect_success 'prune: handle HEAD in multiple worktrees' '
test_cmp third-worktree/blob actual
'
test_expect_success 'prune: handle HEAD reflog in multiple worktrees' '
git config core.logAllRefUpdates true &&
echo "lost blob for third-worktree" >expected &&
(
cd third-worktree &&
cat ../expected >blob &&
git add blob &&
git commit -m "second commit in third" &&
git reset --hard HEAD^
) &&
git prune --expire=now &&
SHA1=`git hash-object expected` &&
git -C third-worktree show "$SHA1" >actual &&
test_cmp expected actual
'
test_done