fetch: refactor calculation of the display table width

When displaying reference updates, we try to print the references in a neat table. As the table's width is determined its contents we thus need to precalculate the overall width before we can start printing updated references. The calculation is driven by `display_state_init()`, which invokes `refcol_width()` for every reference that is to be printed. This split is somewhat confusing. For one, we filter references that shall be attributed to the overall width in both places. And second, we needlessly recalculate the maximum line length based on the terminal columns and display format for every reference. Refactor the code so that the complete width calculations are neatly contained in `refcol_width()`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed May 10, 2023 at 14:34 UTC 9539638a2bbc88717547585ae660bba3bbfaef8b
1 file changed +34 -41
builtin/fetch.c
+34 -41
@@ -753,40 +753,51 @@ out:
753 return ret;
754 }
755
756 -static int refcol_width(const struct ref *ref, int compact_format)
756 +static int refcol_width(const struct ref *ref_map, int compact_format)
757 {
758 - int max, rlen, llen, len;
758 + const struct ref *ref;
759 + int max, width = 10;
760
760 - /* uptodate lines are only shown on high verbosity level */
761 - if (verbosity <= 0 && oideq(&ref->peer_ref->old_oid, &ref->old_oid))
762 - return 0;
761 + max = term_columns();
762 + if (compact_format)
763 + max = max * 2 / 3;
764
764 - max = term_columns();
765 - rlen = utf8_strwidth(prettify_refname(ref->name));
765 + for (ref = ref_map; ref; ref = ref->next) {
766 + int rlen, llen = 0, len;
767
767 - llen = utf8_strwidth(prettify_refname(ref->peer_ref->name));
768 + if (ref->status == REF_STATUS_REJECT_SHALLOW ||
769 + !ref->peer_ref ||
770 + !strcmp(ref->name, "HEAD"))
771 + continue;
772
769 - /*
770 - * rough estimation to see if the output line is too long and
771 - * should not be counted (we can't do precise calculation
772 - * anyway because we don't know if the error explanation part
773 - * will be printed in update_local_ref)
774 - */
775 - if (compact_format) {
776 - llen = 0;
777 - max = max * 2 / 3;
773 + /* uptodate lines are only shown on high verbosity level */
774 + if (verbosity <= 0 && oideq(&ref->peer_ref->old_oid, &ref->old_oid))
775 + continue;
776 +
777 + rlen = utf8_strwidth(prettify_refname(ref->name));
778 + if (!compact_format)
779 + llen = utf8_strwidth(prettify_refname(ref->peer_ref->name));
780 +
781 + /*
782 + * rough estimation to see if the output line is too long and
783 + * should not be counted (we can't do precise calculation
784 + * anyway because we don't know if the error explanation part
785 + * will be printed in update_local_ref)
786 + */
787 + len = 21 /* flag and summary */ + rlen + 4 /* -> */ + llen;
788 + if (len >= max)
789 + continue;
790 +
791 + if (width < rlen)
792 + width = rlen;
793 }
779 - len = 21 /* flag and summary */ + rlen + 4 /* -> */ + llen;
780 - if (len >= max)
781 - return 0;
794
783 - return rlen;
795 + return width;
796 }
797
798 static void display_state_init(struct display_state *display_state, struct ref *ref_map,
799 const char *raw_url)
800 {
789 - struct ref *rm;
801 const char *format = "full";
802 int i;
803
@@ -818,25 +829,7 @@ static void display_state_init(struct display_state *display_state, struct ref *
829 die(_("invalid value for '%s': '%s'"),
830 "fetch.output", format);
831
821 - display_state->refcol_width = 10;
822 - for (rm = ref_map; rm; rm = rm->next) {
823 - int width;
824 -
825 - if (rm->status == REF_STATUS_REJECT_SHALLOW ||
826 - !rm->peer_ref ||
827 - !strcmp(rm->name, "HEAD"))
828 - continue;
829 -
830 - width = refcol_width(rm, display_state->compact_format);
831 -
832 - /*
833 - * Not precise calculation for compact mode because '*' can
834 - * appear on the left hand side of '->' and shrink the column
835 - * back.
836 - */
837 - if (display_state->refcol_width < width)
838 - display_state->refcol_width = width;
839 - }
832 + display_state->refcol_width = refcol_width(ref_map, display_state->compact_format);
833 }
834
835 static void display_state_release(struct display_state *display_state)