diff options
-rw-r--r-- | Documentation/git-clone.txt | 5 | ||||
-rw-r--r-- | builtin-clone.c | 24 | ||||
-rw-r--r-- | builtin-remote.c | 2 | ||||
-rwxr-xr-x | t/t5601-clone.sh | 12 |
4 files changed, 37 insertions, 6 deletions
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 26fd1b111..0e14e732f 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [verse] 'git clone' [--template=<template_directory>] - [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] + [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror] [-o <name>] [-u <upload-pack>] [--reference <repository>] [--depth <depth>] [--] <repository> [<directory>] @@ -106,6 +106,9 @@ then the cloned repository will become corrupt. used, neither remote-tracking branches nor the related configuration variables are created. +--mirror:: + Set up a mirror of the remote repository. This implies --bare. + --origin <name>:: -o <name>:: Instead of using the remote name 'origin' to keep track diff --git a/builtin-clone.c b/builtin-clone.c index e086a40b4..ecdcefa2a 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -33,7 +33,7 @@ static const char * const builtin_clone_usage[] = { NULL }; -static int option_quiet, option_no_checkout, option_bare; +static int option_quiet, option_no_checkout, option_bare, option_mirror; static int option_local, option_no_hardlinks, option_shared; static char *option_template, *option_reference, *option_depth; static char *option_origin = NULL; @@ -45,6 +45,8 @@ static struct option builtin_clone_options[] = { "don't create a checkout"), OPT_BOOLEAN(0, "bare", &option_bare, "create a bare repository"), OPT_BOOLEAN(0, "naked", &option_bare, "create a bare repository"), + OPT_BOOLEAN(0, "mirror", &option_mirror, + "create a mirror repository (implies bare)"), OPT_BOOLEAN('l', "local", &option_local, "to clone from a local repository"), OPT_BOOLEAN(0, "no-hardlinks", &option_no_hardlinks, @@ -345,6 +347,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) char branch_top[256], key[256], value[256]; struct strbuf reflog_msg; struct transport *transport = NULL; + char *src_ref_prefix = "refs/heads/"; struct refspec refspec; @@ -359,6 +362,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (option_no_hardlinks) use_local_hardlinks = 0; + if (option_mirror) + option_bare = 1; + if (option_bare) { if (option_origin) die("--bare and --origin %s options are incompatible.", @@ -440,26 +446,36 @@ int cmd_clone(int argc, const char **argv, const char *prefix) git_config(git_default_config, NULL); if (option_bare) { - strcpy(branch_top, "refs/heads/"); + if (option_mirror) + src_ref_prefix = "refs/"; + strcpy(branch_top, src_ref_prefix); git_config_set("core.bare", "true"); } else { snprintf(branch_top, sizeof(branch_top), "refs/remotes/%s/", option_origin); + } + if (option_mirror || !option_bare) { /* Configure the remote */ + if (option_mirror) { + snprintf(key, sizeof(key), + "remote.%s.mirror", option_origin); + git_config_set(key, "true"); + } + snprintf(key, sizeof(key), "remote.%s.url", option_origin); git_config_set(key, repo); snprintf(key, sizeof(key), "remote.%s.fetch", option_origin); snprintf(value, sizeof(value), - "+refs/heads/*:%s*", branch_top); + "+%s*:%s*", src_ref_prefix, branch_top); git_config_set_multivar(key, value, "^$", 0); } refspec.force = 0; refspec.pattern = 1; - refspec.src = "refs/heads/"; + refspec.src = src_ref_prefix; refspec.dst = branch_top; if (path && !is_bundle) diff --git a/builtin-remote.c b/builtin-remote.c index 54d1c3e3d..01945a865 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -115,7 +115,7 @@ static int add(int argc, const char **argv) if (mirror) { strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.mirror", name); - if (git_config_set(buf.buf, "yes")) + if (git_config_set(buf.buf, "true")) return 1; } diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index d785b3df7..a5334570a 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -70,4 +70,16 @@ test_expect_success 'clone creates intermediate directories for bare repo' ' ' +test_expect_success 'clone --mirror' ' + + git clone --mirror src mirror && + test -f mirror/HEAD && + test ! -f mirror/file && + FETCH="$(cd mirror && git config remote.origin.fetch)" && + test "+refs/*:refs/*" = "$FETCH" && + MIRROR="$(cd mirror && git config --bool remote.origin.mirror)" && + test "$MIRROR" = true + +' + test_done |