Re: [PATCH 3/3] transport: allow summary-width to be computed dynamically

2016-10-22 Thread Junio C Hamano
Jeff King  writes:

> On Fri, Oct 21, 2016 at 09:39:45PM -0700, Junio C Hamano wrote:
>
>> And this is the final one.
>> 
>> -- >8 --
>> From: Junio C Hamano 
>> Date: Fri, 21 Oct 2016 21:33:06 -0700
>> Subject: [PATCH] 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.
>
> I think we crossed emails. :) This is obviously correct, if we don't
> mind paying the find_unique_abbrev cost twice for each sha1.

Indeed we did.  I do not think the cost matters that much in the
codepath to produce the final summary output.

> This is a minor style nit, but I think it's better to avoid mixing
> unrelated bits between the initialization, condition, and iteration bits
> of a for loop.

Yeah, you're right.


Re: [PATCH 3/3] transport: allow summary-width to be computed dynamically

2016-10-21 Thread Jeff King
On Fri, Oct 21, 2016 at 09:39:45PM -0700, Junio C Hamano wrote:

> And this is the final one.
> 
> -- >8 --
> From: Junio C Hamano 
> Date: Fri, 21 Oct 2016 21:33:06 -0700
> Subject: [PATCH] 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.

I think we crossed emails. :) This is obviously correct, if we don't
mind paying the find_unique_abbrev cost twice for each sha1.

>  int transport_summary_width(const struct ref *refs)
>  {
> - return (2 * FALLBACK_DEFAULT_ABBREV + 3);
> + int maxw;
> +
> + for (maxw = -1; refs; refs = refs->next) {
> + maxw = measure_abbrev(&refs->old_oid, maxw);
> + maxw = measure_abbrev(&refs->new_oid, maxw);
> + }

This is a minor style nit, but I think it's better to avoid mixing
unrelated bits between the initialization, condition, and iteration bits
of a for loop. IOW:

  int maxw = -1;

  for (; refs; refs = refs->next) {
...
  }

makes the for-loop _just_ about iteration, and it is more clear that the
manipulation of "maxw" is a side effect of the loop that is valid after
it finishes.

Though in this particular case, the loop and the whole function are
short enough that I don't care that much. Just raising a philosophical
point. :)

-Peff


Re: [PATCH 3/3] transport: allow summary-width to be computed dynamically

2016-10-21 Thread Junio C Hamano
Junio C Hamano  writes:

> 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.

And this is the final one.

-- >8 --
From: Junio C Hamano 
Date: Fri, 21 Oct 2016 21:33:06 -0700
Subject: [PATCH] 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.

Signed-off-by: Junio C Hamano 
---
 transport.c | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/transport.c b/transport.c
index d4b8bf5f25..f1f95cf7c7 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;
+
+   for (maxw = -1; 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,
-- 
2.10.1-723-g2384e83bc3



Re: [PATCH 3/3] transport: allow summary-width to be computed dynamically

2016-10-21 Thread Jeff King
On Fri, Oct 21, 2016 at 03:39:27PM -0700, Junio C Hamano wrote:

> 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.

The final step could be something like this:

diff --git a/transport.c b/transport.c
index 4dac713063..c1eaa4a 100644
--- a/transport.c
+++ b/transport.c
@@ -443,7 +443,21 @@ static int print_one_push_status(struct ref *ref, const 
char *dest, int count,
 
 int transport_summary_width(const struct ref *refs)
 {
-   return (2 * FALLBACK_DEFAULT_ABBREV + 3);
+   int max_abbrev;
+
+   /*
+* Computing the complete set of abbreviated sha1s is expensive just to
+* find their lengths, but we can at least find our real dynamic
+* minimum by picking an arbitrary sha1.
+*/
+   if (refs)
+   max_abbrev = strlen(find_unique_abbrev(refs->old_oid.hash,
+  DEFAULT_ABBREV));
+   else
+   max_abbrev = FALLBACK_DEFAULT_ABBREV;
+
+   /* 2 abbreviated sha1s, plus "..." in between */
+   return (2 * max_abbrev + 3);
 }
 
 void transport_print_push_status(const char *dest, struct ref *refs,


which produces reasonable results for me. But if we really wanted the
true value, I think we'd want to compute and store the abbreviated
sha1s, and then the refactoring done by your series probably isn't the
right direction.

I think we'd instead want to replace "struct strbuf *display" passed
down to update_local_ref() with something more like:

  struct ref_status_table {
struct ref_status_item {
char old_hash[GIT_SHA1_HEX + 1];
char new_hash[GIT_SHA1_HEX + 1];
char *remote_ref;
char *local_ref;
char *summary;
char code;
} *items;
size_t alloc, nr;
  };

and then format_display() would just add to the list (including calling
find_unique_abbrev()), and then at the end we'd call a function to show
them all.

That would also get rid of prepare_format_display(), as we could easily
walk over the prepared list before printing any of them (as opposed to
what that function does now, which is to walk over the ref map; that
requires that it know which refs are going to be printed).

-Peff


[PATCH 3/3] transport: allow summary-width to be computed dynamically

2016-10-21 Thread Junio C Hamano
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 
---
 builtin/fetch.c | 4 ++--
 transport.c | 7 ++-
 transport.h | 2 +-
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/builtin/fetch.c b/builtin/fetch.c
index 40696e5338..09813cd826 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 ec02b78924..d4b8bf5f25 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 e783377e40..706d99e818 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 *);
-- 
2.10.1-723-g2384e83bc3