builtin-remote: teach show to display remote HEAD

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>
This commit is contained in:
Jay Soffian 2009-02-25 03:32:24 -05:00 committed by Junio C Hamano
parent 3bd925636c
commit e61e0cc6b7
2 changed files with 59 additions and 7 deletions

View file

@ -18,6 +18,9 @@ static const char * const builtin_remote_usage[] = {
NULL NULL
}; };
#define GET_REF_STATES (1<<0)
#define GET_HEAD_NAMES (1<<1)
static int verbose; static int verbose;
static int show_all(void); static int show_all(void);
@ -210,7 +213,7 @@ static void read_branches(void)
struct ref_states { struct ref_states {
struct remote *remote; struct remote *remote;
struct string_list new, stale, tracked; struct string_list new, stale, tracked, heads;
}; };
static int handle_one_branch(const char *refname, 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; 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 {
struct known_remote *next; struct known_remote *next;
struct remote *remote; 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->new, 0);
string_list_clear(&states->stale, 0); string_list_clear(&states->stale, 0);
string_list_clear(&states->tracked, 0); string_list_clear(&states->tracked, 0);
string_list_clear(&states->heads, 0);
} }
static int append_ref_to_tracked_list(const char *refname, 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); remote_refs = transport_get_remote_refs(transport);
transport_disconnect(transport); transport_disconnect(transport);
if (query & GET_REF_STATES)
get_ref_states(remote_refs, states); get_ref_states(remote_refs, states);
if (query & GET_HEAD_NAMES)
get_head_names(remote_refs, states);
} else { } else {
for_each_ref(append_ref_to_tracked_list, states); for_each_ref(append_ref_to_tracked_list, states);
sort_string_list(&states->tracked); 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) 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[] = { struct option options[] = {
OPT_GROUP("show specific options"), OPT_GROUP("show specific options"),
OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"), 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) if (argc < 1)
return show_all(); return show_all();
if (!no_query)
query_flag = (GET_REF_STATES | GET_HEAD_NAMES);
memset(&states, 0, sizeof(states)); memset(&states, 0, sizeof(states));
for (; argc; argc--, argv++) { for (; argc; argc--, argv++) {
int i; 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, printf("* remote %s\n URL: %s\n", *argv,
states.remote->url_nr > 0 ? states.remote->url_nr > 0 ?
states.remote->url[0] : "(no URL)"); 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++) { for (i = 0; i < branch_list.nr; i++) {
struct string_list_item *branch = branch_list.items + 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++) { for (; argc; argc--, argv++) {
int i; int i;
get_remote_ref_states(*argv, &states, 1); get_remote_ref_states(*argv, &states, GET_REF_STATES);
if (states.stale.nr) { if (states.stale.nr) {
printf("Pruning %s\n", *argv); printf("Pruning %s\n", *argv);

View file

@ -136,6 +136,7 @@ EOF
cat > test/expect << EOF cat > test/expect << EOF
* remote origin * remote origin
URL: $(pwd)/one URL: $(pwd)/one
HEAD branch: master
Remote branch merged with 'git pull' while on branch master Remote branch merged with 'git pull' while on branch master
master master
New remote branch (next fetch will store in remotes/origin) New remote branch (next fetch will store in remotes/origin)
@ -146,6 +147,11 @@ cat > test/expect << EOF
Local branches pushed with 'git push' Local branches pushed with 'git push'
master:upstream master:upstream
+refs/tags/lastbackup +refs/tags/lastbackup
* remote two
URL: ../two
HEAD branch (remote HEAD is ambiguous, may be one of the following):
another
master
EOF EOF
test_expect_success 'show' ' test_expect_success 'show' '
@ -154,6 +160,7 @@ test_expect_success 'show' '
refs/heads/master:refs/heads/upstream && refs/heads/master:refs/heads/upstream &&
git fetch && git fetch &&
git branch -d -r origin/master && git branch -d -r origin/master &&
git config --add remote.two.url ../two &&
(cd ../one && (cd ../one &&
echo 1 > file && echo 1 > file &&
test_tick && test_tick &&
@ -162,13 +169,14 @@ test_expect_success 'show' '
refs/heads/master:refs/heads/upstream && refs/heads/master:refs/heads/upstream &&
git config --add remote.origin.push \ git config --add remote.origin.push \
+refs/tags/lastbackup && +refs/tags/lastbackup &&
git remote show origin > output && git remote show origin two > output &&
test_cmp expect output) test_cmp expect output)
' '
cat > test/expect << EOF cat > test/expect << EOF
* remote origin * remote origin
URL: $(pwd)/one URL: $(pwd)/one
HEAD branch: (not queried)
Remote branch merged with 'git pull' while on branch master Remote branch merged with 'git pull' while on branch master
master master
Tracked remote branches Tracked remote branches
@ -343,7 +351,7 @@ test_expect_success '"remote show" does not show symbolic refs' '
git clone one three && git clone one three &&
(cd three && (cd three &&
git remote show origin > output && git remote show origin > output &&
! grep HEAD < output && ! grep "^ *HEAD$" < output &&
! grep -i stale < output) ! grep -i stale < output)
' '