Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
04541ec
fixup! odb: scan all sources' packfiles before loose objects
dscho Oct 16, 2026
b9f2eee
setup: split up concerns of `init_db()`
pks-t Sep 10, 2026
d73f69c
builtin/clone: defer setup of the object database
pks-t Sep 10, 2026
b781ec0
builtin/clone: move around `setup_reference()`
pks-t Sep 10, 2026
e6ea2e2
builtin/clone: refactor handling of "--reference{,-if-able}"
pks-t Sep 10, 2026
bbf30b6
builtin/clone: move setup of alternates for shared local clones
pks-t Sep 10, 2026
4f21bd0
builtin/clone: move setup of alternates for non-shared local clones
pks-t Sep 10, 2026
fdfff05
odb/source: support writing alternates when creating the database
pks-t Sep 10, 2026
7f2a360
builtin/clone: write alternates via `odb_create_on_disk()`
pks-t Sep 10, 2026
9343eea
odb/source: remove the ability to write alternates
pks-t Sep 10, 2026
3c4a88b
commit-graph: require resolved packfile paths for `stdin_packs`
pks-t Oct 8, 2026
61329f1
commit-graph: stop depending on `struct odb_source`
pks-t Oct 8, 2026
e7662ea
odb/source-files: introduce `struct odb_files_dir`
pks-t Oct 8, 2026
4a3fcd7
odb: refactor `odb_for_each_alternate()` to yield dirs
pks-t Oct 8, 2026
ad8afd3
odb: refactor `odb_find_source()` to yield dirs
pks-t Oct 8, 2026
c5d78ba
odb/source-files: add the ability to have multiple object dirs
pks-t Oct 8, 2026
616c940
tmp-objdir: absorb logic to set and restore primary sources
pks-t Oct 8, 2026
0e73273
tmp-objdir: manage quarantine as an object directory
pks-t Oct 8, 2026
c3bda4b
tmp-objdir: replace primary source at creation time
pks-t Oct 8, 2026
0a51605
odb/source: make `will_destroy` an implementation detail
pks-t Oct 8, 2026
8340ce2
odb/source-files: extract reading alternates
pks-t Oct 8, 2026
4b3ffd4
odb/source-files: move alternates into the backend
pks-t Oct 8, 2026
17a9afc
odb/source: drop `read_alternates` callback
pks-t Oct 8, 2026
18e7904
odb/source-files: fix performance when reading objects with alternates
pks-t Oct 15, 2026
c8a4c6d
odb/source-files: fix performance when streaming objects with alternates
pks-t Oct 15, 2026
a268ddd
odb/source-files: make the second read an implementation detail
pks-t Oct 15, 2026
4e588d6
odb: remove read loop for found objects
pks-t Oct 15, 2026
2cc9348
odb: don't try re-fetching corrupt objects
pks-t Oct 15, 2026
f7fcf98
odb/source: drop `local` flag
pks-t Oct 15, 2026
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
111 changes: 69 additions & 42 deletions builtin/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,42 +154,34 @@ static char *get_repo_path(const char *repo, int *is_bundle)
return canon;
}

static int add_one_reference(struct string_list_item *item, void *cb_data)
struct collect_alternates_data {
struct strvec *alternates;
bool required;
};

static int collect_one_alternate(struct string_list_item *item, void *cb_data)
{
struct collect_alternates_data *data = cb_data;
struct strbuf err = STRBUF_INIT;
int *required = cb_data;
char *ref_git = compute_alternate_path(item->string, &err);

if (!ref_git) {
if (*required)
if (data->required)
die("%s", err.buf);
else
fprintf(stderr,
_("info: Could not add alternate for '%s': %s\n"),
item->string, err.buf);
} else {
struct strbuf sb = STRBUF_INIT;
strbuf_addf(&sb, "%s/objects", ref_git);
odb_add_to_alternates_file(the_repository->objects, sb.buf);
strbuf_release(&sb);
strvec_pushf(data->alternates, "%s/objects", ref_git);
}

strbuf_release(&err);
free(ref_git);
return 0;
}

static void setup_reference(void)
{
int required = 1;
for_each_string_list(&option_required_reference,
add_one_reference, &required);
required = 0;
for_each_string_list(&option_optional_reference,
add_one_reference, &required);
}

static void copy_alternates(struct strbuf *src, const char *src_repo)
static void read_alternates(struct strvec *alternates, const char *src_repo)
{
/*
* Read from the source objects/info/alternates file
Expand All @@ -203,29 +195,70 @@ static void copy_alternates(struct strbuf *src, const char *src_repo)
* to turn entries with paths relative to the original
* absolute, so that they can be used in the new repository.
*/
FILE *in = xfopen(src->buf, "r");
FILE *in;
struct strbuf path = STRBUF_INIT;
struct strbuf line = STRBUF_INIT;

strbuf_addf(&path, "%s/objects/info/alternates", src_repo);

in = fopen(path.buf, "r");
if (!in) {
if (errno == ENOENT)
goto out;
die_errno("could not read alternates file '%s'", path.buf);
}

while (strbuf_getline(&line, in) != EOF) {
char *abs_path;
if (!line.len || line.buf[0] == '#')
continue;
if (is_absolute_path(line.buf)) {
odb_add_to_alternates_file(the_repository->objects,
line.buf);
strvec_push(alternates, line.buf);
continue;
}
abs_path = mkpathdup("%s/objects/%s", src_repo, line.buf);
if (!normalize_path_copy(abs_path, abs_path))
odb_add_to_alternates_file(the_repository->objects,
abs_path);
strvec_push(alternates, abs_path);
else
warning("skipping invalid relative alternate: %s/%s",
src_repo, line.buf);
free(abs_path);
}

out:
strbuf_release(&path);
strbuf_release(&line);
fclose(in);
if (in)
fclose(in);
}

static void collect_alternates(struct strvec *alternates,
const char *local_source_repo)
{
if (option_required_reference.nr || option_optional_reference.nr) {
struct collect_alternates_data data = {
.alternates = alternates,
.required = true,
};

for_each_string_list(&option_required_reference,
collect_one_alternate, &data);
data.required = false;
for_each_string_list(&option_optional_reference,
collect_one_alternate, &data);
}

if (local_source_repo) {
struct strbuf commondir = STRBUF_INIT;

get_common_dir(&commondir, local_source_repo);
if (option_shared)
strvec_pushf(alternates, "%s/objects", commondir.buf);
else
read_alternates(alternates, commondir.buf);

strbuf_release(&commondir);
}
}

static void mkdir_if_missing(const char *pathname, mode_t mode)
Expand Down Expand Up @@ -301,11 +334,9 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
continue;
}

/* Files that cannot be copied bit-for-bit... */
if (!fspathcmp(iter->relative_path, "info/alternates")) {
copy_alternates(src, src_repo);
/* Alternates were already handled earlier. */
if (!fspathcmp(iter->relative_path, "info/alternates"))
continue;
}

if (unlink(dest->buf) && errno != ENOENT)
die_errno(_("failed to unlink '%s'"), dest->buf);
Expand Down Expand Up @@ -349,13 +380,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,

static void clone_local(const char *src_repo, const char *dest_repo)
{
if (option_shared) {
struct strbuf alt = STRBUF_INIT;
get_common_dir(&alt, src_repo);
strbuf_addstr(&alt, "/objects");
odb_add_to_alternates_file(the_repository->objects, alt.buf);
strbuf_release(&alt);
} else {
if (!option_shared) {
struct strbuf src = STRBUF_INIT;
struct strbuf dest = STRBUF_INIT;
get_common_dir(&src, src_repo);
Expand Down Expand Up @@ -999,6 +1024,7 @@ int cmd_clone(int argc,
N_("uri"), N_("a URI for downloading bundles before fetching from origin remote")),
OPT_END()
};
struct strvec alternates = STRVEC_INIT;

const char * const builtin_clone_usage[] = {
N_("git clone [<options>] [--] <repo> [<dir>]"),
Expand Down Expand Up @@ -1185,10 +1211,9 @@ int cmd_clone(int argc,
* repository, and reference backends may persist that information into
* their on-disk data structures.
*/
init_db(the_repository, git_dir, real_git_dir, work_tree, option_template,
GIT_HASH_UNKNOWN, ref_storage_format, NULL,
do_not_override_repo_unix_permissions,
INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
create_repository(the_repository, git_dir, real_git_dir, work_tree,
option_template, GIT_HASH_UNKNOWN, ref_storage_format,
do_not_override_repo_unix_permissions, NULL);

if (real_git_dir) {
free((char *)git_dir);
Expand Down Expand Up @@ -1311,9 +1336,6 @@ int cmd_clone(int argc,
strbuf_reset(&key);
}

if (option_required_reference.nr || option_optional_reference.nr)
setup_reference();

remote = remote_get_early(remote_name);

if (!option_rev)
Expand Down Expand Up @@ -1342,6 +1364,9 @@ int cmd_clone(int argc,
if (option_local > 0 && !is_local)
warning(_("--local is ignored"));

collect_alternates(&alternates, is_local ? path : NULL);
create_object_database(the_repository, &alternates);

transport = transport_get(remote, path ? path : remote->url.v[0]);
transport_set_verbosity(transport, option_verbosity, option_progress);
transport->family = family;
Expand Down Expand Up @@ -1445,6 +1470,7 @@ int cmd_clone(int argc,
initialize_repository_version(the_repository, hash_algo, the_repository->ref_storage_format, 1);
repo_set_hash_algo(the_repository, hash_algo);
create_reference_database(the_repository, NULL, 1);
startup_info->have_repository = 1;

/*
* Before fetching from the remote, download and install bundle
Expand Down Expand Up @@ -1637,6 +1663,7 @@ int cmd_clone(int argc,
string_list_clear(&option_not, 0);
string_list_clear(&option_config, 0);
string_list_clear(&server_options, 0);
strvec_clear(&alternates);

free(remote_name);
strbuf_release(&reflog_msg);
Expand Down
41 changes: 29 additions & 12 deletions builtin/commit-graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "parse-options.h"
#include "commit-graph.h"
#include "odb.h"
#include "odb/source.h"
#include "odb/source-files.h"
#include "progress.h"
#include "replace-object.h"
#include "strbuf.h"
Expand Down Expand Up @@ -67,7 +69,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix,
struct repository *repo UNUSED)
{
struct commit_graph *graph = NULL;
struct odb_source *source = NULL;
struct odb_files_dir *dir = NULL;
char *graph_name;
char *chain_name;
enum { OPENED_NONE, OPENED_GRAPH, OPENED_CHAIN } opened = OPENED_NONE;
Expand Down Expand Up @@ -102,9 +104,12 @@ static int graph_verify(int argc, const char **argv, const char *prefix,
if (opts.progress)
flags |= COMMIT_GRAPH_WRITE_PROGRESS;

source = odb_find_source_or_die(the_repository->objects, opts.obj_dir);
graph_name = get_commit_graph_filename(source);
chain_name = get_commit_graph_chain_filename(source);
dir = odb_source_files_find_dir(the_repository->objects, opts.obj_dir);
if (!dir)
die(_("could not find object directory matching %s"), opts.obj_dir);

graph_name = get_commit_graph_filename(dir->abspath);
chain_name = get_commit_graph_chain_filename(dir->abspath);
if (open_commit_graph(graph_name, &fd, &st))
opened = OPENED_GRAPH;
else if (errno != ENOENT)
Expand All @@ -122,7 +127,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix,
if (opened == OPENED_NONE)
return 0;
else if (opened == OPENED_GRAPH)
graph = load_commit_graph_one_fd_st(source, fd, &st);
graph = load_commit_graph_one_fd_st(the_repository, dir->abspath, fd, &st);
else
graph = load_commit_graph_chain_fd_st(the_repository->objects, fd, &st,
&incomplete_chain);
Expand Down Expand Up @@ -225,7 +230,7 @@ static int graph_write(int argc, const char **argv, const char *prefix,
struct string_list pack_indexes = STRING_LIST_INIT_DUP;
struct strbuf buf = STRBUF_INIT;
struct oidset commits = OIDSET_INIT;
struct odb_source *source = NULL;
struct odb_files_dir *dir = NULL;
int result = 0;
enum commit_graph_write_flags flags = 0;
struct progress *progress = NULL;
Expand Down Expand Up @@ -293,18 +298,30 @@ static int graph_write(int argc, const char **argv, const char *prefix,
git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0))
flags |= COMMIT_GRAPH_WRITE_BLOOM_FILTERS;

source = odb_find_source_or_die(the_repository->objects, opts.obj_dir);
dir = odb_source_files_find_dir(the_repository->objects, opts.obj_dir);
if (!dir)
die(_("could not find object directory matching %s"), opts.obj_dir);

if (opts.reachable) {
if (write_commit_graph_reachable(source, flags, &write_opts))
if (write_commit_graph_reachable(the_repository, dir->abspath, flags, &write_opts))
result = 1;
goto cleanup;
}

if (opts.stdin_packs) {
while (strbuf_getline(&buf, stdin) != EOF)
string_list_append_nodup(&pack_indexes,
strbuf_detach(&buf, NULL));
struct strbuf packname = STRBUF_INIT;
size_t dirlen;

strbuf_addf(&packname, "%s/pack/", dir->abspath);
dirlen = packname.len;

while (strbuf_getline(&buf, stdin) != EOF) {
strbuf_setlen(&packname, dirlen);
strbuf_addbuf(&packname, &buf);
string_list_append(&pack_indexes, packname.buf);
}

strbuf_release(&packname);
} else if (opts.stdin_commits) {
oidset_init(&commits, 0);
if (opts.progress)
Expand All @@ -323,7 +340,7 @@ static int graph_write(int argc, const char **argv, const char *prefix,
stop_progress(&progress);
}

if (write_commit_graph(source,
if (write_commit_graph(the_repository, dir->abspath,
opts.stdin_packs ? &pack_indexes : NULL,
opts.stdin_commits ? &commits : NULL,
flags,
Expand Down
2 changes: 1 addition & 1 deletion builtin/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -2218,7 +2218,7 @@ int cmd_commit(int argc,
"new index file. Check that disk is not full and quota is\n"
"not exceeded, and then \"git restore --staged :/\" to recover."));

git_test_write_commit_graph_or_die(the_repository->objects->sources);
git_test_write_commit_graph_or_die(the_repository);

repo_rerere(the_repository, 0);
run_auto_maintenance(the_repository, quiet);
Expand Down
6 changes: 3 additions & 3 deletions builtin/count-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ static int count_cruft(const char *basename UNUSED, const char *path,
return 0;
}

static int print_alternate(struct odb_source *alternate, void *data UNUSED)
static int print_alternate(struct odb_files_dir *alternate, void *data UNUSED)
{
printf("alternate: ");
quote_c_style(alternate->path, NULL, stdout, 0);
quote_c_style(alternate->abspath, NULL, stdout, 0);
putchar('\n');
return 0;
}
Expand Down Expand Up @@ -118,7 +118,7 @@ int cmd_count_objects(int argc,
report_linked_checkout_garbage(the_repository);
}

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

if (verbose) {
Expand Down
Loading
Loading