Re: [PATCH 10/33] refs: extract a function ref_resolves_to_object()

2013-04-16 Thread Michael Haggerty
On 04/15/2013 06:51 PM, Junio C Hamano wrote:
 Michael Haggerty mhag...@alum.mit.edu writes:
 
 It is a nice unit of work and soon will be needed from multiple
 locations.

 Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
 ---
  refs.c | 28 
  1 file changed, 20 insertions(+), 8 deletions(-)

 diff --git a/refs.c b/refs.c
 index c523978..dfc8600 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -529,6 +529,22 @@ static void sort_ref_dir(struct ref_dir *dir)
  #define DO_FOR_EACH_INCLUDE_BROKEN 0x01
  
  /*
 + * Return true iff the reference described by entry can be resolved to
 + * an object in the database.  Emit a warning if the referred-to
 + * object does not exist.
 + */
 +static int ref_resolves_to_object(struct ref_entry *entry)
 +{
 +if (entry-flag  REF_ISBROKEN)
 +return 0;
 +if (!has_sha1_file(entry-u.value.sha1)) {
 +error(%s does not point to a valid object!, entry-name);
 +return 0;
 +}
 +return 1;
 +}
 +
 +/*
   * current_ref is a performance hack: when iterating over references
   * using the for_each_ref*() functions, current_ref is set to the
   * current reference's entry before calling the callback function.  If
 @@ -549,14 +565,10 @@ static int do_one_ref(const char *base, each_ref_fn 
 fn, int trim,
  if (prefixcmp(entry-name, base))
  return 0;
  
 -if (!(flags  DO_FOR_EACH_INCLUDE_BROKEN)) {
 -if (entry-flag  REF_ISBROKEN)
 -return 0; /* ignore broken refs e.g. dangling symref */
 -if (!has_sha1_file(entry-u.value.sha1)) {
 -error(%s does not point to a valid object!, 
 entry-name);
 -return 0;
 -}
 -}
 +if (!((flags  DO_FOR_EACH_INCLUDE_BROKEN) ||
 +  ref_resolves_to_object(entry)))
 +return 0;
 +
 
 The original says Unless flags tell us to include broken ones,
 return 0 for the broken ones and the ones that point at invalid
 objects.
 
 The updated says Unless flags tell us to include broken ones or the
 ref is a good one, return 0.
 
 Are they the same?  If we have a good one, and if we are not told to
 include broken one, the original just passes the control down to the
 remainder of the function.  The updated one will return 0.
 
 Oh, wait, that is not the case.  The OR is inside !( A || B ), so
 what it really wants to say is:
 
   if (!(flags  DO_FOR_EACH_INCLUDE_BROKEN) 
 !ref_resolves_to_object(entry))
   return 0;
 
 that is, When we are told to exclude broken ones and the one we are
 looking at is broken, return 0.
 
 Am I the only one who was confused with this, or was the way the
 patch wrote this logic unnecessarily convoluted?

I find either way of writing it hard to read quickly.  I find that the
construct

if (!(situation in which the function should continue))
return

makes it easier to pick out the situation in which the function should
continue.  But granted, the nesting of multiple parentheses across
lines compromises the clarity.

In projects where I can choose the coding standard, I like to use extra
whitespace to help the eye pick out the range of parentheses, like

if (!(
(flags  DO_FOR_EACH_INCLUDE_BROKEN) ||
ref_resolves_to_object(entry)
))
return 0;

but I've never seen this style in the Git project so I haven't used it here.

Since you prefer the other version, I will change it.

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.com/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 10/33] refs: extract a function ref_resolves_to_object()

2013-04-16 Thread Junio C Hamano
Michael Haggerty mhag...@alum.mit.edu writes:

 In projects where I can choose the coding standard, I like to use extra
 whitespace to help the eye pick out the range of parentheses, like

 if (!(
 (flags  DO_FOR_EACH_INCLUDE_BROKEN) ||
 ref_resolves_to_object(entry)
 ))
 return 0;

 but I've never seen this style in the Git project so I haven't used it here.

I _think_ at least to me, it is not the textual grouping style but
the unless X we skip the rest logic itself that confused me.  It
took the same number of minutes to grok the above as the original.

We skip the rest of this function unless the condition inside !()
holds, and the condition is we are told to include broken ones,
in which case we know we will do the remainder without checking
anything else, or we do the checking and find that it is not broken.

I suspect the root cause of the confusion to force the double
negation is INCLUDE_BROKEN; we have to express when we are told to
ignore broken one and this thing is broken, ignore it without
negation, i.e.

if ( !(flags  INCLUDE_BROKEN)  is_broken(thing) )
return;

which would have been much more pleasant to read if it were

if ( (flags  IGNORE_BROKEN)  is_broken(thing) )
return;

Unfortunately, we cannot change it to IGNORE_BROKEN and flip the
meaning of the bit, because almost all callers do want to ignore
broken ones.

Either way is fine by me, even though I find that !(A || B) needs a
bit more mental exercise to grok than (!A  !B).  Perhaps it is
just me who is not so strong at math ;-)


--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 10/33] refs: extract a function ref_resolves_to_object()

2013-04-15 Thread Junio C Hamano
Michael Haggerty mhag...@alum.mit.edu writes:

 It is a nice unit of work and soon will be needed from multiple
 locations.

 Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
 ---
  refs.c | 28 
  1 file changed, 20 insertions(+), 8 deletions(-)

 diff --git a/refs.c b/refs.c
 index c523978..dfc8600 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -529,6 +529,22 @@ static void sort_ref_dir(struct ref_dir *dir)
  #define DO_FOR_EACH_INCLUDE_BROKEN 0x01
  
  /*
 + * Return true iff the reference described by entry can be resolved to
 + * an object in the database.  Emit a warning if the referred-to
 + * object does not exist.
 + */
 +static int ref_resolves_to_object(struct ref_entry *entry)
 +{
 + if (entry-flag  REF_ISBROKEN)
 + return 0;
 + if (!has_sha1_file(entry-u.value.sha1)) {
 + error(%s does not point to a valid object!, entry-name);
 + return 0;
 + }
 + return 1;
 +}
 +
 +/*
   * current_ref is a performance hack: when iterating over references
   * using the for_each_ref*() functions, current_ref is set to the
   * current reference's entry before calling the callback function.  If
 @@ -549,14 +565,10 @@ static int do_one_ref(const char *base, each_ref_fn fn, 
 int trim,
   if (prefixcmp(entry-name, base))
   return 0;
  
 - if (!(flags  DO_FOR_EACH_INCLUDE_BROKEN)) {
 - if (entry-flag  REF_ISBROKEN)
 - return 0; /* ignore broken refs e.g. dangling symref */
 - if (!has_sha1_file(entry-u.value.sha1)) {
 - error(%s does not point to a valid object!, 
 entry-name);
 - return 0;
 - }
 - }
 + if (!((flags  DO_FOR_EACH_INCLUDE_BROKEN) ||
 +   ref_resolves_to_object(entry)))
 + return 0;
 +

The original says Unless flags tell us to include broken ones,
return 0 for the broken ones and the ones that point at invalid
objects.

The updated says Unless flags tell us to include broken ones or the
ref is a good one, return 0.

Are they the same?  If we have a good one, and if we are not told to
include broken one, the original just passes the control down to the
remainder of the function.  The updated one will return 0.

Oh, wait, that is not the case.  The OR is inside !( A || B ), so
what it really wants to say is:

if (!(flags  DO_FOR_EACH_INCLUDE_BROKEN) 
!ref_resolves_to_object(entry))
return 0;

that is, When we are told to exclude broken ones and the one we are
looking at is broken, return 0.

Am I the only one who was confused with this, or was the way the
patch wrote this logic unnecessarily convoluted?

   current_ref = entry;
   retval = fn(entry-name + trim, entry-u.value.sha1, entry-flag, 
 cb_data);
   current_ref = NULL;
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/33] refs: extract a function ref_resolves_to_object()

2013-04-14 Thread Michael Haggerty
It is a nice unit of work and soon will be needed from multiple
locations.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 28 
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/refs.c b/refs.c
index c523978..dfc8600 100644
--- a/refs.c
+++ b/refs.c
@@ -529,6 +529,22 @@ static void sort_ref_dir(struct ref_dir *dir)
 #define DO_FOR_EACH_INCLUDE_BROKEN 0x01
 
 /*
+ * Return true iff the reference described by entry can be resolved to
+ * an object in the database.  Emit a warning if the referred-to
+ * object does not exist.
+ */
+static int ref_resolves_to_object(struct ref_entry *entry)
+{
+   if (entry-flag  REF_ISBROKEN)
+   return 0;
+   if (!has_sha1_file(entry-u.value.sha1)) {
+   error(%s does not point to a valid object!, entry-name);
+   return 0;
+   }
+   return 1;
+}
+
+/*
  * current_ref is a performance hack: when iterating over references
  * using the for_each_ref*() functions, current_ref is set to the
  * current reference's entry before calling the callback function.  If
@@ -549,14 +565,10 @@ static int do_one_ref(const char *base, each_ref_fn fn, 
int trim,
if (prefixcmp(entry-name, base))
return 0;
 
-   if (!(flags  DO_FOR_EACH_INCLUDE_BROKEN)) {
-   if (entry-flag  REF_ISBROKEN)
-   return 0; /* ignore broken refs e.g. dangling symref */
-   if (!has_sha1_file(entry-u.value.sha1)) {
-   error(%s does not point to a valid object!, 
entry-name);
-   return 0;
-   }
-   }
+   if (!((flags  DO_FOR_EACH_INCLUDE_BROKEN) ||
+ ref_resolves_to_object(entry)))
+   return 0;
+
current_ref = entry;
retval = fn(entry-name + trim, entry-u.value.sha1, entry-flag, 
cb_data);
current_ref = NULL;
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html