Show 344 quoted lines
>
> Change calc_maxwidth() to also account for the length of HEAD ref, by
> calling ref-filter:get_head_discription().
>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>
> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
> ---
> builtin/branch.c | 261 ++++++++++++-----------------------------------
> t/t6040-tracking-info.sh | 2 +-
> 2 files changed, 66 insertions(+), 197 deletions(-)
>
> diff --git a/builtin/branch.c b/builtin/branch.c
> index 67ef9f1..4d8b570 100644
> --- a/builtin/branch.c
> +++ b/builtin/branch.c
> @@ -35,12 +35,12 @@ static unsigned char head_sha1[20];
>
> static int branch_use_color = -1;
> static char branch_colors[][COLOR_MAXLEN] = {
> - GIT_COLOR_RESET,
> - GIT_COLOR_NORMAL, /* PLAIN */
> - GIT_COLOR_RED, /* REMOTE */
> - GIT_COLOR_NORMAL, /* LOCAL */
> - GIT_COLOR_GREEN, /* CURRENT */
> - GIT_COLOR_BLUE, /* UPSTREAM */
> + "%(color:reset)",
> + "%(color:reset)", /* PLAIN */
> + "%(color:red)", /* REMOTE */
> + "%(color:reset)", /* LOCAL */
> + "%(color:green)", /* CURRENT */
> + "%(color:blue)", /* UPSTREAM */
> };
> enum color_branch {
> BRANCH_COLOR_RESET = 0,
> @@ -271,192 +271,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
> return(ret);
> }
>
> -static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
> - int show_upstream_ref)
> -{
> - int ours, theirs;
> - char *ref = NULL;
> - struct branch *branch = branch_get(branch_name);
> - const char *upstream;
> - struct strbuf fancy = STRBUF_INIT;
> - int upstream_is_gone = 0;
> - int added_decoration = 1;
> -
> - if (stat_tracking_info(branch, &ours, &theirs, &upstream) < 0) {
> - if (!upstream)
> - return;
> - upstream_is_gone = 1;
> - }
> -
> - if (show_upstream_ref) {
> - ref = shorten_unambiguous_ref(upstream, 0);
> - if (want_color(branch_use_color))
> - strbuf_addf(&fancy, "%s%s%s",
> - branch_get_color(BRANCH_COLOR_UPSTREAM),
> - ref, branch_get_color(BRANCH_COLOR_RESET));
> - else
> - strbuf_addstr(&fancy, ref);
> - }
> -
> - if (upstream_is_gone) {
> - if (show_upstream_ref)
> - strbuf_addf(stat, _("[%s: gone]"), fancy.buf);
> - else
> - added_decoration = 0;
> - } else if (!ours && !theirs) {
> - if (show_upstream_ref)
> - strbuf_addf(stat, _("[%s]"), fancy.buf);
> - else
> - added_decoration = 0;
> - } else if (!ours) {
> - if (show_upstream_ref)
> - strbuf_addf(stat, _("[%s: behind %d]"), fancy.buf, theirs);
> - else
> - strbuf_addf(stat, _("[behind %d]"), theirs);
> -
> - } else if (!theirs) {
> - if (show_upstream_ref)
> - strbuf_addf(stat, _("[%s: ahead %d]"), fancy.buf, ours);
> - else
> - strbuf_addf(stat, _("[ahead %d]"), ours);
> - } else {
> - if (show_upstream_ref)
> - strbuf_addf(stat, _("[%s: ahead %d, behind %d]"),
> - fancy.buf, ours, theirs);
> - else
> - strbuf_addf(stat, _("[ahead %d, behind %d]"),
> - ours, theirs);
> - }
> - strbuf_release(&fancy);
> - if (added_decoration)
> - strbuf_addch(stat, ' ');
> - free(ref);
> -}
> -
> -static void add_verbose_info(struct strbuf *out, struct ref_array_item *item,
> - struct ref_filter *filter, const char *refname)
> -{
> - struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
> - const char *sub = _(" **** invalid ref ****");
> - struct commit *commit = item->commit;
> -
> - if (!parse_commit(commit)) {
> - pp_commit_easy(CMIT_FMT_ONELINE, commit, &subject);
> - sub = subject.buf;
> - }
> -
> - if (item->kind == FILTER_REFS_BRANCHES)
> - fill_tracking_info(&stat, refname, filter->verbose > 1);
> -
> - strbuf_addf(out, " %s %s%s",
> - find_unique_abbrev(item->commit->object.sha1, filter->abbrev),
> - stat.buf, sub);
> - strbuf_release(&stat);
> - strbuf_release(&subject);
> -}
> -
> -/*
> - * This is duplicated in ref-filter.c, will be removed when we adopt
> - * ref-filter's printing APIs.
> - */
> -static char *get_head_description(void)
> -{
> - struct strbuf desc = STRBUF_INIT;
> - struct wt_status_state state;
> - memset(&state, 0, sizeof(state));
> - wt_status_get_state(&state, 1);
> - if (state.rebase_in_progress ||
> - state.rebase_interactive_in_progress)
> - strbuf_addf(&desc, _("(no branch, rebasing %s)"),
> - state.branch);
> - else if (state.bisect_in_progress)
> - strbuf_addf(&desc, _("(no branch, bisect started on %s)"),
> - state.branch);
> - else if (state.detached_from) {
> - /* TRANSLATORS: make sure these match _("HEAD detached at ")
> - and _("HEAD detached from ") in wt-status.c */
> - if (state.detached_at)
> - strbuf_addf(&desc, _("(HEAD detached at %s)"),
> - state.detached_from);
> - else
> - strbuf_addf(&desc, _("(HEAD detached from %s)"),
> - state.detached_from);
> - }
> - else
> - strbuf_addstr(&desc, _("(no branch)"));
> - free(state.branch);
> - free(state.onto);
> - free(state.detached_from);
> - return strbuf_detach(&desc, NULL);
> -}
> -
> -static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth,
> - struct ref_filter *filter, const char *remote_prefix)
> -{
> - char c;
> - int current = 0;
> - int color;
> - struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;
> - const char *prefix = "";
> - const char *desc = item->refname;
> - char *to_free = NULL;
> -
> - switch (item->kind) {
> - case FILTER_REFS_BRANCHES:
> - skip_prefix(desc, "refs/heads/", &desc);
> - if (!filter->detached && !strcmp(desc, head))
> - current = 1;
> - else
> - color = BRANCH_COLOR_LOCAL;
> - break;
> - case FILTER_REFS_REMOTES:
> - skip_prefix(desc, "refs/remotes/", &desc);
> - color = BRANCH_COLOR_REMOTE;
> - prefix = remote_prefix;
> - break;
> - case FILTER_REFS_DETACHED_HEAD:
> - desc = to_free = get_head_description();
> - current = 1;
> - break;
> - default:
> - color = BRANCH_COLOR_PLAIN;
> - break;
> - }
> -
> - c = ' ';
> - if (current) {
> - c = '*';
> - color = BRANCH_COLOR_CURRENT;
> - }
> -
> - strbuf_addf(&name, "%s%s", prefix, desc);
> - if (filter->verbose) {
> - int utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf);
> - strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color),
> - maxwidth + utf8_compensation, name.buf,
> - branch_get_color(BRANCH_COLOR_RESET));
> - } else
> - strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(color),
> - name.buf, branch_get_color(BRANCH_COLOR_RESET));
> -
> - if (item->symref) {
> - skip_prefix(item->symref, "refs/remotes/", &desc);
> - strbuf_addf(&out, " -> %s", desc);
> - }
> - else if (filter->verbose)
> - /* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */
> - add_verbose_info(&out, item, filter, desc);
> - if (column_active(colopts)) {
> - assert(!filter->verbose && "--column and --verbose are incompatible");
> - string_list_append(&output, out.buf);
> - } else {
> - printf("%s\n", out.buf);
> - }
> - strbuf_release(&name);
> - strbuf_release(&out);
> - free(to_free);
> -}
> -
> static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
> {
> int i, max = 0;
> @@ -467,7 +281,10 @@ static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
>
> skip_prefix(it->refname, "refs/heads/", &desc);
> skip_prefix(it->refname, "refs/remotes/", &desc);
> - w = utf8_strwidth(desc);
> + if (it->kind == FILTER_REFS_DETACHED_HEAD)
> + w = strlen(get_head_description());
> + else
> + w = utf8_strwidth(desc);
>
> if (it->kind == FILTER_REFS_REMOTES)
> w += remote_bonus;
> @@ -477,12 +294,51 @@ static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
> return max;
> }
>
> +static char *build_format(struct ref_filter *filter, int maxwidth, const char *remote_prefix)
> +{
> + struct strbuf fmt = STRBUF_INIT;
> + struct strbuf local = STRBUF_INIT;
> + struct strbuf remote = STRBUF_INIT;
> +
> + strbuf_addf(&fmt, "%%(if)%%(HEAD)%%(then)* %s%%(else) %%(end)", branch_get_color(BRANCH_COLOR_CURRENT));
> +
> + if (filter->verbose) {
> + strbuf_addf(&local, "%%(align:%d,left)%%(refname:short)%%(end)", maxwidth);
> + strbuf_addf(&local, "%s", branch_get_color(BRANCH_COLOR_RESET));
> + strbuf_addf(&local, " %%(objectname:short=7) ");
> +
> + if (filter->verbose > 1)
> + strbuf_addf(&local, "%%(if)%%(upstream)%%(then)[%s%%(upstream:short)%s%%(if)%%(upstream:track)"
> + "%%(then): %%(upstream:track,nobracket)%%(end)] %%(end)%%(contents:subject)",
> + branch_get_color(BRANCH_COLOR_UPSTREAM), branch_get_color(BRANCH_COLOR_RESET));
> + else
> + strbuf_addf(&local, "%%(if)%%(upstream:track)%%(then)%%(upstream:track) %%(end)%%(contents:subject)");
> +
> + strbuf_addf(&remote, "%s%%(align:%d,left)%s%%(refname:short)%%(end)%s%%(if)%%(symref)%%(then) -> %%(symref:short)"
> + "%%(else) %%(objectname:short=7) %%(contents:subject)%%(end)",
> + branch_get_color(BRANCH_COLOR_REMOTE), maxwidth,
> + remote_prefix, branch_get_color(BRANCH_COLOR_RESET));
> + } else {
> + strbuf_addf(&local, "%%(refname:short)%s", branch_get_color(BRANCH_COLOR_RESET));
> + strbuf_addf(&remote, "%s%s%%(refname:short)%s%%(if)%%(symref)%%(then) -> %%(symref:short)%%(end)",
> + branch_get_color(BRANCH_COLOR_REMOTE), remote_prefix, branch_get_color(BRANCH_COLOR_RESET));
> + }
> +
> + strbuf_addf(&fmt, "%%(if:notequals=remotes)%%(refname:base)%%(then)%s%%(else)%s%%(end)", local.buf, remote.buf);
> +
> + strbuf_release(&local);
> + strbuf_release(&remote);
> + return strbuf_detach(&fmt, NULL);
> +}
> +
> static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting)
> {
> int i;
> struct ref_array array;
> int maxwidth = 0;
> const char *remote_prefix = "";
> + struct strbuf out = STRBUF_INIT;
> + char *format;
>
> /*
> * If we are listing more than just remote branches,
> @@ -494,12 +350,14 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
>
> memset(&array, 0, sizeof(array));
>
> - verify_ref_format("%(refname)%(symref)");
> filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN);
>
> if (filter->verbose)
> maxwidth = calc_maxwidth(&array, strlen(remote_prefix));
>
> + format = build_format(filter, maxwidth, remote_prefix);
> + verify_ref_format(format);
> +
> /*
> * If no sorting parameter is given then we default to sorting
> * by 'refname'. This would give us an alphabetically sorted
> @@ -511,10 +369,21 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
> sorting = ref_default_sorting();
> ref_array_sort(sorting, &array);
>
> - for (i = 0; i < array.nr; i++)
> - format_and_print_ref_item(array.items[i], maxwidth, filter, remote_prefix);
> + for (i = 0; i < array.nr; i++) {
> + format_ref_array_item(array.items[i], format, 0, &out);
> + if (column_active(colopts)) {
> + assert(!filter->verbose && "--column and --verbose are incompatible");
> + /* format to a string_list to let print_columns() do its job */
> + string_list_append(&output, out.buf);
> + } else {
> + fwrite(out.buf, 1, out.len, stdout);
> + putchar('\n');
> + }
> + strbuf_release(&out);
> + }
>
> ref_array_clear(&array);
> + free(format);
> }
>
> static void rename_branch(const char *oldname, const char *newname, int force)
> diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
> index 3d5c238..97a0765 100755
> --- a/t/t6040-tracking-info.sh
> +++ b/t/t6040-tracking-info.sh
> @@ -44,7 +44,7 @@ b1 [ahead 1, behind 1] d
> b2 [ahead 1, behind 1] d
> b3 [behind 1] b
> b4 [ahead 2] f
> -b5 g
> +b5 [gone] g
> b6 c
> EOF