Skip to content

Commit dbc92b0

Browse files
committed
clone: allow more than one --reference
Also add a test to expose a long-standing bug that is triggered when cloning with --reference option from a local repository that has its own alternates. The alternate object stores specified on the command line are lost, and only alternates copied from the source repository remain. The bug will be fixed in the next patch. Signed-off-by: Junio C Hamano <[email protected]>
1 parent f696543 commit dbc92b0

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

builtin/clone.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,23 @@ static const char * const builtin_clone_usage[] = {
3939

4040
static int option_no_checkout, option_bare, option_mirror;
4141
static int option_local, option_no_hardlinks, option_shared, option_recursive;
42-
static char *option_template, *option_reference, *option_depth;
42+
static char *option_template, *option_depth;
4343
static char *option_origin = NULL;
4444
static char *option_branch = NULL;
4545
static const char *real_git_dir;
4646
static char *option_upload_pack = "git-upload-pack";
4747
static int option_verbosity;
4848
static int option_progress;
49+
static struct string_list option_reference;
50+
51+
static int opt_parse_reference(const struct option *opt, const char *arg, int unset)
52+
{
53+
struct string_list *option_reference = opt->value;
54+
if (!arg)
55+
return -1;
56+
string_list_append(option_reference, arg);
57+
return 0;
58+
}
4959

5060
static struct option builtin_clone_options[] = {
5161
OPT__VERBOSITY(&option_verbosity),
@@ -71,8 +81,8 @@ static struct option builtin_clone_options[] = {
7181
"initialize submodules in the clone"),
7282
OPT_STRING(0, "template", &option_template, "template-directory",
7383
"directory from which templates will be used"),
74-
OPT_STRING(0, "reference", &option_reference, "repo",
75-
"reference repository"),
84+
OPT_CALLBACK(0 , "reference", &option_reference, "repo",
85+
"reference repository", &opt_parse_reference),
7686
OPT_STRING('o', "origin", &option_origin, "branch",
7787
"use <branch> instead of 'origin' to track upstream"),
7888
OPT_STRING('b', "branch", &option_branch, "branch",
@@ -197,7 +207,7 @@ static void strip_trailing_slashes(char *dir)
197207
*end = '\0';
198208
}
199209

200-
static void setup_reference(const char *repo)
210+
static int add_one_reference(struct string_list_item *item, void *cb_data)
201211
{
202212
const char *ref_git;
203213
char *ref_git_copy;
@@ -206,13 +216,13 @@ static void setup_reference(const char *repo)
206216
struct transport *transport;
207217
const struct ref *extra;
208218

209-
ref_git = real_path(option_reference);
219+
ref_git = real_path(item->string);
210220

211221
if (is_directory(mkpath("%s/.git/objects", ref_git)))
212222
ref_git = mkpath("%s/.git", ref_git);
213223
else if (!is_directory(mkpath("%s/objects", ref_git)))
214224
die(_("reference repository '%s' is not a local directory."),
215-
option_reference);
225+
item->string);
216226

217227
ref_git_copy = xstrdup(ref_git);
218228

@@ -227,6 +237,12 @@ static void setup_reference(const char *repo)
227237
transport_disconnect(transport);
228238

229239
free(ref_git_copy);
240+
return 0;
241+
}
242+
243+
static void setup_reference(void)
244+
{
245+
for_each_string_list(&option_reference, add_one_reference, NULL);
230246
}
231247

232248
static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest)
@@ -521,8 +537,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
521537
git_config_set(key.buf, repo);
522538
strbuf_reset(&key);
523539

524-
if (option_reference)
525-
setup_reference(git_dir);
540+
if (option_reference.nr)
541+
setup_reference();
526542

527543
fetch_pattern = value.buf;
528544
refspec = parse_fetch_refspec(1, &fetch_pattern);

t/t5601-clone.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,19 @@ test_expect_success 'clone separate gitdir where target already exists' '
207207
test_must_fail git clone --separate-git-dir realgitdir src dst
208208
'
209209

210+
test_expect_failure 'clone --reference from original' '
211+
git clone --shared --bare src src-1 &&
212+
git clone --bare src src-2 &&
213+
git clone --reference=src-2 --bare src-1 target-8 &&
214+
grep /src-2/ target-8/objects/info/alternates
215+
'
216+
217+
test_expect_success 'clone with more than one --reference' '
218+
git clone --bare src src-3 &&
219+
git clone --bare src src-4 &&
220+
git clone --reference=src-3 --reference=src-4 src target-9 &&
221+
grep /src-3/ target-9/.git/objects/info/alternates &&
222+
grep /src-4/ target-9/.git/objects/info/alternates
223+
'
224+
210225
test_done

0 commit comments

Comments
 (0)