Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7cafb9a
Merge branch 'ps/object-store' into ps/object-file-wo-the-repository
gitster Jul 9, 2025
80e7f52
object-file: fix -Wsign-compare warnings
pks-t Jul 17, 2025
18323f5
object-file: stop using `the_hash_algo`
pks-t Jul 17, 2025
931e8c9
object-file: get rid of `the_repository` in `has_loose_object()`
pks-t Jul 17, 2025
f6638bf
object-file: inline `check_and_freshen()` functions
pks-t Jul 17, 2025
1031f57
object-file: get rid of `the_repository` when freshening objects
pks-t Jul 17, 2025
1efe0ae
object-file: get rid of `the_repository` in `loose_object_info()`
pks-t Jul 17, 2025
cbb388f
object-file: get rid of `the_repository` in `finalize_object_file()`
pks-t Jul 17, 2025
0f9b189
loose: write loose objects map via their source
pks-t Jul 17, 2025
ab1c6e1
odb: introduce `odb_write_object()`
pks-t Jul 17, 2025
e7e952f
object-file: get rid of `the_repository` when writing objects
pks-t Jul 17, 2025
f2c40e5
object-file: inline `for_each_loose_file_in_objdir_buf()`
pks-t Jul 17, 2025
8343929
object-file: remove declaration for `for_each_file_in_obj_subdir()`
pks-t Jul 17, 2025
d81712c
object-file: get rid of `the_repository` in loose object iterators
pks-t Jul 17, 2025
0df0053
object-file: get rid of `the_repository` in `read_loose_object()`
pks-t Jul 17, 2025
c2b5d14
object-file: get rid of `the_repository` in `force_object_loose()`
pks-t Jul 17, 2025
5f2e994
object-file: get rid of `the_repository` in index-related functions
pks-t Jul 17, 2025
1fa06ce
submodule: prevent overwriting .gitmodules on path reuse
jayatheerthkulkarni Jul 24, 2025
bb10dcf
submodule: skip redundant active entries when pattern covers path
jayatheerthkulkarni Jul 24, 2025
9305027
fixup! submodule: prevent overwriting .gitmodules on path reuse
gitster Jul 24, 2025
5ed8c5b
fixup! submodule: skip redundant active entries when pattern covers path
gitster Jul 24, 2025
161e895
git: show alias info only with lone -h
rscharfe Jul 25, 2025
4ce0caa
Merge branch 'ps/object-file-wo-the-repository'
gitster Aug 5, 2025
2823d92
Merge branch 'rs/tighten-alias-help'
gitster Aug 5, 2025
8982c5e
Merge branch 'kj/renamed-submodule'
gitster Aug 5, 2025
64cbe5e
A bit more after -rc0
gitster Aug 5, 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
13 changes: 13 additions & 0 deletions Documentation/RelNotes/2.51.0.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ UI, Workflows & Features
* "git switch" and "git restore" are declared to be no longer
experimental.

* "git -c alias.foo=bar foo -h baz" reported "'foo' is aliased to
'bar'" and then went on to run "git foo -h baz", which was
unexpected. Tighten the rule so that alias expansion is reported
only when "-h" is the sole option.


Performance, Internal Implementation, Development Support etc.
--------------------------------------------------------------
Expand Down Expand Up @@ -136,6 +141,9 @@ Performance, Internal Implementation, Development Support etc.
support a single object source that belongs to one repository. A
midx does span mulitple "object sources".

* Reduce implicit assumption and dependence on the_repository in the
object-file subsystem.


Fixes since v2.50
-----------------
Expand Down Expand Up @@ -284,6 +292,11 @@ including security updates, are included in this release.
and also they learn to honor the -U<n> command-line option.
(merge 2b3ae04011 lm/add-p-context later to maint).

* The case where a new submodule takes a path where used to be a
completely different subproject is now dealt a bit better than
before.
(merge 5ed8c5b465 kj/renamed-submodule 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
7 changes: 7 additions & 0 deletions Documentation/git-submodule.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ OPTIONS
--force::
This option is only valid for add, deinit and update commands.
When running add, allow adding an otherwise ignored submodule path.
This option is also used to bypass a check that the submodule's name
is not already in use. By default, 'git submodule add' will fail if
the proposed name (which is derived from the path) is already registered
for another submodule in the repository. Using '--force' allows the command
to proceed by automatically generating a unique name by appending a number
to the conflicting name (e.g., if a submodule named 'child' exists, it will
try 'child1', and so on).
When running deinit the submodule working trees will be removed even
if they contain local changes.
When running update (only effective with the checkout procedure),
Expand Down
11 changes: 7 additions & 4 deletions apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -3621,7 +3621,7 @@ static int try_threeway(struct apply_state *state,

/* Preimage the patch was prepared for */
if (patch->is_new)
write_object_file("", 0, OBJ_BLOB, &pre_oid);
odb_write_object(the_repository->objects, "", 0, OBJ_BLOB, &pre_oid);
else if (repo_get_oid(the_repository, patch->old_oid_prefix, &pre_oid) ||
read_blob_object(&buf, &pre_oid, patch->old_mode))
return error(_("repository lacks the necessary blob to perform 3-way merge."));
Expand All @@ -3637,7 +3637,8 @@ static int try_threeway(struct apply_state *state,
return -1;
}
/* post_oid is theirs */
write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &post_oid);
odb_write_object(the_repository->objects, tmp_image.buf.buf,
tmp_image.buf.len, OBJ_BLOB, &post_oid);
image_clear(&tmp_image);

/* our_oid is ours */
Expand All @@ -3650,7 +3651,8 @@ static int try_threeway(struct apply_state *state,
return error(_("cannot read the current contents of '%s'"),
patch->old_name);
}
write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &our_oid);
odb_write_object(the_repository->objects, tmp_image.buf.buf,
tmp_image.buf.len, OBJ_BLOB, &our_oid);
image_clear(&tmp_image);

/* in-core three-way merge between post and our using pre as base */
Expand Down Expand Up @@ -4360,7 +4362,8 @@ static int add_index_file(struct apply_state *state,
}
fill_stat_cache_info(state->repo->index, ce, &st);
}
if (write_object_file(buf, size, OBJ_BLOB, &ce->oid) < 0) {
if (odb_write_object(the_repository->objects, buf, size,
OBJ_BLOB, &ce->oid) < 0) {
discard_cache_entry(ce);
return error(_("unable to create backing store "
"for newly created file %s"), path);
Expand Down
2 changes: 1 addition & 1 deletion builtin/cat-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ static void batch_each_object(struct batch_options *opt,
};
struct bitmap_index *bitmap = prepare_bitmap_git(the_repository);

for_each_loose_object(batch_one_object_loose, &payload, 0);
for_each_loose_object(the_repository->objects, batch_one_object_loose, &payload, 0);

if (bitmap && !for_each_bitmapped_object(bitmap, &opt->objects_filter,
batch_one_object_bitmapped, &payload)) {
Expand Down
2 changes: 1 addition & 1 deletion builtin/checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ static int checkout_merged(int pos, const struct checkout *state,
* (it also writes the merge result to the object database even
* when it may contain conflicts).
*/
if (write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &oid))
if (odb_write_object(the_repository->objects, result_buf.ptr, result_buf.size, OBJ_BLOB, &oid))
die(_("Unable to add merge result for '%s'"), path);
free(result_buf.ptr);
ce = make_transient_cache_entry(mode, &oid, path, 2, ce_mem_pool);
Expand Down
2 changes: 1 addition & 1 deletion builtin/count-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ int cmd_count_objects(int argc,
report_linked_checkout_garbage(the_repository);
}

for_each_loose_file_in_objdir(repo_get_object_directory(the_repository),
for_each_loose_file_in_source(the_repository->objects->sources,
count_loose, count_cruft, NULL, NULL);

if (verbose) {
Expand Down
4 changes: 2 additions & 2 deletions builtin/fast-import.c
Original file line number Diff line number Diff line change
Expand Up @@ -822,11 +822,11 @@ static char *keep_pack(const char *curr_index_name)
die_errno("failed to write keep file");

odb_pack_name(pack_data->repo, &name, pack_data->hash, "pack");
if (finalize_object_file(pack_data->pack_name, name.buf))
if (finalize_object_file(pack_data->repo, pack_data->pack_name, name.buf))
die("cannot store pack file");

odb_pack_name(pack_data->repo, &name, pack_data->hash, "idx");
if (finalize_object_file(curr_index_name, name.buf))
if (finalize_object_file(pack_data->repo, curr_index_name, name.buf))
die("cannot store index file");
free((void *)curr_index_name);
return strbuf_detach(&name, NULL);
Expand Down
16 changes: 9 additions & 7 deletions builtin/fsck.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ static void check_connectivity(void)
* and ignore any that weren't present in our earlier
* traversal.
*/
for_each_loose_object(mark_loose_unreachable_referents, NULL, 0);
for_each_loose_object(the_repository->objects,
mark_loose_unreachable_referents, NULL, 0);
for_each_packed_object(the_repository,
mark_packed_unreachable_referents,
NULL,
Expand Down Expand Up @@ -632,7 +633,7 @@ static int fsck_loose(const struct object_id *oid, const char *path,
oi.sizep = &size;
oi.typep = &type;

if (read_loose_object(path, oid, &real_oid, &contents, &oi) < 0) {
if (read_loose_object(the_repository, path, oid, &real_oid, &contents, &oi) < 0) {
if (contents && !oideq(&real_oid, oid))
err = error(_("%s: hash-path mismatch, found at: %s"),
oid_to_hex(&real_oid), path);
Expand Down Expand Up @@ -687,7 +688,7 @@ static int fsck_subdir(unsigned int nr, const char *path UNUSED, void *data)
return 0;
}

static void fsck_object_dir(const char *path)
static void fsck_source(struct odb_source *source)
{
struct progress *progress = NULL;
struct for_each_loose_cb cb_data = {
Expand All @@ -701,8 +702,8 @@ static void fsck_object_dir(const char *path)
progress = start_progress(the_repository,
_("Checking object directories"), 256);

for_each_loose_file_in_objdir(path, fsck_loose, fsck_cruft, fsck_subdir,
&cb_data);
for_each_loose_file_in_source(source, fsck_loose,
fsck_cruft, fsck_subdir, &cb_data);
display_progress(progress, 256);
stop_progress(&progress);
}
Expand Down Expand Up @@ -994,13 +995,14 @@ int cmd_fsck(int argc,
fsck_refs(the_repository);

if (connectivity_only) {
for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
for_each_loose_object(the_repository->objects,
mark_loose_for_connectivity, NULL, 0);
for_each_packed_object(the_repository,
mark_packed_for_connectivity, NULL, 0);
} else {
odb_prepare_alternates(the_repository->objects);
for (source = the_repository->objects->sources; source; source = source->next)
fsck_object_dir(source->path);
fsck_source(source);

if (check_full) {
struct packed_git *p;
Expand Down
10 changes: 4 additions & 6 deletions builtin/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1309,7 +1309,7 @@ static int loose_object_auto_condition(struct gc_config *cfg UNUSED)
if (loose_object_auto_limit < 0)
return 1;

return for_each_loose_file_in_objdir(the_repository->objects->sources->path,
return for_each_loose_file_in_source(the_repository->objects->sources,
loose_object_count,
NULL, NULL, &count);
}
Expand Down Expand Up @@ -1344,7 +1344,7 @@ static int pack_loose(struct maintenance_run_opts *opts)
* Do not start pack-objects process
* if there are no loose objects.
*/
if (!for_each_loose_file_in_objdir(r->objects->sources->path,
if (!for_each_loose_file_in_source(r->objects->sources,
bail_on_loose,
NULL, NULL, NULL))
return 0;
Expand Down Expand Up @@ -1384,11 +1384,9 @@ static int pack_loose(struct maintenance_run_opts *opts)
else if (data.batch_size > 0)
data.batch_size--; /* Decrease for equality on limit. */

for_each_loose_file_in_objdir(r->objects->sources->path,
for_each_loose_file_in_source(r->objects->sources,
write_loose_object_to_stdin,
NULL,
NULL,
&data);
NULL, NULL, &data);

fclose(data.in);

Expand Down
2 changes: 1 addition & 1 deletion builtin/index-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -1598,7 +1598,7 @@ static void rename_tmp_packfile(const char **final_name,
if (!*final_name || strcmp(*final_name, curr_name)) {
if (!*final_name)
*final_name = odb_pack_name(the_repository, name, hash, ext);
if (finalize_object_file(curr_name, *final_name))
if (finalize_object_file(the_repository, curr_name, *final_name))
die(_("unable to rename temporary '*.%s' file to '%s'"),
ext, *final_name);
} else if (make_read_only_if_same) {
Expand Down
3 changes: 2 additions & 1 deletion builtin/merge-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ int cmd_merge_file(int argc,
if (object_id && !to_stdout) {
struct object_id oid;
if (result.size) {
if (write_object_file(result.ptr, result.size, OBJ_BLOB, &oid) < 0)
if (odb_write_object(the_repository->objects, result.ptr,
result.size, OBJ_BLOB, &oid) < 0)
ret = error(_("Could not write object file"));
} else {
oidcpy(&oid, the_hash_algo->empty_blob);
Expand Down
2 changes: 1 addition & 1 deletion builtin/mktag.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ int cmd_mktag(int argc,
if (verify_object_in_tag(&tagged_oid, &tagged_type) < 0)
die(_("tag on stdin did not refer to a valid object"));

if (write_object_file(buf.buf, buf.len, OBJ_TAG, &result) < 0)
if (odb_write_object(the_repository->objects, buf.buf, buf.len, OBJ_TAG, &result) < 0)
die(_("unable to write tag file"));

strbuf_release(&buf);
Expand Down
2 changes: 1 addition & 1 deletion builtin/mktree.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static void write_tree(struct object_id *oid)
strbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz);
}

write_object_file(buf.buf, buf.len, OBJ_TREE, oid);
odb_write_object(the_repository->objects, buf.buf, buf.len, OBJ_TREE, oid);
strbuf_release(&buf);
}

Expand Down
3 changes: 2 additions & 1 deletion builtin/notes.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ static void prepare_note_data(const struct object_id *object, struct note_data *

static void write_note_data(struct note_data *d, struct object_id *oid)
{
if (write_object_file(d->buf.buf, d->buf.len, OBJ_BLOB, oid)) {
if (odb_write_object(the_repository->objects, d->buf.buf,
d->buf.len, OBJ_BLOB, oid)) {
int status = die_message(_("unable to write note object"));

if (d->edit_path)
Expand Down
31 changes: 24 additions & 7 deletions builtin/pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -1455,7 +1455,7 @@ static void write_pack_file(void)
strbuf_setlen(&tmpname, tmpname_len);
}

rename_tmp_packfile_idx(&tmpname, &idx_tmp_name);
rename_tmp_packfile_idx(the_repository, &tmpname, &idx_tmp_name);

free(idx_tmp_name);
strbuf_release(&tmpname);
Expand Down Expand Up @@ -1709,8 +1709,16 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
struct odb_source *source;
struct list_head *pos;

if (!exclude && local && has_loose_object_nonlocal(oid))
return 0;
if (!exclude && local) {
/*
* Note that we start iterating at `sources->next` so that we
* skip the local object source.
*/
struct odb_source *source = the_repository->objects->sources->next;
for (; source; source = source->next)
if (has_loose_object(source, oid))
return 0;
}

/*
* If we already know the pack object lives in, start checks from that
Expand Down Expand Up @@ -3966,7 +3974,14 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type
} else {
if (!want_object_in_pack_mtime(oid, 0, &pack, &offset, mtime))
return;
if (!pack && type == OBJ_BLOB && !has_loose_object(oid)) {
if (!pack && type == OBJ_BLOB) {
struct odb_source *source = the_repository->objects->sources;
int found = 0;

for (; !found && source; source = source->next)
if (has_loose_object(source, oid))
found = 1;

/*
* If a traversed tree has a missing blob then we want
* to avoid adding that missing object to our pack.
Expand All @@ -3980,7 +3995,8 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type
* limited to "ensure non-tip blobs which don't exist in
* packs do exist via loose objects". Confused?
*/
return;
if (!found)
return;
}

entry = create_object_entry(oid, type, pack_name_hash_fn(name),
Expand Down Expand Up @@ -4368,7 +4384,7 @@ static int add_loose_object(const struct object_id *oid, const char *path,
*/
static void add_unreachable_loose_objects(struct rev_info *revs)
{
for_each_loose_file_in_objdir(repo_get_object_directory(the_repository),
for_each_loose_file_in_source(the_repository->objects->sources,
add_loose_object, NULL, NULL, revs);
}

Expand Down Expand Up @@ -4437,7 +4453,8 @@ static void loosen_unused_packed_objects(void)
if (!packlist_find(&to_pack, &oid) &&
!has_sha1_pack_kept_or_nonlocal(&oid) &&
!loosened_object_can_be_discarded(&oid, p->mtime)) {
if (force_object_loose(&oid, p->mtime))
if (force_object_loose(the_repository->objects->sources,
&oid, p->mtime))
die(_("unable to force loose object"));
loosened_objects_nr++;
}
Expand Down
2 changes: 1 addition & 1 deletion builtin/prune.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ int cmd_prune(int argc,
revs.exclude_promisor_objects = 1;
}

for_each_loose_file_in_objdir(repo_get_object_directory(repo),
for_each_loose_file_in_source(repo->objects->sources,
prune_object, prune_cruft, prune_subdir, &revs);

prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);
Expand Down
4 changes: 2 additions & 2 deletions builtin/receive-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -760,8 +760,8 @@ static void prepare_push_cert_sha1(struct child_process *proc)
int bogs /* beginning_of_gpg_sig */;

already_done = 1;
if (write_object_file(push_cert.buf, push_cert.len, OBJ_BLOB,
&push_cert_oid))
if (odb_write_object(the_repository->objects, push_cert.buf,
push_cert.len, OBJ_BLOB, &push_cert_oid))
oidclr(&push_cert_oid, the_repository->hash_algo);

memset(&sigcheck, '\0', sizeof(sigcheck));
Expand Down
3 changes: 2 additions & 1 deletion builtin/replace.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,8 @@ static int create_graft(int argc, const char **argv, int force, int gentle)
return -1;
}

if (write_object_file(buf.buf, buf.len, OBJ_COMMIT, &new_oid)) {
if (odb_write_object(the_repository->objects, buf.buf,
buf.len, OBJ_COMMIT, &new_oid)) {
strbuf_release(&buf);
return error(_("could not write replacement commit for: '%s'"),
old_ref);
Expand Down
Loading