git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3 5/5] builtin/upload-pack: set GIT_NO_LAZY_FETCH to 0 on trusted repo

From
Christian Couder <christian.couder@gmail.com>
Date
Sep 28, 2026, 13:42 UTC
Message-ID
<CAP8UFD3gsp1wJnsf=de=5KT47Zm5KiJFNOQha5FKurordf2VCA@mail.gmail.com>
In-Reply-To
<xmqqmrtrwq0k.fsf@gitster.g>
On Tue, Sep 8, 2026 at 8:34 PM Junio C Hamano <gitster@pobox.com> wrote:
Show 35 quoted lines
>
> Christian Couder <christian.couder@gmail.com> writes:
>
> > A previous commit added a new "uploadpack.lazyFetchTrusted" protected
> > config variable that can contain an allowlist of repos, as well as
> > functions to check if the current repo is in that list. But when the
> > current repo is in that list, we currently do nothing.
> >
> > Let's instead set `GIT_NO_LAZY_FETCH` to `0`, which allows
> > `upload-pack` and its `pack-objects` child process to lazily fetch the
> > objects they need to serve a client, for example when the filter used
> > by the client and the one used by the server don't match.
>
> While I agree that it is a good idea to make it more lenient to work
> with remotes that are explicitly marked as trusted, it somehow feels
> a bit unnatural for a configuration variable, or a conclusion
> derived from the setting of a configuration variable, overriding an
> environment variable.  Who is setting this environment variable in
> the first place?
>
> If NO_LAZY_FETCH is what server operators set and export, I strongly
> suspect that not honoring it merely because the new variable could
> be used to give them a finer-grained control would be very
> surprising experience for them.
>
> If the answer is "this never comes from the end-user or the server
> operator.  We used to automatically set NO_LAZY_FETCH from the
> process that spawns uploadpack because we trusted nobody", then I'd
> imagine that we would prefer to see that code that automatically
> sets NO_LAZY_FETCH to inspect the configuration variable and to
> decide not to do so.
>
> And I think that is what the code is doing (in other words, from a
> cursory read, I think the new code is doing the right thing and it
> is just the way how the above is explained that I found it iffy).
I have tried to improve on that in v4 by rewording the title and commit message.
Show 19 quoted lines
> We used to say "when serving a client, we do not lazy fetch what we
> are missing from our promisor remotes by setting NO_LAZY_FETCH" and
> it was unconditional.
>
> I think what we want to happen is:
>
>  * If the server operator has NO_LAZY_FETCH set, we honor it and do
>    not do anything.
>
>  * If the server operator does not have NO_LAZY_FETCH set, then we
>    see if the configuration variable is there, and if there is, we
>    let it take care of which promisor remote to allow by not futzing
>    with NO_LAZY_FETCH ourselves.
>
>  * Otherwise, we set and export NO_LAZY_FETCH just we used to.
>
> and what you have in the patch is close enough to that (you left the
> historical "disable lazy fetch upfront" so worst case you export the
> thing twice which is not necessary).
This should be fixed in v4, see below.
Show 12 quoted lines
> > This allows server operators to properly control lazy fetching. It is
> > their responsibility, not the client's, to decide if the served repo is
> > trusted,
>
> If "the served repo" refers to where the client is fetching from,
> trusting that repository or not is up to the client; if they do not
> trust it, they should not be coming to you.
>
> I may be misunderstanding what you are trying to say here, but what
> is up to the server operator to decide is if the promisor remotes,
> which the repo that is serving the client uses, is trustworthy,
> right?

I think that by listing a repo in uploadpack.lazyFetchTrusted, the operator vouches for the following:

- the repo's configuration and hooks, because git fetch will execute them,
- the promisor remotes it is configured to lazily fetch from, because
objects will come from there.
I have tried to clarify this in v4 with the following in the commit message:
    +    Note that what a server operator vouches for by listing a repo there
    +    is that the promisor remotes this repo is configured to lazily fetch
    +    from, as well as its configuration and hooks, are trustworthy. Whether
    +    a client trusts the repo it fetches from is a separate matter, and up
    +    to the client.
Show 43 quoted lines
> > As `GIT_NO_LAZY_FETCH` is passed down to child processes through the
> > environment, this works for `pack-objects`, which performs the lazy
> > fetch when serving a client, without any further plumbing.
> >
> > Now that "uploadpack.lazyFetchTrusted" is actually doing something,
> > let's document it and reference it from GIT_NO_LAZY_FETCH's docs.
>
> > diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c
> > index 32831fb879..8b531ca724 100644
> > --- a/builtin/upload-pack.c
> > +++ b/builtin/upload-pack.c
> > @@ -42,10 +42,13 @@ int cmd_upload_pack(int argc,
> >               OPT_END()
> >       };
> >       unsigned enter_repo_flags = ENTER_REPO_ANY_OWNER_OK;
> > +     bool no_lazy_fetch_set;
> >
> >       packet_trace_identity("upload-pack");
> >       disable_replace_refs();
> >       save_commit_buffer = 0;
> > +
> > +     no_lazy_fetch_set = !!getenv(NO_LAZY_FETCH_ENVIRONMENT);
> >       xsetenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 0);
>
> I am not seeing what is in the postcontext of this hunk and in the
> precontext of the next hunk, but I wonder if we can just remove this
> xsetenv (without "no_lazy_fetch_set" variable at all) here ...
>
> >       argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0);
> > @@ -62,6 +65,14 @@ int cmd_upload_pack(int argc,
> >       if (!enter_repo(the_repository, dir, enter_repo_flags))
> >               die("'%s' does not appear to be a git repository", dir);
> >
> > +     /*
> > +      * Relax the GIT_NO_LAZY_FETCH=1 default if the served repo is in
> > +      * the "uploadpack.lazyFetchTrusted" protected allowlist and
> > +      * GIT_NO_LAZY_FETCH was not already set explicitly.
> > +      */
> > +     if (!no_lazy_fetch_set && upload_pack_lazy_fetch_trusted(the_repository))
> > +             xsetenv(NO_LAZY_FETCH_ENVIRONMENT, "0", 1);
>
> ... and instead check the existing environment here, and do the
> choice from three possibilities I listed above here.

Yes, that's what is implemented in v4. The three possibilities are also listed in the commit message now.

> Other than that, this is a great endgame of the series.
Thanks.
Previous: Junio C HamanoNext: Christian Couder
Message 36 of 70 in “Introduce a 'fromAccepted' option to GIT_NO_LAZY_FETCH”
  1. 0/3 Introduce a 'fromAccepted' option to GIT_NO_LAZY_FETCHChristian Couder, Jul 10, 2026
  2. 1/3 promisor-remote: factor out lazy_fetch_objects()Christian Couder, Jul 10, 2026
  3. 2/3 promisor-remote: introduce enum allow_lazy_fetchChristian Couder, Jul 10, 2026
  4. 3/3 promisor-remote: teach 'fromAccepted' to GIT_NO_LAZY_FETCHChristian Couder, Jul 10, 2026
  5. brian m. carlsonJul 10, 2026
  6. Christian CouderJul 12, 2026
  7. 0/5 Introduce 'uploadpack.lazyFetchTrusted'Christian Couder, Aug 7, 2026
  8. 1/5 promisor-remote: factor out lazy_fetch_objects()Christian Couder, Aug 7, 2026
  9. Christian CouderAug 7, 2026
  10. 2/5 setup: extract path_allowlist_apply()Christian Couder, Aug 7, 2026
  11. 4/5 upload-pack: read uploadpack.lazyFetchTrustedChristian Couder, Aug 7, 2026
  12. 5/5 builtin/upload-pack: set GIT_NO_LAZY_FETCH to 0 on trusted repoChristian Couder, Aug 7, 2026
  13. 3/5 setup: add 'allow_dot' arg to path_allowlist_apply()Christian Couder, Aug 7, 2026
  14. Junio C HamanoAug 7, 2026
  15. Christian CouderAug 10, 2026
  16. Junio C HamanoAug 11, 2026
  17. 0/5 Introduce 'uploadpack.lazyFetchTrusted'Christian Couder, Aug 13, 2026
  18. Junio C HamanoAug 13, 2026
  19. Christian CouderAug 14, 2026
  20. Junio C HamanoAug 14, 2026
  21. 0/5 Introduce 'uploadpack.lazyFetchTrusted'Christian Couder, Sep 8, 2026
  22. 1/5 promisor-remote: factor out lazy_fetch_objects()Christian Couder, Sep 8, 2026
  23. Junio C HamanoSep 8, 2026
  24. Christian CouderSep 28, 2026
  25. 2/5 setup: extract path_allowlist_apply()Christian Couder, Sep 8, 2026
  26. Junio C HamanoSep 8, 2026
  27. Christian CouderSep 28, 2026
  28. 3/5 upload-pack: read uploadpack.lazyFetchTrustedChristian Couder, Sep 8, 2026
  29. 4/5 promisor-remote: prevent infinite recursion when lazy fetchingChristian Couder, Sep 8, 2026
  30. Junio C HamanoSep 8, 2026
  31. Christian CouderSep 9, 2026
  32. Junio C HamanoSep 9, 2026
  33. Christian CouderSep 28, 2026
  34. 5/5 builtin/upload-pack: set GIT_NO_LAZY_FETCH to 0 on trusted repoChristian Couder, Sep 8, 2026
  35. Junio C HamanoSep 8, 2026
  36. Christian CouderSep 28, 2026
  37. 0/5 Introduce 'uploadpack.lazyFetchTrusted'Christian Couder, Sep 28, 2026
  38. 1/5 promisor-remote: factor out lazy_fetch_objects()Christian Couder, Sep 28, 2026
  39. 2/5 setup: extract path_allowlist_apply()Christian Couder, Sep 28, 2026
  40. Junio C HamanoSep 29, 2026
  41. Christian CouderOct 2, 2026
  42. 3/5 upload-pack: read uploadpack.lazyFetchTrustedChristian Couder, Sep 28, 2026
  43. 4/5 promisor-remote: prevent infinite recursion when lazy fetchingChristian Couder, Sep 28, 2026
  44. 5/5 builtin/upload-pack: don't disable lazy fetching on trusted repoChristian Couder, Sep 28, 2026
  45. Junio C HamanoSep 29, 2026
  46. Christian CouderOct 2, 2026
  47. Christian CouderOct 2, 2026
  48. 0/5 Introduce 'uploadpack.lazyFetchTrusted'Christian Couder, Oct 2, 2026
  49. 1/5 promisor-remote: factor out lazy_fetch_objects()Christian Couder, Oct 2, 2026
  50. 2/5 setup: extract path_allowlist_apply()Christian Couder, Oct 2, 2026
  51. 3/5 upload-pack: read uploadpack.lazyFetchTrustedChristian Couder, Oct 2, 2026
  52. 4/5 promisor-remote: prevent infinite recursion when lazy fetchingChristian Couder, Oct 2, 2026
  53. 5/5 builtin/upload-pack: don't disable lazy fetching on trusted repoChristian Couder, Oct 2, 2026
  54. Junio C HamanoOct 5, 2026
  55. Christian CouderOct 6, 2026
  56. 1/5 promisor-remote: factor out lazy_fetch_objects()Christian Couder, Aug 13, 2026
  57. Junio C HamanoAug 14, 2026
  58. Christian CouderSep 8, 2026
  59. 2/5 setup: extract path_allowlist_apply()Christian Couder, Aug 13, 2026
  60. Junio C HamanoAug 14, 2026
  61. Christian CouderSep 8, 2026
  62. Junio C HamanoSep 8, 2026
  63. 3/5 setup: add 'allow_dot' arg to path_allowlist_apply()Christian Couder, Aug 13, 2026
  64. Junio C HamanoAug 14, 2026
  65. Christian CouderSep 8, 2026
  66. 4/5 upload-pack: read uploadpack.lazyFetchTrustedChristian Couder, Aug 13, 2026
  67. Junio C HamanoAug 14, 2026
  68. 5/5 builtin/upload-pack: set GIT_NO_LAZY_FETCH to 0 on trusted repoChristian Couder, Aug 13, 2026
  69. Junio C HamanoAug 14, 2026
  70. Christian CouderSep 8, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.