builtin-remote: teach show to display remote HEAD
authorJay Soffian <jaysoffian@gmail.com>
Wed, 25 Feb 2009 08:32:24 +0000 (03:32 -0500)
committerJunio C Hamano <gitster@pobox.com>
Fri, 27 Feb 2009 23:19:09 +0000 (15:19 -0800)
This is in preparation for teaching remote how to set
refs/remotes/<remote>/HEAD to match what HEAD is set to at <remote>, but
is useful in its own right.

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-remote.c
t/t5505-remote.sh

index 963be6df95e2d38166a54a2727c895f14663127d..4543cf082653f7273a44dcc9c18914302d688d3e 100644 (file)
@@ -18,6 +18,9 @@ static const char * const builtin_remote_usage[] = {
        NULL
 };
 
+#define GET_REF_STATES (1<<0)
+#define GET_HEAD_NAMES (1<<1)
+
 static int verbose;
 
 static int show_all(void);
@@ -210,7 +213,7 @@ static void read_branches(void)
 
 struct ref_states {
        struct remote *remote;
-       struct string_list new, stale, tracked;
+       struct string_list new, stale, tracked, heads;
 };
 
 static int handle_one_branch(const char *refname,
@@ -264,6 +267,28 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
        return 0;
 }
 
+static int get_head_names(const struct ref *remote_refs, struct ref_states *states)
+{
+       struct ref *ref, *matches;
+       struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
+       struct refspec refspec;
+
+       refspec.force = 0;
+       refspec.pattern = 1;
+       refspec.src = refspec.dst = "refs/heads/";
+       states->heads.strdup_strings = 1;
+       get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
+       matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
+                                   fetch_map, 1);
+       for(ref = matches; ref; ref = ref->next)
+               string_list_append(abbrev_branch(ref->name), &states->heads);
+
+       free_refs(fetch_map);
+       free_refs(matches);
+
+       return 0;
+}
+
 struct known_remote {
        struct known_remote *next;
        struct remote *remote;
@@ -630,6 +655,7 @@ static void free_remote_ref_states(struct ref_states *states)
        string_list_clear(&states->new, 0);
        string_list_clear(&states->stale, 0);
        string_list_clear(&states->tracked, 0);
+       string_list_clear(&states->heads, 0);
 }
 
 static int append_ref_to_tracked_list(const char *refname,
@@ -668,7 +694,10 @@ static int get_remote_ref_states(const char *name,
                remote_refs = transport_get_remote_refs(transport);
                transport_disconnect(transport);
 
-               get_ref_states(remote_refs, states);
+               if (query & GET_REF_STATES)
+                       get_ref_states(remote_refs, states);
+               if (query & GET_HEAD_NAMES)
+                       get_head_names(remote_refs, states);
        } else {
                for_each_ref(append_ref_to_tracked_list, states);
                sort_string_list(&states->tracked);
@@ -679,7 +708,7 @@ static int get_remote_ref_states(const char *name,
 
 static int show(int argc, const char **argv)
 {
-       int no_query = 0, result = 0;
+       int no_query = 0, result = 0, query_flag = 0;
        struct option options[] = {
                OPT_GROUP("show specific options"),
                OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"),
@@ -692,15 +721,30 @@ static int show(int argc, const char **argv)
        if (argc < 1)
                return show_all();
 
+       if (!no_query)
+               query_flag = (GET_REF_STATES | GET_HEAD_NAMES);
+
        memset(&states, 0, sizeof(states));
        for (; argc; argc--, argv++) {
                int i;
 
-               get_remote_ref_states(*argv, &states, !no_query);
+               get_remote_ref_states(*argv, &states, query_flag);
 
                printf("* remote %s\n  URL: %s\n", *argv,
                        states.remote->url_nr > 0 ?
                                states.remote->url[0] : "(no URL)");
+               if (no_query)
+                       printf("  HEAD branch: (not queried)\n");
+               else if (!states.heads.nr)
+                       printf("  HEAD branch: (unknown)\n");
+               else if (states.heads.nr == 1)
+                       printf("  HEAD branch: %s\n", states.heads.items[0].string);
+               else {
+                       printf("  HEAD branch (remote HEAD is ambiguous,"
+                              " may be one of the following):\n");
+                       for (i = 0; i < states.heads.nr; i++)
+                               printf("    %s\n", states.heads.items[i].string);
+               }
 
                for (i = 0; i < branch_list.nr; i++) {
                        struct string_list_item *branch = branch_list.items + i;
@@ -772,7 +816,7 @@ static int prune(int argc, const char **argv)
        for (; argc; argc--, argv++) {
                int i;
 
-               get_remote_ref_states(*argv, &states, 1);
+               get_remote_ref_states(*argv, &states, GET_REF_STATES);
 
                if (states.stale.nr) {
                        printf("Pruning %s\n", *argv);
index a13d4b66d6766c003c1cbad1d0c70f385b12b0f3..91525c3f9c1a04437516dbc7fa095cef0ef4a666 100755 (executable)
@@ -136,6 +136,7 @@ EOF
 cat > test/expect << EOF
 * remote origin
   URL: $(pwd)/one
+  HEAD branch: master
   Remote branch merged with 'git pull' while on branch master
     master
   New remote branch (next fetch will store in remotes/origin)
@@ -146,6 +147,11 @@ cat > test/expect << EOF
   Local branches pushed with 'git push'
     master:upstream
     +refs/tags/lastbackup
+* remote two
+  URL: ../two
+  HEAD branch (remote HEAD is ambiguous, may be one of the following):
+    another
+    master
 EOF
 
 test_expect_success 'show' '
@@ -154,6 +160,7 @@ test_expect_success 'show' '
                refs/heads/master:refs/heads/upstream &&
         git fetch &&
         git branch -d -r origin/master &&
+        git config --add remote.two.url ../two &&
         (cd ../one &&
          echo 1 > file &&
          test_tick &&
@@ -162,13 +169,14 @@ test_expect_success 'show' '
                refs/heads/master:refs/heads/upstream &&
         git config --add remote.origin.push \
                +refs/tags/lastbackup &&
-        git remote show origin > output &&
+        git remote show origin two > output &&
         test_cmp expect output)
 '
 
 cat > test/expect << EOF
 * remote origin
   URL: $(pwd)/one
+  HEAD branch: (not queried)
   Remote branch merged with 'git pull' while on branch master
     master
   Tracked remote branches
@@ -343,7 +351,7 @@ test_expect_success '"remote show" does not show symbolic refs' '
        git clone one three &&
        (cd three &&
         git remote show origin > output &&
-        ! grep HEAD < output &&
+        ! grep "^ *HEAD$" < output &&
         ! grep -i stale < output)
 
 '