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

[RFC PATCH 00/20] submodule: remove git-submodule.sh, create bare builtin/submodule.c

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Jun 10, 2022, 02:01 UTC
Message-ID
<RFC-cover-00.20-00000000000-20220610T011725Z-avarab@gmail.com>
In-Reply-To
<pull.1275.git.git.1654820781.gitgitgadget@gmail.com>
On Fri, Jun 10 2022, Glen Choo via GitGitGadget wrote:
> As a follow up to ar/submodule-update [1] and its successors
> gc/submodule-update-part* [2] [3], this series converts the last remaining
> piece of "git submodule update" into C, namely, the option parsing in
> git-submodule.sh.
Aside at the end at [2].
Show 21 quoted lines
> As a result, git-submodule.sh::cmd_update() is now an (almost) one-liner:
>
> cmd_update() { git ${wt_prefix:+-C "$wt_prefix"} submodule--helper update
> ${wt_prefix:+--prefix "$wt_prefix"}
> "$@" }
>
> and best of all, "git submodule update" now shows a usage string for its own
> subcommand instead of a giant usage string for all of "git submodule" :)
>
> Given how many options "git submodule update" accepts, this series takes a
> gradual approach:
>
>  1. Create a variable opts, which holds the literal options we want to pass
>     to "git submodule--helper update". Then, for each option...
>  2. If "git submodule--helper update" already understands the string option,
>     append it to opts and remove any special handling (1-3/8).
>  3. Otherwise, if the option makes sense, teach "git submodule--helper
>     update" to understand the option. Goto 2. (4-5/8).
>  4. Otherwise, if the option makes no sense, drop it (6/8).
>  5. When we've processed all options, delete all the option parsing code
>     (7/8) and clean up (8/8).

That's quite the timing coincidence. I hacked this up yesterday, thinking that the submodule topic had been too quiet for a while, and wondering how hard it was to convert the rest of git-submodule.sh.

It's more than 2x the length of yours, but gets to the point where we can "git rm git-submodule.sh".

Some brief comparison/commentary:
> Glen Choo (8):
>   submodule update: remove intermediate parsing
>   submodule update: pass options containing "[no-]"
>   submodule update: pass options with stuck forms

Yeah, this is the alternate approach I considered and ended up discarding. I.e. to make forward progress with migrating things away from the cmd_*() functions you either have to prepare things in advance and then sweep the rug from under them in one go.

Or, as you're doing here teaching them about the options they're not-really-parsing anymore, but must know about because they're in a loop that ends with a "if unknown option, usage".

>   submodule update: pass --require-init and --init
Almost the same as my 12/20.
>   submodule--helper update: use one param per type

Same as my 13/20, but I ended up doing it in a more narrow/smaller way. I tried your way and ran into some bug, then figured I'd do it more narrowly instead of debugging it.

>   submodule update: remove -v, pass --quiet

Hrm, so we don't need it at all then. Well, that's a bit simpler than my 1[45]/20 and 17/20 :)

So yeah, definitely RFC-quality, but I ran into that one test that used -v, and then saw the missing docs etc. But no cheating, so I've left it in :)

I do wonder if we should leave it in anyway, we never documented -v, but we *did* understand it, and if you look at:

    git log -p -Gsay -- git-submodule.sh

We used to have a lot more code impacted by it, but looking at this again now it would have only been for users of command-lines like:

    git submodule --quiet update -v [...]

I.e. where we already set the flag to the non-default quiet, and then used -v to flip it.

I think at this point I've talked myself into "let's just remove it", but maybe...

>   submodule update: stop parsing options in .sh

Same effect as my 16/20, but it's the last one I converted, the cmd_update() case being the trickiest.

>   submodule update: remove never-used expansion

Same as my 02/20, but as seen there I think you missed several "prefix" non-uses.

Brief commentary on my patches, details in commit messages:
Ævar Arnfjörð Bjarmason (20):
  git-submodule.sh: remove unused sanitize_submodule_env()
  git-submodule.sh: remove unused $prefix variable
  git-submodule.sh: remove unused --super-prefix logic
I removed a bit more dead code here than yours.
  git-submodule.sh: normalize parsing of "--branch"
  git-submodule.sh: normalize parsing of --cached

This & various other prep commits (hereafter "easy prep") make subsequent one-time conversions of whole cmd_*() easier.

  submodule--helper: rename "absorb-git-dirs" to "absorbgitdirs"
  git-submodule.sh: create a "case" dispatch statement
easy prep
  submodule--helper: pretend to be "git submodule" in "-h" output
easy prep & bug fix for existing (on master) output bugs.
  git-submodule.sh: dispatch "sync" to helper
  git-submodule.sh: dispatch directly to helper
  git-submodule.sh: dispatch "foreach" to helper

These are easy conversions as the options 1=1 map after the above prep.

  submodule--helper: have --require-init imply --init
  submodule--helper: understand --checkout, --merge and --rebase
    synonyms
  git-submodule doc: document the -v" option to "update"
  submodule--helper: understand -v option for "update"
not-so-easy prep for "cmd_update()"
  git-submodule.sh: dispatch "update" to helper
Full cmd_update() migration in one go.
  git-submodule.sh: use "$quiet", not "$GIT_QUIET"

"easy prep", but this one is less overall churn if done at the end, but as noted above could/should maybe be dropped entirely.

  git-submodule.sh: simplify parsing loop

Not really needed, but I wanted to get the code as close to minimal for the next step, to eyeball the resulting sh v.s. C version.

  submodule: make it a built-in, remove git-submodule.sh

We now have a builtin/submodule.c *and* the current builtin/submodule--helper.c, and we even dispatch to "git submodule--helper" via run_command()!

The idea is to be as close as possible to a bug-for-bug implementation of the shellscript, and that reviewers should be confident in being able to trace what commands we invoked before/after, we're invoking the same "git submodule--helper" commands.

Of course we eventually want to get to some full union of builtin/submodule{,--helper}.c, but that can wait.

  submodule: add a subprocess-less submodule.useBuiltin setting

Wait, a useBuiltin setting to switch between two built-ins? Yeah, maybe it makes little sense, but here we get rid of the run_command() overhead, and could generally use the built-in to experiment with deeper integration between the two.

Performance is around ~2x faster with the "real" built-in than the run_command() version, whic hin turn is more than 6x as fast on basic overhead than the shellscript version, to the extent that anyone cares about "git submodule" overhead. See [1] at the end for a benchmark.

That last change adds a CI target for GIT_TEST_SUBMODULE_USE_BUILTIN=true, full CI run here: https://github.com/avar/git/actions/runs/2472131257

 Documentation/config/submodule.txt |   4 +
 Documentation/git-submodule.txt    |   8 +-
 Makefile                           |   2 +-
 builtin.h                          |   1 +
 builtin/submodule--helper.c        | 118 +++---
 builtin/submodule.c                | 169 ++++++++
 ci/run-build-and-tests.sh          |   1 +
 git-sh-setup.sh                    |   7 -
 git-submodule.sh                   | 637 -----------------------------
 git.c                              |   1 +
 submodule.c                        |   2 +-
 t/README                           |   4 +
 12 files changed, 255 insertions(+), 699 deletions(-)
 create mode 100644 builtin/submodule.c
 delete mode 100755 git-submodule.sh
1. GIT_TEST_SUBMODULE_USE_BUILTIN=true git hyperfine -L rev origin/master,HEAD~0 -L v false,true -s 'make CFLAGS=-O3' 'GIT_TEST_SUBMODULE_USE_BUILTIN={v} ./git --exec-path=$PWD submodule status' -r 20
Benchmark 1: GIT_TEST_SUBMODULE_USE_BUILTIN=false ./git --exec-path=$PWD submodule status' in 'origin/master
  Time (mean ± σ):      40.9 ms ±   0.3 ms    [User: 33.3 ms, System: 9.7 ms]
  Range (min … max):    40.2 ms …  41.5 ms    20 runs
Benchmark 2: GIT_TEST_SUBMODULE_USE_BUILTIN=false ./git --exec-path=$PWD submodule status' in 'HEAD~0
  Time (mean ± σ):      12.4 ms ±   0.1 ms    [User: 9.9 ms, System: 2.5 ms]
  Range (min … max):    12.2 ms …  12.7 ms    20 runs
Benchmark 3: GIT_TEST_SUBMODULE_USE_BUILTIN=true ./git --exec-path=$PWD submodule status' in 'origin/master
  Time (mean ± σ):      40.9 ms ±   0.5 ms    [User: 35.6 ms, System: 7.2 ms]
  Range (min … max):    40.1 ms …  41.8 ms    20 runs
Benchmark 4: GIT_TEST_SUBMODULE_USE_BUILTIN=true ./git --exec-path=$PWD submodule status' in 'HEAD~0
  Time (mean ± σ):       6.4 ms ±   0.1 ms    [User: 3.9 ms, System: 2.5 ms]
  Range (min … max):     6.3 ms …   6.6 ms    20 runs
Summary
  'GIT_TEST_SUBMODULE_USE_BUILTIN=true ./git --exec-path=$PWD submodule status' in 'HEAD~0' ran
    1.94 ± 0.03 times faster than 'GIT_TEST_SUBMODULE_USE_BUILTIN=false ./git --exec-path=$PWD submodule status' in 'HEAD~0'
    6.40 ± 0.11 times faster than 'GIT_TEST_SUBMODULE_USE_BUILTIN=true ./git --exec-path=$PWD submodule status' in 'origin/master'
    6.40 ± 0.10 times faster than 'GIT_TEST_SUBMODULE_USE_BUILTIN=false ./git --exec-path=$PWD submodule status' in 'origin/master'
2. Aside: I don't think these ever made it on-list but Atharva's
   version of what we're trying to do here is at:
   https://github.com/tfidfwastaken/git/tree/submodule-make-builtin-2
   I'd looked those over at some distant point in the past, and
   skimmed them again yesterday, but thought they were too much
   all-at-once to be confident in testing it myself, hence coming up
   with this alternate & smaller approach.
-- 
2.36.1.1178.gb5b1747c546
Previous: Glen Choo via GitGitGadgetNext: Ævar Arnfjörð Bjarmason
Message 10 of 90 in “[RFC] submodule update: parse all options in C”
  1. 0/8 [RFC] submodule update: parse all options in CGlen Choo via GitGitGadget, Jun 10, 2022
  2. 1/8 submodule update: remove intermediate parsingGlen Choo via GitGitGadget, Jun 10, 2022
  3. 2/8 submodule update: pass options containing "[no-]"Glen Choo via GitGitGadget, Jun 10, 2022
  4. 3/8 submodule update: pass options with stuck formsGlen Choo via GitGitGadget, Jun 10, 2022
  5. 4/8 submodule update: pass --require-init and --initGlen Choo via GitGitGadget, Jun 10, 2022
  6. 5/8 submodule--helper update: use one param per typeGlen Choo via GitGitGadget, Jun 10, 2022
  7. 7/8 submodule update: stop parsing options in .shGlen Choo via GitGitGadget, Jun 10, 2022
  8. 8/8 submodule update: remove never-used expansionGlen Choo via GitGitGadget, Jun 10, 2022
  9. 6/8 submodule update: remove -v, pass --quietGlen Choo via GitGitGadget, Jun 10, 2022
  10. 00/20 submodule: remove git-submodule.sh, create bare builtin/submodule.cÆvar Arnfjörð Bjarmason, Jun 10, 2022
  11. 01/20 git-submodule.sh: remove unused sanitize_submodule_env()Ævar Arnfjörð Bjarmason, Jun 10, 2022
  12. 02/20 git-submodule.sh: remove unused $prefix variableÆvar Arnfjörð Bjarmason, Jun 10, 2022
  13. 04/20 git-submodule.sh: normalize parsing of "--branch"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  14. 03/20 git-submodule.sh: remove unused --super-prefix logicÆvar Arnfjörð Bjarmason, Jun 10, 2022
  15. 05/20 git-submodule.sh: normalize parsing of --cachedÆvar Arnfjörð Bjarmason, Jun 10, 2022
  16. 06/20 submodule--helper: rename "absorb-git-dirs" to "absorbgitdirs"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  17. 07/20 git-submodule.sh: create a "case" dispatch statementÆvar Arnfjörð Bjarmason, Jun 10, 2022
  18. 09/20 git-submodule.sh: dispatch "sync" to helperÆvar Arnfjörð Bjarmason, Jun 10, 2022
  19. 08/20 submodule--helper: pretend to be "git submodule" in "-h" outputÆvar Arnfjörð Bjarmason, Jun 10, 2022
  20. 10/20 git-submodule.sh: dispatch directly to helperÆvar Arnfjörð Bjarmason, Jun 10, 2022
  21. 12/20 submodule--helper: have --require-init imply --initÆvar Arnfjörð Bjarmason, Jun 10, 2022
  22. 11/20 git-submodule.sh: dispatch "foreach" to helperÆvar Arnfjörð Bjarmason, Jun 10, 2022
  23. 15/20 submodule--helper: understand -v option for "update"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  24. 14/20 git-submodule doc: document the -v" option to "update"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  25. 18/20 git-submodule.sh: simplify parsing loopÆvar Arnfjörð Bjarmason, Jun 10, 2022
  26. 20/20 submodule: add a subprocess-less submodule.useBuiltin settingÆvar Arnfjörð Bjarmason, Jun 10, 2022
  27. 19/20 submodule: make it a built-in, remove git-submodule.shÆvar Arnfjörð Bjarmason, Jun 10, 2022
  28. 17/20 git-submodule.sh: use "$quiet", not "$GIT_QUIET"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  29. 13/20 submodule--helper: understand --checkout, --merge and --rebase synonymsÆvar Arnfjörð Bjarmason, Jun 10, 2022
  30. 16/20 git-submodule.sh: dispatch "update" to helperÆvar Arnfjörð Bjarmason, Jun 10, 2022
  31. Glen ChooJun 13, 2022
  32. 00/12 submodule: make "git submodule--helper" behave like "git submodule"Ævar Arnfjörð Bjarmason, Jun 13, 2022
  33. 01/12 git-submodule.sh: remove unused sanitize_submodule_env()Ævar Arnfjörð Bjarmason, Jun 13, 2022
  34. 02/12 git-submodule.sh: remove unused $prefix var and --super-prefixÆvar Arnfjörð Bjarmason, Jun 13, 2022
  35. 03/12 git-submodule.sh: make "$cached" variable a booleanÆvar Arnfjörð Bjarmason, Jun 13, 2022
  36. 04/12 git-submodule.sh: remove unused top-level "--branch" argumentÆvar Arnfjörð Bjarmason, Jun 13, 2022
  37. Glen ChooJun 15, 2022
  38. 05/12 submodule--helper: have --require-init imply --initÆvar Arnfjörð Bjarmason, Jun 13, 2022
  39. Glen ChooJun 15, 2022
  40. 06/12 submodule update: remove "-v" optionÆvar Arnfjörð Bjarmason, Jun 13, 2022
  41. Glen ChooJun 15, 2022
  42. 09/12 submodule--helper: understand --checkout, --merge and --rebase synonymsÆvar Arnfjörð Bjarmason, Jun 13, 2022
  43. 08/12 submodule--helper: report "submodule" as our name in "-h" outputÆvar Arnfjörð Bjarmason, Jun 13, 2022
  44. Glen ChooJun 15, 2022
  45. Glen ChooJun 15, 2022
  46. Ævar Arnfjörð BjarmasonJun 15, 2022
  47. 07/12 submodule--helper: rename "absorb-git-dirs" to "absorbgitdirs"Ævar Arnfjörð Bjarmason, Jun 13, 2022
  48. 11/12 git-submodule.sh: use "$quiet", not "$GIT_QUIET"Ævar Arnfjörð Bjarmason, Jun 13, 2022
  49. 12/12 git-sh-setup.sh: remove "say" function, change last usersÆvar Arnfjörð Bjarmason, Jun 13, 2022
  50. Glen ChooJun 15, 2022
  51. 10/12 submodule--helper: eliminate internal "--update" optionÆvar Arnfjörð Bjarmason, Jun 13, 2022
  52. Glen ChooJun 15, 2022
  53. Glen ChooJun 13, 2022
  54. Ævar Arnfjörð BjarmasonJun 13, 2022
  55. Glen ChooJun 15, 2022
  56. Glen ChooJun 15, 2022
  57. 00/12 submodule: make "git submodule--helper" behave like "git submodule"Ævar Arnfjörð Bjarmason, Jun 22, 2022
  58. 12/12 git-sh-setup.sh: remove "say" function, change last usersÆvar Arnfjörð Bjarmason, Jun 22, 2022
  59. 01/12 git-submodule.sh: remove unused sanitize_submodule_env()Ævar Arnfjörð Bjarmason, Jun 22, 2022
  60. 02/12 git-submodule.sh: remove unused $prefix var and --super-prefixÆvar Arnfjörð Bjarmason, Jun 22, 2022
  61. Glen ChooJun 22, 2022
  62. Ævar Arnfjörð BjarmasonJun 24, 2022
  63. Glen ChooJun 24, 2022
  64. 03/12 git-submodule.sh: make the "$cached" variable a booleanÆvar Arnfjörð Bjarmason, Jun 22, 2022
  65. 04/12 git-submodule.sh: remove unused top-level "--branch" argumentÆvar Arnfjörð Bjarmason, Jun 22, 2022
  66. 06/12 submodule update: remove "-v" optionÆvar Arnfjörð Bjarmason, Jun 22, 2022
  67. 05/12 submodule--helper: have --require-init imply --initÆvar Arnfjörð Bjarmason, Jun 22, 2022
  68. 10/12 submodule--helper: eliminate internal "--update" optionÆvar Arnfjörð Bjarmason, Jun 22, 2022
  69. 09/12 submodule--helper: understand --checkout, --merge and --rebase synonymsÆvar Arnfjörð Bjarmason, Jun 22, 2022
  70. Glen ChooJun 22, 2022
  71. Glen ChooJun 22, 2022
  72. 08/12 submodule--helper: report "submodule" as our name in some "-h" outputÆvar Arnfjörð Bjarmason, Jun 22, 2022
  73. Glen ChooJun 22, 2022
  74. 07/12 submodule--helper: rename "absorb-git-dirs" to "absorbgitdirs"Ævar Arnfjörð Bjarmason, Jun 22, 2022
  75. 11/12 git-submodule.sh: use "$quiet", not "$GIT_QUIET"Ævar Arnfjörð Bjarmason, Jun 22, 2022
  76. Glen ChooJun 24, 2022
  77. 00/12 submodule: make "git submodule--helper" behave like "git submodule"Ævar Arnfjörð Bjarmason, Jun 28, 2022
  78. 01/12 git-submodule.sh: remove unused sanitize_submodule_env()Ævar Arnfjörð Bjarmason, Jun 28, 2022
  79. 02/12 git-submodule.sh: remove unused $prefix variableÆvar Arnfjörð Bjarmason, Jun 28, 2022
  80. 03/12 git-submodule.sh: make the "$cached" variable a booleanÆvar Arnfjörð Bjarmason, Jun 28, 2022
  81. 08/12 submodule--helper: report "submodule" as our name in some "-h" outputÆvar Arnfjörð Bjarmason, Jun 28, 2022
  82. 07/12 submodule--helper: rename "absorb-git-dirs" to "absorbgitdirs"Ævar Arnfjörð Bjarmason, Jun 28, 2022
  83. 06/12 submodule update: remove "-v" optionÆvar Arnfjörð Bjarmason, Jun 28, 2022
  84. 12/12 git-sh-setup.sh: remove "say" function, change last usersÆvar Arnfjörð Bjarmason, Jun 28, 2022
  85. 04/12 git-submodule.sh: remove unused top-level "--branch" argumentÆvar Arnfjörð Bjarmason, Jun 28, 2022
  86. 05/12 submodule--helper: have --require-init imply --initÆvar Arnfjörð Bjarmason, Jun 28, 2022
  87. 10/12 submodule--helper: eliminate internal "--update" optionÆvar Arnfjörð Bjarmason, Jun 28, 2022
  88. 11/12 git-submodule.sh: use "$quiet", not "$GIT_QUIET"Ævar Arnfjörð Bjarmason, Jun 28, 2022
  89. 09/12 submodule--helper: understand --checkout, --merge and --rebase synonymsÆvar Arnfjörð Bjarmason, Jun 28, 2022
  90. Glen ChooJun 28, 2022

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.