* [PATCH] Teach the --all option to 'git fetch'
@ 2009-11-08 8:34 Björn Gustavsson
2009-11-08 9:33 ` Junio C Hamano
0 siblings, 1 reply; 3+ messages in thread
From: Björn Gustavsson @ 2009-11-08 8:34 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
'git remote' is meant for managing remotes and 'git fetch' is meant
for actually fetching data from remote repositories. Therefore, it is
not logical that you must use 'git remote update' to fetch from
several repositories at once. (Junio called 'git remote update'
a "half-baked UI experiment that failed" in topic 130891 in Gmane.)
Add the --all option to 'git fetch', to tell it to attempt to fetch
from all remotes. (The configuration variable skipDefaultUpdate for
the remote will NOT be consulted.)
Other options except -v and -q are silently ignored.
Signed-off-by: Björn Gustavsson <bgustavsson@gmail.com>
---
See
http://thread.gmane.org/gmane.comp.version-control.git/130819/focus=130891
for a previous discussion.
My implementation is deliberately minimal:
* There is no way to configure that certain remotes should be skipped by
the --all option. I have never used skipDefaultUpdate with 'git remote
update'. If there is a real need for that feature, it can easily be added.
(But it should not use the existing skipDefaultUpdate configuration
variable, as the name does not make sense for 'git fetch --all'.)
* All options except -q and -v are silently ignored. It might be useful
to support some more options if there is a real need for them.
(Perhaps --keep or --no-tags?)
Documentation/git-fetch.txt | 5 +++
builtin-fetch.c | 80 +++++++++++++++++++++++++++++++++++++-----
t/t5514-fetch-all.sh | 76 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 151 insertions(+), 10 deletions(-)
create mode 100755 t/t5514-fetch-all.sh
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index f2483d6..9172454 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -10,6 +10,8 @@ SYNOPSIS
--------
'git fetch' <options> <repository> <refspec>...
+'git fetch' --all <options>
+
DESCRIPTION
-----------
@@ -31,6 +33,9 @@ branches you are not interested in, you will not get them.
OPTIONS
-------
+--all::
+ Fetch all remotes.
+
include::fetch-options.txt[]
include::pull-fetch-param.txt[]
diff --git a/builtin-fetch.c b/builtin-fetch.c
index a35a6f8..c1c3c46 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -14,6 +14,7 @@
static const char * const builtin_fetch_usage[] = {
"git fetch [options] [<repository> <refspec>...]",
+ "git fetch --all [options]",
NULL
};
@@ -23,7 +24,7 @@ enum {
TAGS_SET = 2
};
-static int append, force, keep, update_head_ok, verbosity;
+static int all, append, force, keep, update_head_ok, verbosity;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
@@ -32,6 +33,8 @@ static struct transport *transport;
static struct option builtin_fetch_options[] = {
OPT__VERBOSITY(&verbosity),
+ OPT_BOOLEAN(0, "all", &all,
+ "fetch from all remotes"),
OPT_BOOLEAN('a', "append", &append,
"append to .git/FETCH_HEAD instead of overwriting"),
OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
@@ -680,7 +683,53 @@ static void set_option(const char *name, const char *value)
name, transport->url);
}
-int cmd_fetch(int argc, const char **argv, const char *prefix)
+static int get_one_remote_for_fetch(struct remote *remote, void *priv)
+{
+ struct string_list *list = priv;
+ string_list_append(remote->name, list);
+ return 0;
+}
+
+static int fetch_all(int argc)
+{
+ int i, result = 0;
+ struct string_list list = { NULL, 0, 0, 0 };
+ const char *argv[] = { "fetch", NULL, NULL, NULL, NULL };
+
+ if (argc == 1)
+ die("fetch --all does not take a repository argument");
+ else if (argc > 1)
+ die("fetch --all does not make sense with refspecs");
+
+ argc = 1;
+ if (verbosity >= 2)
+ argv[argc++] = "-v";
+ if (verbosity >= 1)
+ argv[argc++] = "-v";
+ else if (verbosity < 0)
+ argv[argc++] = "-q";
+
+ result = for_each_remote(get_one_remote_for_fetch, &list);
+
+ for (i = 0; i < list.nr; i++) {
+ const char *name = list.items[i].string;
+ argv[argc] = name;
+ if (verbosity >= 0)
+ printf("Fetching %s\n", name);
+ if (run_command_v_opt(argv, RUN_GIT_CMD)) {
+ error("Could not fetch %s", name);
+ result = 1;
+ }
+ }
+
+ /* all names were strdup()ed or strndup()ed */
+ list.strdup_strings = 1;
+ string_list_clear(&list, 0);
+
+ return result;
+}
+
+static int fetch_one(int argc, const char **argv)
{
struct remote *remote;
int i;
@@ -688,14 +737,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
int ref_nr = 0;
int exit_code;
- /* Record the command line for the reflog */
- strbuf_addstr(&default_rla, "fetch");
- for (i = 1; i < argc; i++)
- strbuf_addf(&default_rla, " %s", argv[i]);
-
- argc = parse_options(argc, argv, prefix,
- builtin_fetch_options, builtin_fetch_usage, 0);
-
if (argc == 0)
remote = remote_get(NULL);
else
@@ -746,3 +787,22 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
transport = NULL;
return exit_code;
}
+
+int cmd_fetch(int argc, const char **argv, const char *prefix)
+{
+ int i;
+
+ /* Record the command line for the reflog */
+ strbuf_addstr(&default_rla, "fetch");
+ for (i = 1; i < argc; i++)
+ strbuf_addf(&default_rla, " %s", argv[i]);
+
+ argc = parse_options(argc, argv, prefix,
+ builtin_fetch_options, builtin_fetch_usage, 0);
+
+ if (all) {
+ return fetch_all(argc);
+ } else {
+ return fetch_one(argc, argv);
+ }
+}
diff --git a/t/t5514-fetch-all.sh b/t/t5514-fetch-all.sh
new file mode 100755
index 0000000..25244bf
--- /dev/null
+++ b/t/t5514-fetch-all.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+test_description='fetch --all works correctly'
+
+. ./test-lib.sh
+
+setup_repository () {
+ mkdir "$1" && (
+ cd "$1" &&
+ git init &&
+ >file &&
+ git add file &&
+ test_tick &&
+ git commit -m "Initial" &&
+ git checkout -b side &&
+ >elif &&
+ git add elif &&
+ test_tick &&
+ git commit -m "Second" &&
+ git checkout master
+ )
+}
+
+test_expect_success setup '
+ setup_repository one &&
+ setup_repository two &&
+ (
+ cd two && git branch another
+ ) &&
+ git clone --mirror two three
+ git clone one test
+'
+
+cat > test/expect << EOF
+ one/master
+ one/side
+ origin/HEAD -> origin/master
+ origin/master
+ origin/side
+ three/another
+ three/master
+ three/side
+ two/another
+ two/master
+ two/side
+EOF
+
+test_expect_success 'git fetch --all' '
+ (cd test &&
+ git remote add one ../one &&
+ git remote add two ../two &&
+ git remote add three ../three &&
+ git fetch --all &&
+ git branch -r > output &&
+ test_cmp expect output)
+'
+
+test_expect_success 'git fetch --all should continue if a remote has errors' '
+ (git clone one test2 &&
+ cd test2 &&
+ git remote add bad ../non-existing &&
+ git remote add one ../one &&
+ git remote add two ../two &&
+ git remote add three ../three &&
+ test_must_fail git fetch --all &&
+ git branch -r > output &&
+ test_cmp ../test/expect output)
+'
+
+test_expect_success 'git fetch --all does not allow non-option arguments' '
+ (cd test &&
+ test_must_fail git fetch --all origin &&
+ test_must_fail git fetch --all origin master)
+'
+
+test_done
--
1.6.5.1.69.g36942
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] Teach the --all option to 'git fetch'
2009-11-08 8:34 [PATCH] Teach the --all option to 'git fetch' Björn Gustavsson
@ 2009-11-08 9:33 ` Junio C Hamano
2009-11-08 15:18 ` Björn Gustavsson
0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2009-11-08 9:33 UTC (permalink / raw)
To: Björn Gustavsson; +Cc: git
Björn Gustavsson <bgustavsson@gmail.com> writes:
> 'git remote' is meant for managing remotes and 'git fetch' is meant
> for actually fetching data from remote repositories. Therefore, it is
> not logical that you must use 'git remote update' to fetch from
> several repositories at once. (Junio called 'git remote update'
> a "half-baked UI experiment that failed" in topic 130891 in Gmane.)
Please drop the "because I said so" part, as I made myself clear in the
message I was speaking as mere one-of-participants to the project, not as
the maintainer.
> +static int get_one_remote_for_fetch(struct remote *remote, void *priv)
> +{
> + struct string_list *list = priv;
> + string_list_append(remote->name, list);
> + return 0;
> +}
> +
> +static int fetch_all(int argc)
> +{
> +...
> + for (i = 0; i < list.nr; i++) {
> + const char *name = list.items[i].string;
> + argv[argc] = name;
> + if (verbosity >= 0)
> + printf("Fetching %s\n", name);
> + if (run_command_v_opt(argv, RUN_GIT_CMD)) {
> + error("Could not fetch %s", name);
> + result = 1;
> + }
> + }
> +...
> +}
> +
> ...
> +int cmd_fetch(int argc, const char **argv, const char *prefix)
> +{
> + int i;
> +
> + /* Record the command line for the reflog */
> + strbuf_addstr(&default_rla, "fetch");
> + for (i = 1; i < argc; i++)
> + strbuf_addf(&default_rla, " %s", argv[i]);
> +
> + argc = parse_options(argc, argv, prefix,
> + builtin_fetch_options, builtin_fetch_usage, 0);
> +
> + if (all) {
> + return fetch_all(argc);
> + } else {
> + return fetch_one(argc, argv);
> + }
> +}
Very nice. I like the simplicity of this.
Hopefully after the parse_options() we can inspect the "repo" argument to
see if it names remote groups and transplant the support for that from
"remote update" codepath into this, right?
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Teach the --all option to 'git fetch'
2009-11-08 9:33 ` Junio C Hamano
@ 2009-11-08 15:18 ` Björn Gustavsson
0 siblings, 0 replies; 3+ messages in thread
From: Björn Gustavsson @ 2009-11-08 15:18 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
2009/11/8 Junio C Hamano <gitster@pobox.com>:
> Björn Gustavsson <bgustavsson@gmail.com> writes:
>
> Please drop the "because I said so" part, as I made myself clear in the
> message I was speaking as mere one-of-participants to the project, not as
> the maintainer.
OK.
> Very nice. I like the simplicity of this.
Thanks!
> Hopefully after the parse_options() we can inspect the "repo" argument to
> see if it names remote groups and transplant the support for that from
> "remote update" codepath into this, right?
Yes, it can be done, but it will lose some of its simplicity. I'll send a new
patch series that do that soon.
/Björn
--
Björn Gustavsson, Erlang/OTP, Ericsson AB
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2009-11-08 15:18 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-08 8:34 [PATCH] Teach the --all option to 'git fetch' Björn Gustavsson
2009-11-08 9:33 ` Junio C Hamano
2009-11-08 15:18 ` Björn Gustavsson
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).