Skip to content

Commit 8a044c7

Browse files
committed
Merge branch 'nd/prune-in-worktree'
"git gc" and friends when multiple worktrees are used off of a single repository did not consider the index and per-worktree refs of other worktrees as the root for reachability traversal, making objects that are in use only in other worktrees to be subject to garbage collection. * nd/prune-in-worktree: refs.c: reindent get_submodule_ref_store() refs.c: remove fallback-to-main-store code get_submodule_ref_store() rev-list: expose and document --single-worktree revision.c: --reflog add HEAD reflog from all worktrees files-backend: make reflog iterator go through per-worktree reflog revision.c: --all adds HEAD from all worktrees refs: remove dead for_each_*_submodule() refs.c: move for_each_remote_ref_submodule() to submodule.c revision.c: use refs_for_each*() instead of for_each_*_submodule() refs: add refs_head_ref() refs: move submodule slash stripping code to get_submodule_ref_store refs.c: refactor get_submodule_ref_store(), share common free block revision.c: --indexed-objects add objects from all worktrees revision.c: refactor add_index_objects_to_pending() refs.c: use is_dir_sep() in resolve_gitlink_ref() revision.h: new flag in struct rev_info wrt. worktree-related refs
2 parents dafbe19 + 873ea90 commit 8a044c7

13 files changed

Lines changed: 308 additions & 136 deletions

Documentation/rev-list-options.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ explicitly.
184184
Pretend as if all objects mentioned by reflogs are listed on the
185185
command line as `<commit>`.
186186

187+
--single-worktree::
188+
By default, all working trees will be examined by the
189+
following options when there are more than one (see
190+
linkgit:git-worktree[1]): `--all`, `--reflog` and
191+
`--indexed-objects`.
192+
This option forces them to examine the current working tree
193+
only.
194+
187195
--ignore-missing::
188196
Upon seeing an invalid object name in the input, pretend as if
189197
the bad input was not given.

Documentation/technical/api-ref-iteration.txt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,8 @@ Iteration functions
3232

3333
* `for_each_glob_ref_in()` the previous and `for_each_ref_in()` combined.
3434

35-
* `head_ref_submodule()`, `for_each_ref_submodule()`,
36-
`for_each_ref_in_submodule()`, `for_each_tag_ref_submodule()`,
37-
`for_each_branch_ref_submodule()`, `for_each_remote_ref_submodule()`
38-
do the same as the functions described above but for a specified
39-
submodule.
35+
* Use `refs_` API for accessing submodules. The submodule ref store could
36+
be obtained with `get_submodule_ref_store()`.
4037

4138
* `for_each_rawref()` can be used to learn about broken ref and symref.
4239

reachable.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "progress.h"
1111
#include "list-objects.h"
1212
#include "packfile.h"
13+
#include "worktree.h"
1314

1415
struct connectivity_progress {
1516
struct progress *progress;
@@ -177,6 +178,7 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
177178

178179
/* detached HEAD is not included in the list above */
179180
head_ref(add_one_ref, revs);
181+
other_head_refs(add_one_ref, revs);
180182

181183
/* Add all reflog info */
182184
if (mark_reflog)

refs.c

Lines changed: 31 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -336,12 +336,6 @@ int for_each_tag_ref(each_ref_fn fn, void *cb_data)
336336
return refs_for_each_tag_ref(get_main_ref_store(), fn, cb_data);
337337
}
338338

339-
int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
340-
{
341-
return refs_for_each_tag_ref(get_submodule_ref_store(submodule),
342-
fn, cb_data);
343-
}
344-
345339
int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
346340
{
347341
return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
@@ -352,12 +346,6 @@ int for_each_branch_ref(each_ref_fn fn, void *cb_data)
352346
return refs_for_each_branch_ref(get_main_ref_store(), fn, cb_data);
353347
}
354348

355-
int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
356-
{
357-
return refs_for_each_branch_ref(get_submodule_ref_store(submodule),
358-
fn, cb_data);
359-
}
360-
361349
int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
362350
{
363351
return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
@@ -368,12 +356,6 @@ int for_each_remote_ref(each_ref_fn fn, void *cb_data)
368356
return refs_for_each_remote_ref(get_main_ref_store(), fn, cb_data);
369357
}
370358

371-
int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
372-
{
373-
return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
374-
fn, cb_data);
375-
}
376-
377359
int head_ref_namespaced(each_ref_fn fn, void *cb_data)
378360
{
379361
struct strbuf buf = STRBUF_INIT;
@@ -1266,27 +1248,21 @@ int refs_rename_ref_available(struct ref_store *refs,
12661248
return ok;
12671249
}
12681250

1269-
int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
1251+
int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
12701252
{
12711253
struct object_id oid;
12721254
int flag;
12731255

1274-
if (submodule) {
1275-
if (resolve_gitlink_ref(submodule, "HEAD", oid.hash) == 0)
1276-
return fn("HEAD", &oid, 0, cb_data);
1277-
1278-
return 0;
1279-
}
1280-
1281-
if (!read_ref_full("HEAD", RESOLVE_REF_READING, oid.hash, &flag))
1256+
if (!refs_read_ref_full(refs, "HEAD", RESOLVE_REF_READING,
1257+
oid.hash, &flag))
12821258
return fn("HEAD", &oid, flag, cb_data);
12831259

12841260
return 0;
12851261
}
12861262

12871263
int head_ref(each_ref_fn fn, void *cb_data)
12881264
{
1289-
return head_ref_submodule(NULL, fn, cb_data);
1265+
return refs_head_ref(get_main_ref_store(), fn, cb_data);
12901266
}
12911267

12921268
struct ref_iterator *refs_ref_iterator_begin(
@@ -1344,11 +1320,6 @@ int for_each_ref(each_ref_fn fn, void *cb_data)
13441320
return refs_for_each_ref(get_main_ref_store(), fn, cb_data);
13451321
}
13461322

1347-
int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
1348-
{
1349-
return refs_for_each_ref(get_submodule_ref_store(submodule), fn, cb_data);
1350-
}
1351-
13521323
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
13531324
each_ref_fn fn, void *cb_data)
13541325
{
@@ -1370,23 +1341,15 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsig
13701341
prefix, fn, 0, flag, cb_data);
13711342
}
13721343

1373-
int for_each_ref_in_submodule(const char *submodule, const char *prefix,
1374-
each_ref_fn fn, void *cb_data)
1375-
{
1376-
return refs_for_each_ref_in(get_submodule_ref_store(submodule),
1377-
prefix, fn, cb_data);
1378-
}
1379-
1380-
int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
1381-
each_ref_fn fn, void *cb_data,
1382-
unsigned int broken)
1344+
int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
1345+
each_ref_fn fn, void *cb_data,
1346+
unsigned int broken)
13831347
{
13841348
unsigned int flag = 0;
13851349

13861350
if (broken)
13871351
flag = DO_FOR_EACH_INCLUDE_BROKEN;
1388-
return do_for_each_ref(get_submodule_ref_store(submodule),
1389-
prefix, fn, 0, flag, cb_data);
1352+
return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
13901353
}
13911354

13921355
int for_each_replace_ref(each_ref_fn fn, void *cb_data)
@@ -1521,25 +1484,10 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
15211484
int resolve_gitlink_ref(const char *submodule, const char *refname,
15221485
unsigned char *sha1)
15231486
{
1524-
size_t len = strlen(submodule);
15251487
struct ref_store *refs;
15261488
int flags;
15271489

1528-
while (len && submodule[len - 1] == '/')
1529-
len--;
1530-
1531-
if (!len)
1532-
return -1;
1533-
1534-
if (submodule[len]) {
1535-
/* We need to strip off one or more trailing slashes */
1536-
char *stripped = xmemdupz(submodule, len);
1537-
1538-
refs = get_submodule_ref_store(stripped);
1539-
free(stripped);
1540-
} else {
1541-
refs = get_submodule_ref_store(submodule);
1542-
}
1490+
refs = get_submodule_ref_store(submodule);
15431491

15441492
if (!refs)
15451493
return -1;
@@ -1654,39 +1602,43 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
16541602
{
16551603
struct strbuf submodule_sb = STRBUF_INIT;
16561604
struct ref_store *refs;
1657-
int ret;
1605+
char *to_free = NULL;
1606+
size_t len;
16581607

1659-
if (!submodule || !*submodule) {
1660-
/*
1661-
* FIXME: This case is ideally not allowed. But that
1662-
* can't happen until we clean up all the callers.
1663-
*/
1664-
return get_main_ref_store();
1665-
}
1608+
if (!submodule)
1609+
return NULL;
1610+
1611+
len = strlen(submodule);
1612+
while (len && is_dir_sep(submodule[len - 1]))
1613+
len--;
1614+
if (!len)
1615+
return NULL;
1616+
1617+
if (submodule[len])
1618+
/* We need to strip off one or more trailing slashes */
1619+
submodule = to_free = xmemdupz(submodule, len);
16661620

16671621
refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
16681622
if (refs)
1669-
return refs;
1623+
goto done;
16701624

16711625
strbuf_addstr(&submodule_sb, submodule);
1672-
ret = is_nonbare_repository_dir(&submodule_sb);
1673-
strbuf_release(&submodule_sb);
1674-
if (!ret)
1675-
return NULL;
1626+
if (!is_nonbare_repository_dir(&submodule_sb))
1627+
goto done;
16761628

1677-
ret = submodule_to_gitdir(&submodule_sb, submodule);
1678-
if (ret) {
1679-
strbuf_release(&submodule_sb);
1680-
return NULL;
1681-
}
1629+
if (submodule_to_gitdir(&submodule_sb, submodule))
1630+
goto done;
16821631

16831632
/* assume that add_submodule_odb() has been called */
16841633
refs = ref_store_init(submodule_sb.buf,
16851634
REF_STORE_READ | REF_STORE_ODB);
16861635
register_ref_store_map(&submodule_ref_stores, "submodule",
16871636
refs, submodule);
16881637

1638+
done:
16891639
strbuf_release(&submodule_sb);
1640+
free(to_free);
1641+
16901642
return refs;
16911643
}
16921644

refs.h

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,8 @@ typedef int each_ref_fn(const char *refname,
275275
* modifies the reference also returns a nonzero value to immediately
276276
* stop the iteration. Returned references are sorted.
277277
*/
278+
int refs_head_ref(struct ref_store *refs,
279+
each_ref_fn fn, void *cb_data);
278280
int refs_for_each_ref(struct ref_store *refs,
279281
each_ref_fn fn, void *cb_data);
280282
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
@@ -289,6 +291,9 @@ int refs_for_each_remote_ref(struct ref_store *refs,
289291
int head_ref(each_ref_fn fn, void *cb_data);
290292
int for_each_ref(each_ref_fn fn, void *cb_data);
291293
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
294+
int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
295+
each_ref_fn fn, void *cb_data,
296+
unsigned int broken);
292297
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data,
293298
unsigned int broken);
294299
int for_each_tag_ref(each_ref_fn fn, void *cb_data);
@@ -299,21 +304,6 @@ int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data);
299304
int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
300305
const char *prefix, void *cb_data);
301306

302-
int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data);
303-
int for_each_ref_submodule(const char *submodule,
304-
each_ref_fn fn, void *cb_data);
305-
int for_each_ref_in_submodule(const char *submodule, const char *prefix,
306-
each_ref_fn fn, void *cb_data);
307-
int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
308-
each_ref_fn fn, void *cb_data,
309-
unsigned int broken);
310-
int for_each_tag_ref_submodule(const char *submodule,
311-
each_ref_fn fn, void *cb_data);
312-
int for_each_branch_ref_submodule(const char *submodule,
313-
each_ref_fn fn, void *cb_data);
314-
int for_each_remote_ref_submodule(const char *submodule,
315-
each_ref_fn fn, void *cb_data);
316-
317307
int head_ref_namespaced(each_ref_fn fn, void *cb_data);
318308
int for_each_namespaced_ref(each_ref_fn fn, void *cb_data);
319309

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:
@@ -2059,23 +2050,63 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {
20592050
files_reflog_iterator_abort
20602051
};
20612052

2062-
static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
2053+
static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store,
2054+
const char *gitdir)
20632055
{
2064-
struct files_ref_store *refs =
2065-
files_downcast(ref_store, REF_STORE_READ,
2066-
"reflog_iterator_begin");
20672056
struct files_reflog_iterator *iter = xcalloc(1, sizeof(*iter));
20682057
struct ref_iterator *ref_iterator = &iter->base;
20692058
struct strbuf sb = STRBUF_INIT;
20702059

20712060
base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable);
2072-
files_reflog_path(refs, &sb, NULL);
2061+
strbuf_addf(&sb, "%s/logs", gitdir);
20732062
iter->dir_iterator = dir_iterator_begin(sb.buf);
20742063
iter->ref_store = ref_store;
20752064
strbuf_release(&sb);
2065+
20762066
return ref_iterator;
20772067
}
20782068

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

0 commit comments

Comments
 (0)