From: Michael Haggerty <mhagger@alum.mit.edu>
To: "Carlos Martín Nieto" <cmn@elego.de>
Cc: git@vger.kernel.org
Subject: Re: [PATCH 2/2] fetch: handle overlaping refspecs on --prune
Date: Thu, 27 Feb 2014 11:21:53 +0100 [thread overview]
Message-ID: <530F11C1.7040407@alum.mit.edu> (raw)
In-Reply-To: <1393491610-19476-2-git-send-email-cmn@elego.de>
On 02/27/2014 10:00 AM, Carlos Martín Nieto wrote:
> From: Carlos Martín Nieto <cmn@dwim.me>
>
> We need to consider that a remote-tracking branch may match more than
> one rhs of a fetch refspec. In such a case, it is not enough to stop at
> the first match but look at all of the matches in order to determine
> whether a head is stale.
>
> To this goal, introduce a variant of query_refspecs which returns all of
> the matching refspecs and loop over those answers to check for
> staleness.
>
> Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
> ---
>
> There is an unfortunate duplication of code here, as
> query_refspecs_multiple is mostly query_refspecs but we only care
> about the other side of matching refspecs and disregard the 'force'
> information which query_refspecs does want.
>
> I thought about putting both together via callbacks and having
> query_refspecs stop at the first one, but I'm not sure that it would
> make it easier to read or manage.
>
> remote.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++-----
> t/t5510-fetch.sh | 2 +-
> 2 files changed, 48 insertions(+), 6 deletions(-)
>
> diff --git a/remote.c b/remote.c
> index 9f1a8aa..26140c7 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -821,6 +821,33 @@ static int match_name_with_pattern(const char *key, const char *name,
> return ret;
> }
>
> +static void query_refspecs_multiple(struct refspec *refs, int ref_count, struct refspec *query, struct string_list *results)
> +{
> + int i;
> + int find_src = !query->src;
> +
> + if (find_src && !query->dst)
> + error("query_refspecs_multiple: need either src or dst");
> +
> + for (i = 0; i < ref_count; i++) {
> + struct refspec *refspec = &refs[i];
> + const char *key = find_src ? refspec->dst : refspec->src;
> + const char *value = find_src ? refspec->src : refspec->dst;
> + const char *needle = find_src ? query->dst : query->src;
> + char **result = find_src ? &query->src : &query->dst;
> +
> + if (!refspec->dst)
> + continue;
> + if (refspec->pattern) {
> + if (match_name_with_pattern(key, needle, value, result)) {
> + string_list_append_nodup(results, *result);
> + }
> + } else if (!strcmp(needle, key)) {
> + string_list_append(results, value);
> + }
> + }
> +}
> +
> static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
> {
> int i;
> @@ -1954,25 +1981,40 @@ static int get_stale_heads_cb(const char *refname,
> const unsigned char *sha1, int flags, void *cb_data)
> {
> struct stale_heads_info *info = cb_data;
> + struct string_list matches = STRING_LIST_INIT_DUP;
> struct refspec query;
> + int i, stale = 1;
> memset(&query, 0, sizeof(struct refspec));
> query.dst = (char *)refname;
>
> - if (query_refspecs(info->refs, info->ref_count, &query))
> + query_refspecs_multiple(info->refs, info->ref_count, &query, &matches);
> + if (matches.nr == 0)
> return 0; /* No matches */
>
> /*
> * If we did find a suitable refspec and it's not a symref and
> * it's not in the list of refs that currently exist in that
> - * remote we consider it to be stale.
> + * remote we consider it to be stale. In order to deal with
> + * overlapping refspecs, we need to go over all of the
> + * matching refs.
> */
> - if (!((flags & REF_ISSYMREF) ||
> - string_list_has_string(info->ref_names, query.src))) {
> + if (flags & REF_ISSYMREF)
> + return 0;
> +
> + for (i = 0; i < matches.nr; i++) {
> + if (string_list_has_string(info->ref_names, matches.items[i].string)) {
> + stale = 0;
> + break;
> + }
> + }
> +
> + string_list_clear(&matches, 0);
> +
> + if (stale) {
> struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
> hashcpy(ref->new_sha1, sha1);
> }
>
> - free(query.src);
> return 0;
> }
I didn't have time to review this fully, but I think you are missing
calls to string_list_clear(&matches) on a couple of code paths.
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
next prev parent reply other threads:[~2014-02-27 10:22 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-27 9:00 [PATCH 1/2] fetch: add a failing test for prunning with overlapping refspecs Carlos Martín Nieto
2014-02-27 9:00 ` [PATCH 2/2] fetch: handle overlaping refspecs on --prune Carlos Martín Nieto
2014-02-27 10:21 ` Michael Haggerty [this message]
2014-02-27 19:29 ` Carlos Martín Nieto
2014-02-27 20:19 ` Junio C Hamano
2014-02-27 20:41 ` Junio C Hamano
2014-02-28 12:21 ` Carlos Martín Nieto
2014-02-28 18:04 ` Junio C Hamano
2014-03-24 19:24 ` Junio C Hamano
2014-02-27 20:18 ` [PATCH 1/2] fetch: add a failing test for prunning with overlapping refspecs Eric Sunshine
2014-02-27 20:19 ` Eric Sunshine
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=530F11C1.7040407@alum.mit.edu \
--to=mhagger@alum.mit.edu \
--cc=cmn@elego.de \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.