From: Paolo Bonzini <bonzini@gnu.org>
To: <git@vger.kernel.org>
Subject: [PATCH RFC 8/8] clone: add --push option
Date: Mon, 20 Jul 2009 19:49:55 +0200 [thread overview]
Message-ID: <1248112195-3761-9-git-send-email-bonzini@gnu.org> (raw)
In-Reply-To: <1248112195-3761-1-git-send-email-bonzini@gnu.org>
This patch completes the series by supporting --push within
git clone as well.
The bulk of the patch actually is just moving the options struct
for builtin-clone as late as possible to make it possible to use
OPT_CALLBACK. The actual implementation of --push is essentially
reusing setup_remote_config, and actually simplifies the code.
Signed-off-by: Paolo Bonzini <bonzini@gnu.org>
---
Documentation/git-clone.txt | 13 ++++++-
builtin-clone.c | 90 ++++++++++++++++++++++++++-----------------
t/t5601-clone.sh | 78 +++++++++++++++++++++++++++++++++++++
3 files changed, 145 insertions(+), 36 deletions(-)
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index b14de6c..d5753c4 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -27,6 +27,9 @@ all the remote-tracking branches, and a `git pull` without
arguments will in addition merge the remote master branch into the
current master branch, if any.
+Optionally, `git clone` can also set up the behavior upon `git push`.
+This will be done only if the `--push` option is provided.
+
This default configuration is achieved by creating references to
the remote branch heads under `$GIT_DIR/refs/remotes/origin` and
by initializing `remote.origin.url` and `remote.origin.fetch`
@@ -111,8 +114,16 @@ then the cloned repository will become corrupt.
used, neither remote-tracking branches nor the related
configuration variables are created.
+--push=<strategy>::
+ Set up the clone's behavior upon `git push`. Valid values
+ for `\--push` are `matching`, `mirror, `tracking`, `current`
+ and `nothing`. The meanings are the same as for the
+ `push.default` configuration key. If no strategy is
+ specified, the contents of `push.default` will be used.
+
--mirror::
- Set up a mirror of the remote repository. This implies --bare.
+ Set up a mirror of the remote repository. This is the
+ same as `\--push=mirror --bare`.
--origin <name>::
-o <name>::
diff --git a/builtin-clone.c b/builtin-clone.c
index 68d8a68..b9f2f16 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -40,40 +40,12 @@ static const char * const builtin_clone_usage[] = {
static int option_quiet, option_no_checkout, option_bare, option_mirror;
static int option_local, option_no_hardlinks, option_shared;
+static int option_push = PUSH_DEFAULT_UNKNOWN;
static char *option_template, *option_reference, *option_depth;
static char *option_origin = NULL;
static char *option_upload_pack = "git-upload-pack";
static int option_verbose;
-static struct option builtin_clone_options[] = {
- OPT__QUIET(&option_quiet),
- OPT__VERBOSE(&option_verbose),
- OPT_BOOLEAN('n', "no-checkout", &option_no_checkout,
- "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,
- "don't use local hardlinks, always copy"),
- OPT_BOOLEAN('s', "shared", &option_shared,
- "setup as shared repository"),
- OPT_STRING(0, "template", &option_template, "path",
- "path the template repository"),
- OPT_STRING(0, "reference", &option_reference, "repo",
- "reference repository"),
- OPT_STRING('o', "origin", &option_origin, "branch",
- "use <branch> instead of 'origin' to track upstream"),
- OPT_STRING('u', "upload-pack", &option_upload_pack, "path",
- "path to git-upload-pack on the remote"),
- OPT_STRING(0, "depth", &option_depth, "depth",
- "create a shallow clone of that depth"),
-
- OPT_END()
-};
-
static char *get_repo_path(const char *repo, int *is_bundle)
{
static char *suffix[] = { "/.git", ".git", "" };
@@ -341,6 +313,50 @@ static struct ref *write_remote_refs(const struct ref *refs,
return local_refs;
}
+static int opt_parse_push(const struct option *opt, const char *arg, int not)
+{
+ int *value = opt->value;
+ if (not)
+ *value = PUSH_DEFAULT_NOTHING;
+ else if (!arg)
+ *value = push_default;
+ else
+ return git_parse_push_default("--push", arg, value);
+
+ return 0;
+}
+
+static struct option builtin_clone_options[] = {
+ OPT__QUIET(&option_quiet),
+ OPT__VERBOSE(&option_verbose),
+ OPT_BOOLEAN('n', "no-checkout", &option_no_checkout,
+ "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"),
+ { OPTION_CALLBACK, 0, "push", &option_push, "strategy",
+ "how to setup pushing", PARSE_OPT_OPTARG, opt_parse_push },
+ OPT_BOOLEAN(0, "mirror", &option_mirror,
+ "create a mirror repository (implies --bare and --push=mirror)"),
+ OPT_BOOLEAN('l', "local", &option_local,
+ "to clone from a local repository"),
+ OPT_BOOLEAN(0, "no-hardlinks", &option_no_hardlinks,
+ "don't use local hardlinks, always copy"),
+ OPT_BOOLEAN('s', "shared", &option_shared,
+ "setup as shared repository"),
+ OPT_STRING(0, "template", &option_template, "path",
+ "path the template repository"),
+ OPT_STRING(0, "reference", &option_reference, "repo",
+ "reference repository"),
+ OPT_STRING('o', "origin", &option_origin, "branch",
+ "use <branch> instead of 'origin' to track upstream"),
+ OPT_STRING('u', "upload-pack", &option_upload_pack, "path",
+ "path to git-upload-pack on the remote"),
+ OPT_STRING(0, "depth", &option_depth, "depth",
+ "create a shallow clone of that depth"),
+
+ OPT_END()
+};
+
int cmd_clone(int argc, const char **argv, const char *prefix)
{
int is_bundle = 0;
@@ -358,14 +374,22 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
junk_pid = getpid();
+ git_config_norepo(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, builtin_clone_options,
builtin_clone_usage, 0);
if (argc == 0)
die("You must specify a repository to clone.");
- if (option_mirror)
+ if (option_push == PUSH_DEFAULT_UNKNOWN)
+ option_push = (option_mirror
+ ? PUSH_DEFAULT_MIRROR
+ : PUSH_DEFAULT_NOTHING);
+ if (option_mirror) {
option_bare = 1;
+ if (option_push != PUSH_DEFAULT_MIRROR)
+ die ("--mirror and --push are incompatible");
+ }
if (option_bare) {
if (option_origin)
@@ -454,11 +478,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_mirror || !option_bare) {
struct string_list track = { NULL, 0, 0 };
- setup_remote_config (option_origin, repo,
- option_mirror
- ? PUSH_DEFAULT_MIRROR
- : PUSH_DEFAULT_NOTHING,
- &track);
+ setup_remote_config(option_origin, repo, option_push, &track);
fetch_pattern = track.items[0].util;
refspec = parse_fetch_refspec(1, &fetch_pattern);
string_list_clear(&track, 1);
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 2335d8b..6445dad 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -83,11 +83,89 @@ test_expect_success 'clone --mirror' '
test ! -f mirror/file &&
FETCH="$(cd mirror && git config remote.origin.fetch)" &&
test "+refs/*:refs/*" = "$FETCH" &&
+ PUSH="$(cd mirror && git config remote.origin.push)" &&
+ test "+refs/*:refs/*" = "$PUSH" &&
MIRROR="$(cd mirror && git config --bool remote.origin.mirror)" &&
test "$MIRROR" = true
'
+test_expect_success 'clone --push=mirror' '
+
+ git clone --push=mirror src mirrorx &&
+ test -f mirrorx/.git/HEAD &&
+ test -f mirrorx/file &&
+ FETCH="$(cd mirrorx && git config remote.origin.fetch)" &&
+ test "+refs/*:refs/*" = "$FETCH" &&
+ PUSH="$(cd mirrorx && git config remote.origin.push)" &&
+ test "+refs/*:refs/*" = "$PUSH" &&
+ MIRROR="$(cd mirrorx && git config --bool remote.origin.mirror)" &&
+ test "$MIRROR" = true
+
+'
+
+test_expect_success 'clone --push=current' '
+
+ git clone --push=current src current &&
+ test -f current/.git/HEAD &&
+ test -f current/file &&
+ ! (cd current/.git && git config --bool remote.origin.mirror) &&
+ (cd current/.git && git config --bool remote.origin.pushHeadOnly) &&
+ ! (cd current/.git && git config --bool remote.origin.autosetuppush) &&
+ test "+refs/heads/*:refs/remotes/origin/*" = \
+ "$(cd current && git config remote.origin.fetch)" &&
+ test HEAD = "$(cd current && git config remote.origin.push)"
+
+'
+
+test_expect_success 'clone --push' '
+
+ HOME=$(pwd) &&
+ export HOME &&
+ test_config="$HOME/.gitconfig" &&
+ unset GIT_CONFIG_NOGLOBAL &&
+ echo "[push] default=current" > $test_config
+ git clone --push src default &&
+ test -f default/.git/HEAD &&
+ test -f default/file &&
+ ! (cd default/.git && git config --bool remote.origin.mirror) &&
+ (cd default/.git && git config --bool remote.origin.pushHeadOnly) &&
+ ! (cd default/.git && git config --bool remote.origin.autosetuppush) &&
+ test "+refs/heads/*:refs/remotes/origin/*" = \
+ "$(cd default && git config remote.origin.fetch)" &&
+ test HEAD = "$(cd default && git config remote.origin.push)"
+
+'
+
+test_expect_success 'clone --push=tracking' '
+
+ git clone --push=tracking src tracking &&
+ test -f tracking/.git/HEAD &&
+ test -f tracking/file &&
+ ! (cd tracking && git config --bool remote.origin.mirror) &&
+ (cd tracking && git config --bool remote.origin.pushHeadOnly) &&
+ (cd tracking && git config --bool remote.origin.autosetuppush) &&
+ test "+refs/heads/*:refs/remotes/origin/*" = \
+ "$(cd tracking && git config remote.origin.fetch)" &&
+ test refs/heads/master:refs/heads/master = \
+ "$(cd tracking && git config remote.origin.push)"
+
+'
+
+test_expect_success 'clone --push=matching' '
+
+ git clone --push=matching src matching &&
+ test -f matching/.git/HEAD &&
+ test -f matching/file &&
+ ! (cd matching && git config --bool remote.origin.mirror) &&
+ ! (cd matching && git config --bool remote.origin.pushHeadOnly) &&
+ ! (cd matching && git config --bool remote.origin.autosetuppush) &&
+ test "+refs/heads/*:refs/remotes/origin/*" = \
+ "$(cd matching && git config remote.origin.fetch)" &&
+ test : = "$(cd matching && git config remote.origin.push)"
+
+'
+
test_expect_success 'clone --bare names the local repository <name>.git' '
git clone --bare src &&
--
1.6.2.5
next prev parent reply other threads:[~2009-07-20 17:51 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-07-20 17:49 [PATCH RFC 0/8] introduce 'git remote add --push' and 'git clone --push' Paolo Bonzini
2009-07-20 17:49 ` [PATCH RFC 1/8] reintroduce PUSH_DEFAULT_UNSPECIFIED Paolo Bonzini
2009-07-20 17:49 ` [PATCH RFC 2/8] push: add push.default = mirror Paolo Bonzini
2009-07-20 20:46 ` Junio C Hamano
2009-07-20 21:14 ` Paolo Bonzini
2009-07-20 21:34 ` Junio C Hamano
2009-07-20 21:36 ` Paolo Bonzini
2009-07-20 17:49 ` [PATCH RFC 3/8] git remote add: refactor configuration Paolo Bonzini
2009-07-20 17:49 ` [PATCH RFC 4/8] git remote add: add --push option Paolo Bonzini
2009-07-20 17:49 ` [PATCH RFC 5/8] clone: refactoring of building the fetch refspec Paolo Bonzini
2009-07-20 17:49 ` [PATCH RFC 6/8] clone: use setup_remote_config Paolo Bonzini
2009-07-20 17:49 ` [PATCH RFC 7/8] config: add git_config_norepo Paolo Bonzini
2009-07-20 17:49 ` Paolo Bonzini [this message]
2009-07-20 22:15 ` [PATCH RFC 0/8] introduce 'git remote add --push' and 'git clone --push' Junio C Hamano
2009-07-21 10:33 ` Paolo Bonzini
2009-07-21 21:00 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1248112195-3761-9-git-send-email-bonzini@gnu.org \
--to=bonzini@gnu.org \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).