mirror of
https://github.com/git/git.git
synced 2024-12-18 06:14:59 +08:00
builtin-remote: new show output style
The existing output of "git remote show <remote>" is too verbose for the information it provides. This patch teaches it to provide more information in less space. The output for push refspecs is addressed in the next patch. Before the patch: $ git remote show origin * remote origin URL: git://git.kernel.org/pub/scm/git/git.git HEAD branch: master Remote branch merged with 'git pull' while on branch master master Remote branch merged with 'git pull' while on branch next next Remote branches merged with 'git pull' while on branch octopus foo bar baz frotz New remote branch (next fetch will store in remotes/origin) html Stale tracking branch (use 'git remote prune') bogus Tracked remote branches maint man master next pu todo After this patch: $ git remote show origin * remote origin URL: git://git.kernel.org/pub/scm/git/git.git HEAD branch: master Remote branches: bogus stale (use 'git remote prune' to remove) html new (next fetch will store in remotes/origin) maint tracked man tracked master tracked next tracked pu tracked todo tracked Local branches configured for 'git pull': master rebases onto remote master next rebases onto remote next octopus merges with remote foo and with remote bar and with remote baz and with remote frotz $ git remote show origin -n * remote origin URL: git://git.kernel.org/pub/scm/git/git.git HEAD branch: (not queried) Remote branches: (status not queried) bogus maint man master next pu todo Local branches configured for 'git pull': master rebases onto remote master next rebases onto remote next octopus merges with remote foo and with remote bar and with remote baz and with remote frotz Signed-off-by: Jay Soffian <jaysoffian@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
fbb074c253
commit
7ecbbf877c
178
builtin-remote.c
178
builtin-remote.c
@ -149,6 +149,7 @@ static int add(int argc, const char **argv)
|
|||||||
struct branch_info {
|
struct branch_info {
|
||||||
char *remote_name;
|
char *remote_name;
|
||||||
struct string_list merge;
|
struct string_list merge;
|
||||||
|
int rebase;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct string_list branch_list;
|
static struct string_list branch_list;
|
||||||
@ -165,10 +166,11 @@ static const char *abbrev_ref(const char *name, const char *prefix)
|
|||||||
static int config_read_branches(const char *key, const char *value, void *cb)
|
static int config_read_branches(const char *key, const char *value, void *cb)
|
||||||
{
|
{
|
||||||
if (!prefixcmp(key, "branch.")) {
|
if (!prefixcmp(key, "branch.")) {
|
||||||
|
const char *orig_key = key;
|
||||||
char *name;
|
char *name;
|
||||||
struct string_list_item *item;
|
struct string_list_item *item;
|
||||||
struct branch_info *info;
|
struct branch_info *info;
|
||||||
enum { REMOTE, MERGE } type;
|
enum { REMOTE, MERGE, REBASE } type;
|
||||||
|
|
||||||
key += 7;
|
key += 7;
|
||||||
if (!postfixcmp(key, ".remote")) {
|
if (!postfixcmp(key, ".remote")) {
|
||||||
@ -177,6 +179,9 @@ static int config_read_branches(const char *key, const char *value, void *cb)
|
|||||||
} else if (!postfixcmp(key, ".merge")) {
|
} else if (!postfixcmp(key, ".merge")) {
|
||||||
name = xstrndup(key, strlen(key) - 6);
|
name = xstrndup(key, strlen(key) - 6);
|
||||||
type = MERGE;
|
type = MERGE;
|
||||||
|
} else if (!postfixcmp(key, ".rebase")) {
|
||||||
|
name = xstrndup(key, strlen(key) - 7);
|
||||||
|
type = REBASE;
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -187,9 +192,9 @@ static int config_read_branches(const char *key, const char *value, void *cb)
|
|||||||
info = item->util;
|
info = item->util;
|
||||||
if (type == REMOTE) {
|
if (type == REMOTE) {
|
||||||
if (info->remote_name)
|
if (info->remote_name)
|
||||||
warning("more than one branch.%s", key);
|
warning("more than one %s", orig_key);
|
||||||
info->remote_name = xstrdup(value);
|
info->remote_name = xstrdup(value);
|
||||||
} else {
|
} else if (type == MERGE) {
|
||||||
char *space = strchr(value, ' ');
|
char *space = strchr(value, ' ');
|
||||||
value = abbrev_branch(value);
|
value = abbrev_branch(value);
|
||||||
while (space) {
|
while (space) {
|
||||||
@ -200,7 +205,8 @@ static int config_read_branches(const char *key, const char *value, void *cb)
|
|||||||
space = strchr(value, ' ');
|
space = strchr(value, ' ');
|
||||||
}
|
}
|
||||||
string_list_append(xstrdup(value), &info->merge);
|
string_list_append(xstrdup(value), &info->merge);
|
||||||
}
|
} else
|
||||||
|
info->rebase = git_config_bool(orig_key, value);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -215,6 +221,7 @@ static void read_branches(void)
|
|||||||
struct ref_states {
|
struct ref_states {
|
||||||
struct remote *remote;
|
struct remote *remote;
|
||||||
struct string_list new, stale, tracked, heads;
|
struct string_list new, stale, tracked, heads;
|
||||||
|
int queried;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int handle_one_branch(const char *refname,
|
static int handle_one_branch(const char *refname,
|
||||||
@ -637,20 +644,6 @@ static int rm(int argc, const char **argv)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_list(const char *title, struct string_list *list,
|
|
||||||
const char *extra_arg)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!list->nr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
printf(title, list->nr > 1 ? "es" : "", extra_arg);
|
|
||||||
printf("\n");
|
|
||||||
for (i = 0; i < list->nr; i++)
|
|
||||||
printf(" %s\n", list->items[i].string);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_remote_ref_states(struct ref_states *states)
|
static void free_remote_ref_states(struct ref_states *states)
|
||||||
{
|
{
|
||||||
string_list_clear(&states->new, 0);
|
string_list_clear(&states->new, 0);
|
||||||
@ -695,6 +688,7 @@ 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);
|
||||||
|
|
||||||
|
states->queried = 1;
|
||||||
if (query & GET_REF_STATES)
|
if (query & GET_REF_STATES)
|
||||||
get_ref_states(remote_refs, states);
|
get_ref_states(remote_refs, states);
|
||||||
if (query & GET_HEAD_NAMES)
|
if (query & GET_HEAD_NAMES)
|
||||||
@ -707,6 +701,104 @@ static int get_remote_ref_states(const char *name,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct show_info {
|
||||||
|
struct string_list *list;
|
||||||
|
struct ref_states *states;
|
||||||
|
int width;
|
||||||
|
int any_rebase;
|
||||||
|
};
|
||||||
|
|
||||||
|
int add_remote_to_show_info(struct string_list_item *item, void *cb_data)
|
||||||
|
{
|
||||||
|
struct show_info *info = cb_data;
|
||||||
|
int n = strlen(item->string);
|
||||||
|
if (n > info->width)
|
||||||
|
info->width = n;
|
||||||
|
string_list_insert(item->string, info->list);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int show_remote_info_item(struct string_list_item *item, void *cb_data)
|
||||||
|
{
|
||||||
|
struct show_info *info = cb_data;
|
||||||
|
struct ref_states *states = info->states;
|
||||||
|
const char *name = item->string;
|
||||||
|
|
||||||
|
if (states->queried) {
|
||||||
|
const char *fmt = "%s";
|
||||||
|
const char *arg = "";
|
||||||
|
if (string_list_has_string(&states->new, name)) {
|
||||||
|
fmt = " new (next fetch will store in remotes/%s)";
|
||||||
|
arg = states->remote->name;
|
||||||
|
} else if (string_list_has_string(&states->tracked, name))
|
||||||
|
arg = " tracked";
|
||||||
|
else if (string_list_has_string(&states->stale, name))
|
||||||
|
arg = " stale (use 'git remote prune' to remove)";
|
||||||
|
else
|
||||||
|
arg = " ???";
|
||||||
|
printf(" %-*s", info->width, name);
|
||||||
|
printf(fmt, arg);
|
||||||
|
printf("\n");
|
||||||
|
} else
|
||||||
|
printf(" %s\n", name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_local_to_show_info(struct string_list_item *branch_item, void *cb_data)
|
||||||
|
{
|
||||||
|
struct show_info *show_info = cb_data;
|
||||||
|
struct ref_states *states = show_info->states;
|
||||||
|
struct branch_info *branch_info = branch_item->util;
|
||||||
|
struct string_list_item *item;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (!branch_info->merge.nr || !branch_info->remote_name ||
|
||||||
|
strcmp(states->remote->name, branch_info->remote_name))
|
||||||
|
return 0;
|
||||||
|
if ((n = strlen(branch_item->string)) > show_info->width)
|
||||||
|
show_info->width = n;
|
||||||
|
if (branch_info->rebase)
|
||||||
|
show_info->any_rebase = 1;
|
||||||
|
|
||||||
|
item = string_list_insert(branch_item->string, show_info->list);
|
||||||
|
item->util = branch_info;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int show_local_info_item(struct string_list_item *item, void *cb_data)
|
||||||
|
{
|
||||||
|
struct show_info *show_info = cb_data;
|
||||||
|
struct branch_info *branch_info = item->util;
|
||||||
|
struct string_list *merge = &branch_info->merge;
|
||||||
|
const char *also;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (branch_info->rebase && branch_info->merge.nr > 1) {
|
||||||
|
error("invalid branch.%s.merge; cannot rebase onto > 1 branch",
|
||||||
|
item->string);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" %-*s ", show_info->width, item->string);
|
||||||
|
if (branch_info->rebase) {
|
||||||
|
printf("rebases onto remote %s\n", merge->items[0].string);
|
||||||
|
return 0;
|
||||||
|
} else if (show_info->any_rebase) {
|
||||||
|
printf(" merges with remote %s\n", merge->items[0].string);
|
||||||
|
also = " and with remote";
|
||||||
|
} else {
|
||||||
|
printf("merges with remote %s\n", merge->items[0].string);
|
||||||
|
also = " and with remote";
|
||||||
|
}
|
||||||
|
for (i = 1; i < merge->nr; i++)
|
||||||
|
printf(" %-*s %s %s\n", show_info->width, "", also,
|
||||||
|
merge->items[i].string);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int show(int argc, const char **argv)
|
static int show(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int no_query = 0, result = 0, query_flag = 0;
|
int no_query = 0, result = 0, query_flag = 0;
|
||||||
@ -716,6 +808,8 @@ static int show(int argc, const char **argv)
|
|||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
struct ref_states states;
|
struct ref_states states;
|
||||||
|
struct string_list info_list = { NULL, 0, 0, 0 };
|
||||||
|
struct show_info info;
|
||||||
|
|
||||||
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
|
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
|
||||||
|
|
||||||
@ -726,6 +820,9 @@ static int show(int argc, const char **argv)
|
|||||||
query_flag = (GET_REF_STATES | GET_HEAD_NAMES);
|
query_flag = (GET_REF_STATES | GET_HEAD_NAMES);
|
||||||
|
|
||||||
memset(&states, 0, sizeof(states));
|
memset(&states, 0, sizeof(states));
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
info.states = &states;
|
||||||
|
info.list = &info_list;
|
||||||
for (; argc; argc--, argv++) {
|
for (; argc; argc--, argv++) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -747,32 +844,29 @@ static int show(int argc, const char **argv)
|
|||||||
printf(" %s\n", states.heads.items[i].string);
|
printf(" %s\n", states.heads.items[i].string);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < branch_list.nr; i++) {
|
/* remote branch info */
|
||||||
struct string_list_item *branch = branch_list.items + i;
|
info.width = 0;
|
||||||
struct branch_info *info = branch->util;
|
for_each_string_list(add_remote_to_show_info, &states.new, &info);
|
||||||
int j;
|
for_each_string_list(add_remote_to_show_info, &states.tracked, &info);
|
||||||
|
for_each_string_list(add_remote_to_show_info, &states.stale, &info);
|
||||||
|
if (info.list->nr)
|
||||||
|
printf(" Remote branch%s:%s\n",
|
||||||
|
info.list->nr > 1 ? "es" : "",
|
||||||
|
no_query ? " (status not queried)" : "");
|
||||||
|
for_each_string_list(show_remote_info_item, info.list, &info);
|
||||||
|
string_list_clear(info.list, 0);
|
||||||
|
|
||||||
if (!info->merge.nr || strcmp(*argv, info->remote_name))
|
/* git pull info */
|
||||||
continue;
|
info.width = 0;
|
||||||
printf(" Remote branch%s merged with 'git pull' "
|
info.any_rebase = 0;
|
||||||
"while on branch %s\n ",
|
for_each_string_list(add_local_to_show_info, &branch_list, &info);
|
||||||
info->merge.nr > 1 ? "es" : "",
|
if (info.list->nr)
|
||||||
branch->string);
|
printf(" Local branch%s configured for 'git pull':\n",
|
||||||
for (j = 0; j < info->merge.nr; j++)
|
info.list->nr > 1 ? "es" : "");
|
||||||
printf(" %s", info->merge.items[j].string);
|
for_each_string_list(show_local_info_item, info.list, &info);
|
||||||
printf("\n");
|
string_list_clear(info.list, 0);
|
||||||
}
|
|
||||||
|
|
||||||
if (!no_query) {
|
|
||||||
show_list(" New remote branch%s (next fetch "
|
|
||||||
"will store in remotes/%s)",
|
|
||||||
&states.new, states.remote->name);
|
|
||||||
show_list(" Stale tracking branch%s (use 'git remote "
|
|
||||||
"prune')", &states.stale, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
show_list(" Tracked remote branch%s", &states.tracked, "");
|
|
||||||
|
|
||||||
|
/* git push info */
|
||||||
if (states.remote->push_refspec_nr) {
|
if (states.remote->push_refspec_nr) {
|
||||||
printf(" Local branch%s pushed with 'git push'\n",
|
printf(" Local branch%s pushed with 'git push'\n",
|
||||||
states.remote->push_refspec_nr > 1 ?
|
states.remote->push_refspec_nr > 1 ?
|
||||||
|
@ -28,7 +28,7 @@ tokens_match () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check_remote_track () {
|
check_remote_track () {
|
||||||
actual=$(git remote show "$1" | sed -e '1,/Tracked/d') &&
|
actual=$(git remote show "$1" | sed -ne 's|^ \(.*\) tracked$|\1|p')
|
||||||
shift &&
|
shift &&
|
||||||
tokens_match "$*" "$actual"
|
tokens_match "$*" "$actual"
|
||||||
}
|
}
|
||||||
@ -137,13 +137,15 @@ cat > test/expect << EOF
|
|||||||
* remote origin
|
* remote origin
|
||||||
URL: $(pwd)/one
|
URL: $(pwd)/one
|
||||||
HEAD branch: master
|
HEAD branch: master
|
||||||
Remote branch merged with 'git pull' while on branch master
|
Remote branches:
|
||||||
master
|
master new (next fetch will store in remotes/origin)
|
||||||
New remote branch (next fetch will store in remotes/origin)
|
side tracked
|
||||||
master
|
Local branches configured for 'git pull':
|
||||||
Tracked remote branches
|
master merges with remote master
|
||||||
master
|
octopus merges with remote topic-a
|
||||||
side
|
and with remote topic-b
|
||||||
|
and with remote topic-c
|
||||||
|
rebase rebases onto remote master
|
||||||
Local branches pushed with 'git push'
|
Local branches pushed with 'git push'
|
||||||
master:upstream
|
master:upstream
|
||||||
+refs/tags/lastbackup
|
+refs/tags/lastbackup
|
||||||
@ -156,20 +158,22 @@ EOF
|
|||||||
|
|
||||||
test_expect_success 'show' '
|
test_expect_success 'show' '
|
||||||
(cd test &&
|
(cd test &&
|
||||||
git config --add remote.origin.fetch \
|
git config --add remote.origin.fetch refs/heads/master:refs/heads/upstream &&
|
||||||
refs/heads/master:refs/heads/upstream &&
|
|
||||||
git fetch &&
|
git fetch &&
|
||||||
|
git branch --track octopus origin/master &&
|
||||||
|
git branch --track rebase origin/master &&
|
||||||
git branch -d -r origin/master &&
|
git branch -d -r origin/master &&
|
||||||
git config --add remote.two.url ../two &&
|
git config --add remote.two.url ../two &&
|
||||||
|
git config branch.rebase.rebase true &&
|
||||||
|
git config branch.octopus.merge "topic-a topic-b topic-c" &&
|
||||||
(cd ../one &&
|
(cd ../one &&
|
||||||
echo 1 > file &&
|
echo 1 > file &&
|
||||||
test_tick &&
|
test_tick &&
|
||||||
git commit -m update file) &&
|
git commit -m update file) &&
|
||||||
git config remote.origin.push \
|
git config remote.origin.push refs/heads/master:refs/heads/upstream &&
|
||||||
refs/heads/master:refs/heads/upstream &&
|
git config --add remote.origin.push +refs/tags/lastbackup &&
|
||||||
git config --add remote.origin.push \
|
|
||||||
+refs/tags/lastbackup &&
|
|
||||||
git remote show origin two > output &&
|
git remote show origin two > output &&
|
||||||
|
git branch -d rebase octopus &&
|
||||||
test_cmp expect output)
|
test_cmp expect output)
|
||||||
'
|
'
|
||||||
|
|
||||||
@ -177,11 +181,11 @@ cat > test/expect << EOF
|
|||||||
* remote origin
|
* remote origin
|
||||||
URL: $(pwd)/one
|
URL: $(pwd)/one
|
||||||
HEAD branch: (not queried)
|
HEAD branch: (not queried)
|
||||||
Remote branch merged with 'git pull' while on branch master
|
Remote branches: (status not queried)
|
||||||
master
|
|
||||||
Tracked remote branches
|
|
||||||
master
|
master
|
||||||
side
|
side
|
||||||
|
Local branch configured for 'git pull':
|
||||||
|
master merges with remote master
|
||||||
Local branches pushed with 'git push'
|
Local branches pushed with 'git push'
|
||||||
master:upstream
|
master:upstream
|
||||||
+refs/tags/lastbackup
|
+refs/tags/lastbackup
|
||||||
|
Loading…
Reference in New Issue
Block a user