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

Re: [PATCH 01/24] init-db: remove unnecessary global variable & document existing bug

From
Elijah Newren <newren@gmail.com>
Date
May 12, 2023, 01:21 UTC
Message-ID
<CABPp-BFT_aAmMcD7HKVuaZR3kkGND1mBF3R8OvisHimYWiX48g@mail.gmail.com>
In-Reply-To
<kl6lsfc2zjje.fsf@chooglen-macbookpro.roam.corp.google.com>
On Thu, May 11, 2023 at 1:43 PM Glen Choo <chooglen@google.com> wrote:
Show 21 quoted lines
>
> "Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: Elijah Newren <newren@gmail.com>
> >
> > This commit was prompted by a desire to move the functions which
> > builtin/init-db.c and builtin/clone.c share out of the former file and
> > into setup.c.  One issue that made it difficult was the
> > init_is_bare_repository global variable.
> >
> > init_is_bare_repository is actually not very useful.  It merely stores
> > the return value from is_bare_repository() and only for the duration of
> > a few additional function calls before its value is checked, and none of
> > those functions do anything that could change is_bare_repository()'s
> > return value.  So, we can simply dispense with the global by replacing
> > it with is_bare_repository().
>
> I think the purpose of init_is_bare_repository is something different.
> But based off my different understanding, I can't reproduce any
> different behavior. I don't know if I'm just confused or not, but I'll
> leave some breadcrumbs here to check my understanding.

So, while my patch does not change behavior under any circumstances, my explanation was slightly wrong. More on that below...

Show 17 quoted lines
> Reordering the hunks for clarity,
>
> > @@ -422,8 +436,6 @@ int init_db(const char *git_dir, const char *real_git_dir,
> >
> >       safe_create_dir(git_dir, 0);
> >
> > -     init_is_bare_repository = is_bare_repository();
> > -
> >       /* Check to see if the repository version is right.
> >        * Note that a newly created repository does not have
> >        * config file, so this will not fail.  What we are catching
>
> Here, init_db() caches the value of is_bare_repository(), which itself
> reads the value of is_bare_repository_cfg, which can be modified by when
> we read "core.bare" via git_config(git_default_config) or similar
> (basically, any config callback that uses git_default_config). It is
> also modified in other places though, like setup.c.

Close. is_bare_repository() not only reads the value of is_bare_repository_cfg, but it ANDs the result with !get_git_work_tree(). This turns out to be important.

> IIUC, we haven't actually parsed "core.bare" at this point. The
> git_config() call just above this calls "plaform_core_config", which is
> either "mingw_core_config" (doesn't read "core.bare") or
> noop_core_config (noop).
I believe this is correct.
Show 41 quoted lines
> > @@ -231,9 +230,24 @@ static int create_default_files(const char *template_path,
> >        * We must make sure command-line options continue to override any
> >        * values we might have just re-read from the config.
> >        */
> > -     is_bare_repository_cfg = init_is_bare_repository || !work_tree;
> >       if (init_shared_repository != -1)
> >               set_shared_repository(init_shared_repository);
> > +     /*
> > +      * TODO: heed core.bare from config file in templates if no
> > +      *       command-line override given
> > +      *
> > +      * Unfortunately, this location in the code is far too late to
> > +      * allow this to happen; both builtin/init.db and
> > +      * builtin/clone.c setup the new repository and call
> > +      * set_git_work_tree() before this point.  (Note that both do
> > +      * that repository setup before calling init_db(), which in
> > +      * turn calls create_default_files().)  Fixing it would
> > +      * require too much refactoring, and no one seems to have
> > +      * wanted this behavior in 15+ years, so we'll continue
> > +      * ignoring the config for now and just override
> > +      * is_bare_repository_cfg unconditionally.
> > +      */
> > +     is_bare_repository_cfg = is_bare_repository() || !work_tree;
> >
> >       /*
> >        * We would have created the above under user's umask -- under
>
> Now, we're in the midst of the re-init. Expanding the context a little,
> we see:
>
>         git_config(git_default_config, NULL);
>
>         /*
>          * We must make sure command-line options continue to override any
>          * values we might have just re-read from the config.
>          */
>         is_bare_repository_cfg = init_is_bare_repository || !work_tree;
>
> So now we've read the new config of the re-inited repo, which might have
> "core.bare" set to a value other than what "git init-db [--bare]"
> started with
Correct.
> so we want to _intentionally_ ignore it.

That's what the code does, but not what it should do. If neither `--bare` nor `--no-bare` is given on the command line, we ought to pay attention to the config setting.

The fact that we do ignore the config regardless of command line flags is the bug that this patch documents.

> We do this by
> reading out the cached value, _not_ by calling is_bare_repository()
> again.

Almost, but you missed part of the line you are commenting on. We read out the cached value *and* OR it with !work_tree. The distinction may look small, but it turns out to be critical.

> So it seems to me like this patch changes the intent.
Yeah, looks like it does.
But it doesn't change the result.  Note the critical thing here is we
changed from computing:
   init_is_bare_repository || !work_tree;
to
   is_bare_repository() || !work_tree;
Further,
   init_is_bare_repository = [cached value of] is_bare_repository_cfg
&& [cached value of] !get_git_work_tree()
   is_bare_repository() = [current value of] is_bare_repository_cfg &&
[current value of] !get_git_work_tree()
However, nothing calls repo_init() or set_git_work_tree() between any
of these calls, so
   [current value of] !get_git_work_tree() == [cached value of]
!get_git_work_tree() == !work_tree
So, both before and after what we are computing simplifies to
   <something> && !work_tree || !work_tree
which further simplifies, regardless of whether <something> is true or
false, down to
   !work_tree
So whether we are using a cached value of is_bare_repository_cfg or a
current value of is_bare_repository_cfg is irrelevant.  In fact, from
the analysis above, we can simplify this line to just
   is_bare_repository_cfg = !work_tree;
completely ignoring both is_bare_repository_cfg and
is_bare_repository(), and it won't change the behavior.  I just did
it; it passes all tests.
> Where I struggling with is how to make this behave badly. The lines
> above seem to be defensive in nature - we never use
> is_bare_repository_cfg past this point, but we want to guard against
> unintentional behavior in the future.

Not quite true; there is another call to is_bare_repository() in the same function about 60 lines later, which does pay attention to is_bare_repository_cfg.

[...]
> If I'm right (which I'm not sure about), we might need to keep
> init_is_bare_repository around _somewhere_. Not a global, but maybe
> as a param.

This makes sense, despite the other bugs present. I'll make this change, as well as split this patch into two as Calvin suggested, and update the description to correct my errors and explain the bug better.

Previous: Glen ChooNext: Glen Choo
Message 6 of 115 in “Header cleanups (final splitting of cache.h, and some splitting of other headers)”
  1. 00/24 Header cleanups (final splitting of cache.h, and some splitting of other headers)Elijah Newren via GitGitGadget, May 7, 2023
  2. 01/24 init-db: remove unnecessary global variable & document existing bugElijah Newren via GitGitGadget, May 7, 2023
  3. Calvin WanMay 11, 2023
  4. Elijah NewrenMay 12, 2023
  5. Glen ChooMay 11, 2023
  6. Elijah NewrenMay 12, 2023
  7. Glen ChooMay 12, 2023
  8. 02/24 init-db, clone: change unnecessary global into passed parameterElijah Newren via GitGitGadget, May 7, 2023
  9. 05/24 add: modify add_files_to_cache() to avoid globalsElijah Newren via GitGitGadget, May 7, 2023
  10. 04/24 read-cache: move shared commit and ls-files codeElijah Newren via GitGitGadget, May 7, 2023
  11. 08/24 run-command.h: move declarations for run-command.c from cache.hElijah Newren via GitGitGadget, May 7, 2023
  12. 06/24 read-cache: move shared add/checkout/commit codeElijah Newren via GitGitGadget, May 7, 2023
  13. 03/24 setup: adopt shared init-db & clone codeElijah Newren via GitGitGadget, May 7, 2023
  14. 07/24 statinfo: move stat_{data,validity} functions from cache/read-cacheElijah Newren via GitGitGadget, May 7, 2023
  15. 09/24 name-hash.h: move declarations for name-hash.c from cache.hElijah Newren via GitGitGadget, May 7, 2023
  16. 10/24 sparse-index.h: move declarations for sparse-index.c from cache.hElijah Newren via GitGitGadget, May 7, 2023
  17. 11/24 preload-index.h: move declarations for preload-index.c from elsewhereElijah Newren via GitGitGadget, May 7, 2023
  18. 12/24 diff.h: move declaration for global in diff.c from cache.hElijah Newren via GitGitGadget, May 7, 2023
  19. 13/24 merge.h: move declarations for merge.c from cache.hElijah Newren via GitGitGadget, May 7, 2023
  20. 14/24 repository.h: move declaration of the_index from cache.hElijah Newren via GitGitGadget, May 7, 2023
  21. 19/24 diff.h: remove unnecessary include of oidset.hElijah Newren via GitGitGadget, May 7, 2023
  22. 17/24 log-tree: replace include of revision.h with simple forward declarationElijah Newren via GitGitGadget, May 7, 2023
  23. 20/24 list-objects-filter-options.h: remove unneccessary includeElijah Newren via GitGitGadget, May 7, 2023
  24. 15/24 read-cache*.h: move declarations for read-cache.c functions from cache.hElijah Newren via GitGitGadget, May 7, 2023
  25. 18/24 repository: remove unnecessary include of path.hElijah Newren via GitGitGadget, May 7, 2023
  26. 21/24 builtin.h: remove unneccessary includesElijah Newren via GitGitGadget, May 7, 2023
  27. 16/24 cache.h: remove this no-longer-used headerElijah Newren via GitGitGadget, May 7, 2023
  28. 22/24 git-compat-util.h: remove unneccessary include of wildmatch.hElijah Newren via GitGitGadget, May 7, 2023
  29. 24/24 fsmonitor-ll.h: split this header out of fsmonitor.hElijah Newren via GitGitGadget, May 7, 2023
  30. 23/24 hash-ll, hashmap: move oidhash() to hash-llElijah Newren via GitGitGadget, May 7, 2023
  31. Calvin WanMay 11, 2023
  32. Jeff KingMay 11, 2023
  33. Felipe ContrerasMay 11, 2023
  34. Elijah NewrenMay 12, 2023
  35. Jeff KingMay 12, 2023
  36. Junio C HamanoMay 8, 2023
  37. Elijah NewrenMay 9, 2023
  38. Junio C HamanoMay 9, 2023
  39. Junio C HamanoMay 8, 2023
  40. Calvin WanMay 11, 2023
  41. Elijah NewrenMay 12, 2023
  42. 00/27 Header cleanups (final splitting of cache.h, and some splitting of other headers)Elijah Newren via GitGitGadget, May 12, 2023
  43. 03/27 init-db, clone: change unnecessary global into passed parameterElijah Newren via GitGitGadget, May 12, 2023
  44. Jonathan TanMay 12, 2023
  45. Elijah NewrenMay 16, 2023
  46. 02/27 init-db: remove unnecessary global variableElijah Newren via GitGitGadget, May 12, 2023
  47. Glen ChooMay 12, 2023
  48. 01/27 init-db: document existing bug with core.bare in template configElijah Newren via GitGitGadget, May 12, 2023
  49. Jonathan TanMay 12, 2023
  50. Elijah NewrenMay 16, 2023
  51. 06/27 add: modify add_files_to_cache() to avoid globalsElijah Newren via GitGitGadget, May 12, 2023
  52. Jonathan TanMay 15, 2023
  53. 05/27 read-cache: move shared commit and ls-files codeElijah Newren via GitGitGadget, May 12, 2023
  54. Jonathan TanMay 12, 2023
  55. 09/27 run-command.h: move declarations for run-command.c from cache.hElijah Newren via GitGitGadget, May 12, 2023
  56. 04/27 setup: adopt shared init-db & clone codeElijah Newren via GitGitGadget, May 12, 2023
  57. 07/27 read-cache: move shared add/checkout/commit codeElijah Newren via GitGitGadget, May 12, 2023
  58. 08/27 statinfo: move stat_{data,validity} functions from cache/read-cacheElijah Newren via GitGitGadget, May 12, 2023
  59. 11/27 sparse-index.h: move declarations for sparse-index.c from cache.hElijah Newren via GitGitGadget, May 12, 2023
  60. 10/27 name-hash.h: move declarations for name-hash.c from cache.hElijah Newren via GitGitGadget, May 12, 2023
  61. 13/27 diff.h: move declaration for global in diff.c from cache.hElijah Newren via GitGitGadget, May 12, 2023
  62. 12/27 preload-index.h: move declarations for preload-index.c from elsewhereElijah Newren via GitGitGadget, May 12, 2023
  63. 15/27 repository.h: move declaration of the_index from cache.hElijah Newren via GitGitGadget, May 12, 2023
  64. Jonathan TanMay 15, 2023
  65. 14/27 merge.h: move declarations for merge.c from cache.hElijah Newren via GitGitGadget, May 12, 2023
  66. 18/27 log-tree: replace include of revision.h with simple forward declarationElijah Newren via GitGitGadget, May 12, 2023
  67. 19/27 repository: remove unnecessary include of path.hElijah Newren via GitGitGadget, May 12, 2023
  68. 21/27 list-objects-filter-options.h: remove unneccessary includeElijah Newren via GitGitGadget, May 12, 2023
  69. 20/27 diff.h: remove unnecessary include of oidset.hElijah Newren via GitGitGadget, May 12, 2023
  70. 16/27 read-cache*.h: move declarations for read-cache.c functions from cache.hElijah Newren via GitGitGadget, May 12, 2023
  71. Jonathan TanMay 16, 2023
  72. 17/27 cache.h: remove this no-longer-used headerElijah Newren via GitGitGadget, May 12, 2023
  73. Jonathan TanMay 16, 2023
  74. Elijah NewrenMay 16, 2023
  75. 23/27 git-compat-util.h: remove unneccessary include of wildmatch.hElijah Newren via GitGitGadget, May 12, 2023
  76. 22/27 builtin.h: remove unneccessary includesElijah Newren via GitGitGadget, May 12, 2023
  77. 25/27 khash: name the structs that khash declaresElijah Newren via GitGitGadget, May 12, 2023
  78. 24/27 merge-ll: rename from ll-mergeElijah Newren via GitGitGadget, May 12, 2023
  79. 27/27 fsmonitor-ll.h: split this header out of fsmonitor.hElijah Newren via GitGitGadget, May 12, 2023
  80. Jonathan TanMay 16, 2023
  81. Elijah NewrenMay 16, 2023
  82. 26/27 hash-ll, hashmap: move oidhash() to hash-llElijah Newren via GitGitGadget, May 12, 2023
  83. Jonathan TanMay 16, 2023
  84. Elijah NewrenMay 16, 2023
  85. 00/28 Header cleanups (final splitting of cache.h, and some splitting of other headers)Elijah Newren via GitGitGadget, May 16, 2023
  86. 02/28 init-db: remove unnecessary global variableElijah Newren via GitGitGadget, May 16, 2023
  87. 01/28 init-db: document existing bug with core.bare in template configElijah Newren via GitGitGadget, May 16, 2023
  88. 03/28 init-db, clone: change unnecessary global into passed parameterElijah Newren via GitGitGadget, May 16, 2023
  89. 05/28 read-cache: move shared commit and ls-files codeElijah Newren via GitGitGadget, May 16, 2023
  90. 06/28 add: modify add_files_to_cache() to avoid globalsElijah Newren via GitGitGadget, May 16, 2023
  91. 07/28 read-cache: move shared add/checkout/commit codeElijah Newren via GitGitGadget, May 16, 2023
  92. 04/28 setup: adopt shared init-db & clone codeElijah Newren via GitGitGadget, May 16, 2023
  93. 09/28 run-command.h: move declarations for run-command.c from cache.hElijah Newren via GitGitGadget, May 16, 2023
  94. 10/28 name-hash.h: move declarations for name-hash.c from cache.hElijah Newren via GitGitGadget, May 16, 2023
  95. 08/28 statinfo: move stat_{data,validity} functions from cache/read-cacheElijah Newren via GitGitGadget, May 16, 2023
  96. 11/28 sparse-index.h: move declarations for sparse-index.c from cache.hElijah Newren via GitGitGadget, May 16, 2023
  97. 14/28 merge.h: move declarations for merge.c from cache.hElijah Newren via GitGitGadget, May 16, 2023
  98. 12/28 preload-index.h: move declarations for preload-index.c from elsewhereElijah Newren via GitGitGadget, May 16, 2023
  99. 15/28 repository.h: move declaration of the_index from cache.hElijah Newren via GitGitGadget, May 16, 2023
  100. 18/28 log-tree: replace include of revision.h with simple forward declarationElijah Newren via GitGitGadget, May 16, 2023
  101. 13/28 diff.h: move declaration for global in diff.c from cache.hElijah Newren via GitGitGadget, May 16, 2023
  102. 19/28 repository: remove unnecessary include of path.hElijah Newren via GitGitGadget, May 16, 2023
  103. 16/28 read-cache*.h: move declarations for read-cache.c functions from cache.hElijah Newren via GitGitGadget, May 16, 2023
  104. 17/28 cache.h: remove this no-longer-used headerElijah Newren via GitGitGadget, May 16, 2023
  105. 22/28 builtin.h: remove unneccessary includesElijah Newren via GitGitGadget, May 16, 2023
  106. 25/28 khash: name the structs that khash declaresElijah Newren via GitGitGadget, May 16, 2023
  107. 23/28 git-compat-util.h: remove unneccessary include of wildmatch.hElijah Newren via GitGitGadget, May 16, 2023
  108. 24/28 merge-ll: rename from ll-mergeElijah Newren via GitGitGadget, May 16, 2023
  109. 27/28 hash-ll, hashmap: move oidhash() to hash-llElijah Newren via GitGitGadget, May 16, 2023
  110. 28/28 fsmonitor-ll.h: split this header out of fsmonitor.hElijah Newren via GitGitGadget, May 16, 2023
  111. 26/28 object-store-ll.h: split this header out of object-store.hElijah Newren via GitGitGadget, May 16, 2023
  112. 21/28 list-objects-filter-options.h: remove unneccessary includeElijah Newren via GitGitGadget, May 16, 2023
  113. 20/28 diff.h: remove unnecessary include of oidset.hElijah Newren via GitGitGadget, May 16, 2023
  114. Calvin WanMay 23, 2023
  115. Elijah NewrenMay 24, 2023

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.