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 <gitster@pobox.com>
Junio C Hamano committed
Aug 22, 2011 at 18:05 UTC
dbc92b072dd7023f8ba1f682a8060022fc72504a
2 files changed
+39
-8
builtin/clone.c
+24
-8
@@ -39,13 +39,23 @@ static const char * const builtin_clone_usage[] = {
39
40
static int option_no_checkout, option_bare, option_mirror;
41
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;
43
static char *option_origin = NULL;
44
static char *option_branch = NULL;
45
static const char *real_git_dir;
46
static char *option_upload_pack = "git-upload-pack";
47
static int option_verbosity;
48
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
+}
59
60
static struct option builtin_clone_options[] = {
61
OPT__VERBOSITY(&option_verbosity),
@@ -71,8 +81,8 @@ static struct option builtin_clone_options[] = {
81
"initialize submodules in the clone"),
82
OPT_STRING(0, "template", &option_template, "template-directory",
83
"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),
86
OPT_STRING('o', "origin", &option_origin, "branch",
87
"use <branch> instead of 'origin' to track upstream"),
88
OPT_STRING('b', "branch", &option_branch, "branch",
@@ -197,7 +207,7 @@ static void strip_trailing_slashes(char *dir)
207
*end = '\0';
208
}
209
200
-static void setup_reference(const char *repo)
210
+static int add_one_reference(struct string_list_item *item, void *cb_data)
211
{
212
const char *ref_git;
213
char *ref_git_copy;
@@ -206,13 +216,13 @@ static void setup_reference(const char *repo)
216
struct transport *transport;
217
const struct ref *extra;
218
209
- ref_git = real_path(option_reference);
219
+ ref_git = real_path(item->string);
220
221
if (is_directory(mkpath("%s/.git/objects", ref_git)))
222
ref_git = mkpath("%s/.git", ref_git);
223
else if (!is_directory(mkpath("%s/objects", ref_git)))
224
die(_("reference repository '%s' is not a local directory."),
215
- option_reference);
225
+ item->string);
226
227
ref_git_copy = xstrdup(ref_git);
228
@@ -227,6 +237,12 @@ static void setup_reference(const char *repo)
237
transport_disconnect(transport);
238
239
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);
246
}
247
248
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)
537
git_config_set(key.buf, repo);
538
strbuf_reset(&key);
539
524
- if (option_reference)
525
- setup_reference(git_dir);
540
+ if (option_reference.nr)
541
+ setup_reference();
542
543
fetch_pattern = value.buf;
544
refspec = parse_fetch_refspec(1, &fetch_pattern);
t/t5601-clone.sh
+15
@@ -207,4 +207,19 @@ test_expect_success 'clone separate gitdir where target already exists' '
207
test_must_fail git clone --separate-git-dir realgitdir src dst
208
'
209
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
+
225
test_done