git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Elijah Newren <newren@gmail.com>
To: Patrick Steinhardt <ps@pks.im>
Cc: Git Mailing List <git@vger.kernel.org>
Subject: Re: [PATCH 5/6] fetch: make `--atomic` flag cover backfilling of tags
Date: Wed, 16 Feb 2022 17:34:23 -0800	[thread overview]
Message-ID: <CABPp-BFM67LzZFL=w-iA7vButaBKokpetDR5dr8TTnbSCmBdeA@mail.gmail.com> (raw)
In-Reply-To: <55dbe19a1a4d05d84c81356af1a3f04b65f8aa7b.1644565025.git.ps@pks.im>

On Mon, Feb 14, 2022 at 1:32 AM Patrick Steinhardt <ps@pks.im> wrote:
>
> When fetching references from a remote we by default also fetch all tags
> which point into the history we have fetched. This is a separate step
> performed after updating local references because it requires us to walk
> over the history on the client-side to determine whether the remote has
> announced any tags which point to one of the fetched commits.
>
> This backfilling of tags isn't covered by the `--atomic` flag: right
> now, it only applies to the step where we update our local references.
> This is an oversight at the time the flag was introduced: its purpose is
> to either update all references or none, but right now we happily update
> local references even in the case where backfilling failed.
>
> Fix this by pulling up creation of the reference transaction such that
> we can pass the same transaction to both the code which updates local
> references and to the code which backfills tags. This allows us to only
> commit the transaction in case both actions succeed.
>
> Note that we also have to start passing the transaction into
> `find_non_local_tags()`: this function is responsible for finding all
> tags which we need to backfill. Right now, it will happily return tags
> which we have already been updated with our local references. But when
> we use a single transaction for both local references and backfilling
> then it may happen that we try to queue the same reference update twice
> to the transaction, which consequentially triggers a bug. We thus have
> to skip over any tags which have already been queued. Unfortunately,
> this requires us to reach into internals of the reference transaction to
> access queued updates, but there is no non-internal interface right now
> which would allow us to access this information.

I like the changes you are making here in general, but I do agree that
reaching into refs-internal feels a bit icky.  I'm not familiar with
the refs API nor the fetching code, so feel free to ignore these
ideas, but I'm just throwing them out there as possibilities to avoid
reaching into refs-internal:

  - you are trying to check for existing transactions to avoid
duplicates, but those existing transactions came from elsewhere in the
same code we control.  Could we store a strset or strmap of the items
being updated (in addition to storing them in the transaction), and
then use the strset/strmap to filter out which tags we need to
backfill?  Or would that require plumbing an extra variable through an
awful lot of callers to get the information into the right places?

  - would it make sense to add a flag to the transaction API to allow
duplicates if both updates update the ref to the same value?  (I'm
guessing you're updating to the same value, right?)

  - should we just add something to the refs API along the lines of
"transaction_includes_update_for()" or something like that?

[...]
> @@ -361,12 +362,28 @@ static void find_non_local_tags(const struct ref *refs,
>         const struct ref *ref;
>         struct refname_hash_entry *item = NULL;
>         const int quick_flags = OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT;
> +       int i;
>
>         refname_hash_init(&existing_refs);
>         refname_hash_init(&remote_refs);
>         create_fetch_oidset(head, &fetch_oids);
>
>         for_each_ref(add_one_refname, &existing_refs);
> +
> +       /*
> +        * If we already have a transaction, then we need to filter out all
> +        * tags which have already been queued up.
> +        */
> +       for (i = 0; transaction && i < transaction->nr; i++) {
> +               if (!starts_with(transaction->updates[i]->refname, "refs/tags/") ||
> +                   !(transaction->updates[i]->flags & REF_HAVE_NEW))
> +                       continue;
> +               (void) refname_hash_add(&existing_refs,
> +                                       transaction->updates[i]->refname,
> +                                       &transaction->updates[i]->new_oid);

Why the typecast here?

  parent reply	other threads:[~2022-02-17  1:34 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-11  7:46 [PATCH 0/6] fetch: improve atomicity of `--atomic` flag Patrick Steinhardt
2022-02-11  7:46 ` [PATCH 1/6] fetch: increase test coverage of fetches Patrick Steinhardt
2022-02-15  6:19   ` Christian Couder
2022-02-17 11:13     ` Patrick Steinhardt
2022-02-11  7:46 ` [PATCH 2/6] fetch: backfill tags before setting upstream Patrick Steinhardt
2022-02-15  6:43   ` Christian Couder
2022-02-11  7:46 ` [PATCH 3/6] fetch: control lifecycle of FETCH_HEAD in a single place Patrick Steinhardt
2022-02-15  7:32   ` Christian Couder
2022-02-17 11:18     ` Patrick Steinhardt
2022-02-11  7:46 ` [PATCH 4/6] fetch: report errors when backfilling tags fails Patrick Steinhardt
2022-02-15  7:52   ` Christian Couder
2022-02-17 11:27     ` Patrick Steinhardt
2022-02-17 12:47       ` Patrick Steinhardt
2022-02-16 23:35   ` Jonathan Tan
2022-02-17  1:31   ` Elijah Newren
2022-02-11  7:47 ` [PATCH 5/6] fetch: make `--atomic` flag cover backfilling of tags Patrick Steinhardt
2022-02-15  8:11   ` Christian Couder
2022-02-16 23:41     ` Jonathan Tan
2022-02-17 11:37     ` Patrick Steinhardt
2022-02-17  1:34   ` Elijah Newren [this message]
2022-02-17 11:58     ` Patrick Steinhardt
2022-02-11  7:47 ` [PATCH 6/6] fetch: make `--atomic` flag cover pruning of refs Patrick Steinhardt
2022-02-15  9:12   ` Christian Couder
2022-02-17 12:03     ` Patrick Steinhardt
2022-02-16 23:39   ` Jonathan Tan
2022-02-17  1:40   ` Elijah Newren
2022-02-17 12:06     ` Patrick Steinhardt

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

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CABPp-BFM67LzZFL=w-iA7vButaBKokpetDR5dr8TTnbSCmBdeA@mail.gmail.com' \
    --to=newren@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=ps@pks.im \
    /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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).