Skip to content

Commit

Permalink
clone: allow more than one --reference
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Junio C Hamano committed Aug 23, 2011
1 parent f696543 commit dbc92b0
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
32 changes: 24 additions & 8 deletions builtin/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,23 @@ static const char * const builtin_clone_usage[] = {

static int option_no_checkout, option_bare, option_mirror;
static int option_local, option_no_hardlinks, option_shared, option_recursive;
static char *option_template, *option_reference, *option_depth;
static char *option_template, *option_depth;
static char *option_origin = NULL;
static char *option_branch = NULL;
static const char *real_git_dir;
static char *option_upload_pack = "git-upload-pack";
static int option_verbosity;
static int option_progress;
static struct string_list option_reference;

static int opt_parse_reference(const struct option *opt, const char *arg, int unset)
{
struct string_list *option_reference = opt->value;
if (!arg)
return -1;
string_list_append(option_reference, arg);
return 0;
}

static struct option builtin_clone_options[] = {
OPT__VERBOSITY(&option_verbosity),
Expand All @@ -71,8 +81,8 @@ static struct option builtin_clone_options[] = {
"initialize submodules in the clone"),
OPT_STRING(0, "template", &option_template, "template-directory",
"directory from which templates will be used"),
OPT_STRING(0, "reference", &option_reference, "repo",
"reference repository"),
OPT_CALLBACK(0 , "reference", &option_reference, "repo",
"reference repository", &opt_parse_reference),
OPT_STRING('o', "origin", &option_origin, "branch",
"use <branch> instead of 'origin' to track upstream"),
OPT_STRING('b', "branch", &option_branch, "branch",
Expand Down Expand Up @@ -197,7 +207,7 @@ static void strip_trailing_slashes(char *dir)
*end = '\0';
}

static void setup_reference(const char *repo)
static int add_one_reference(struct string_list_item *item, void *cb_data)
{
const char *ref_git;
char *ref_git_copy;
Expand All @@ -206,13 +216,13 @@ static void setup_reference(const char *repo)
struct transport *transport;
const struct ref *extra;

ref_git = real_path(option_reference);
ref_git = real_path(item->string);

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

ref_git_copy = xstrdup(ref_git);

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

free(ref_git_copy);
return 0;
}

static void setup_reference(void)
{
for_each_string_list(&option_reference, add_one_reference, NULL);
}

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

if (option_reference)
setup_reference(git_dir);
if (option_reference.nr)
setup_reference();

fetch_pattern = value.buf;
refspec = parse_fetch_refspec(1, &fetch_pattern);
Expand Down
15 changes: 15 additions & 0 deletions t/t5601-clone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,19 @@ test_expect_success 'clone separate gitdir where target already exists' '
test_must_fail git clone --separate-git-dir realgitdir src dst
'

test_expect_failure 'clone --reference from original' '
git clone --shared --bare src src-1 &&
git clone --bare src src-2 &&
git clone --reference=src-2 --bare src-1 target-8 &&
grep /src-2/ target-8/objects/info/alternates
'

test_expect_success 'clone with more than one --reference' '
git clone --bare src src-3 &&
git clone --bare src src-4 &&
git clone --reference=src-3 --reference=src-4 src target-9 &&
grep /src-3/ target-9/.git/objects/info/alternates &&
grep /src-4/ target-9/.git/objects/info/alternates
'

test_done

0 comments on commit dbc92b0

Please sign in to comment.