Jeff King <p...@peff.net> writes:

> diff --git a/remote.c b/remote.c
> index dca3442..1b7051a 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -1705,10 +1705,35 @@ int branch_merge_matches(struct branch *branch,
>       return refname_match(branch->merge[i]->src, refname);
>  }
>  
> -const char *branch_get_upstream(struct branch *branch)
> +__attribute((format (printf,2,3)))
> +static const char *error_buf(struct strbuf *err, const char *fmt, ...)
>  {
> -     if (!branch || !branch->merge || !branch->merge[0])
> -             return NULL;
> +     if (err) {
> +             va_list ap;
> +             va_start(ap, fmt);
> +             strbuf_vaddf(err, fmt, ap);
> +             va_end(ap);
> +     }
> +     return NULL;
> +}

Many of our functions return -1 to signal an error, and that is why
it makes sense for our error() helper to return -1 to save code in
the caller, but only because the callers of this private helper use
a NULL to signal an error, this also returns NULL.  If we were to
use the "callers can opt into detailed message by passing strbuf"
pattern more widely, we would want a variant of the above that
returns -1, too.  And such a helper would do the same thing as
above, with only difference from the above is to return -1.

It's a shame that we have to return something from this function,
whose primary purpose is "we may or may not want an error message in
a strbuf, so format the message when and only when we give you a
strbuf", but C forces us to make it "always return NULL to signal an
error to the caller, and optionally format the message into a strbuf
if given".

And the name of this helper function only captures the "optionally
format the message" part, not the "always return NULL" part.

> +const char *branch_get_upstream(struct branch *branch, struct strbuf *err)
> +{
> +     if (!branch)
> +             return error_buf(err, _("HEAD does not point to a branch"));
> +     if (!branch->merge || !branch->merge[0] || !branch->merge[0]->dst) {
> +             if (!ref_exists(branch->refname))
> +                     return error_buf(err, _("no such branch: '%s'"),
> +                                      branch->name);
> +             if (!branch->merge)
> +                     return error_buf(err,
> +                                      _("no upstream configured for branch 
> '%s'"),
> +                                      branch->name);
> +             return error_buf(err,
> +                              _("upstream branch '%s' not stored as a 
> remote-tracking branch"),
> +                              branch->merge[0]->src);
> +     }
> +
>       return branch->merge[0]->dst;
>  }

This is a faithful conversion of what the get_upstream_branch() used
to do, but that ref_exists() check and the error checking there look
somewhat out of place.

It makes the reader wonder what should happen when "branch->refname"
does not exist as a ref, but "branch->merge[0]->dst" can be fully
dereferenced.  Should it be an error, or if it is OK, the reason why
it is OK is...?
--
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

Reply via email to