Skip to content

Commit 7a75e13

Browse files
committed
Merge branch 'ps/clone-into-reftable-repository' into ps/refstorage-extension
* ps/clone-into-reftable-repository: builtin/clone: create the refdb with the correct object format builtin/clone: skip reading HEAD when retrieving remote builtin/clone: set up sparse checkout later builtin/clone: fix bundle URIs with mismatching object formats remote-curl: rediscover repository when fetching refs setup: allow skipping creation of the refdb setup: extract function to create the refdb
2 parents 055bb6e + 18c9cb7 commit 7a75e13

File tree

8 files changed

+150
-91
lines changed

8 files changed

+150
-91
lines changed

builtin/clone.c

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,8 +1101,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11011101
}
11021102
}
11031103

1104+
/*
1105+
* Initialize the repository, but skip initializing the reference
1106+
* database. We do not yet know about the object format of the
1107+
* repository, and reference backends may persist that information into
1108+
* their on-disk data structures.
1109+
*/
11041110
init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
1105-
do_not_override_repo_unix_permissions, INIT_DB_QUIET);
1111+
do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
11061112

11071113
if (real_git_dir) {
11081114
free((char *)git_dir);
@@ -1189,10 +1195,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11891195
if (option_required_reference.nr || option_optional_reference.nr)
11901196
setup_reference();
11911197

1192-
if (option_sparse_checkout && git_sparse_checkout_init(dir))
1193-
return 1;
1194-
1195-
remote = remote_get(remote_name);
1198+
remote = remote_get_early(remote_name);
11961199

11971200
refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
11981201
branch_top.buf);
@@ -1270,6 +1273,27 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
12701273
if (transport->smart_options && !deepen && !filter_options.choice)
12711274
transport->smart_options->check_self_contained_and_connected = 1;
12721275

1276+
strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
1277+
refspec_ref_prefixes(&remote->fetch,
1278+
&transport_ls_refs_options.ref_prefixes);
1279+
if (option_branch)
1280+
expand_ref_prefix(&transport_ls_refs_options.ref_prefixes,
1281+
option_branch);
1282+
if (!option_no_tags)
1283+
strvec_push(&transport_ls_refs_options.ref_prefixes,
1284+
"refs/tags/");
1285+
1286+
refs = transport_get_remote_refs(transport, &transport_ls_refs_options);
1287+
1288+
/*
1289+
* Now that we know what algorithm the remote side is using, let's set
1290+
* ours to the same thing.
1291+
*/
1292+
hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
1293+
initialize_repository_version(hash_algo, 1);
1294+
repo_set_hash_algo(the_repository, hash_algo);
1295+
create_reference_database(NULL, 1);
1296+
12731297
/*
12741298
* Before fetching from the remote, download and install bundle
12751299
* data from the --bundle-uri option.
@@ -1285,24 +1309,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
12851309
bundle_uri);
12861310
else if (has_heuristic)
12871311
git_config_set_gently("fetch.bundleuri", bundle_uri);
1288-
}
1289-
1290-
strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
1291-
refspec_ref_prefixes(&remote->fetch,
1292-
&transport_ls_refs_options.ref_prefixes);
1293-
if (option_branch)
1294-
expand_ref_prefix(&transport_ls_refs_options.ref_prefixes,
1295-
option_branch);
1296-
if (!option_no_tags)
1297-
strvec_push(&transport_ls_refs_options.ref_prefixes,
1298-
"refs/tags/");
1299-
1300-
refs = transport_get_remote_refs(transport, &transport_ls_refs_options);
1301-
1302-
if (refs)
1303-
mapped_refs = wanted_peer_refs(refs, &remote->fetch);
1304-
1305-
if (!bundle_uri) {
1312+
} else {
13061313
/*
13071314
* Populate transport->got_remote_bundle_uri and
13081315
* transport->bundle_uri. We might get nothing.
@@ -1323,13 +1330,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
13231330
}
13241331
}
13251332

1326-
/*
1327-
* Now that we know what algorithm the remote side is using,
1328-
* let's set ours to the same thing.
1329-
*/
1330-
hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
1331-
initialize_repository_version(hash_algo, 1);
1332-
repo_set_hash_algo(the_repository, hash_algo);
1333+
if (refs)
1334+
mapped_refs = wanted_peer_refs(refs, &remote->fetch);
13331335

13341336
if (mapped_refs) {
13351337
/*
@@ -1432,6 +1434,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
14321434
dissociate_from_references();
14331435
}
14341436

1437+
if (option_sparse_checkout && git_sparse_checkout_init(dir))
1438+
return 1;
1439+
14351440
junk_mode = JUNK_LEAVE_REPO;
14361441
err = checkout(submodule_progress, filter_submodules);
14371442

remote-curl.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,8 +1564,11 @@ int cmd_main(int argc, const char **argv)
15641564
if (buf.len == 0)
15651565
break;
15661566
if (starts_with(buf.buf, "fetch ")) {
1567-
if (nongit)
1568-
die(_("remote-curl: fetch attempted without a local repo"));
1567+
if (nongit) {
1568+
setup_git_directory_gently(&nongit);
1569+
if (nongit)
1570+
die(_("remote-curl: fetch attempted without a local repo"));
1571+
}
15691572
parse_fetch(&buf);
15701573

15711574
} else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {

remote.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ static void alias_all_urls(struct remote_state *remote_state)
509509
}
510510
}
511511

512-
static void read_config(struct repository *repo)
512+
static void read_config(struct repository *repo, int early)
513513
{
514514
int flag;
515515

@@ -518,7 +518,7 @@ static void read_config(struct repository *repo)
518518
repo->remote_state->initialized = 1;
519519

520520
repo->remote_state->current_branch = NULL;
521-
if (startup_info->have_repository) {
521+
if (startup_info->have_repository && !early) {
522522
const char *head_ref = refs_resolve_ref_unsafe(
523523
get_main_ref_store(repo), "HEAD", 0, NULL, &flag);
524524
if (head_ref && (flag & REF_ISSYMREF) &&
@@ -561,7 +561,7 @@ static const char *remotes_remote_for_branch(struct remote_state *remote_state,
561561

562562
const char *remote_for_branch(struct branch *branch, int *explicit)
563563
{
564-
read_config(the_repository);
564+
read_config(the_repository, 0);
565565
die_on_missing_branch(the_repository, branch);
566566

567567
return remotes_remote_for_branch(the_repository->remote_state, branch,
@@ -587,7 +587,7 @@ remotes_pushremote_for_branch(struct remote_state *remote_state,
587587

588588
const char *pushremote_for_branch(struct branch *branch, int *explicit)
589589
{
590-
read_config(the_repository);
590+
read_config(the_repository, 0);
591591
die_on_missing_branch(the_repository, branch);
592592

593593
return remotes_pushremote_for_branch(the_repository->remote_state,
@@ -599,7 +599,7 @@ static struct remote *remotes_remote_get(struct remote_state *remote_state,
599599

600600
const char *remote_ref_for_branch(struct branch *branch, int for_push)
601601
{
602-
read_config(the_repository);
602+
read_config(the_repository, 0);
603603
die_on_missing_branch(the_repository, branch);
604604

605605
if (branch) {
@@ -709,7 +709,13 @@ remotes_remote_get(struct remote_state *remote_state, const char *name)
709709

710710
struct remote *remote_get(const char *name)
711711
{
712-
read_config(the_repository);
712+
read_config(the_repository, 0);
713+
return remotes_remote_get(the_repository->remote_state, name);
714+
}
715+
716+
struct remote *remote_get_early(const char *name)
717+
{
718+
read_config(the_repository, 1);
713719
return remotes_remote_get(the_repository->remote_state, name);
714720
}
715721

@@ -722,7 +728,7 @@ remotes_pushremote_get(struct remote_state *remote_state, const char *name)
722728

723729
struct remote *pushremote_get(const char *name)
724730
{
725-
read_config(the_repository);
731+
read_config(the_repository, 0);
726732
return remotes_pushremote_get(the_repository->remote_state, name);
727733
}
728734

@@ -738,7 +744,7 @@ int remote_is_configured(struct remote *remote, int in_repo)
738744
int for_each_remote(each_remote_fn fn, void *priv)
739745
{
740746
int i, result = 0;
741-
read_config(the_repository);
747+
read_config(the_repository, 0);
742748
for (i = 0; i < the_repository->remote_state->remotes_nr && !result;
743749
i++) {
744750
struct remote *remote =
@@ -1831,7 +1837,7 @@ struct branch *branch_get(const char *name)
18311837
{
18321838
struct branch *ret;
18331839

1834-
read_config(the_repository);
1840+
read_config(the_repository, 0);
18351841
if (!name || !*name || !strcmp(name, "HEAD"))
18361842
ret = the_repository->remote_state->current_branch;
18371843
else
@@ -1973,7 +1979,7 @@ static const char *branch_get_push_1(struct remote_state *remote_state,
19731979

19741980
const char *branch_get_push(struct branch *branch, struct strbuf *err)
19751981
{
1976-
read_config(the_repository);
1982+
read_config(the_repository, 0);
19771983
die_on_missing_branch(the_repository, branch);
19781984

19791985
if (!branch)

remote.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ struct remote {
118118
* and configuration.
119119
*/
120120
struct remote *remote_get(const char *name);
121+
struct remote *remote_get_early(const char *name);
121122

122123
struct remote *pushremote_get(const char *name);
123124
int remote_is_configured(struct remote *remote, int in_repo);

setup.c

Lines changed: 69 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,21 +1887,79 @@ void initialize_repository_version(int hash_algo, int reinit)
18871887
git_config_set_gently("extensions.objectformat", NULL);
18881888
}
18891889

1890+
static int is_reinit(void)
1891+
{
1892+
struct strbuf buf = STRBUF_INIT;
1893+
char junk[2];
1894+
int ret;
1895+
1896+
git_path_buf(&buf, "HEAD");
1897+
ret = !access(buf.buf, R_OK) || readlink(buf.buf, junk, sizeof(junk) - 1) != -1;
1898+
strbuf_release(&buf);
1899+
return ret;
1900+
}
1901+
1902+
void create_reference_database(const char *initial_branch, int quiet)
1903+
{
1904+
struct strbuf err = STRBUF_INIT;
1905+
int reinit = is_reinit();
1906+
1907+
/*
1908+
* We need to create a "refs" dir in any case so that older versions of
1909+
* Git can tell that this is a repository. This serves two main purposes:
1910+
*
1911+
* - Clients will know to stop walking the parent-directory chain when
1912+
* detecting the Git repository. Otherwise they may end up detecting
1913+
* a Git repository in a parent directory instead.
1914+
*
1915+
* - Instead of failing to detect a repository with unknown reference
1916+
* format altogether, old clients will print an error saying that
1917+
* they do not understand the reference format extension.
1918+
*/
1919+
safe_create_dir(git_path("refs"), 1);
1920+
adjust_shared_perm(git_path("refs"));
1921+
1922+
if (refs_init_db(&err))
1923+
die("failed to set up refs db: %s", err.buf);
1924+
1925+
/*
1926+
* Point the HEAD symref to the initial branch with if HEAD does
1927+
* not yet exist.
1928+
*/
1929+
if (!reinit) {
1930+
char *ref;
1931+
1932+
if (!initial_branch)
1933+
initial_branch = git_default_branch_name(quiet);
1934+
1935+
ref = xstrfmt("refs/heads/%s", initial_branch);
1936+
if (check_refname_format(ref, 0) < 0)
1937+
die(_("invalid initial branch name: '%s'"),
1938+
initial_branch);
1939+
1940+
if (create_symref("HEAD", ref, NULL) < 0)
1941+
exit(1);
1942+
free(ref);
1943+
}
1944+
1945+
if (reinit && initial_branch)
1946+
warning(_("re-init: ignored --initial-branch=%s"),
1947+
initial_branch);
1948+
1949+
strbuf_release(&err);
1950+
}
1951+
18901952
static int create_default_files(const char *template_path,
18911953
const char *original_git_dir,
1892-
const char *initial_branch,
18931954
const struct repository_format *fmt,
18941955
int prev_bare_repository,
1895-
int init_shared_repository,
1896-
int quiet)
1956+
int init_shared_repository)
18971957
{
18981958
struct stat st1;
18991959
struct strbuf buf = STRBUF_INIT;
19001960
char *path;
1901-
char junk[2];
19021961
int reinit;
19031962
int filemode;
1904-
struct strbuf err = STRBUF_INIT;
19051963
const char *init_template_dir = NULL;
19061964
const char *work_tree = get_git_work_tree();
19071965

@@ -1921,6 +1979,8 @@ static int create_default_files(const char *template_path,
19211979
reset_shared_repository();
19221980
git_config(git_default_config, NULL);
19231981

1982+
reinit = is_reinit();
1983+
19241984
/*
19251985
* We must make sure command-line options continue to override any
19261986
* values we might have just re-read from the config.
@@ -1964,39 +2024,6 @@ static int create_default_files(const char *template_path,
19642024
adjust_shared_perm(get_git_dir());
19652025
}
19662026

1967-
/*
1968-
* We need to create a "refs" dir in any case so that older
1969-
* versions of git can tell that this is a repository.
1970-
*/
1971-
safe_create_dir(git_path("refs"), 1);
1972-
adjust_shared_perm(git_path("refs"));
1973-
1974-
if (refs_init_db(&err))
1975-
die("failed to set up refs db: %s", err.buf);
1976-
1977-
/*
1978-
* Point the HEAD symref to the initial branch with if HEAD does
1979-
* not yet exist.
1980-
*/
1981-
path = git_path_buf(&buf, "HEAD");
1982-
reinit = (!access(path, R_OK)
1983-
|| readlink(path, junk, sizeof(junk)-1) != -1);
1984-
if (!reinit) {
1985-
char *ref;
1986-
1987-
if (!initial_branch)
1988-
initial_branch = git_default_branch_name(quiet);
1989-
1990-
ref = xstrfmt("refs/heads/%s", initial_branch);
1991-
if (check_refname_format(ref, 0) < 0)
1992-
die(_("invalid initial branch name: '%s'"),
1993-
initial_branch);
1994-
1995-
if (create_symref("HEAD", ref, NULL) < 0)
1996-
exit(1);
1997-
free(ref);
1998-
}
1999-
20002027
initialize_repository_version(fmt->hash_algo, 0);
20012028

20022029
/* Check filemode trustability */
@@ -2156,14 +2183,11 @@ int init_db(const char *git_dir, const char *real_git_dir,
21562183
validate_hash_algorithm(&repo_fmt, hash);
21572184

21582185
reinit = create_default_files(template_dir, original_git_dir,
2159-
initial_branch, &repo_fmt,
2160-
prev_bare_repository,
2161-
init_shared_repository,
2162-
flags & INIT_DB_QUIET);
2163-
if (reinit && initial_branch)
2164-
warning(_("re-init: ignored --initial-branch=%s"),
2165-
initial_branch);
2186+
&repo_fmt, prev_bare_repository,
2187+
init_shared_repository);
21662188

2189+
if (!(flags & INIT_DB_SKIP_REFDB))
2190+
create_reference_database(initial_branch, flags & INIT_DB_QUIET);
21672191
create_object_directory();
21682192

21692193
if (get_shared_repository()) {

setup.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,16 @@ int verify_repository_format(const struct repository_format *format,
169169
*/
170170
void check_repository_format(struct repository_format *fmt);
171171

172-
#define INIT_DB_QUIET 0x0001
173-
#define INIT_DB_EXIST_OK 0x0002
172+
#define INIT_DB_QUIET (1 << 0)
173+
#define INIT_DB_EXIST_OK (1 << 1)
174+
#define INIT_DB_SKIP_REFDB (1 << 2)
174175

175176
int init_db(const char *git_dir, const char *real_git_dir,
176177
const char *template_dir, int hash_algo,
177178
const char *initial_branch, int init_shared_repository,
178179
unsigned int flags);
179180
void initialize_repository_version(int hash_algo, int reinit);
181+
void create_reference_database(const char *initial_branch, int quiet);
180182

181183
/*
182184
* NOTE NOTE NOTE!!

0 commit comments

Comments
 (0)