Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ade14bf
rebase: write script before initializing state
Osse Jun 9, 2025
db0583b
Merge branch 'ps/object-store' into ps/object-store-midx
gitster Jul 9, 2025
6bde5d4
refs: expose `ref_iterator` via 'refs.h'
KarthikNayak Jul 15, 2025
883a7ea
ref-cache: remove unused function 'find_ref_entry()'
KarthikNayak Jul 15, 2025
2b4648b
refs: selectively set prefix in the seek functions
KarthikNayak Jul 15, 2025
526530a
ref-filter: remove unnecessary else clause
KarthikNayak Jul 15, 2025
dabecb9
for-each-ref: introduce a '--start-after' option
KarthikNayak Jul 15, 2025
c29998d
Merge branch 'tb/midx-avoid-cruft-packs' into ps/object-store-midx
gitster Jul 15, 2025
4d8be89
midx: start tracking per object database source
pks-t Jul 15, 2025
ec4380f
packfile: refactor `prepare_packed_git_one()` to work on sources
pks-t Jul 15, 2025
6567432
midx: stop using linked list when closing MIDX
pks-t Jul 15, 2025
736bb72
packfile: refactor `get_multi_pack_index()` to work on sources
pks-t Jul 15, 2025
7fc1998
packfile: stop using linked MIDX list in `find_pack_entry()`
pks-t Jul 15, 2025
c620586
packfile: stop using linked MIDX list in `get_all_packs()`
pks-t Jul 15, 2025
ec865d9
midx: remove now-unused linked list of multi-pack indices
pks-t Jul 15, 2025
8cc1925
t/helper/test-truncate: close file descriptor after truncation
lhywk Jul 22, 2025
bc235a6
test-delta: handle errors with die()
peff Jul 24, 2025
760dd80
test-delta: use strbufs to hold input files
peff Jul 24, 2025
0f1b338
test-delta: close output descriptor after use
peff Jul 24, 2025
9201261
ref-cache: set prefix_state when seeking
KarthikNayak Jul 24, 2025
8d9f536
Merge branch 'kn/for-each-ref-skip'
gitster Aug 4, 2025
733b640
Merge branch 'ps/object-store-midx'
gitster Aug 4, 2025
f61d8ce
Merge branch 'ow/rebase-verify-insn-fmt-before-initializing-state'
gitster Aug 4, 2025
750a95b
Merge branch 'hl/test-helper-fd-close'
gitster Aug 4, 2025
e075325
The seventeenth batch, just before -rc0
gitster Aug 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Documentation/RelNotes/2.51.0.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ UI, Workflows & Features
* "git pull" learned to pay attention to pull.autostash configuration
variable, which overrides rebase/merge.autostash.

* "git for-each-ref" learns "--start-after" option to help
applications that want to page its output.


Performance, Internal Implementation, Development Support etc.
--------------------------------------------------------------
Expand Down Expand Up @@ -125,6 +128,11 @@ Performance, Internal Implementation, Development Support etc.
* The reftable unit tests are now ported to the "clar" unit testing
framework.

* Redefine where the multi-pack-index sits in the object subsystem,
which recently was restructured to allow multiple backends that
support a single object source that belongs to one repository. A
midx does span mulitple "object sources".


Fixes since v2.50
-----------------
Expand Down Expand Up @@ -252,6 +260,15 @@ including security updates, are included in this release.
core.commentstring is set to 'auto'.
(merge 92b7c7c9f5 ac/auto-comment-char-fix later to maint).

* "git rebase -i" with bogus rebase.instructionFormat configuration
failed to produce the todo file after recording the state files,
leading to confused "git status"; this has been corrected.
(merge ade14bffd7 ow/rebase-verify-insn-fmt-before-initializing-state later to maint).

* A few file descriptors left unclosed upon program completion in a
few test helper programs are now closed.
(merge 0f1b33815b hl/test-helper-fd-close later to maint).

* Other code cleanup, docfix, build fix, etc.
(merge b257adb571 lo/my-first-ow-doc-update later to maint).
(merge 8b34b6a220 ly/sequencer-update-squash-is-fixup-only later to maint).
Expand Down
10 changes: 9 additions & 1 deletion Documentation/git-for-each-ref.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ SYNOPSIS
[--points-at=<object>]
[--merged[=<object>]] [--no-merged[=<object>]]
[--contains[=<object>]] [--no-contains[=<object>]]
[--exclude=<pattern> ...]
[--exclude=<pattern> ...] [--start-after=<marker>]

DESCRIPTION
-----------
Expand Down Expand Up @@ -108,6 +108,14 @@ TAB %(refname)`.
--include-root-refs::
List root refs (HEAD and pseudorefs) apart from regular refs.

--start-after=<marker>::
Allows paginating the output by skipping references up to and including the
specified marker. When paging, it should be noted that references may be
deleted, modified or added between invocations. Output will only yield those
references which follow the marker lexicographically. Output begins from the
first reference that would come after the marker alphabetically. Cannot be
used with general pattern matching or custom sort options.

FIELD NAMES
-----------

Expand Down
8 changes: 8 additions & 0 deletions builtin/for-each-ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ static char const * const for_each_ref_usage[] = {
N_("git for-each-ref [--points-at <object>]"),
N_("git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"),
N_("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"),
N_("git for-each-ref [--start-after <marker>]"),
NULL
};

Expand Down Expand Up @@ -44,6 +45,7 @@ int cmd_for_each_ref(int argc,
OPT_GROUP(""),
OPT_INTEGER( 0 , "count", &format.array_opts.max_count, N_("show only <n> matched refs")),
OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")),
OPT_STRING( 0 , "start-after", &filter.start_after, N_("start-start"), N_("start iteration after the provided marker")),
OPT__COLOR(&format.use_color, N_("respect format colors")),
OPT_REF_FILTER_EXCLUDE(&filter),
OPT_REF_SORT(&sorting_options),
Expand Down Expand Up @@ -79,6 +81,9 @@ int cmd_for_each_ref(int argc,
if (verify_ref_format(&format))
usage_with_options(for_each_ref_usage, opts);

if (filter.start_after && sorting_options.nr > 1)
die(_("cannot use --start-after with custom sort options"));

sorting = ref_sorting_options(&sorting_options);
ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);
filter.ignore_case = icase;
Expand All @@ -100,6 +105,9 @@ int cmd_for_each_ref(int argc,
filter.name_patterns = argv;
}

if (filter.start_after && filter.name_patterns && filter.name_patterns[0])
die(_("cannot use --start-after with patterns"));

if (include_root_refs)
flags |= FILTER_REFS_ROOT_REFS | FILTER_REFS_DETACHED_HEAD;

Expand Down
10 changes: 7 additions & 3 deletions builtin/pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -1706,8 +1706,8 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
uint32_t found_mtime)
{
int want;
struct odb_source *source;
struct list_head *pos;
struct multi_pack_index *m;

if (!exclude && local && has_loose_object_nonlocal(oid))
return 0;
Expand All @@ -1727,9 +1727,13 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
*found_offset = 0;
}

for (m = get_multi_pack_index(the_repository); m; m = m->next) {
odb_prepare_alternates(the_repository->objects);

for (source = the_repository->objects->sources; source; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
struct pack_entry e;
if (fill_midx_entry(the_repository, oid, &e, m)) {

if (m && fill_midx_entry(the_repository, oid, &e, m)) {
want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime);
if (want != -1)
return want;
Expand Down
42 changes: 21 additions & 21 deletions builtin/rebase.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,6 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
&revisions, &shortrevisions))
goto cleanup;

if (init_basic_state(&replay,
opts->head_name ? opts->head_name : "detached HEAD",
opts->onto, &opts->orig_head->object.oid))
goto cleanup;

if (!opts->upstream && opts->squash_onto)
write_file(path_squash_onto(), "%s\n",
oid_to_hex(opts->squash_onto));

strvec_pushl(&make_script_args, "", revisions, NULL);
if (opts->restrict_revision)
strvec_pushf(&make_script_args, "^%s",
Expand All @@ -310,21 +301,30 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
ret = sequencer_make_script(the_repository, &todo_list.buf,
make_script_args.nr, make_script_args.v,
flags);

if (ret)
if (ret) {
error(_("could not generate todo list"));
else {
discard_index(the_repository->index);
if (todo_list_parse_insn_buffer(the_repository, &replay,
todo_list.buf.buf, &todo_list))
BUG("unusable todo list");

ret = complete_action(the_repository, &replay, flags,
shortrevisions, opts->onto_name, opts->onto,
&opts->orig_head->object.oid, &opts->exec,
opts->autosquash, opts->update_refs, &todo_list);
goto cleanup;
}

if (init_basic_state(&replay,
opts->head_name ? opts->head_name : "detached HEAD",
opts->onto, &opts->orig_head->object.oid))
goto cleanup;

if (!opts->upstream && opts->squash_onto)
write_file(path_squash_onto(), "%s\n",
oid_to_hex(opts->squash_onto));

discard_index(the_repository->index);
if (todo_list_parse_insn_buffer(the_repository, &replay,
todo_list.buf.buf, &todo_list))
BUG("unusable todo list");

ret = complete_action(the_repository, &replay, flags,
shortrevisions, opts->onto_name, opts->onto,
&opts->orig_head->object.oid, &opts->exec,
opts->autosquash, opts->update_refs, &todo_list);

cleanup:
replay_opts_release(&replay);
free(revisions);
Expand Down
10 changes: 5 additions & 5 deletions builtin/repack.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,9 @@ static void mark_packs_for_deletion(struct existing_packs *existing,
static void remove_redundant_pack(const char *dir_name, const char *base_name)
{
struct strbuf buf = STRBUF_INIT;
struct multi_pack_index *m = get_local_multi_pack_index(the_repository);
struct multi_pack_index *m = get_multi_pack_index(the_repository->objects->sources);
strbuf_addf(&buf, "%s.pack", base_name);
if (m && midx_contains_pack(m, buf.buf))
if (m && m->local && midx_contains_pack(m, buf.buf))
clear_midx_file(the_repository);
strbuf_insertf(&buf, 0, "%s/", dir_name);
unlink_pack_path(buf.buf, 1);
Expand Down Expand Up @@ -1531,7 +1531,7 @@ int cmd_repack(int argc,
* midx_has_unknown_packs() will make the decision for
* us.
*/
if (!get_local_multi_pack_index(the_repository))
if (!get_multi_pack_index(the_repository->objects->sources))
midx_must_contain_cruft = 1;
}

Expand Down Expand Up @@ -1614,9 +1614,9 @@ int cmd_repack(int argc,

string_list_sort(&names);

if (get_local_multi_pack_index(the_repository)) {
if (get_multi_pack_index(the_repository->objects->sources)) {
struct multi_pack_index *m =
get_local_multi_pack_index(the_repository);
get_multi_pack_index(the_repository->objects->sources);

ALLOC_ARRAY(midx_pack_names,
m->num_packs + m->num_packs_in_base);
Expand Down
22 changes: 2 additions & 20 deletions midx-write.c
Original file line number Diff line number Diff line change
Expand Up @@ -916,26 +916,8 @@ static int write_midx_bitmap(struct write_midx_context *ctx,
static struct multi_pack_index *lookup_multi_pack_index(struct repository *r,
const char *object_dir)
{
struct multi_pack_index *result = NULL;
struct multi_pack_index *cur;
char *obj_dir_real = real_pathdup(object_dir, 1);
struct strbuf cur_path_real = STRBUF_INIT;

/* Ensure the given object_dir is local, or a known alternate. */
odb_find_source(r->objects, obj_dir_real);

for (cur = get_multi_pack_index(r); cur; cur = cur->next) {
strbuf_realpath(&cur_path_real, cur->object_dir, 1);
if (!strcmp(obj_dir_real, cur_path_real.buf)) {
result = cur;
goto cleanup;
}
}

cleanup:
free(obj_dir_real);
strbuf_release(&cur_path_real);
return result;
struct odb_source *source = odb_find_source(r->objects, object_dir);
return get_multi_pack_index(source);
}

static int fill_packs_from_midx(struct write_midx_context *ctx,
Expand Down
36 changes: 14 additions & 22 deletions midx.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@ void close_midx(struct multi_pack_index *m)
if (!m)
return;

close_midx(m->next);
close_midx(m->base_midx);

munmap((unsigned char *)m->data, m->data_len);
Expand Down Expand Up @@ -724,32 +723,20 @@ int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id)
return 0;
}

int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local)
int prepare_multi_pack_index_one(struct odb_source *source, int local)
{
struct multi_pack_index *m;
struct multi_pack_index *m_search;
struct repository *r = source->odb->repo;

prepare_repo_settings(r);
if (!r->settings.core_multi_pack_index)
return 0;

for (m_search = r->objects->multi_pack_index; m_search; m_search = m_search->next)
if (!strcmp(object_dir, m_search->object_dir))
return 1;

m = load_multi_pack_index(r, object_dir, local);

if (m) {
struct multi_pack_index *mp = r->objects->multi_pack_index;
if (mp) {
m->next = mp->next;
mp->next = m;
} else
r->objects->multi_pack_index = m;
if (source->midx)
return 1;
}

return 0;
source->midx = load_multi_pack_index(r, source->path, local);

return !!source->midx;
}

int midx_checksum_valid(struct multi_pack_index *m)
Expand Down Expand Up @@ -834,9 +821,14 @@ void clear_midx_file(struct repository *r)

get_midx_filename(r->hash_algo, &midx, r->objects->sources->path);

if (r->objects && r->objects->multi_pack_index) {
close_midx(r->objects->multi_pack_index);
r->objects->multi_pack_index = NULL;
if (r->objects) {
struct odb_source *source;

for (source = r->objects->sources; source; source = source->next) {
if (source->midx)
close_midx(source->midx);
source->midx = NULL;
}
}

if (remove_path(midx.buf))
Expand Down
5 changes: 2 additions & 3 deletions midx.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ struct pack_entry;
struct repository;
struct bitmapped_pack;
struct git_hash_algo;
struct odb_source;

#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
#define MIDX_VERSION 1
Expand All @@ -34,8 +35,6 @@ struct git_hash_algo;
"GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL"

struct multi_pack_index {
struct multi_pack_index *next;

const unsigned char *data;
size_t data_len;

Expand Down Expand Up @@ -123,7 +122,7 @@ int fill_midx_entry(struct repository *r, const struct object_id *oid, struct pa
int midx_contains_pack(struct multi_pack_index *m,
const char *idx_or_pack_name);
int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id);
int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local);
int prepare_multi_pack_index_one(struct odb_source *source, int local);

/*
* Variant of write_midx_file which writes a MIDX containing only the packs
Expand Down
22 changes: 15 additions & 7 deletions object-name.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,16 +199,20 @@ static void unique_in_pack(struct packed_git *p,

static void find_short_packed_object(struct disambiguate_state *ds)
{
struct multi_pack_index *m;
struct odb_source *source;
struct packed_git *p;

/* Skip, unless oids from the storage hash algorithm are wanted */
if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo))
return;

for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous;
m = m->next)
unique_in_midx(m, ds);
odb_prepare_alternates(ds->repo->objects);
for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
if (m)
unique_in_midx(m, ds);
}

for (p = get_packed_git(ds->repo); p && !ds->ambiguous;
p = p->next)
unique_in_pack(p, ds);
Expand Down Expand Up @@ -793,11 +797,15 @@ static void find_abbrev_len_for_pack(struct packed_git *p,

static void find_abbrev_len_packed(struct min_abbrev_data *mad)
{
struct multi_pack_index *m;
struct packed_git *p;

for (m = get_multi_pack_index(mad->repo); m; m = m->next)
find_abbrev_len_for_midx(m, mad);
odb_prepare_alternates(mad->repo->objects);
for (struct odb_source *source = mad->repo->objects->sources; source; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
if (m)
find_abbrev_len_for_midx(m, mad);
}

for (p = get_packed_git(mad->repo); p; p = p->next)
find_abbrev_len_for_pack(p, mad);
}
Expand Down
Loading