diff --git a/refs/files-backend.c b/refs/files-backend.c index 2ffc63185f..551cafdf76 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -2210,32 +2210,6 @@ static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store, return ref_iterator; } -static enum iterator_selection reflog_iterator_select( - struct ref_iterator *iter_worktree, - struct ref_iterator *iter_common, - void *cb_data UNUSED) -{ - if (iter_worktree) { - /* - * We're a bit loose here. We probably should ignore - * common refs if they are accidentally added as - * per-worktree refs. - */ - return ITER_SELECT_0; - } else if (iter_common) { - if (parse_worktree_ref(iter_common->refname, NULL, NULL, - NULL) == REF_WORKTREE_SHARED) - return ITER_SELECT_1; - - /* - * The main ref store may contain main worktree's - * per-worktree refs, which should be ignored - */ - return ITER_SKIP_1; - } else - return ITER_DONE; -} - static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store) { struct files_ref_store *refs = @@ -2246,9 +2220,9 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st return reflog_iterator_begin(ref_store, refs->gitcommondir); } else { return merge_ref_iterator_begin( - 0, reflog_iterator_begin(ref_store, refs->base.gitdir), + 1, reflog_iterator_begin(ref_store, refs->base.gitdir), reflog_iterator_begin(ref_store, refs->gitcommondir), - reflog_iterator_select, refs); + ref_iterator_select, refs); } } diff --git a/refs/iterator.c b/refs/iterator.c index 6b680f610e..b7ab5dc92f 100644 --- a/refs/iterator.c +++ b/refs/iterator.c @@ -98,6 +98,49 @@ struct merge_ref_iterator { struct ref_iterator **current; }; +enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree, + struct ref_iterator *iter_common, + void *cb_data UNUSED) +{ + if (iter_worktree && !iter_common) { + /* + * Return the worktree ref if there are no more common refs. + */ + return ITER_SELECT_0; + } else if (iter_common) { + /* + * In case we have pending worktree and common refs we need to + * yield them based on their lexicographical order. Worktree + * refs that have the same name as common refs shadow the + * latter. + */ + if (iter_worktree) { + int cmp = strcmp(iter_worktree->refname, + iter_common->refname); + if (cmp < 0) + return ITER_SELECT_0; + else if (!cmp) + return ITER_SELECT_0_SKIP_1; + } + + /* + * We now know that the lexicographically-next ref is a common + * ref. When the common ref is a shared one we return it. + */ + if (parse_worktree_ref(iter_common->refname, NULL, NULL, + NULL) == REF_WORKTREE_SHARED) + return ITER_SELECT_1; + + /* + * Otherwise, if the common ref is a per-worktree ref we skip + * it because it would belong to the main worktree, not ours. + */ + return ITER_SKIP_1; + } else { + return ITER_DONE; + } +} + static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator) { struct merge_ref_iterator *iter = diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 83e0f0bba3..51f612e122 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -386,6 +386,15 @@ typedef enum iterator_selection ref_iterator_select_fn( struct ref_iterator *iter0, struct ref_iterator *iter1, void *cb_data); +/* + * An implementation of ref_iterator_select_fn that merges worktree and common + * refs. Per-worktree refs from the common iterator are ignored, worktree refs + * override common refs. Refs are selected lexicographically. + */ +enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree, + struct ref_iterator *iter_common, + void *cb_data); + /* * Iterate over the entries from iter0 and iter1, with the values * interleaved as directed by the select function. The iterator takes diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index a14f2ad7f4..68d32a9101 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -504,49 +504,6 @@ done: return iter; } -static enum iterator_selection iterator_select(struct ref_iterator *iter_worktree, - struct ref_iterator *iter_common, - void *cb_data UNUSED) -{ - if (iter_worktree && !iter_common) { - /* - * Return the worktree ref if there are no more common refs. - */ - return ITER_SELECT_0; - } else if (iter_common) { - /* - * In case we have pending worktree and common refs we need to - * yield them based on their lexicographical order. Worktree - * refs that have the same name as common refs shadow the - * latter. - */ - if (iter_worktree) { - int cmp = strcmp(iter_worktree->refname, - iter_common->refname); - if (cmp < 0) - return ITER_SELECT_0; - else if (!cmp) - return ITER_SELECT_0_SKIP_1; - } - - /* - * We now know that the lexicographically-next ref is a common - * ref. When the common ref is a shared one we return it. - */ - if (parse_worktree_ref(iter_common->refname, NULL, NULL, - NULL) == REF_WORKTREE_SHARED) - return ITER_SELECT_1; - - /* - * Otherwise, if the common ref is a per-worktree ref we skip - * it because it would belong to the main worktree, not ours. - */ - return ITER_SKIP_1; - } else { - return ITER_DONE; - } -} - static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_store, const char *prefix, const char **exclude_patterns, @@ -576,7 +533,7 @@ static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_sto */ worktree_iter = ref_iterator_for_stack(refs, refs->worktree_stack, prefix, flags); return merge_ref_iterator_begin(1, &worktree_iter->base, &main_iter->base, - iterator_select, NULL); + ref_iterator_select, NULL); } static int reftable_be_read_raw_ref(struct ref_store *ref_store, @@ -1759,7 +1716,7 @@ static struct ref_iterator *reftable_be_reflog_iterator_begin(struct ref_store * worktree_iter = reflog_iterator_for_stack(refs, refs->worktree_stack); return merge_ref_iterator_begin(1, &worktree_iter->base, &main_iter->base, - iterator_select, NULL); + ref_iterator_select, NULL); } static int yield_log_record(struct reftable_log_record *log,