From 0ecfcb3b700e7e3097a55f015894ad75f1097090 Mon Sep 17 00:00:00 2001 From: Olivier Marin <dkr@freesurf.fr> Date: Tue, 10 Jun 2008 16:51:08 +0200 Subject: [PATCH 1/5] remote show: fix the -n option The perl version accepted a -n flag, to show local informations only without querying remote heads, that seems to have been lost in the C revrite. This restores the older behaviour and add a test case. Signed-off-by: Olivier Marin <dkr@freesurf.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com> --- Documentation/git-remote.txt | 2 +- builtin-remote.c | 44 +++++++++++++++++++----------------- t/t5505-remote.sh | 17 ++++++++++++++ 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 782b0554cf..7bd024eeba 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -12,7 +12,7 @@ SYNOPSIS 'git-remote' [-v | --verbose] 'git-remote' add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url> 'git-remote' rm <name> -'git-remote' show <name> +'git-remote' show [-n] <name> 'git-remote' prune <name> 'git-remote' update [group] diff --git a/builtin-remote.c b/builtin-remote.c index c49f00f58b..efe74c7d5d 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -421,10 +421,10 @@ static void show_list(const char *title, struct path_list *list) static int show_or_prune(int argc, const char **argv, int prune) { - int dry_run = 0, result = 0; + int no_query = 0, result = 0; struct option options[] = { OPT_GROUP("show specific options"), - OPT__DRY_RUN(&dry_run), + OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"), OPT_END() }; struct ref_states states; @@ -442,21 +442,23 @@ static int show_or_prune(int argc, const char **argv, int prune) struct transport *transport; const struct ref *ref; struct strbuf buf; - int i, got_states; + int i; states.remote = remote_get(*argv); if (!states.remote) return error("No such remote: %s", *argv); - transport = transport_get(NULL, states.remote->url_nr > 0 ? - states.remote->url[0] : NULL); - ref = transport_get_remote_refs(transport); - transport_disconnect(transport); read_branches(); - got_states = get_ref_states(ref, &states); - if (got_states) - result = error("Error getting local info for '%s'", - states.remote->name); + + if (!no_query) { + transport = transport_get(NULL, + states.remote->url_nr > 0 ? + states.remote->url[0] : NULL); + ref = transport_get_remote_refs(transport); + transport_disconnect(transport); + + get_ref_states(ref, &states); + } if (prune) { for (i = 0; i < states.stale.nr; i++) { @@ -486,17 +488,17 @@ static int show_or_prune(int argc, const char **argv, int prune) printf("\n"); } - if (got_states) - continue; - strbuf_init(&buf, 0); - strbuf_addf(&buf, " New remote branch%%s (next fetch will " - "store in remotes/%s)", states.remote->name); - show_list(buf.buf, &states.new); - strbuf_release(&buf); - show_list(" Stale tracking branch%s (use 'git remote prune')", - &states.stale); - show_list(" Tracked remote branch%s", + if (!no_query) { + strbuf_init(&buf, 0); + strbuf_addf(&buf, " New remote branch%%s (next fetch " + "will store in remotes/%s)", states.remote->name); + show_list(buf.buf, &states.new); + strbuf_release(&buf); + show_list(" Stale tracking branch%s (use 'git remote " + "prune')", &states.stale); + show_list(" Tracked remote branch%s", &states.tracked); + } if (states.remote->push_refspec_nr) { printf(" Local branch%s pushed with 'git push'\n ", diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 0d7ed1f99b..c6a7bfb448 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -138,6 +138,23 @@ test_expect_success 'show' ' test_cmp expect output) ' +cat > test/expect << EOF +* remote origin + URL: $(pwd)/one/.git + Remote branch merged with 'git pull' while on branch master + master + Local branches pushed with 'git push' + master:upstream +refs/tags/lastbackup +EOF + +test_expect_success 'show -n' ' + (mv one one.unreachable && + cd test && + git remote show -n origin > output && + mv ../one.unreachable ../one && + test_cmp expect output) +' + test_expect_success 'prune' ' (cd one && git branch -m side side2) && From 67a7e2d07162dc470f7e3ae1889aad146e5b7917 Mon Sep 17 00:00:00 2001 From: Olivier Marin <dkr@freesurf.fr> Date: Tue, 10 Jun 2008 16:51:21 +0200 Subject: [PATCH 2/5] builtin-remote: split show_or_prune() in two separate functions This allow us to add different features to each of them and keep the code simple at the same time. Also create a get_remote_ref_states() to avoid duplicated code. Signed-off-by: Olivier Marin <dkr@freesurf.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com> --- builtin-remote.c | 101 +++++++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 34 deletions(-) diff --git a/builtin-remote.c b/builtin-remote.c index efe74c7d5d..745a4ee6c5 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -419,7 +419,32 @@ static void show_list(const char *title, struct path_list *list) printf("\n"); } -static int show_or_prune(int argc, const char **argv, int prune) +static int get_remote_ref_states(const char *name, + struct ref_states *states, + int query) +{ + struct transport *transport; + const struct ref *ref; + + states->remote = remote_get(name); + if (!states->remote) + return error("No such remote: %s", name); + + read_branches(); + + if (query) { + transport = transport_get(NULL, states->remote->url_nr > 0 ? + states->remote->url[0] : NULL); + ref = transport_get_remote_refs(transport); + transport_disconnect(transport); + + get_ref_states(ref, states); + } + + return 0; +} + +static int show(int argc, const char **argv) { int no_query = 0, result = 0; struct option options[] = { @@ -431,42 +456,15 @@ static int show_or_prune(int argc, const char **argv, int prune) argc = parse_options(argc, argv, options, builtin_remote_usage, 0); - if (argc < 1) { - if (!prune) - return show_all(); - usage_with_options(builtin_remote_usage, options); - } + if (argc < 1) + return show_all(); memset(&states, 0, sizeof(states)); for (; argc; argc--, argv++) { - struct transport *transport; - const struct ref *ref; struct strbuf buf; int i; - states.remote = remote_get(*argv); - if (!states.remote) - return error("No such remote: %s", *argv); - - read_branches(); - - if (!no_query) { - transport = transport_get(NULL, - states.remote->url_nr > 0 ? - states.remote->url[0] : NULL); - ref = transport_get_remote_refs(transport); - transport_disconnect(transport); - - get_ref_states(ref, &states); - } - - if (prune) { - for (i = 0; i < states.stale.nr; i++) { - const char *refname = states.stale.items[i].util; - result |= delete_ref(refname, NULL); - } - goto cleanup_states; - } + get_remote_ref_states(*argv, &states, !no_query); printf("* remote %s\n URL: %s\n", *argv, states.remote->url_nr > 0 ? @@ -513,7 +511,42 @@ static int show_or_prune(int argc, const char **argv, int prune) } printf("\n"); } -cleanup_states: + + /* NEEDSWORK: free remote */ + path_list_clear(&states.new, 0); + path_list_clear(&states.stale, 0); + path_list_clear(&states.tracked, 0); + } + + return result; +} + +static int prune(int argc, const char **argv) +{ + int no_query = 0, result = 0; + struct option options[] = { + OPT_GROUP("prune specific options"), + OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"), + OPT_END() + }; + struct ref_states states; + + argc = parse_options(argc, argv, options, builtin_remote_usage, 0); + + if (argc < 1) + usage_with_options(builtin_remote_usage, options); + + memset(&states, 0, sizeof(states)); + for (; argc; argc--, argv++) { + int i; + + get_remote_ref_states(*argv, &states, !no_query); + + for (i = 0; i < states.stale.nr; i++) { + const char *refname = states.stale.items[i].util; + result |= delete_ref(refname, NULL); + } + /* NEEDSWORK: free remote */ path_list_clear(&states.new, 0); path_list_clear(&states.stale, 0); @@ -634,9 +667,9 @@ int cmd_remote(int argc, const char **argv, const char *prefix) else if (!strcmp(argv[0], "rm")) result = rm(argc, argv); else if (!strcmp(argv[0], "show")) - result = show_or_prune(argc, argv, 0); + result = show(argc, argv); else if (!strcmp(argv[0], "prune")) - result = show_or_prune(argc, argv, 1); + result = prune(argc, argv); else if (!strcmp(argv[0], "update")) result = update(argc, argv); else { From 8d7679276af861b44e307c9879f6c4774f4944fc Mon Sep 17 00:00:00 2001 From: Olivier Marin <dkr@freesurf.fr> Date: Tue, 10 Jun 2008 16:51:35 +0200 Subject: [PATCH 3/5] remote prune: print the list of pruned branches This command is really too quiet which make it unconfortable to use. Also implement a --dry-run option, in place of the original -n one, to list stale tracking branches that will be pruned, but do not actually prune them. Add a test case for --dry-run. Signed-off-by: Olivier Marin <dkr@freesurf.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com> --- Documentation/git-remote.txt | 7 +++---- builtin-remote.c | 20 ++++++++++++++++---- t/t5505-remote.sh | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 7bd024eeba..345943a264 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -13,7 +13,7 @@ SYNOPSIS 'git-remote' add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url> 'git-remote' rm <name> 'git-remote' show [-n] <name> -'git-remote' prune <name> +'git-remote' prune [-n | --dry-run] <name> 'git-remote' update [group] DESCRIPTION @@ -80,9 +80,8 @@ These stale branches have already been removed from the remote repository referenced by <name>, but are still locally available in "remotes/<name>". + -With `-n` option, the remote heads are not confirmed first with `git -ls-remote <name>`; cached information is used instead. Use with -caution. +With `--dry-run` option, report what branches will be pruned, but do no +actually prune them. 'update':: diff --git a/builtin-remote.c b/builtin-remote.c index 745a4ee6c5..6bce55cd53 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -523,10 +523,10 @@ static int show(int argc, const char **argv) static int prune(int argc, const char **argv) { - int no_query = 0, result = 0; + int dry_run = 0, result = 0; struct option options[] = { OPT_GROUP("prune specific options"), - OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"), + OPT__DRY_RUN(&dry_run), OPT_END() }; struct ref_states states; @@ -540,11 +540,23 @@ static int prune(int argc, const char **argv) for (; argc; argc--, argv++) { int i; - get_remote_ref_states(*argv, &states, !no_query); + get_remote_ref_states(*argv, &states, 1); + + printf("Pruning %s\n", *argv); + if (states.stale.nr) + printf("URL: %s\n", + states.remote->url_nr + ? states.remote->url[0] + : "(no URL)"); for (i = 0; i < states.stale.nr; i++) { const char *refname = states.stale.items[i].util; - result |= delete_ref(refname, NULL); + + if (!dry_run) + result |= delete_ref(refname, NULL); + + printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned", + skip_prefix(refname, "refs/remotes/")); } /* NEEDSWORK: free remote */ diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index c6a7bfb448..c17d9dcc74 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -165,6 +165,24 @@ test_expect_success 'prune' ' ! git rev-parse refs/remotes/origin/side) ' +cat > test/expect << EOF +Pruning origin +URL: $(pwd)/one/.git + * [would prune] origin/side2 +EOF + +test_expect_success 'prune --dry-run' ' + (cd one && + git branch -m side2 side) && + (cd test && + git remote prune --dry-run origin > output && + git rev-parse refs/remotes/origin/side2 && + ! git rev-parse refs/remotes/origin/side && + (cd ../one && + git branch -m side side2) && + test_cmp expect output) +' + test_expect_success 'add --mirror && prune' ' (mkdir mirror && cd mirror && From e7d5a97d5e131925ccae48db94f2069631a8aa41 Mon Sep 17 00:00:00 2001 From: Olivier Marin <dkr@freesurf.fr> Date: Wed, 11 Jun 2008 00:54:49 +0200 Subject: [PATCH 4/5] remote show: list tracked remote branches with -n Signed-off-by: Olivier Marin <dkr@freesurf.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com> --- builtin-remote.c | 22 ++++++++++++++++++++-- t/t5505-remote.sh | 2 ++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/builtin-remote.c b/builtin-remote.c index 6bce55cd53..4b00cf9258 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -444,6 +444,22 @@ static int get_remote_ref_states(const char *name, return 0; } +static int append_ref_to_tracked_list(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)) { + path_list_append(skip_prefix(refspec.src, "refs/heads/"), + &states->tracked); + } + + return 0; +} + static int show(int argc, const char **argv) { int no_query = 0, result = 0; @@ -494,10 +510,12 @@ static int show(int argc, const char **argv) strbuf_release(&buf); show_list(" Stale tracking branch%s (use 'git remote " "prune')", &states.stale); - show_list(" Tracked remote branch%s", - &states.tracked); } + if (no_query) + for_each_ref(append_ref_to_tracked_list, &states); + show_list(" Tracked remote branch%s", &states.tracked); + if (states.remote->push_refspec_nr) { printf(" Local branch%s pushed with 'git push'\n ", states.remote->push_refspec_nr > 1 ? diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index c17d9dcc74..1e192a2207 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -143,6 +143,8 @@ cat > test/expect << EOF URL: $(pwd)/one/.git Remote branch merged with 'git pull' while on branch master master + Tracked remote branches + master side Local branches pushed with 'git push' master:upstream +refs/tags/lastbackup EOF From 8b7d4e738ee5489fecb5c4a55d14884b09e0dc6d Mon Sep 17 00:00:00 2001 From: Junio C Hamano <gitster@pobox.com> Date: Wed, 11 Jun 2008 23:43:25 -0700 Subject: [PATCH 5/5] "remote prune": be quiet when there is nothing to prune The previous commit made it always say "Pruning $remote" but reported the URL only when there is something to prune. Make it consistent by not saying anything at all when there is nothing to prune. Signed-off-by: Junio C Hamano <gitster@pobox.com> --- builtin-remote.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/builtin-remote.c b/builtin-remote.c index 4b00cf9258..145dd8568c 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -560,12 +560,13 @@ static int prune(int argc, const char **argv) get_remote_ref_states(*argv, &states, 1); - printf("Pruning %s\n", *argv); - if (states.stale.nr) + if (states.stale.nr) { + printf("Pruning %s\n", *argv); printf("URL: %s\n", states.remote->url_nr ? states.remote->url[0] : "(no URL)"); + } for (i = 0; i < states.stale.nr; i++) { const char *refname = states.stale.items[i].util;