Skip to content

Commit ae36652

Browse files
committed
Merge branch 'ps/clone-into-reftable-repository' into seen
"git clone" has been prepared to allow cloning a repository with non-default hash function into a repository that uses the reftable backend. * 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 3bc315c + 18c9cb7 commit ae36652

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
@@ -1100,8 +1100,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11001100
}
11011101
}
11021102

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

11061112
if (real_git_dir) {
11071113
free((char *)git_dir);
@@ -1188,10 +1194,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11881194
if (option_required_reference.nr || option_optional_reference.nr)
11891195
setup_reference();
11901196

1191-
if (option_sparse_checkout && git_sparse_checkout_init(dir))
1192-
return 1;
1193-
1194-
remote = remote_get(remote_name);
1197+
remote = remote_get_early(remote_name);
11951198

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

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

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

13331335
if (mapped_refs) {
13341336
/*
@@ -1431,6 +1433,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
14311433
dissociate_from_references();
14321434
}
14331435

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

remote-curl.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,8 +1571,11 @@ int cmd_main(int argc, const char **argv)
15711571
if (buf.len == 0)
15721572
break;
15731573
if (starts_with(buf.buf, "fetch ")) {
1574-
if (nongit)
1575-
die(_("remote-curl: fetch attempted without a local repo"));
1574+
if (nongit) {
1575+
setup_git_directory_gently(&nongit);
1576+
if (nongit)
1577+
die(_("remote-curl: fetch attempted without a local repo"));
1578+
}
15761579
parse_fetch(&buf);
15771580

15781581
} 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
@@ -508,7 +508,7 @@ static void alias_all_urls(struct remote_state *remote_state)
508508
}
509509
}
510510

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

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

519519
repo->remote_state->current_branch = NULL;
520-
if (startup_info->have_repository) {
520+
if (startup_info->have_repository && !early) {
521521
const char *head_ref = refs_resolve_ref_unsafe(
522522
get_main_ref_store(repo), "HEAD", 0, NULL, &flag);
523523
if (head_ref && (flag & REF_ISSYMREF) &&
@@ -560,7 +560,7 @@ static const char *remotes_remote_for_branch(struct remote_state *remote_state,
560560

561561
const char *remote_for_branch(struct branch *branch, int *explicit)
562562
{
563-
read_config(the_repository);
563+
read_config(the_repository, 0);
564564
die_on_missing_branch(the_repository, branch);
565565

566566
return remotes_remote_for_branch(the_repository->remote_state, branch,
@@ -586,7 +586,7 @@ remotes_pushremote_for_branch(struct remote_state *remote_state,
586586

587587
const char *pushremote_for_branch(struct branch *branch, int *explicit)
588588
{
589-
read_config(the_repository);
589+
read_config(the_repository, 0);
590590
die_on_missing_branch(the_repository, branch);
591591

592592
return remotes_pushremote_for_branch(the_repository->remote_state,
@@ -598,7 +598,7 @@ static struct remote *remotes_remote_get(struct remote_state *remote_state,
598598

599599
const char *remote_ref_for_branch(struct branch *branch, int for_push)
600600
{
601-
read_config(the_repository);
601+
read_config(the_repository, 0);
602602
die_on_missing_branch(the_repository, branch);
603603

604604
if (branch) {
@@ -708,7 +708,13 @@ remotes_remote_get(struct remote_state *remote_state, const char *name)
708708

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

@@ -721,7 +727,7 @@ remotes_pushremote_get(struct remote_state *remote_state, const char *name)
721727

722728
struct remote *pushremote_get(const char *name)
723729
{
724-
read_config(the_repository);
730+
read_config(the_repository, 0);
725731
return remotes_pushremote_get(the_repository->remote_state, name);
726732
}
727733

@@ -737,7 +743,7 @@ int remote_is_configured(struct remote *remote, int in_repo)
737743
int for_each_remote(each_remote_fn fn, void *priv)
738744
{
739745
int i, result = 0;
740-
read_config(the_repository);
746+
read_config(the_repository, 0);
741747
for (i = 0; i < the_repository->remote_state->remotes_nr && !result;
742748
i++) {
743749
struct remote *remote =
@@ -1830,7 +1836,7 @@ struct branch *branch_get(const char *name)
18301836
{
18311837
struct branch *ret;
18321838

1833-
read_config(the_repository);
1839+
read_config(the_repository, 0);
18341840
if (!name || !*name || !strcmp(name, "HEAD"))
18351841
ret = the_repository->remote_state->current_branch;
18361842
else
@@ -1972,7 +1978,7 @@ static const char *branch_get_push_1(struct remote_state *remote_state,
19721978

19731979
const char *branch_get_push(struct branch *branch, struct strbuf *err)
19741980
{
1975-
read_config(the_repository);
1981+
read_config(the_repository, 0);
19761982
die_on_missing_branch(the_repository, branch);
19771983

19781984
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
@@ -1908,21 +1908,79 @@ void initialize_repository_version(int hash_algo, int reinit)
19081908
git_config_set_gently("extensions.objectformat", NULL);
19091909
}
19101910

1911+
static int is_reinit(void)
1912+
{
1913+
struct strbuf buf = STRBUF_INIT;
1914+
char junk[2];
1915+
int ret;
1916+
1917+
git_path_buf(&buf, "HEAD");
1918+
ret = !access(buf.buf, R_OK) || readlink(buf.buf, junk, sizeof(junk) - 1) != -1;
1919+
strbuf_release(&buf);
1920+
return ret;
1921+
}
1922+
1923+
void create_reference_database(const char *initial_branch, int quiet)
1924+
{
1925+
struct strbuf err = STRBUF_INIT;
1926+
int reinit = is_reinit();
1927+
1928+
/*
1929+
* We need to create a "refs" dir in any case so that older versions of
1930+
* Git can tell that this is a repository. This serves two main purposes:
1931+
*
1932+
* - Clients will know to stop walking the parent-directory chain when
1933+
* detecting the Git repository. Otherwise they may end up detecting
1934+
* a Git repository in a parent directory instead.
1935+
*
1936+
* - Instead of failing to detect a repository with unknown reference
1937+
* format altogether, old clients will print an error saying that
1938+
* they do not understand the reference format extension.
1939+
*/
1940+
safe_create_dir(git_path("refs"), 1);
1941+
adjust_shared_perm(git_path("refs"));
1942+
1943+
if (refs_init_db(&err))
1944+
die("failed to set up refs db: %s", err.buf);
1945+
1946+
/*
1947+
* Point the HEAD symref to the initial branch with if HEAD does
1948+
* not yet exist.
1949+
*/
1950+
if (!reinit) {
1951+
char *ref;
1952+
1953+
if (!initial_branch)
1954+
initial_branch = git_default_branch_name(quiet);
1955+
1956+
ref = xstrfmt("refs/heads/%s", initial_branch);
1957+
if (check_refname_format(ref, 0) < 0)
1958+
die(_("invalid initial branch name: '%s'"),
1959+
initial_branch);
1960+
1961+
if (create_symref("HEAD", ref, NULL) < 0)
1962+
exit(1);
1963+
free(ref);
1964+
}
1965+
1966+
if (reinit && initial_branch)
1967+
warning(_("re-init: ignored --initial-branch=%s"),
1968+
initial_branch);
1969+
1970+
strbuf_release(&err);
1971+
}
1972+
19111973
static int create_default_files(const char *template_path,
19121974
const char *original_git_dir,
1913-
const char *initial_branch,
19141975
const struct repository_format *fmt,
19151976
int prev_bare_repository,
1916-
int init_shared_repository,
1917-
int quiet)
1977+
int init_shared_repository)
19181978
{
19191979
struct stat st1;
19201980
struct strbuf buf = STRBUF_INIT;
19211981
char *path;
1922-
char junk[2];
19231982
int reinit;
19241983
int filemode;
1925-
struct strbuf err = STRBUF_INIT;
19261984
const char *init_template_dir = NULL;
19271985
const char *work_tree = get_git_work_tree();
19281986

@@ -1942,6 +2000,8 @@ static int create_default_files(const char *template_path,
19422000
reset_shared_repository();
19432001
git_config(git_default_config, NULL);
19442002

2003+
reinit = is_reinit();
2004+
19452005
/*
19462006
* We must make sure command-line options continue to override any
19472007
* values we might have just re-read from the config.
@@ -1985,39 +2045,6 @@ static int create_default_files(const char *template_path,
19852045
adjust_shared_perm(get_git_dir());
19862046
}
19872047

1988-
/*
1989-
* We need to create a "refs" dir in any case so that older
1990-
* versions of git can tell that this is a repository.
1991-
*/
1992-
safe_create_dir(git_path("refs"), 1);
1993-
adjust_shared_perm(git_path("refs"));
1994-
1995-
if (refs_init_db(&err))
1996-
die("failed to set up refs db: %s", err.buf);
1997-
1998-
/*
1999-
* Point the HEAD symref to the initial branch with if HEAD does
2000-
* not yet exist.
2001-
*/
2002-
path = git_path_buf(&buf, "HEAD");
2003-
reinit = (!access(path, R_OK)
2004-
|| readlink(path, junk, sizeof(junk)-1) != -1);
2005-
if (!reinit) {
2006-
char *ref;
2007-
2008-
if (!initial_branch)
2009-
initial_branch = git_default_branch_name(quiet);
2010-
2011-
ref = xstrfmt("refs/heads/%s", initial_branch);
2012-
if (check_refname_format(ref, 0) < 0)
2013-
die(_("invalid initial branch name: '%s'"),
2014-
initial_branch);
2015-
2016-
if (create_symref("HEAD", ref, NULL) < 0)
2017-
exit(1);
2018-
free(ref);
2019-
}
2020-
20212048
initialize_repository_version(fmt->hash_algo, 0);
20222049

20232050
/* Check filemode trustability */
@@ -2177,14 +2204,11 @@ int init_db(const char *git_dir, const char *real_git_dir,
21772204
validate_hash_algorithm(&repo_fmt, hash);
21782205

21792206
reinit = create_default_files(template_dir, original_git_dir,
2180-
initial_branch, &repo_fmt,
2181-
prev_bare_repository,
2182-
init_shared_repository,
2183-
flags & INIT_DB_QUIET);
2184-
if (reinit && initial_branch)
2185-
warning(_("re-init: ignored --initial-branch=%s"),
2186-
initial_branch);
2207+
&repo_fmt, prev_bare_repository,
2208+
init_shared_repository);
21872209

2210+
if (!(flags & INIT_DB_SKIP_REFDB))
2211+
create_reference_database(initial_branch, flags & INIT_DB_QUIET);
21882212
create_object_directory();
21892213

21902214
if (get_shared_repository()) {

setup.h

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

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

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

182184
/*
183185
* NOTE NOTE NOTE!!

0 commit comments

Comments
 (0)