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

[PATCH 0/6] [RFC] config.c: use struct for config reading state

From
Glen Choo via GitGitGadget <gitgitgadget@gmail.com>
Date
Mar 1, 2023, 00:38 UTC
Message-ID
<pull.1463.git.git.1677631097.gitgitgadget@gmail.com>

This RFC is preparation for config.[ch] to be libified as as part of the libification effort that Emily described in [1]. One of the first goals is to read config from a file, but the trouble with how config.c is written today is that all reading operations rely on global state, so before turning that into a library, we'd want to make that state non-global.

This series gets us about halfway there; it does enough plumbing for a workable-but-kinda-ugly library interface, but with a little bit more work, I think we can get rid of global state in-tree as well. That requires a fair amount of work though, so I'd like to get thoughts on that before starting work.

= Description

This series extracts the global config reading state into "struct config_reader" and plumbs it through the config reading machinery. It's very similar to how we've plumbed "struct repository" and other 'context objects' in the past, except:

 * The global state (named "the_reader") for the git process lives in a
   config.c static variable, and not on "the_repository". See 3/6 for the
   rationale.
 * I've stopped short of adding "struct config_reader" to config.h public
   functions, since that would affect non-config.c callers.

If we stop right here, it's quite easy to extend it to a future config-lib.h without having to adjust the config.h interface:

 * Move the core config reading functionality from config.c to config-lib.c.
 * Have config-lib.h accept "struct config_reader" as an arg.
 * Have config.h call config-lib.h while passing "the_reader".

and I have some WIP patches that do just that [3], but I think they can be significantly improved if we go a bit further...

= Leftover bits and RFC

With a bit more work on the config machinery, we could make it so that config reading stops being global even without adjusting non-config.c callers. The idea is pretty simple: have the config machinery initialize an internal "struct config_reader" every time we read config and expose that state to the config callbacks (instead of, in this series, asking the caller to initialize "struct config_reader" themselves). I believe that only config callbacks are accessing this state, e.g. because they use the low-level information (like builtin/config.c printing the filename and scope of the value) or for error reporting (like git_parse_int() reporting the filename and line number of the value it failed to parse), and only config callbacks should be accessing this state anyway.

The catch (aka the reason I stopped halfway through) is that I couldn't find a way to expose "struct config_reader" state without some fairly big changes, complexity-wise or LoC-wise, e.g.

 * We could add "struct config_reader" to "config_fn_t", i.e.
   
   -typedef int (*config_fn_t)(const char *var, const char *val, void
   *data); +typedef int (*config_fn_t)(const struct config_reader *reader,
   const char *var, const char *val, void *data);
   
   which isn't complex at all, except that there are ~100 config_fn_t
   implementations [3] and a good number of them may never reference
   "reader". If the churn is tolerable, I think this a good way forward.
 * We could create a new kind of "config_fn_t" that accepts "struct
   config_reader", e.g.
   
   typedef int (*config_fn_t)(const char *var, const char *val, void *data);
   +typedef int (*config_state_fn_t)(const struct config_reader *reader,
   const char *var, const char *val, void *data);
   
   and only adjust the callers that would actually reference "reader". This
   is less churn, but I couldn't find a great way to do this kind of
   'switching between config callback types' elegantly.
 * We could smuggle "struct config_reader" to callback functions in a way
   that interested callers could see it, but uninterested callers could
   ignore. One trick that Jonathan Tan came up with (though not necessarily
   endorsed) would be to allocate a struct for the config value + "struct
   config_reader", then, interested callers could use "offset_of" to recover
   the "struct config_reader". It's a little hacky, but it's low-churn.
= Questions
 * Is this worth merging without the extra work? There are some cleanups in
   this series that could make it valuable, but there are also some hacks
   (see 4/6) that aren't so great.
 * Is the extra work even worth it?
 * Do any of the ideas seem more promising than the others? Are there other
   ideas I'm missing?

[1] https://lore.kernel.org/git/CAJoAoZ=Cig_kLocxKGax31sU7Xe4==BGzC__Bg2_pr7krNq6MA@mail.gmail.com [2] https://github.com/chooglen/git/compare/config/structify-reading...chooglen:git:config/read-without-globals [3] This is a rough estimate based on "git grep"-ing callers of the config.h functions. I vaguely recall callbacks being called "old-style", with the suggestion that we should replace them with the "new-style" constant time git_config_get_*() family of functions. That would decrease the number of config callbacks significantly.

Glen Choo (6):
  config.c: plumb config_source through static fns
  config.c: don't assign to "cf" directly
  config.c: create config_reader and the_reader
  config.c: plumb the_reader through callbacks
  config.c: remove current_config_kvi
  config.c: remove current_parsing_scope
 config.c | 489 ++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 287 insertions(+), 202 deletions(-)
base-commit: dadc8e6dacb629f46aee39bde90b6f09b73722eb
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1463%2Fchooglen%2Fconfig%2Fstructify-reading-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1463/chooglen/config/structify-reading-v1
Pull-Request: https://github.com/git/git/pull/1463
-- 
gitgitgadget
Next: Glen Choo via GitGitGadget
Message 1 of 72 in “[RFC] config.c: use struct for config reading state”
  1. 0/6 [RFC] config.c: use struct for config reading stateGlen Choo via GitGitGadget, Mar 1, 2023
  2. 2/6 config.c: don't assign to "cf" directlyGlen Choo via GitGitGadget, Mar 1, 2023
  3. 1/6 config.c: plumb config_source through static fnsGlen Choo via GitGitGadget, Mar 1, 2023
  4. Junio C HamanoMar 3, 2023
  5. 3/6 config.c: create config_reader and the_readerGlen Choo via GitGitGadget, Mar 1, 2023
  6. Junio C HamanoMar 3, 2023
  7. 5/6 config.c: remove current_config_kviGlen Choo via GitGitGadget, Mar 1, 2023
  8. Calvin WanMar 6, 2023
  9. 4/6 config.c: plumb the_reader through callbacksGlen Choo via GitGitGadget, Mar 1, 2023
  10. Ævar Arnfjörð BjarmasonMar 8, 2023
  11. Glen ChooMar 8, 2023
  12. Junio C HamanoMar 8, 2023
  13. 6/6 config.c: remove current_parsing_scopeGlen Choo via GitGitGadget, Mar 1, 2023
  14. Jonathan TanMar 6, 2023
  15. Glen ChooMar 6, 2023
  16. Jonathan TanMar 6, 2023
  17. Ævar Arnfjörð BjarmasonMar 8, 2023
  18. Glen ChooMar 8, 2023
  19. Ævar Arnfjörð BjarmasonMar 7, 2023
  20. Glen ChooMar 7, 2023
  21. Ævar Arnfjörð BjarmasonMar 7, 2023
  22. Junio C HamanoMar 7, 2023
  23. Glen ChooMar 7, 2023
  24. Ævar Arnfjörð BjarmasonMar 8, 2023
  25. Glen ChooMar 8, 2023
  26. 0/8 config.c: use struct for config reading stateGlen Choo via GitGitGadget, Mar 16, 2023
  27. 2/8 config.c: don't assign to "cf_global" directlyGlen Choo via GitGitGadget, Mar 16, 2023
  28. Jonathan TanMar 16, 2023
  29. Junio C HamanoMar 16, 2023
  30. Glen ChooMar 16, 2023
  31. 1/8 config.c: plumb config_source through static fnsGlen Choo via GitGitGadget, Mar 16, 2023
  32. Jonathan TanMar 16, 2023
  33. 3/8 config.c: create config_reader and the_readerGlen Choo via GitGitGadget, Mar 16, 2023
  34. Jonathan TanMar 16, 2023
  35. 4/8 config.c: plumb the_reader through callbacksGlen Choo via GitGitGadget, Mar 16, 2023
  36. 6/8 config.c: remove current_parsing_scopeGlen Choo via GitGitGadget, Mar 16, 2023
  37. 5/8 config.c: remove current_config_kviGlen Choo via GitGitGadget, Mar 16, 2023
  38. 7/8 config: report cached filenames in die_bad_number()Glen Choo via GitGitGadget, Mar 16, 2023
  39. Jonathan TanMar 16, 2023
  40. Glen ChooMar 16, 2023
  41. 8/8 config.c: rename "struct config_source cf"Glen Choo via GitGitGadget, Mar 16, 2023
  42. Glen ChooMar 16, 2023
  43. Jonathan TanMar 16, 2023
  44. 0/5 bypass config.c global state with configsetÆvar Arnfjörð Bjarmason, Mar 17, 2023
  45. 1/5 config.h: move up "struct key_value_info"Ævar Arnfjörð Bjarmason, Mar 17, 2023
  46. 2/5 config.c: use "enum config_origin_type", not "int"Ævar Arnfjörð Bjarmason, Mar 17, 2023
  47. 3/5 config API: add a config_origin_type_name() helperÆvar Arnfjörð Bjarmason, Mar 17, 2023
  48. 4/5 config.c: refactor configset_iter()Ævar Arnfjörð Bjarmason, Mar 17, 2023
  49. 5/5 config API: add and use a repo_config_kvi()Ævar Arnfjörð Bjarmason, Mar 17, 2023
  50. Junio C HamanoMar 17, 2023
  51. Jonathan TanMar 17, 2023
  52. Junio C HamanoMar 17, 2023
  53. Glen ChooMar 17, 2023
  54. Glen ChooMar 17, 2023
  55. Glen ChooMar 17, 2023
  56. Ævar Arnfjörð BjarmasonMar 29, 2023
  57. 0/8 config.c: use struct for config reading stateGlen Choo via GitGitGadget, Mar 28, 2023
  58. 1/8 config.c: plumb config_source through static fnsGlen Choo via GitGitGadget, Mar 28, 2023
  59. 2/8 config.c: don't assign to "cf_global" directlyGlen Choo via GitGitGadget, Mar 28, 2023
  60. 3/8 config.c: create config_reader and the_readerGlen Choo via GitGitGadget, Mar 28, 2023
  61. Ævar Arnfjörð BjarmasonMar 29, 2023
  62. Junio C HamanoMar 29, 2023
  63. Glen ChooMar 29, 2023
  64. Glen ChooMar 30, 2023
  65. 4/8 config.c: plumb the_reader through callbacksGlen Choo via GitGitGadget, Mar 28, 2023
  66. 5/8 config.c: remove current_config_kviGlen Choo via GitGitGadget, Mar 28, 2023
  67. 6/8 config.c: remove current_parsing_scopeGlen Choo via GitGitGadget, Mar 28, 2023
  68. 7/8 config: report cached filenames in die_bad_number()Glen Choo via GitGitGadget, Mar 28, 2023
  69. 8/8 config.c: rename "struct config_source cf"Glen Choo via GitGitGadget, Mar 28, 2023
  70. Glen ChooMar 28, 2023
  71. Junio C HamanoMar 28, 2023
  72. Glen ChooMar 28, 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.