* [PATCH 2/5] Teach the --multiple option to 'git fetch'
From: Björn Gustavsson @ 2009-11-09 20:10 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
Add the --multiple option to specify that all arguments are either
groups or remotes. The primary reason for adding this option is
to allow us to re-implement 'git remote update' using fetch.
It would have been nice if this option was not needed, but since
the colon in a refspec is optional, it is in general not possible
to know whether a single, colon-less argument is a remote or a
refspec.
Signed-off-by: Björn Gustavsson <bgustavsson@gmail.com>
---
Documentation/fetch-options.txt | 6 +++++
Documentation/git-fetch.txt | 2 +
builtin-fetch.c | 11 ++++++++-
t/t5514-fetch-multiple.sh | 44 +++++++++++++++++++++++++++++++++++++++
4 files changed, 62 insertions(+), 1 deletions(-)
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 93d73c3..8b0cf58 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -24,6 +24,12 @@
--keep::
Keep downloaded pack.
+ifndef::git-pull[]
+--multiple::
+ Allow several <repository> and <group> arguments to be
+ specified. No <refspec>s may be specified.
+endif::git-pull[]
+
ifdef::git-pull[]
--no-tags::
endif::git-pull[]
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index 3616466..9b9e568 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -12,6 +12,8 @@ SYNOPSIS
'git fetch' <options> <group>
+'git fetch' --multiple <options> [<repository> | <group>]...
+
'git fetch' --all <options>
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 2bf51cc..a5a70a0 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -15,6 +15,7 @@
static const char * const builtin_fetch_usage[] = {
"git fetch [options] [<repository> <refspec>...]",
"git fetch [options] <group>",
+ "git fetch --multiple [options] [<repository> | <group>]...",
"git fetch --all [options]",
NULL
};
@@ -25,7 +26,7 @@ enum {
TAGS_SET = 2
};
-static int all, append, force, keep, update_head_ok, verbosity;
+static int all, append, force, keep, multiple, update_head_ok, verbosity;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
@@ -42,6 +43,8 @@ static struct option builtin_fetch_options[] = {
"path to upload pack on remote end"),
OPT_BOOLEAN('f', "force", &force,
"force overwrite of local branch"),
+ OPT_BOOLEAN('m', "multiple", &multiple,
+ "fetch from multiple remotes"),
OPT_SET_INT('t', "tags", &tags,
"fetch all tags and associated objects", TAGS_SET),
OPT_SET_INT('n', NULL, &tags,
@@ -839,6 +842,12 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
/* No arguments -- use default remote */
remote = remote_get(NULL);
result = fetch_one(remote, argc, argv);
+ } else if (multiple) {
+ /* All arguments are assumed to be remotes or groups */
+ for (i = 0; i < argc; i++)
+ if (!add_remote_or_group(argv[i], &list))
+ die("No such remote or remote group: %s", argv[i]);
+ result = fetch_multiple(&list);
} else {
/* Single remote or group */
(void) add_remote_or_group(argv[0], &list);
diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh
index 25244bf..69c64ab 100755
--- a/t/t5514-fetch-multiple.sh
+++ b/t/t5514-fetch-multiple.sh
@@ -73,4 +73,48 @@ test_expect_success 'git fetch --all does not allow non-option arguments' '
test_must_fail git fetch --all origin master)
'
+cat > expect << EOF
+ origin/HEAD -> origin/master
+ origin/master
+ origin/side
+ three/another
+ three/master
+ three/side
+EOF
+
+test_expect_success 'git fetch --multiple (but only one remote)' '
+ (git clone one test3 &&
+ cd test3 &&
+ git remote add three ../three &&
+ git fetch --multiple three &&
+ git branch -r > output &&
+ test_cmp ../expect output)
+'
+
+cat > expect << EOF
+ one/master
+ one/side
+ origin/HEAD -> origin/master
+ origin/master
+ origin/side
+ two/another
+ two/master
+ two/side
+EOF
+
+test_expect_success 'git fetch --multiple (two remotes)' '
+ (git clone one test4 &&
+ cd test4 &&
+ git remote add one ../one &&
+ git remote add two ../two &&
+ git fetch --multiple one two &&
+ git branch -r > output &&
+ test_cmp ../expect output)
+'
+
+test_expect_success 'git fetch --multiple (bad remote names)' '
+ (cd test4 &&
+ test_must_fail git fetch --multiple four)
+'
+
test_done
--
1.6.5.1.69.g36942
^ permalink raw reply related
* [PATCH 3/5] Add the configuration option skipFetchAll
From: Björn Gustavsson @ 2009-11-09 20:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
Implement the configuration skipFetchAll option to allow
certain remotes to be skipped when doing 'git fetch --all' and
'git remote update'. The existing skipDefaultUpdate variable
is still honored (by 'git fetch --all' and 'git remote update').
(If both are set in the configuration file with different values,
the value of the last occurrence will be used.)
Signed-off-by: Björn Gustavsson <bgustavsson@gmail.com>
---
Documentation/config.txt | 8 +++++++-
builtin-fetch.c | 3 ++-
remote.c | 3 ++-
t/t5514-fetch-multiple.sh | 40 +++++++++++++++++++++++++++++++++++++---
4 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index d1e2120..348b367 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1394,7 +1394,13 @@ remote.<name>.mirror::
remote.<name>.skipDefaultUpdate::
If true, this remote will be skipped by default when updating
- using the update subcommand of linkgit:git-remote[1].
+ using linkgit:git-fetch[1] or the `update` subcommand of
+ linkgit:git-remote[1].
+
+remote.<name>.skipFetchAll::
+ If true, this remote will be skipped by default when updating
+ using linkgit:git-fetch[1] or the `update` subcommand of
+ linkgit:git-remote[1].
remote.<name>.receivepack::
The default program to execute on the remote side when pushing. See
diff --git a/builtin-fetch.c b/builtin-fetch.c
index a5a70a0..945dfd8 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -690,7 +690,8 @@ static void set_option(const char *name, const char *value)
static int get_one_remote_for_fetch(struct remote *remote, void *priv)
{
struct string_list *list = priv;
- string_list_append(remote->name, list);
+ if (!remote->skip_default_update)
+ string_list_append(remote->name, list);
return 0;
}
diff --git a/remote.c b/remote.c
index 73d33f2..beaf9fb 100644
--- a/remote.c
+++ b/remote.c
@@ -396,7 +396,8 @@ static int handle_config(const char *key, const char *value, void *cb)
remote->mirror = git_config_bool(key, value);
else if (!strcmp(subkey, ".skipdefaultupdate"))
remote->skip_default_update = git_config_bool(key, value);
-
+ else if (!strcmp(subkey, ".skipfetchall"))
+ remote->skip_default_update = git_config_bool(key, value);
else if (!strcmp(subkey, ".url")) {
const char *v;
if (git_config_string(&v, key, value))
diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh
index 69c64ab..b737332 100755
--- a/t/t5514-fetch-multiple.sh
+++ b/t/t5514-fetch-multiple.sh
@@ -94,9 +94,6 @@ test_expect_success 'git fetch --multiple (but only one remote)' '
cat > expect << EOF
one/master
one/side
- origin/HEAD -> origin/master
- origin/master
- origin/side
two/another
two/master
two/side
@@ -105,6 +102,7 @@ EOF
test_expect_success 'git fetch --multiple (two remotes)' '
(git clone one test4 &&
cd test4 &&
+ git remote rm origin &&
git remote add one ../one &&
git remote add two ../two &&
git fetch --multiple one two &&
@@ -117,4 +115,40 @@ test_expect_success 'git fetch --multiple (bad remote names)' '
test_must_fail git fetch --multiple four)
'
+
+test_expect_success 'git fetch --all (skipFetchAll)' '
+ (cd test4 &&
+ for b in $(git branch -r)
+ do
+ git branch -r -d $b || break
+ done &&
+ git remote add three ../three &&
+ git config remote.three.skipFetchAll true &&
+ git fetch --all &&
+ git branch -r > output &&
+ test_cmp ../expect output)
+'
+
+cat > expect << EOF
+ one/master
+ one/side
+ three/another
+ three/master
+ three/side
+ two/another
+ two/master
+ two/side
+EOF
+
+test_expect_success 'git fetch --multiple (ignoring skipFetchAll)' '
+ (cd test4 &&
+ for b in $(git branch -r)
+ do
+ git branch -r -d $b || break
+ done &&
+ git fetch --multiple one two three &&
+ git branch -r > output &&
+ test_cmp ../expect output)
+'
+
test_done
--
1.6.5.1.69.g36942
^ permalink raw reply related
* [PATCH 4/5] Add missing test for 'git remote update --prune'
From: Björn Gustavsson @ 2009-11-09 20:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
Signed-off-by: Björn Gustavsson <bgustavsson@gmail.com>
---
t/t5505-remote.sh | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 852ccb5..e931ce6 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -365,6 +365,17 @@ test_expect_success 'update with arguments' '
'
+test_expect_success 'update --prune' '
+
+ (cd one &&
+ git branch -m side2 side3) &&
+ (cd test &&
+ git remote update --prune &&
+ (cd ../one && git branch -m side3 side2)
+ git rev-parse refs/remotes/origin/side3 &&
+ test_must_fail git rev-parse refs/remotes/origin/side2)
+'
+
cat > one/expect << EOF
apis/master
apis/side
--
1.6.5.1.69.g36942
^ permalink raw reply related
* [PATCH 5/5] Re-implement 'git remote update' using 'git fetch'
From: Björn Gustavsson @ 2009-11-09 20:12 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In order not to duplicate functionality, re-implement 'git remote
update' in terms of 'git fetch'.
There is currently one backward incompatibility: the --prune
option is silently ignored.
Signed-off-by: Björn Gustavsson <bgustavsson@gmail.com>
---
builtin-remote.c | 86 ++++++++++++++++-------------------------------------
t/t5505-remote.sh | 2 +-
2 files changed, 27 insertions(+), 61 deletions(-)
diff --git a/builtin-remote.c b/builtin-remote.c
index 0777dd7..fd7e0b2 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -1189,88 +1189,54 @@ static int prune_remote(const char *remote, int dry_run)
return result;
}
-static int get_one_remote_for_update(struct remote *remote, void *priv)
+static int get_remote_default(const char *key, const char *value, void *priv)
{
- struct string_list *list = priv;
- if (!remote->skip_default_update)
- string_list_append(remote->name, list);
- return 0;
-}
-
-static struct remote_group {
- const char *name;
- struct string_list *list;
-} remote_group;
-
-static int get_remote_group(const char *key, const char *value, void *num_hits)
-{
- if (!prefixcmp(key, "remotes.") &&
- !strcmp(key + 8, remote_group.name)) {
- /* split list by white space */
- int space = strcspn(value, " \t\n");
- while (*value) {
- if (space > 1) {
- string_list_append(xstrndup(value, space),
- remote_group.list);
- ++*((int *)num_hits);
- }
- value += space + (value[space] != '\0');
- space = strcspn(value, " \t\n");
- }
+ if (strcmp(key, "remotes.default") == 0) {
+ int *found = priv;
+ *found = 1;
}
-
return 0;
}
static int update(int argc, const char **argv)
{
- int i, result = 0, prune = 0;
- struct string_list list = { NULL, 0, 0, 0 };
- static const char *default_argv[] = { NULL, "default", NULL };
+ int i, prune = 0;
struct option options[] = {
OPT_GROUP("update specific options"),
OPT_BOOLEAN('p', "prune", &prune,
"prune remotes after fetching"),
OPT_END()
};
+ const char **fetch_argv;
+ int fetch_argc = 0;
+ int default_defined = 0;
+
+ fetch_argv = xmalloc(sizeof(char *) * (argc+4));
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
PARSE_OPT_KEEP_ARGV0);
- if (argc < 2) {
- argc = 2;
- argv = default_argv;
- }
- remote_group.list = &list;
- for (i = 1; i < argc; i++) {
- int groups_found = 0;
- remote_group.name = argv[i];
- result = git_config(get_remote_group, &groups_found);
- if (!groups_found && (i != 1 || strcmp(argv[1], "default"))) {
- struct remote *remote;
- if (!remote_is_configured(argv[i]))
- die("No such remote or remote group: %s",
- argv[i]);
- remote = remote_get(argv[i]);
- string_list_append(remote->name, remote_group.list);
- }
- }
+ fetch_argv[fetch_argc++] = "fetch";
- if (!result && !list.nr && argc == 2 && !strcmp(argv[1], "default"))
- result = for_each_remote(get_one_remote_for_update, &list);
+ if (verbose)
+ fetch_argv[fetch_argc++] = "-v";
+ if (argc < 2) {
+ fetch_argv[fetch_argc++] = "default";
+ } else {
+ fetch_argv[fetch_argc++] = "--multiple";
+ for (i = 1; i < argc; i++)
+ fetch_argv[fetch_argc++] = argv[i];
+ }
- for (i = 0; i < list.nr; i++) {
- int err = fetch_remote(list.items[i].string);
- result |= err;
- if (!err && prune)
- result |= prune_remote(list.items[i].string, 0);
+ if (strcmp(fetch_argv[fetch_argc-1], "default") == 0) {
+ git_config(get_remote_default, &default_defined);
+ if (!default_defined)
+ fetch_argv[fetch_argc-1] = "--all";
}
- /* all names were strdup()ed or strndup()ed */
- list.strdup_strings = 1;
- string_list_clear(&list, 0);
+ fetch_argv[fetch_argc] = NULL;
- return result;
+ return run_command_v_opt(fetch_argv, RUN_GIT_CMD);
}
static int get_one_entry(struct remote *remote, void *priv)
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index e931ce6..562cca2 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -365,7 +365,7 @@ test_expect_success 'update with arguments' '
'
-test_expect_success 'update --prune' '
+test_expect_failure 'update --prune' '
(cd one &&
git branch -m side2 side3) &&
--
1.6.5.1.69.g36942
^ permalink raw reply related
* Re: Problem signing a tag
From: Joshua J. Kugler @ 2009-11-09 20:15 UTC (permalink / raw)
To: Michael J Gruber; +Cc: Junio C Hamano, Alex Riesen, git
In-Reply-To: <4AF3F23B.8080203@drmicha.warpmail.net>
On Friday 06 November 2009, Michael J Gruber said something like:
> Junio C Hamano venit, vidit, dixit 05.11.2009 21:09:
> > Michael J Gruber <git@drmicha.warpmail.net> writes:
> >> Dig dig dig... gpg exits with 2 in a lot of cases, one would need
> >> to parse fd-error to find out more. But it also looks as if gpg
> >> exits normally with a good passphrase. So I tried, and at least
> >> with gpg 1.4.9 and git 1.6.5.2 I can sign tags with "use-agent"
> >> and without a running agent: I get asked for the passphrase (after
> >> reporting the agent MIA), and everything's fine.
> >>
> >> My gpg returns 0 in this case; it returns 2 only if I don't enter
> >> the passphrase. So, this seems to depend on the version of gpg. Or
> >> on entering the correct passphrase ;)
> >
> > If the problematic gpg that gives 2 is older than yours, the
> > situation looks to me that "exiting 2 when failed to contact agent
> > but got a good passphrase some other way and successfully signed"
> > was diagnosed as a bug and then fixed in gpg. If that is the case
> > can we find out which version that fix is in, and add an entry to
> > FAQ to help next person who will be hit by this when using "tag
> > -s"?
>
> Both of us seem to be using gpg 1.4.9, which is weird. I even checked
> Fedora's srpm, they don't apply any patches for this. For the record,
> I'm doing
>
> unset GPG_AGENT_INFO
> echo a |gpg -bsa
>
> with "use-agent" and a default key signing specified in my gpg conf.
> This returns "0" if I enter the correct passphrase (after being
> warned about the missing agent) and "2" if I enter a wrong one
> repeatedly. Joshua, your reports seem to confirm that you get 2 in
> both cases from your gpg 1.4.9, right?
I discovered that there must have been something locked up or wedged. I
rebooted (kernel update), and it worked. I looked at the warning again,
and realized that the warning I got when the exit value was 2 was:
gpg: problem with the agent - disabling agent use
while the warning I got when the exit value was 0 was:
gpg: gpg-agent is not available in this session
So, two different warnings.
Thanks again for all the troubleshooting help!
j
--
Joshua Kugler
Part-Time System Admin/Programmer
http://www.eeinternet.com
PGP Key: http://pgp.mit.edu/ ID 0x14EA086E
^ permalink raw reply
* Re: [PATCH v2 4/4] Add explicit Cygwin check to guard WIN32 header inclusion
From: Junio C Hamano @ 2009-11-09 20:30 UTC (permalink / raw)
To: Ramsay Jones; +Cc: Marius Storm-Olsen, Johannes Sixt, GIT Mailing-list
In-Reply-To: <4AF86CDB.6030200@ramsay1.demon.co.uk>
Ramsay Jones <ramsay@ramsay1.demon.co.uk> writes:
> Ramsay Jones wrote:
>> diff --git a/git-compat-util.h b/git-compat-util.h
>>...
>
> Arrgghhh.
>
> Sorry, Junio, I meant to change this before sending it out. :(
>
> I had intended to remove the added indentation (which I don't even remember
> doing!), since it obscures the "real change", which simply consists of the
> new expression in the #if preprocessor line.
>
> I'll send a new version of this patch.
Thanks for a notice.
The only reason I queue patches to 'pu' is to give them (slightly) wider
exposure than merely being in the mailing list archive, and I do not
expect myself merging this series to 'next' before seeing Acks from
Windows stakeholders, as I do not build anything on that platform myself.
I saw a comment on substance not form of this patch from J6t, and I
suspect that it was a more important issue. You can de-indent while
sending your updated patch to address that issue.
Thanks.
^ permalink raw reply
* Re: [PATCH v3 08/12] Allow helper to map private ref names into normal names
From: Junio C Hamano @ 2009-11-09 20:32 UTC (permalink / raw)
To: Sverre Rabbelier
Cc: Junio C Hamano, Daniel Barkalow, Git List, Johannes Schindelin,
Johan Herland
In-Reply-To: <fabb9a1e0911090910g4745325l842cdb91e4d9485c@mail.gmail.com>
Sverre Rabbelier <srabbelier@gmail.com> writes:
> Heya,
>
> On Mon, Nov 9, 2009 at 17:44, Junio C Hamano <gitster@pobox.com> wrote:
>> Sverre Rabbelier <srabbelier@gmail.com> writes:
>>> It's in next now, so please send follow-ups against sr/vcs-helper.
>>
>> Do you mean 'pu' or 'next'?
>
> Sorry, my hands did not type what my mind intended, I meant to say
> 'pu', apologies!
Fine---mistakes happen; it made me worried for a while.
So either follow-up, squash-in or replacement would be fine.
^ permalink raw reply
* Re: Git drawbacks?
From: Dmitry Potapov @ 2009-11-09 21:06 UTC (permalink / raw)
To: Dmitry Smirnov; +Cc: B Smith-Mannschott, git
In-Reply-To: <28c656e20911091047r353e9451hd856b99541fbd5ff@mail.gmail.com>
On Mon, Nov 09, 2009 at 07:47:08PM +0100, B Smith-Mannschott wrote:
>
> You don't have to wait to comitting to your own branches, but do make
> sure to run your usual builds and tests before pushing or asking
> another to pull changes from you.
Yes, it is one most useful feature of Git that you can commit (save)
your changes immediately but amend them later. This helps a lot to
make changes smaller, cleaner and easier to review.
With many other VCS, a typical policy is that you do not commit your
changes unless you have finished and tested them. But it means that
your changes are not committed and stored only in the work tree for
a long time. Moreover, when you eventually decide that they are good
enough to commit, you will produce a huge patch, which will be difficult
to review or to bisect history later.
With Git you do not have to worry about testing when you can commit your
changes. Typically I would commit some my changes as I progress to my
goal, but later I will review all commits. Probably, squash some changes
with fixes, clean up some other, add better explanations of what is done
and why, etc... But I do not have to worry about all those trifles as
I write code to see if some feature is worth or not, if this solution
works or I should try something else...
So, you can always commit your changes as your progress to your goal and
review amend them later before publishing. This means that you can have
as many work-in-progress branches as you wish, and you do not need a
separate work tree for each of them -- everything can be stored in the
repository, and you can go to another computer, issue 'git fetch' and
continue your work at the exact point where you left it. So, it is very
flexible.
Dmitry
^ permalink raw reply
* Re: pulling git -- version confusion
From: Junio C Hamano @ 2009-11-09 21:58 UTC (permalink / raw)
To: Rustom Mody; +Cc: Sverre Rabbelier, git
In-Reply-To: <f46c52560911090524l51140858sdde29d76e2cfed49@mail.gmail.com>
Rustom Mody <rustompmody@gmail.com> writes:
> On Mon, Nov 9, 2009 at 1:21 PM, Sverre Rabbelier <srabbelier@gmail.com> wrote:
>> On Mon, Nov 9, 2009 at 08:45, Rustom Mody <rustompmody@gmail.com> wrote:
>>> Gives me
>>> fatal: ambiguous argument 'origin/master': unknown revision or path
>>> not in the working tree.
>>> Use '--' to separate paths from revisions
>>
>> Well, as what remote do you have upstream configured?
>>
>> What is the output of
>> $ git config -l
>
> gives me
>
> core.safecrlf=true
> user.email=<my email>
> user.name=<my name>
> core.repositoryformatversion=0
> core.filemode=true
> gui.geometry=885x450+0+27 207 192
>
> So theres no remote?
> But .git/remotes/origin has
>
> URL: git://git.kernel.org/pub/scm/git/git.git
> Pull: refs/heads/master:refs/heads/origin
> Pull: refs/heads/maint:refs/heads/maint
> Pull: refs/heads/next:refs/heads/next
> Pull: refs/heads/html:refs/heads/html
> Pull: refs/heads/pu:refs/heads/pu
> Pull: refs/heads/todo:refs/heads/todo
> Pull: refs/heads/man:refs/heads/man
That's a layout that was default before 1.5.0, I think. 3 years is an eon
in git timescale.
People giving advice based on modern git experience would say things like
"origin/master", but in your layout that ref that keeps track of where the
'master' branch at the remote repository is is not called 'origin/master',
but simply 'origin'.
So instead of
> Try either:
> $ git checkout master
> $ git reset --hard origin/master
that Sverre gave you, in your repository you would do:
$ git checkout master
$ git reset --hard origin
^ permalink raw reply
* Re: [PATCH v3 4/4] Add explicit Cygwin check to guard WIN32 header inclusion
From: Junio C Hamano @ 2009-11-09 22:25 UTC (permalink / raw)
To: Ramsay Jones; +Cc: Marius Storm-Olsen, Johannes Sixt, GIT Mailing-list
In-Reply-To: <4AF86E0C.4080001@ramsay1.demon.co.uk>
Ramsay Jones <ramsay@ramsay1.demon.co.uk> writes:
> Changes since v2:
> - removed indentation from the #if-#endif block
>
> I hope you don't mind, but I've only sent this patch, rather than
> re-send the whole series. If you would like a complete re-send, just
> let me know.
No, I don't mind "replace only this one out of the four-patch series" at
all as long as what's being replaced is marked clearly enough (which you
did in this case).
But I thought J6t had problems with what this particular patch does, not
how the patch was indented? So I'd wait for more comments and hopefully
an Ack from him before touching this one.
^ permalink raw reply
* [RFC, PATCH] git send-email: Make --no-chain-reply-to the default
From: Ingo Molnar @ 2009-11-10 4:08 UTC (permalink / raw)
To: Peter Zijlstra, git, Junio C Hamano
In-Reply-To: <1257789555.4108.348.camel@laptop>
(moved from lkml to the Git list)
* Peter Zijlstra <peterz@infradead.org> wrote:
> > Mailer:
> > git-send-email 1.6.5.2
>
> Please teach your git-send-email thing to use --no-chain-reply-to.
about half of every patch series that gets sent to me on lkml is
unreadable in my email client due to the default threading that
git-send-email does. It looks like this:
28685 r T Nov 05 Hitoshi Mitake ( 31) [PATCH v5 0/7] Adding general performance benchmarki
28686 T Nov 05 Hitoshi Mitake ( 31) +->[PATCH v5 1/7] Adding new directory and header fo
28687 T Nov 05 Hitoshi Mitake ( 368) | +->[PATCH v5 2/7] sched-messaging.c: benchmark for
28688 T Nov 05 Hitoshi Mitake ( 148) | | +->[PATCH v5 3/7] sched-pipe.c: benchmark for pi
28689 T Nov 05 Hitoshi Mitake ( 149) | | | +->[PATCH v5 4/7] builtin-bench.c: General fra
28690 T Nov 05 Hitoshi Mitake ( 24) | | | | +->[PATCH v5 5/7] Modifying builtin.h for ne
28691 T Nov 05 Hitoshi Mitake ( 25) | | | | | +->[PATCH v5 6/7] Modyfing perf.c for subc
28692 T Nov 05 Hitoshi Mitake ( 30) | | | | | | +->[PATCH v5 7/7] Modyfing Makefile to b
and with 10 or more patches it's an absolute pain as threading depth
increases. Furthermore, the subject lines are not aligned vertically,
making it very hard to see the general shortlog-alike structure of the
series, at a glance. Plus i dont even _see_ the title over a certain
depth, as i run out of screen real estate.
So ... the question would be ... could git-send-email flip its default
please, via the patch below? Am i missing something subtle about why
this default was chosen?
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/git-send-email.perl b/git-send-email.perl
index a0279de..ff00940 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -188,7 +188,7 @@ my (@suppress_cc);
my %config_bool_settings = (
"thread" => [\$thread, 1],
- "chainreplyto" => [\$chain_reply_to, 1],
+ "chainreplyto" => [\$chain_reply_to, 0],
"suppressfrom" => [\$suppress_from, undef],
"signedoffbycc" => [\$signed_off_by_cc, undef],
"signedoffcc" => [\$signed_off_by_cc, undef], # Deprecated
^ permalink raw reply related
* [PATCH 0/4] Teach fetch --prune and --dry run options
From: Jay Soffian @ 2009-11-10 4:58 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
This series builds on bg/fetch-multi, by teaching fetch --prune, re-enabling
"remote update --prune" and ensuring its corresponding test now passes.
As a convenience to users used to "remote prune" supporting the "--dry-run"
option, we also teach this option to fetch since it's trivial to do so.
I've left out re-implementing "remote prune" as a synonym for "update --prune"
since it's not a 1:1 match. And as per Junio's comments, teaching fetch a
"--prune-only" option would be a UI wart.
Jay Soffian (4):
remote: refactor some logic into get_stale_heads()
teach warn_dangling_symref to take a FILE argument
builtin-fetch: add --prune option
builtin-fetch: add --dry-run option
Documentation/fetch-options.txt | 9 ++++++++
builtin-fetch.c | 42 +++++++++++++++++++++++++++++++++++---
builtin-remote.c | 38 +++++++++++------------------------
refs.c | 7 +++--
refs.h | 2 +-
remote.c | 40 +++++++++++++++++++++++++++++++++++++
remote.h | 3 ++
t/t5505-remote.sh | 2 +-
8 files changed, 108 insertions(+), 35 deletions(-)
^ permalink raw reply
* [PATCH 1/4] remote: refactor some logic into get_stale_heads()
From: Jay Soffian @ 2009-11-10 4:58 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
In-Reply-To: <1257829113-52168-1-git-send-email-jaysoffian@gmail.com>
Move the logic in builtin-remote.c which determines which local heads are stale
to remote.c so it can be used by other builtins.
---
builtin-remote.c | 32 ++++++++------------------------
remote.c | 40 ++++++++++++++++++++++++++++++++++++++++
remote.h | 3 +++
3 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/builtin-remote.c b/builtin-remote.c
index fd7e0b2..0ea4e60 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -227,32 +227,10 @@ struct ref_states {
int queried;
};
-static int handle_one_branch(const char *refname,
- const unsigned char *sha1, int flags, void *cb_data)
-{
- struct ref_states *states = cb_data;
- struct refspec refspec;
-
- memset(&refspec, 0, sizeof(refspec));
- refspec.dst = (char *)refname;
- if (!remote_find_tracking(states->remote, &refspec)) {
- struct string_list_item *item;
- const char *name = abbrev_branch(refspec.src);
- /* symbolic refs pointing nowhere were handled already */
- if ((flags & REF_ISSYMREF) ||
- string_list_has_string(&states->tracked, name) ||
- string_list_has_string(&states->new, name))
- return 0;
- item = string_list_append(name, &states->stale);
- item->util = xstrdup(refname);
- }
- return 0;
-}
-
static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
{
struct ref *fetch_map = NULL, **tail = &fetch_map;
- struct ref *ref;
+ struct ref *ref, *stale_refs;
int i;
for (i = 0; i < states->remote->fetch_refspec_nr; i++)
@@ -268,11 +246,17 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
else
string_list_append(abbrev_branch(ref->name), &states->tracked);
}
+ stale_refs = get_stale_heads(states->remote, fetch_map);
+ for (ref = stale_refs; ref; ref = ref->next) {
+ struct string_list_item *item =
+ string_list_append(abbrev_branch(ref->name), &states->stale);
+ item->util = xstrdup(ref->name);
+ }
+ free_refs(stale_refs);
free_refs(fetch_map);
sort_string_list(&states->new);
sort_string_list(&states->tracked);
- for_each_ref(handle_one_branch, states);
sort_string_list(&states->stale);
return 0;
diff --git a/remote.c b/remote.c
index beaf9fb..eae5866 100644
--- a/remote.c
+++ b/remote.c
@@ -6,6 +6,7 @@
#include "revision.h"
#include "dir.h"
#include "tag.h"
+#include "string-list.h"
static struct refspec s_tag_refspec = {
0,
@@ -1587,3 +1588,42 @@ struct ref *guess_remote_head(const struct ref *head,
return list;
}
+
+struct stale_heads_info {
+ struct remote *remote;
+ struct string_list *ref_names;
+ struct ref **stale_refs_tail;
+};
+
+static int get_stale_heads_cb(const char *refname,
+ const unsigned char *sha1, int flags, void *cb_data)
+{
+ struct stale_heads_info *info = cb_data;
+ struct refspec refspec;
+ memset(&refspec, 0, sizeof(refspec));
+ refspec.dst = (char *)refname;
+ if (!remote_find_tracking(info->remote, &refspec)) {
+ if (!((flags & REF_ISSYMREF) ||
+ string_list_has_string(info->ref_names, refspec.src))) {
+ struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
+ hashcpy(ref->new_sha1, sha1);
+ }
+ }
+ return 0;
+}
+
+struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map)
+{
+ struct ref *ref, *stale_refs = NULL;
+ struct string_list ref_names = { NULL, 0, 0, 0 };
+ struct stale_heads_info info;
+ info.remote = remote;
+ info.ref_names = &ref_names;
+ info.stale_refs_tail = &stale_refs;
+ for (ref = fetch_map; ref; ref = ref->next)
+ string_list_append(ref->name, &ref_names);
+ sort_string_list(&ref_names);
+ for_each_ref(get_stale_heads_cb, &info);
+ string_list_clear(&ref_names, 0);
+ return stale_refs;
+}
diff --git a/remote.h b/remote.h
index 5db8420..d0aba81 100644
--- a/remote.h
+++ b/remote.h
@@ -154,4 +154,7 @@ struct ref *guess_remote_head(const struct ref *head,
const struct ref *refs,
int all);
+/* Return refs which no longer exist on remote */
+struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map);
+
#endif
--
1.6.4.2
^ permalink raw reply related
* [PATCH 3/4] builtin-fetch: add --prune option
From: Jay Soffian @ 2009-11-10 4:58 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
In-Reply-To: <1257829113-52168-3-git-send-email-jaysoffian@gmail.com>
Teach fetch to cull stale remote tracking branches after fetching via --prune.
We can now enable the "--prune" option to "remote update", which was recently
re-implemented as an invocation of git fetch.
---
Documentation/fetch-options.txt | 4 ++++
builtin-fetch.c | 32 ++++++++++++++++++++++++++++++--
builtin-remote.c | 4 +++-
t/t5505-remote.sh | 2 +-
4 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 8b0cf58..500637a 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -28,6 +28,10 @@ ifndef::git-pull[]
--multiple::
Allow several <repository> and <group> arguments to be
specified. No <refspec>s may be specified.
+
+--prune::
+ After fetching, remove any remote tracking branches which
+ no longer exist on the remote.
endif::git-pull[]
ifdef::git-pull[]
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 945dfd8..fd31072 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -26,7 +26,7 @@ enum {
TAGS_SET = 2
};
-static int all, append, force, keep, multiple, update_head_ok, verbosity;
+static int all, append, force, keep, multiple, prune, update_head_ok, verbosity;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
@@ -49,6 +49,8 @@ static struct option builtin_fetch_options[] = {
"fetch all tags and associated objects", TAGS_SET),
OPT_SET_INT('n', NULL, &tags,
"do not fetch all tags (--no-tags)", TAGS_UNSET),
+ OPT_BOOLEAN('p', "prune", &prune,
+ "prune tracking branches no longer on remote"),
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
"allow updating of HEAD ref"),
@@ -492,6 +494,28 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
return ret;
}
+static int prune_refs(struct transport *transport, struct ref *ref_map)
+{
+ int result = 0;
+ struct ref *ref, *stale_refs = get_stale_heads(transport->remote, ref_map);
+ const char *dangling_msg = dry_run
+ ? " (%s will become dangling)\n"
+ : " (%s has become dangling)\n";
+
+ for (ref = stale_refs; ref; ref = ref->next) {
+ if (!dry_run)
+ result |= delete_ref(ref->name, NULL, 0);
+ if (verbosity >= 0) {
+ fprintf(stderr, " x %-*s %-*s -> %s\n",
+ SUMMARY_WIDTH, "[deleted]",
+ REFCOL_WIDTH, "(none)", prettify_refname(ref->name));
+ warn_dangling_symref(stderr, dangling_msg, ref->name);
+ }
+ }
+ free_refs(stale_refs);
+ return result;
+}
+
static int add_existing(const char *refname, const unsigned char *sha1,
int flag, void *cbdata)
{
@@ -657,6 +681,8 @@ static int do_fetch(struct transport *transport,
free_refs(ref_map);
return 1;
}
+ if (prune)
+ prune_refs(transport, ref_map);
free_refs(ref_map);
/* if neither --no-tags nor --tags was specified, do automated tag
@@ -740,9 +766,11 @@ static int add_remote_or_group(const char *name, struct string_list *list)
static int fetch_multiple(struct string_list *list)
{
int i, result = 0;
- const char *argv[] = { "fetch", NULL, NULL, NULL, NULL };
+ const char *argv[] = { "fetch", NULL, NULL, NULL, NULL, NULL };
int argc = 1;
+ if (prune)
+ argv[argc++] = "--prune";
if (verbosity >= 2)
argv[argc++] = "-v";
if (verbosity >= 1)
diff --git a/builtin-remote.c b/builtin-remote.c
index e67b89f..fb0d66d 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -1195,13 +1195,15 @@ static int update(int argc, const char **argv)
int fetch_argc = 0;
int default_defined = 0;
- fetch_argv = xmalloc(sizeof(char *) * (argc+4));
+ fetch_argv = xmalloc(sizeof(char *) * (argc+5));
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
PARSE_OPT_KEEP_ARGV0);
fetch_argv[fetch_argc++] = "fetch";
+ if (prune)
+ fetch_argv[fetch_argc++] = "--prune";
if (verbose)
fetch_argv[fetch_argc++] = "-v";
if (argc < 2) {
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 562cca2..e931ce6 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -365,7 +365,7 @@ test_expect_success 'update with arguments' '
'
-test_expect_failure 'update --prune' '
+test_expect_success 'update --prune' '
(cd one &&
git branch -m side2 side3) &&
--
1.6.4.2
^ permalink raw reply related
* [PATCH 2/4] teach warn_dangling_symref to take a FILE argument
From: Jay Soffian @ 2009-11-10 4:58 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
In-Reply-To: <1257829113-52168-2-git-send-email-jaysoffian@gmail.com>
Different callers of warn_dangling_symref() may want to control whether its
output goes to stdout or stderr so let it take a FILE argument.
---
builtin-remote.c | 2 +-
refs.c | 7 ++++---
refs.h | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/builtin-remote.c b/builtin-remote.c
index 0ea4e60..e67b89f 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -1166,7 +1166,7 @@ static int prune_remote(const char *remote, int dry_run)
printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
abbrev_ref(refname, "refs/remotes/"));
- warn_dangling_symref(dangling_msg, refname);
+ warn_dangling_symref(stdout, dangling_msg, refname);
}
free_remote_ref_states(&states);
diff --git a/refs.c b/refs.c
index 808f56b..3e73a0a 100644
--- a/refs.c
+++ b/refs.c
@@ -286,6 +286,7 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
}
struct warn_if_dangling_data {
+ FILE *fp;
const char *refname;
const char *msg_fmt;
};
@@ -304,13 +305,13 @@ static int warn_if_dangling_symref(const char *refname, const unsigned char *sha
if (!resolves_to || strcmp(resolves_to, d->refname))
return 0;
- printf(d->msg_fmt, refname);
+ fprintf(d->fp, d->msg_fmt, refname);
return 0;
}
-void warn_dangling_symref(const char *msg_fmt, const char *refname)
+void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
{
- struct warn_if_dangling_data data = { refname, msg_fmt };
+ struct warn_if_dangling_data data = { fp, refname, msg_fmt };
for_each_rawref(warn_if_dangling_symref, &data);
}
diff --git a/refs.h b/refs.h
index 777b5b7..e141991 100644
--- a/refs.h
+++ b/refs.h
@@ -29,7 +29,7 @@ extern int for_each_replace_ref(each_ref_fn, void *);
/* can be used to learn about broken ref and symref */
extern int for_each_rawref(each_ref_fn, void *);
-extern void warn_dangling_symref(const char *msg_fmt, const char *refname);
+extern void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname);
/*
* Extra refs will be listed by for_each_ref() before any actual refs
--
1.6.4.2
^ permalink raw reply related
* [PATCH 4/4] builtin-fetch: add --dry-run option
From: Jay Soffian @ 2009-11-10 4:58 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
In-Reply-To: <1257829113-52168-4-git-send-email-jaysoffian@gmail.com>
Teach fetch --dry-run as users of "git remote prune" switching to "git fetch
--prune" may expect it. Unfortunately OPT__DRY_RUN() cannot be used as fetch
already uses "-n" for something else.
---
Documentation/fetch-options.txt | 5 +++++
builtin-fetch.c | 14 ++++++++++----
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 500637a..ab6419f 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -12,6 +12,11 @@
`git clone` with `--depth=<depth>` option (see linkgit:git-clone[1])
by the specified number of commits.
+ifndef::git-pull[]
+--dry-run::
+ Show what would be done, without making any changes.
+endif::git-pull[]
+
-f::
--force::
When 'git-fetch' is used with `<rbranch>:<lbranch>`
diff --git a/builtin-fetch.c b/builtin-fetch.c
index fd31072..8082d36 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -26,7 +26,7 @@ enum {
TAGS_SET = 2
};
-static int all, append, force, keep, multiple, prune, update_head_ok, verbosity;
+static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
@@ -51,6 +51,8 @@ static struct option builtin_fetch_options[] = {
"do not fetch all tags (--no-tags)", TAGS_UNSET),
OPT_BOOLEAN('p', "prune", &prune,
"prune tracking branches no longer on remote"),
+ OPT_BOOLEAN(0, "dry-run", &dry_run,
+ "dry run"),
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
"allow updating of HEAD ref"),
@@ -187,6 +189,8 @@ static int s_update_ref(const char *action,
char *rla = getenv("GIT_REFLOG_ACTION");
static struct ref_lock *lock;
+ if (dry_run)
+ return 0;
if (!rla)
rla = default_rla.buf;
snprintf(msg, sizeof(msg), "%s: %s", rla, action);
@@ -312,7 +316,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
char note[1024];
const char *what, *kind;
struct ref *rm;
- char *url, *filename = git_path("FETCH_HEAD");
+ char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD");
fp = fopen(filename, "a");
if (!fp)
@@ -658,7 +662,7 @@ static int do_fetch(struct transport *transport,
die("Don't know how to fetch from %s", transport->url);
/* if not appending, truncate FETCH_HEAD */
- if (!append) {
+ if (!append && !dry_run) {
char *filename = git_path("FETCH_HEAD");
FILE *fp = fopen(filename, "w");
if (!fp)
@@ -766,9 +770,11 @@ static int add_remote_or_group(const char *name, struct string_list *list)
static int fetch_multiple(struct string_list *list)
{
int i, result = 0;
- const char *argv[] = { "fetch", NULL, NULL, NULL, NULL, NULL };
+ const char *argv[] = { "fetch", NULL, NULL, NULL, NULL, NULL, NULL };
int argc = 1;
+ if (dry_run)
+ argv[argc++] = "--dry-run";
if (prune)
argv[argc++] = "--prune";
if (verbosity >= 2)
--
1.6.4.2
^ permalink raw reply related
* [PATCH 0/4] Teach fetch --prune and --dry run options
From: Jay Soffian @ 2009-11-10 5:03 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
(Darn it, I left the SOB off. This is a resend of the series with SOB. Sorry
for the noise...)
This series builds on bg/fetch-multi, by teaching fetch --prune, re-enabling
"remote update --prune" and ensuring its corresponding test now passes.
As a convenience to users used to "remote prune" supporting the "--dry-run"
option, we also teach this option to fetch since it's trivial to do so.
I've left out re-implementing "remote prune" as a synonym for "update --prune"
since it's not a 1:1 match. And as per Junio's comments, teaching fetch a
"--prune-only" option would be a UI wart.
Jay Soffian (4):
remote: refactor some logic into get_stale_heads()
teach warn_dangling_symref to take a FILE argument
builtin-fetch: add --prune option
builtin-fetch: add --dry-run option
Documentation/fetch-options.txt | 9 ++++++++
builtin-fetch.c | 42 +++++++++++++++++++++++++++++++++++---
builtin-remote.c | 38 +++++++++++------------------------
refs.c | 7 +++--
refs.h | 2 +-
remote.c | 40 +++++++++++++++++++++++++++++++++++++
remote.h | 3 ++
t/t5505-remote.sh | 2 +-
8 files changed, 108 insertions(+), 35 deletions(-)
^ permalink raw reply
* [PATCH 1/4] remote: refactor some logic into get_stale_heads()
From: Jay Soffian @ 2009-11-10 5:03 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
In-Reply-To: <1257829414-52316-1-git-send-email-jaysoffian@gmail.com>
Move the logic in builtin-remote.c which determines which local heads are stale
to remote.c so it can be used by other builtins.
Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
builtin-remote.c | 32 ++++++++------------------------
remote.c | 40 ++++++++++++++++++++++++++++++++++++++++
remote.h | 3 +++
3 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/builtin-remote.c b/builtin-remote.c
index fd7e0b2..0ea4e60 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -227,32 +227,10 @@ struct ref_states {
int queried;
};
-static int handle_one_branch(const char *refname,
- const unsigned char *sha1, int flags, void *cb_data)
-{
- struct ref_states *states = cb_data;
- struct refspec refspec;
-
- memset(&refspec, 0, sizeof(refspec));
- refspec.dst = (char *)refname;
- if (!remote_find_tracking(states->remote, &refspec)) {
- struct string_list_item *item;
- const char *name = abbrev_branch(refspec.src);
- /* symbolic refs pointing nowhere were handled already */
- if ((flags & REF_ISSYMREF) ||
- string_list_has_string(&states->tracked, name) ||
- string_list_has_string(&states->new, name))
- return 0;
- item = string_list_append(name, &states->stale);
- item->util = xstrdup(refname);
- }
- return 0;
-}
-
static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
{
struct ref *fetch_map = NULL, **tail = &fetch_map;
- struct ref *ref;
+ struct ref *ref, *stale_refs;
int i;
for (i = 0; i < states->remote->fetch_refspec_nr; i++)
@@ -268,11 +246,17 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
else
string_list_append(abbrev_branch(ref->name), &states->tracked);
}
+ stale_refs = get_stale_heads(states->remote, fetch_map);
+ for (ref = stale_refs; ref; ref = ref->next) {
+ struct string_list_item *item =
+ string_list_append(abbrev_branch(ref->name), &states->stale);
+ item->util = xstrdup(ref->name);
+ }
+ free_refs(stale_refs);
free_refs(fetch_map);
sort_string_list(&states->new);
sort_string_list(&states->tracked);
- for_each_ref(handle_one_branch, states);
sort_string_list(&states->stale);
return 0;
diff --git a/remote.c b/remote.c
index beaf9fb..eae5866 100644
--- a/remote.c
+++ b/remote.c
@@ -6,6 +6,7 @@
#include "revision.h"
#include "dir.h"
#include "tag.h"
+#include "string-list.h"
static struct refspec s_tag_refspec = {
0,
@@ -1587,3 +1588,42 @@ struct ref *guess_remote_head(const struct ref *head,
return list;
}
+
+struct stale_heads_info {
+ struct remote *remote;
+ struct string_list *ref_names;
+ struct ref **stale_refs_tail;
+};
+
+static int get_stale_heads_cb(const char *refname,
+ const unsigned char *sha1, int flags, void *cb_data)
+{
+ struct stale_heads_info *info = cb_data;
+ struct refspec refspec;
+ memset(&refspec, 0, sizeof(refspec));
+ refspec.dst = (char *)refname;
+ if (!remote_find_tracking(info->remote, &refspec)) {
+ if (!((flags & REF_ISSYMREF) ||
+ string_list_has_string(info->ref_names, refspec.src))) {
+ struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
+ hashcpy(ref->new_sha1, sha1);
+ }
+ }
+ return 0;
+}
+
+struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map)
+{
+ struct ref *ref, *stale_refs = NULL;
+ struct string_list ref_names = { NULL, 0, 0, 0 };
+ struct stale_heads_info info;
+ info.remote = remote;
+ info.ref_names = &ref_names;
+ info.stale_refs_tail = &stale_refs;
+ for (ref = fetch_map; ref; ref = ref->next)
+ string_list_append(ref->name, &ref_names);
+ sort_string_list(&ref_names);
+ for_each_ref(get_stale_heads_cb, &info);
+ string_list_clear(&ref_names, 0);
+ return stale_refs;
+}
diff --git a/remote.h b/remote.h
index 5db8420..d0aba81 100644
--- a/remote.h
+++ b/remote.h
@@ -154,4 +154,7 @@ struct ref *guess_remote_head(const struct ref *head,
const struct ref *refs,
int all);
+/* Return refs which no longer exist on remote */
+struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map);
+
#endif
--
1.6.4.2
^ permalink raw reply related
* [PATCH 2/4] teach warn_dangling_symref to take a FILE argument
From: Jay Soffian @ 2009-11-10 5:03 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
In-Reply-To: <1257829414-52316-2-git-send-email-jaysoffian@gmail.com>
Different callers of warn_dangling_symref() may want to control whether its
output goes to stdout or stderr so let it take a FILE argument.
Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
builtin-remote.c | 2 +-
refs.c | 7 ++++---
refs.h | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/builtin-remote.c b/builtin-remote.c
index 0ea4e60..e67b89f 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -1166,7 +1166,7 @@ static int prune_remote(const char *remote, int dry_run)
printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
abbrev_ref(refname, "refs/remotes/"));
- warn_dangling_symref(dangling_msg, refname);
+ warn_dangling_symref(stdout, dangling_msg, refname);
}
free_remote_ref_states(&states);
diff --git a/refs.c b/refs.c
index 808f56b..3e73a0a 100644
--- a/refs.c
+++ b/refs.c
@@ -286,6 +286,7 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
}
struct warn_if_dangling_data {
+ FILE *fp;
const char *refname;
const char *msg_fmt;
};
@@ -304,13 +305,13 @@ static int warn_if_dangling_symref(const char *refname, const unsigned char *sha
if (!resolves_to || strcmp(resolves_to, d->refname))
return 0;
- printf(d->msg_fmt, refname);
+ fprintf(d->fp, d->msg_fmt, refname);
return 0;
}
-void warn_dangling_symref(const char *msg_fmt, const char *refname)
+void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
{
- struct warn_if_dangling_data data = { refname, msg_fmt };
+ struct warn_if_dangling_data data = { fp, refname, msg_fmt };
for_each_rawref(warn_if_dangling_symref, &data);
}
diff --git a/refs.h b/refs.h
index 777b5b7..e141991 100644
--- a/refs.h
+++ b/refs.h
@@ -29,7 +29,7 @@ extern int for_each_replace_ref(each_ref_fn, void *);
/* can be used to learn about broken ref and symref */
extern int for_each_rawref(each_ref_fn, void *);
-extern void warn_dangling_symref(const char *msg_fmt, const char *refname);
+extern void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname);
/*
* Extra refs will be listed by for_each_ref() before any actual refs
--
1.6.4.2
^ permalink raw reply related
* [PATCH 3/4] builtin-fetch: add --prune option
From: Jay Soffian @ 2009-11-10 5:03 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
In-Reply-To: <1257829414-52316-3-git-send-email-jaysoffian@gmail.com>
Teach fetch to cull stale remote tracking branches after fetching via --prune.
We can now enable the "--prune" option to "remote update", which was recently
re-implemented as an invocation of git fetch.
Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
Documentation/fetch-options.txt | 4 ++++
builtin-fetch.c | 32 ++++++++++++++++++++++++++++++--
builtin-remote.c | 4 +++-
t/t5505-remote.sh | 2 +-
4 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 8b0cf58..500637a 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -28,6 +28,10 @@ ifndef::git-pull[]
--multiple::
Allow several <repository> and <group> arguments to be
specified. No <refspec>s may be specified.
+
+--prune::
+ After fetching, remove any remote tracking branches which
+ no longer exist on the remote.
endif::git-pull[]
ifdef::git-pull[]
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 945dfd8..fd31072 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -26,7 +26,7 @@ enum {
TAGS_SET = 2
};
-static int all, append, force, keep, multiple, update_head_ok, verbosity;
+static int all, append, force, keep, multiple, prune, update_head_ok, verbosity;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
@@ -49,6 +49,8 @@ static struct option builtin_fetch_options[] = {
"fetch all tags and associated objects", TAGS_SET),
OPT_SET_INT('n', NULL, &tags,
"do not fetch all tags (--no-tags)", TAGS_UNSET),
+ OPT_BOOLEAN('p', "prune", &prune,
+ "prune tracking branches no longer on remote"),
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
"allow updating of HEAD ref"),
@@ -492,6 +494,28 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
return ret;
}
+static int prune_refs(struct transport *transport, struct ref *ref_map)
+{
+ int result = 0;
+ struct ref *ref, *stale_refs = get_stale_heads(transport->remote, ref_map);
+ const char *dangling_msg = dry_run
+ ? " (%s will become dangling)\n"
+ : " (%s has become dangling)\n";
+
+ for (ref = stale_refs; ref; ref = ref->next) {
+ if (!dry_run)
+ result |= delete_ref(ref->name, NULL, 0);
+ if (verbosity >= 0) {
+ fprintf(stderr, " x %-*s %-*s -> %s\n",
+ SUMMARY_WIDTH, "[deleted]",
+ REFCOL_WIDTH, "(none)", prettify_refname(ref->name));
+ warn_dangling_symref(stderr, dangling_msg, ref->name);
+ }
+ }
+ free_refs(stale_refs);
+ return result;
+}
+
static int add_existing(const char *refname, const unsigned char *sha1,
int flag, void *cbdata)
{
@@ -657,6 +681,8 @@ static int do_fetch(struct transport *transport,
free_refs(ref_map);
return 1;
}
+ if (prune)
+ prune_refs(transport, ref_map);
free_refs(ref_map);
/* if neither --no-tags nor --tags was specified, do automated tag
@@ -740,9 +766,11 @@ static int add_remote_or_group(const char *name, struct string_list *list)
static int fetch_multiple(struct string_list *list)
{
int i, result = 0;
- const char *argv[] = { "fetch", NULL, NULL, NULL, NULL };
+ const char *argv[] = { "fetch", NULL, NULL, NULL, NULL, NULL };
int argc = 1;
+ if (prune)
+ argv[argc++] = "--prune";
if (verbosity >= 2)
argv[argc++] = "-v";
if (verbosity >= 1)
diff --git a/builtin-remote.c b/builtin-remote.c
index e67b89f..fb0d66d 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -1195,13 +1195,15 @@ static int update(int argc, const char **argv)
int fetch_argc = 0;
int default_defined = 0;
- fetch_argv = xmalloc(sizeof(char *) * (argc+4));
+ fetch_argv = xmalloc(sizeof(char *) * (argc+5));
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
PARSE_OPT_KEEP_ARGV0);
fetch_argv[fetch_argc++] = "fetch";
+ if (prune)
+ fetch_argv[fetch_argc++] = "--prune";
if (verbose)
fetch_argv[fetch_argc++] = "-v";
if (argc < 2) {
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 562cca2..e931ce6 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -365,7 +365,7 @@ test_expect_success 'update with arguments' '
'
-test_expect_failure 'update --prune' '
+test_expect_success 'update --prune' '
(cd one &&
git branch -m side2 side3) &&
--
1.6.4.2
^ permalink raw reply related
* [PATCH 4/4] builtin-fetch: add --dry-run option
From: Jay Soffian @ 2009-11-10 5:03 UTC (permalink / raw)
To: git; +Cc: Jay Soffian, Junio C Hamano, Björn Gustavsson
In-Reply-To: <1257829414-52316-4-git-send-email-jaysoffian@gmail.com>
Teach fetch --dry-run as users of "git remote prune" switching to "git fetch
--prune" may expect it. Unfortunately OPT__DRY_RUN() cannot be used as fetch
already uses "-n" for something else.
Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
Documentation/fetch-options.txt | 5 +++++
builtin-fetch.c | 14 ++++++++++----
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 500637a..ab6419f 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -12,6 +12,11 @@
`git clone` with `--depth=<depth>` option (see linkgit:git-clone[1])
by the specified number of commits.
+ifndef::git-pull[]
+--dry-run::
+ Show what would be done, without making any changes.
+endif::git-pull[]
+
-f::
--force::
When 'git-fetch' is used with `<rbranch>:<lbranch>`
diff --git a/builtin-fetch.c b/builtin-fetch.c
index fd31072..8082d36 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -26,7 +26,7 @@ enum {
TAGS_SET = 2
};
-static int all, append, force, keep, multiple, prune, update_head_ok, verbosity;
+static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
@@ -51,6 +51,8 @@ static struct option builtin_fetch_options[] = {
"do not fetch all tags (--no-tags)", TAGS_UNSET),
OPT_BOOLEAN('p', "prune", &prune,
"prune tracking branches no longer on remote"),
+ OPT_BOOLEAN(0, "dry-run", &dry_run,
+ "dry run"),
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
"allow updating of HEAD ref"),
@@ -187,6 +189,8 @@ static int s_update_ref(const char *action,
char *rla = getenv("GIT_REFLOG_ACTION");
static struct ref_lock *lock;
+ if (dry_run)
+ return 0;
if (!rla)
rla = default_rla.buf;
snprintf(msg, sizeof(msg), "%s: %s", rla, action);
@@ -312,7 +316,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
char note[1024];
const char *what, *kind;
struct ref *rm;
- char *url, *filename = git_path("FETCH_HEAD");
+ char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD");
fp = fopen(filename, "a");
if (!fp)
@@ -658,7 +662,7 @@ static int do_fetch(struct transport *transport,
die("Don't know how to fetch from %s", transport->url);
/* if not appending, truncate FETCH_HEAD */
- if (!append) {
+ if (!append && !dry_run) {
char *filename = git_path("FETCH_HEAD");
FILE *fp = fopen(filename, "w");
if (!fp)
@@ -766,9 +770,11 @@ static int add_remote_or_group(const char *name, struct string_list *list)
static int fetch_multiple(struct string_list *list)
{
int i, result = 0;
- const char *argv[] = { "fetch", NULL, NULL, NULL, NULL, NULL };
+ const char *argv[] = { "fetch", NULL, NULL, NULL, NULL, NULL, NULL };
int argc = 1;
+ if (dry_run)
+ argv[argc++] = "--dry-run";
if (prune)
argv[argc++] = "--prune";
if (verbosity >= 2)
--
1.6.4.2
^ permalink raw reply related
* Re: [RFC, PATCH] git send-email: Make --no-chain-reply-to the default
From: Jay Soffian @ 2009-11-10 5:12 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Peter Zijlstra, git, Junio C Hamano
In-Reply-To: <20091110040847.GC29454@elte.hu>
On Mon, Nov 9, 2009 at 11:08 PM, Ingo Molnar <mingo@elte.hu> wrote:
> So ... the question would be ... could git-send-email flip its default
This is already in next for 1.7.0. See 41fe87f.
>From Junio's What's Cooking messages:
* jc/1.7.0-send-email-no-thread-default (2009-08-22) 1 commit
(merged to 'next' on 2009-08-22 at 5106de8)
> Am i missing something subtle about why this default was chosen?
I'm not sure it was chosen so much as it was just the way the cookie crumbled.
j.
^ permalink raw reply
* Re: [RFC, PATCH] git send-email: Make --no-chain-reply-to the default
From: Ingo Molnar @ 2009-11-10 5:22 UTC (permalink / raw)
To: Jay Soffian; +Cc: Peter Zijlstra, git, Junio C Hamano
In-Reply-To: <76718490911092112v4d1e7761ue98def756ed0d93b@mail.gmail.com>
* Jay Soffian <jaysoffian@gmail.com> wrote:
> On Mon, Nov 9, 2009 at 11:08 PM, Ingo Molnar <mingo@elte.hu> wrote:
> > So ... the question would be ... could git-send-email flip its default
>
> This is already in next for 1.7.0. See 41fe87f.
>
> >From Junio's What's Cooking messages:
>
> * jc/1.7.0-send-email-no-thread-default (2009-08-22) 1 commit
> (merged to 'next' on 2009-08-22 at 5106de8)
Ah, awesome!
+1 for putting it into a .1.6.x stable branch too. (Unless there's a
case where the recursive threading is actually useful and is being
relied on.)
Ingo
^ permalink raw reply
* Re: [RFC, PATCH] git send-email: Make --no-chain-reply-to the default
From: Junio C Hamano @ 2009-11-10 5:29 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Peter Zijlstra, git, Junio C Hamano
In-Reply-To: <20091110040847.GC29454@elte.hu>
Ingo Molnar <mingo@elte.hu> writes:
> (moved from lkml to the Git list)
>
> * Peter Zijlstra <peterz@infradead.org> wrote:
>
>> > Mailer:
>> > git-send-email 1.6.5.2
>>
>> Please teach your git-send-email thing to use --no-chain-reply-to.
> ...
> So ... the question would be ... could git-send-email flip its default
> please, via the patch below? Am i missing something subtle about why
> this default was chosen?
I do not think there was any conscious decision made when the
chain-reply-to was added. It was done and it got stuck.
I think the _only_ argument anybody _could_ make (and I won't be making
it, as I'd rather wish we had no-chain-reply-to the default from day one)
against the change of default is that it is a change [*1*].
Lkml already had two rather heated discussion in the past,
After the first round, I said we'd change the default to no-chain-reply-to
in release 1.6.3 unless somebody makes a convincing argument why the
default should not change, back around the time we were preparing for
1.6.2 (February 2009).
http://thread.gmane.org/gmane.comp.version-control.git/109790
Nobody complained.
Then I forgot to make such a declaration in the release notes to 1.6.3,
and no such declaration appeard in later release notes, either.
But nobody complained (nor reminded me).
The second round of the discussion was in August 2009. This time I did
something to prevent me from forgetting in the future.
http://thread.gmane.org/gmane.linux.kernel/879975/focus=880938
This patch is queued in 'next', scheduled to graduate to 'master' for the
1.7.0 release.
[Footnote]
*1* To spell it out... The people who are in the "hate chain-reply-to
very much" camp would have already done their own configuration to get the
behaviour they want by now, so changing the default would not help them
much, while potentially hurting "love chain-reply-to" people who have been
content because they got what they wanted without setting any
configuration.
^ permalink raw reply
* Re: [RFC, PATCH] git send-email: Make --no-chain-reply-to the default
From: Junio C Hamano @ 2009-11-10 6:05 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Jay Soffian, Peter Zijlstra, git
In-Reply-To: <20091110052211.GK7897@elte.hu>
Ingo Molnar <mingo@elte.hu> writes:
> +1 for putting it into a .1.6.x stable branch too. (Unless there's a
> case where the recursive threading is actually useful and is being
> relied on.)
As I wrote in the LKML message when that patch was made (please see my
other message for the URL to the archive), my assessment of this issue is
that it would have been the right thing to do if we were doing this now
without any existing users, but nobody really cares deeply enough either
way to warrant fast tracking the schedule we promised back in August.
It would take a bit stronger nudging than "unless there is a case against
changing the default because it is being relied on", as I know that people
who rely on would not speak up for a long time. We already saw that it
took 6 month between Feb 2009 to Aug 2009 for people who wanted to change
the default to notice and complain that the change they were promised did
not happen ;-).
Some people will complain when we switch the default to no-chain-reply-to
in the 1.7.0 release. I am willing to take flak from them and defend the
change.
But I am not convinced that this deserves to be fast-tracked to the 1.6.x
series. We gave them until 1.7.0 and I have no good answer to "why didn't
you wait as you promised?" I'd rather avoid telling them that "that is
how kernel people wanted it, and sorry, their wish trumps yours." if I
can.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox