From 7101e10ce7ba917d1b7a6ff73e0008c2be4a43ed Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 21 Oct 2016 14:39:41 -0700 Subject: transport: pass summary_width down the callchain The callchain that originates at transport_print_push_status() eventually hits a single leaf function, print_ref_status(), that is used to show from what old object to what new object a ref got updated, and the width of the part that shows old and new object names used a constant TRANSPORT_SUMMARY_WIDTH. Teach the callchain to pass the width down from the top instead. This allows a future enhancement to compute the necessary display width before calling down this callchain. Signed-off-by: Junio C Hamano diff --git a/transport.c b/transport.c index 94d6dc3..ec02b78 100644 --- a/transport.c +++ b/transport.c @@ -295,7 +295,9 @@ void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int v } } -static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain) +static void print_ref_status(char flag, const char *summary, + struct ref *to, struct ref *from, const char *msg, + int porcelain, int summary_width) { if (porcelain) { if (from) @@ -307,7 +309,7 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str else fprintf(stdout, "%s\n", summary); } else { - fprintf(stderr, " %c %-*s ", flag, TRANSPORT_SUMMARY_WIDTH, summary); + fprintf(stderr, " %c %-*s ", flag, summary_width, summary); if (from) fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name)); else @@ -321,15 +323,16 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str } } -static void print_ok_ref_status(struct ref *ref, int porcelain) +static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_width) { if (ref->deletion) - print_ref_status('-', "[deleted]", ref, NULL, NULL, porcelain); + print_ref_status('-', "[deleted]", ref, NULL, NULL, + porcelain, summary_width); else if (is_null_oid(&ref->old_oid)) print_ref_status('*', (starts_with(ref->name, "refs/tags/") ? "[new tag]" : "[new branch]"), - ref, ref->peer_ref, NULL, porcelain); + ref, ref->peer_ref, NULL, porcelain, summary_width); else { struct strbuf quickref = STRBUF_INIT; char type; @@ -349,12 +352,14 @@ static void print_ok_ref_status(struct ref *ref, int porcelain) strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV); - print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg, porcelain); + print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg, + porcelain, summary_width); strbuf_release(&quickref); } } -static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain) +static int print_one_push_status(struct ref *ref, const char *dest, int count, + int porcelain, int summary_width) { if (!count) { char *url = transport_anonymize_url(dest); @@ -364,56 +369,60 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i switch(ref->status) { case REF_STATUS_NONE: - print_ref_status('X', "[no match]", ref, NULL, NULL, porcelain); + print_ref_status('X', "[no match]", ref, NULL, NULL, + porcelain, summary_width); break; case REF_STATUS_REJECT_NODELETE: print_ref_status('!', "[rejected]", ref, NULL, - "remote does not support deleting refs", porcelain); + "remote does not support deleting refs", + porcelain, summary_width); break; case REF_STATUS_UPTODATE: print_ref_status('=', "[up to date]", ref, - ref->peer_ref, NULL, porcelain); + ref->peer_ref, NULL, porcelain, summary_width); break; case REF_STATUS_REJECT_NONFASTFORWARD: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "non-fast-forward", porcelain); + "non-fast-forward", porcelain, summary_width); break; case REF_STATUS_REJECT_ALREADY_EXISTS: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "already exists", porcelain); + "already exists", porcelain, summary_width); break; case REF_STATUS_REJECT_FETCH_FIRST: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "fetch first", porcelain); + "fetch first", porcelain, summary_width); break; case REF_STATUS_REJECT_NEEDS_FORCE: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "needs force", porcelain); + "needs force", porcelain, summary_width); break; case REF_STATUS_REJECT_STALE: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "stale info", porcelain); + "stale info", porcelain, summary_width); break; case REF_STATUS_REJECT_SHALLOW: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "new shallow roots not allowed", porcelain); + "new shallow roots not allowed", + porcelain, summary_width); break; case REF_STATUS_REMOTE_REJECT: print_ref_status('!', "[remote rejected]", ref, - ref->deletion ? NULL : ref->peer_ref, - ref->remote_status, porcelain); + ref->deletion ? NULL : ref->peer_ref, + ref->remote_status, porcelain, summary_width); break; case REF_STATUS_EXPECTING_REPORT: print_ref_status('!', "[remote failure]", ref, - ref->deletion ? NULL : ref->peer_ref, - "remote failed to report status", porcelain); + ref->deletion ? NULL : ref->peer_ref, + "remote failed to report status", + porcelain, summary_width); break; case REF_STATUS_ATOMIC_PUSH_FAILED: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "atomic push failed", porcelain); + "atomic push failed", porcelain, summary_width); break; case REF_STATUS_OK: - print_ok_ref_status(ref, porcelain); + print_ok_ref_status(ref, porcelain, summary_width); break; } @@ -427,25 +436,29 @@ void transport_print_push_status(const char *dest, struct ref *refs, int n = 0; unsigned char head_sha1[20]; char *head; + int summary_width = TRANSPORT_SUMMARY_WIDTH; head = resolve_refdup("HEAD", RESOLVE_REF_READING, head_sha1, NULL); if (verbose) { for (ref = refs; ref; ref = ref->next) if (ref->status == REF_STATUS_UPTODATE) - n += print_one_push_status(ref, dest, n, porcelain); + n += print_one_push_status(ref, dest, n, + porcelain, summary_width); } for (ref = refs; ref; ref = ref->next) if (ref->status == REF_STATUS_OK) - n += print_one_push_status(ref, dest, n, porcelain); + n += print_one_push_status(ref, dest, n, + porcelain, summary_width); *reject_reasons = 0; for (ref = refs; ref; ref = ref->next) { if (ref->status != REF_STATUS_NONE && ref->status != REF_STATUS_UPTODATE && ref->status != REF_STATUS_OK) - n += print_one_push_status(ref, dest, n, porcelain); + n += print_one_push_status(ref, dest, n, + porcelain, summary_width); if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD) { if (head != NULL && !strcmp(head, ref->name)) *reject_reasons |= REJECT_NON_FF_HEAD; -- cgit v0.10.2-6-g49f6 From 901f3d403ef2416fb287399f8ed9c5dc5fb632f9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 21 Oct 2016 15:22:55 -0700 Subject: fetch: pass summary_width down the callchain The leaf function on the "fetch" side that uses TRANSPORT_SUMMARY_WIDTH constant is builtin/fetch.c::format_display() and it has two distinct callchains. The one that reports the primary result of fetch originates at store_updated_refs(); the other one that reports the pruning of the remote-tracking refs originates at prune_refs(). Teach these two places to pass summary_width down the callchain, just like we did for the "push" side in the previous commit. Signed-off-by: Junio C Hamano diff --git a/builtin/fetch.c b/builtin/fetch.c index a9f12cc..40696e5 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -17,9 +17,6 @@ #include "argv-array.h" #include "utf8.h" -#define TRANSPORT_SUMMARY(x) \ - (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x) - static const char * const builtin_fetch_usage[] = { N_("git fetch [] [ [...]]"), N_("git fetch [] "), @@ -569,9 +566,12 @@ static void print_compact(struct strbuf *display, static void format_display(struct strbuf *display, char code, const char *summary, const char *error, - const char *remote, const char *local) + const char *remote, const char *local, + int summary_width) { - strbuf_addf(display, "%c %-*s ", code, TRANSPORT_SUMMARY(summary)); + int width = (summary_width + strlen(summary) - gettext_width(summary)); + + strbuf_addf(display, "%c %-*s ", code, width, summary); if (!compact_format) print_remote_to_local(display, remote, local); else @@ -583,7 +583,8 @@ static void format_display(struct strbuf *display, char code, static int update_local_ref(struct ref *ref, const char *remote, const struct ref *remote_ref, - struct strbuf *display) + struct strbuf *display, + int summary_width) { struct commit *current = NULL, *updated; enum object_type type; @@ -597,7 +598,7 @@ static int update_local_ref(struct ref *ref, if (!oidcmp(&ref->old_oid, &ref->new_oid)) { if (verbosity > 0) format_display(display, '=', _("[up to date]"), NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); return 0; } @@ -611,7 +612,7 @@ static int update_local_ref(struct ref *ref, */ format_display(display, '!', _("[rejected]"), _("can't fetch in current branch"), - remote, pretty_ref); + remote, pretty_ref, summary_width); return 1; } @@ -621,7 +622,7 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("updating tag", ref, 0); format_display(display, r ? '!' : 't', _("[tag update]"), r ? _("unable to update local ref") : NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); return r; } @@ -654,7 +655,7 @@ static int update_local_ref(struct ref *ref, r = s_update_ref(msg, ref, 0); format_display(display, r ? '!' : '*', what, r ? _("unable to update local ref") : NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); return r; } @@ -670,7 +671,7 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("fast-forward", ref, 1); format_display(display, r ? '!' : ' ', quickref.buf, r ? _("unable to update local ref") : NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); strbuf_release(&quickref); return r; } else if (force || ref->force) { @@ -685,12 +686,12 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("forced-update", ref, 1); format_display(display, r ? '!' : '+', quickref.buf, r ? _("unable to update local ref") : _("forced update"), - remote, pretty_ref); + remote, pretty_ref, summary_width); strbuf_release(&quickref); return r; } else { format_display(display, '!', _("[rejected]"), _("non-fast-forward"), - remote, pretty_ref); + remote, pretty_ref, summary_width); return 1; } } @@ -721,6 +722,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, char *url; const char *filename = dry_run ? "/dev/null" : git_path_fetch_head(); int want_status; + int summary_width = TRANSPORT_SUMMARY_WIDTH; fp = fopen(filename, "a"); if (!fp) @@ -830,13 +832,14 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, strbuf_reset(¬e); if (ref) { - rc |= update_local_ref(ref, what, rm, ¬e); + rc |= update_local_ref(ref, what, rm, ¬e, + summary_width); free(ref); } else format_display(¬e, '*', *kind ? kind : "branch", NULL, *what ? what : "HEAD", - "FETCH_HEAD"); + "FETCH_HEAD", summary_width); if (note.len) { if (verbosity >= 0 && !shown_url) { fprintf(stderr, _("From %.*s\n"), @@ -903,6 +906,7 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, int url_len, i, result = 0; struct ref *ref, *stale_refs = get_stale_heads(refs, ref_count, ref_map); char *url; + int summary_width = TRANSPORT_SUMMARY_WIDTH; const char *dangling_msg = dry_run ? _(" (%s will become dangling)") : _(" (%s has become dangling)"); @@ -938,7 +942,8 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, shown_url = 1; } format_display(&sb, '-', _("[deleted]"), NULL, - _("(none)"), prettify_refname(ref->name)); + _("(none)"), prettify_refname(ref->name), + summary_width); fprintf(stderr, " %s\n",sb.buf); strbuf_release(&sb); warn_dangling_symref(stderr, dangling_msg, ref->name); -- cgit v0.10.2-6-g49f6 From 11fd66de9bceac5ffb70ad3ad225203b95d19aa2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 21 Oct 2016 15:28:07 -0700 Subject: transport: allow summary-width to be computed dynamically Now we have identified three callchains that have a set of refs that they want to show their object names in an aligned output, we can replace their reference to the constant TRANSPORT_SUMMARY_WIDTH with a helper function call to transport_summary_width() that takes the set of ref as a parameter. This step does not yet iterate over the refs and compute, which is left as an exercise to the readers. Signed-off-by: Junio C Hamano diff --git a/builtin/fetch.c b/builtin/fetch.c index 40696e5..09813cd 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -722,7 +722,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, char *url; const char *filename = dry_run ? "/dev/null" : git_path_fetch_head(); int want_status; - int summary_width = TRANSPORT_SUMMARY_WIDTH; + int summary_width = transport_summary_width(ref_map); fp = fopen(filename, "a"); if (!fp) @@ -906,7 +906,7 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, int url_len, i, result = 0; struct ref *ref, *stale_refs = get_stale_heads(refs, ref_count, ref_map); char *url; - int summary_width = TRANSPORT_SUMMARY_WIDTH; + int summary_width = transport_summary_width(stale_refs); const char *dangling_msg = dry_run ? _(" (%s will become dangling)") : _(" (%s has become dangling)"); diff --git a/transport.c b/transport.c index ec02b78..d4b8bf5 100644 --- a/transport.c +++ b/transport.c @@ -429,6 +429,11 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, return 1; } +int transport_summary_width(const struct ref *refs) +{ + return (2 * FALLBACK_DEFAULT_ABBREV + 3); +} + void transport_print_push_status(const char *dest, struct ref *refs, int verbose, int porcelain, unsigned int *reject_reasons) { @@ -436,7 +441,7 @@ void transport_print_push_status(const char *dest, struct ref *refs, int n = 0; unsigned char head_sha1[20]; char *head; - int summary_width = TRANSPORT_SUMMARY_WIDTH; + int summary_width = transport_summary_width(refs); head = resolve_refdup("HEAD", RESOLVE_REF_READING, head_sha1, NULL); diff --git a/transport.h b/transport.h index e783377..706d99e 100644 --- a/transport.h +++ b/transport.h @@ -142,7 +142,7 @@ struct transport { #define TRANSPORT_PUSH_ATOMIC 8192 #define TRANSPORT_PUSH_OPTIONS 16384 -#define TRANSPORT_SUMMARY_WIDTH (2 * FALLBACK_DEFAULT_ABBREV + 3) +extern int transport_summary_width(const struct ref *refs); /* Returns a transport suitable for the url */ struct transport *transport_get(struct remote *, const char *); -- cgit v0.10.2-6-g49f6 From db98d9bafa7081aa95c15c278e39b5dfa5af8e48 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 21 Oct 2016 21:33:06 -0700 Subject: transport: compute summary-width dynamically Now all that is left to do is to actually iterate over the refs and measure the display width needed to show their abbreviation. Helped-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/transport.c b/transport.c index d4b8bf5..2af1109 100644 --- a/transport.c +++ b/transport.c @@ -429,9 +429,25 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, return 1; } +static int measure_abbrev(const struct object_id *oid, int sofar) +{ + char hex[GIT_SHA1_HEXSZ + 1]; + int w = find_unique_abbrev_r(hex, oid->hash, DEFAULT_ABBREV); + + return (w < sofar) ? sofar : w; +} + int transport_summary_width(const struct ref *refs) { - return (2 * FALLBACK_DEFAULT_ABBREV + 3); + int maxw = -1; + + for (; refs; refs = refs->next) { + maxw = measure_abbrev(&refs->old_oid, maxw); + maxw = measure_abbrev(&refs->new_oid, maxw); + } + if (maxw < 0) + maxw = FALLBACK_DEFAULT_ABBREV; + return (2 * maxw + 3); } void transport_print_push_status(const char *dest, struct ref *refs, -- cgit v0.10.2-6-g49f6