git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Derrick Stolee <stolee@gmail.com>
To: Eric Sunshine <sunshine@sunshineco.com>,
	Derrick Stolee via GitGitGadget <gitgitgadget@gmail.com>
Cc: Git List <git@vger.kernel.org>,
	Sean Allred <allred.sean@gmail.com>,
	Junio C Hamano <gitster@pobox.com>,
	Derrick Stolee <derrickstolee@github.com>,
	Derrick Stolee <dstolee@microsoft.com>
Subject: Re: [PATCH v2 3/5] worktree: add upgrade_to_worktree_config()
Date: Tue, 28 Dec 2021 10:03:03 -0500	[thread overview]
Message-ID: <53f3531d-29ee-f16e-1d60-21ca7b4a3fbd@gmail.com> (raw)
In-Reply-To: <CAPig+cQrJ9yWjkc8VMu=uyx_qtrXdL3cNnxLVafoxOo6e-r9kw@mail.gmail.com>

On 12/21/2021 7:45 PM, Eric Sunshine wrote:
> On Tue, Dec 21, 2021 at 2:14 PM Derrick Stolee via GitGitGadget
> <gitgitgadget@gmail.com> wrote:
>> Some features, such as the sparse-checkout builtin, require using the
>> worktree config extension. It might seem simple to upgrade the
>> repository format and add extensions.worktreeConfig, and that is what
>> happens in the sparse-checkout builtin.
>>
>> Transitioning from one config file to multiple has some strange
>> side-effects. In particular, if the base repository is bare and the
>> worktree is not, Git knows to treat the worktree as non-bare as a
>> special case when not using worktree config. Once worktree config is
>> enabled, Git stops that special case since the core.bare setting could
>> apply at the worktree config level. This opens the door for bare
>> worktrees.
> 
> It would be a good idea to drop the final sentence since there is no
> such thing as a bare worktree (either conceptually or practically),
> and end the first sentence at "case": i.e. "... stops that special
> case."

Bare worktrees don't exist, that is correct. But if one existed it
would be a directory where you could operate as if it is a bare repo,
but it has its own HEAD different from the base repo's HEAD. Not sure
why one would want it.

I guess the question is: what happens if someone writes core.bare=true
into their worktree config? A question to resolve another day, perhaps.
 
>> To help resolve this transition, create upgrade_to_worktree_config() to
>> navigate the intricacies of this operation. In particular, we need to
>> look for core.bare=true within the base config file and move that
>> setting into the core repository's config.worktree file.
>>
>> To gain access to the core repository's config and config.worktree file,
>> we reference a repository struct's 'commondir' member. If the repository
>> was a submodule instead of a worktree, then this still applies
>> correctly.
> 
> I'm not sure how much this commit message is going to help someone who
> did not participate in the discussion which led to this patch series.
> I think the entire commit message could be written more concisely like
> this:

Good suggestions to add the necessary context here. Thanks.

>     worktree: add helper to upgrade repository to per-worktree config
> 
>     Changing a repository to use per-worktree configuration is a
>     somewhat involved manual process, as described in the
>     `git-worktree` documentation, but it's easy to get wrong if the
>     steps are not followed precisely, which could lead to odd
>     anomalies such as Git thinking that a worktree is "bare" (which
>     conceptually makes no sense). Therefore, add a utility function to
>     automate the process of switching to per-worktree configuration
>     for modules which require such configuration. (In the future, it
>     may make sense to also expose this convenience as a `git-worktree`
>     command to automate the process for end-users, as well.)
> 
>     To upgrade the repository to per-worktree configuration, it performs
>     these steps:
> 
>     * enable `extensions.worktreeConfig` in .git/config
> 
>     * relocate `core.bare` from .git/config to .git/config.worktree
>       (if key exists)
> 
>     * relocate `core.worktree` from .git/config to
>       .git/config.worktree (if key exists)
> 
>     It also upgrades the repository format to 1 if necessary since
>     that is a prerequisite of using `extensions`.
> 
>> Helped-by: Eric Sunshine <sunshine@sunshineco.com>
>> Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
>> ---
>> diff --git a/worktree.c b/worktree.c
>> @@ -830,3 +831,49 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath,
>> +int upgrade_to_worktree_config(struct repository *r)
>> +{
>> +       int res;
>> +       int bare = 0;
>> +       struct config_set cs = { 0 };
> 
> This function is doing a lot of unnecessary work if per-worktree
> configuration is already enabled. The very first thing it should be
> doing is checking whether or not it actually needs to do that work,
> and short-circuit if it doesn't. I would think that simply checking
> whether `extensions.worktreeConfig` is true and returning early if it
> is would be sufficient.

That would be good. I originally erred on the side of least complicated
but slower because this is not run very often.

>> +       char *base_config_file = xstrfmt("%s/config", r->commondir);
> 
> If we look at path.c:strbuf_worktree_gitdir(), we see that this should
> be using `r->gitdir`, not `r->commondir`.
> 
>> +       char *base_worktree_file = xstrfmt("%s/config.worktree", r->commondir);
> 
> Per path.c:strbuf_worktree_gitdir(), this use of `r->commondir` is
> correct. Good.
> 
> Can we use more meaningful variable names? It's not at all clear what
> "base" means in this context (I don't think it has any analog in Git
> terminology). Perhaps name these `shared_config` and `repo_config`,
> respectively.

'repo_config' is too generic, because I want the worktree config for
the "original" repo. I chose to call that the "base" repo and its
worktree config. Shared_config is a good name, though.

>> +       git_configset_init(&cs);
>> +       git_configset_add_file(&cs, base_config_file);
>> +
>> +       /*
>> +        * If the base repository is bare, then we need to move core.bare=true
>> +        * out of the base config file and into the base repository's
>> +        * config.worktree file.
>> +        */
> 
> Here, too, it's not clear what "base" means. I think you want to say
> that it needs to "move `core.bare` from the shared config to the
> repo-specific config".

Yes, but specific to the original/root/bare repo. I'm open to preferences
here, but "repo" isn't specific enough.

>> +       if (!git_configset_get_bool(&cs, "core.bare", &bare) && bare) {
>> +               if ((res = git_config_set_in_file_gently(base_worktree_file,
>> +                                                       "core.bare", "true"))) {
>> +                       error(_("unable to set core.bare=true in '%s'"), base_worktree_file);
>> +                       goto cleanup;
>> +               }
>> +
>> +               if ((res = git_config_set_in_file_gently(base_config_file,
>> +                                                       "core.bare", NULL))) {
>> +                       error(_("unable to unset core.bare=true in '%s'"), base_config_file);
>> +                       goto cleanup;
>> +               }
>> +       }
> 
> This seems unnecessarily complicated and overly specific, thus
> potentially confusing. The requirements laid out in git-worktree.txt
> say only to move the configuration key from .git/config to
> .git/config.worktree; it doesn't add any qualifiers about the value
> being "true". And, indeed, we should not care about the value; it's
> immaterial to this operation. Instead, we should just treat it
> opaquely and relocate the key and value from .git/config (if it
> exists) to .git/config.worktree without interpretation.
> 
> The error messages are too specific, as well, by mentioning "true".
> They could instead be:
> 
>     unable to set `core.bare` in '%s'
> 
> and
> 
>     unable to remove `core.bare` from '%s'
> 
> However, there is a much more _severe_ problem with this
> implementation: it is incomplete. As documented in git-worktree.txt
> (and mentioned several times during this discussion), this utility
> function _must_ relocate both `core.bare` _and_ `core.worktree` (if
> they exist) from .git/config to .git/config.worktree. This
> implementation neglects to relocate `core.worktree`, which can leave
> things in quite a broken state (just as neglecting to relocate
> `core.bare` can).

It took me a long time to actually understand the purpose of
core.worktree, since it seems in conflict with the 'git worktree'
feature. Indeed, it is special-cased the same way core.bare is, so
this relocation is required.

>> +       if (upgrade_repository_format(r, 1) < 0) {
>> +               res = error(_("unable to upgrade repository format to enable worktreeConfig"));
>> +               goto cleanup;
>> +       }
>> +       if ((res = git_config_set_gently("extensions.worktreeConfig", "true"))) {
>> +               error(_("failed to set extensions.worktreeConfig setting"));
>> +               goto cleanup;
>> +       }
> 
> The order in which this function performs its operations can leave the
> repository in a broken state if any of the steps fails. For instance,
> if setting `extensions.worktreeConfig=true` fails _after_ you've
> relocated `core.bare` (and `core.worktree`) to .git/config.worktree,
> then those configuration values will no longer be "active" since the
> config system won't consult .git/config.worktree without
> `extensions.worktreeConfig` enabled.
> 
> To be resilient against this sort of problem, you should perform the
> operations in this order:
> 
> (1) upgrade repository format to 1
> (2) enable `extensions.worktreeConfig`
> (3) relocate `core.bare` and `core.worktree`

This order can still cause some issues, specifically the worktree will
still think it is bare or the core.worktree value is incorrect, but that
is less serious than a broken base repo.

>> +cleanup:
>> +       git_configset_clear(&cs);
>> +       free(base_config_file);
>> +       free(base_worktree_file);
>> +       trace2_printf("returning %d", res);
> 
> Is this leftover debugging or intentional?

Leftover debugging. Thanks for catching.

Thanks,
-Stolee

  reply	other threads:[~2021-12-28 15:03 UTC|newest]

Thread overview: 138+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-20 15:57 [PATCH 0/4] Sparse checkout: fix bug with worktree of bare repo Derrick Stolee via GitGitGadget
2021-12-20 15:57 ` [PATCH 1/4] setup: use a repository when upgrading format Derrick Stolee via GitGitGadget
2021-12-20 15:57 ` [PATCH 2/4] config: make some helpers repo-aware Derrick Stolee via GitGitGadget
2021-12-20 15:57 ` [PATCH 3/4] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-20 17:32   ` Derrick Stolee
2021-12-21  0:01     ` Eric Sunshine
2021-12-21  5:59       ` Eric Sunshine
2021-12-21 13:41       ` Derrick Stolee
2021-12-21  5:53   ` Eric Sunshine
2021-12-21 13:45     ` Derrick Stolee
2021-12-21 23:29       ` Eric Sunshine
2021-12-20 15:57 ` [PATCH 4/4] sparse-checkout: use repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-20 16:21 ` [PATCH 0/4] Sparse checkout: fix bug with worktree of bare repo Eric Sunshine
2021-12-20 17:34   ` Derrick Stolee
2021-12-21  6:10     ` Eric Sunshine
2021-12-21 19:14 ` [PATCH v2 0/5] " Derrick Stolee via GitGitGadget
2021-12-21 19:14   ` [PATCH v2 1/5] setup: use a repository when upgrading format Derrick Stolee via GitGitGadget
2021-12-21 19:14   ` [PATCH v2 2/5] config: make some helpers repo-aware Derrick Stolee via GitGitGadget
2021-12-21 19:14   ` [PATCH v2 3/5] worktree: add upgrade_to_worktree_config() Derrick Stolee via GitGitGadget
2021-12-22  0:45     ` Eric Sunshine
2021-12-28 15:03       ` Derrick Stolee [this message]
2021-12-28 16:58         ` Eric Sunshine
2021-12-28 17:03           ` Derrick Stolee
2021-12-22  5:38     ` Junio C Hamano
2021-12-28 15:13       ` Derrick Stolee
2021-12-21 19:14   ` [PATCH v2 4/5] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-22  1:11     ` Eric Sunshine
2021-12-21 19:14   ` [PATCH v2 5/5] sparse-checkout: use repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-22  5:48     ` Eric Sunshine
2021-12-22  6:05   ` [PATCH v2 0/5] Sparse checkout: fix bug with worktree of bare repo Eric Sunshine
2021-12-22 22:54   ` Elijah Newren
2021-12-27  7:15     ` Eric Sunshine
2021-12-27  7:34       ` Eric Sunshine
2021-12-27 20:16         ` Elijah Newren
2021-12-28  9:11           ` Eric Sunshine
2021-12-30  6:21           ` Eric Sunshine
2021-12-30 17:40             ` Elijah Newren
2021-12-27 19:35       ` Elijah Newren
2021-12-28  7:33         ` Eric Sunshine
2021-12-28 18:16           ` Elijah Newren
2021-12-30  6:40             ` Eric Sunshine
2021-12-30 18:38               ` Elijah Newren
2022-01-03  6:51                 ` Eric Sunshine
2021-12-28 21:32   ` [PATCH v3 0/6] " Derrick Stolee via GitGitGadget
2021-12-28 21:32     ` [PATCH v3 1/6] setup: use a repository when upgrading format Derrick Stolee via GitGitGadget
2021-12-28 21:32     ` [PATCH v3 2/6] config: make some helpers repo-aware Derrick Stolee via GitGitGadget
2021-12-28 21:32     ` [PATCH v3 3/6] worktree: add 'init-worktree-config' subcommand Derrick Stolee via GitGitGadget
2021-12-29  6:48       ` Eric Sunshine
2021-12-30  8:41       ` Eric Sunshine
2021-12-30 17:29         ` Derrick Stolee
2022-01-03  6:38           ` Eric Sunshine
2021-12-28 21:32     ` [PATCH v3 4/6] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-28 21:32     ` [PATCH v3 5/6] sparse-checkout: use repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-30  9:01       ` Eric Sunshine
2021-12-28 21:32     ` [PATCH v3 6/6] worktree: copy sparse-checkout patterns and config on add Derrick Stolee via GitGitGadget
2021-12-29  6:37       ` Eric Sunshine
2021-12-29 17:31         ` Derrick Stolee
2021-12-29 19:51           ` Elijah Newren
2021-12-29 21:39             ` Derrick Stolee
2021-12-29 22:45               ` Elijah Newren
2021-12-30  8:16                 ` Eric Sunshine
2021-12-30  8:01             ` Eric Sunshine
2021-12-29  9:39     ` [PATCH v3 0/6] Sparse checkout: fix bug with worktree of bare repo Elijah Newren
2021-12-29 17:38       ` Derrick Stolee
2021-12-30  7:41         ` Eric Sunshine
2021-12-30  7:40       ` Eric Sunshine
2021-12-30 17:41         ` Derrick Stolee
2021-12-30 19:29           ` Elijah Newren
2022-01-03  7:11             ` Eric Sunshine
2021-12-30 18:46         ` Elijah Newren
2022-01-25 18:42     ` [PATCH v4 0/5] " Derrick Stolee via GitGitGadget
2022-01-25 18:42       ` [PATCH v4 1/5] Documentation: add extensions.worktreeConfig details Derrick Stolee via GitGitGadget
2022-01-26  6:59         ` Bagas Sanjaya
2022-01-27 14:15           ` Derrick Stolee
2022-01-27  6:43         ` Elijah Newren
2022-01-27 14:17           ` Derrick Stolee
2022-01-25 18:42       ` [PATCH v4 2/5] worktree: create init_worktree_config() Derrick Stolee via GitGitGadget
2022-01-27  7:01         ` Elijah Newren
2022-01-25 18:42       ` [PATCH v4 3/5] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2022-01-25 18:42       ` [PATCH v4 4/5] sparse-checkout: set worktree-config correctly Derrick Stolee via GitGitGadget
2022-01-27  7:15         ` Elijah Newren
2022-01-27 14:24           ` Derrick Stolee
2022-01-25 18:42       ` [PATCH v4 5/5] worktree: copy sparse-checkout patterns and config on add Derrick Stolee via GitGitGadget
2022-01-27  7:09         ` Elijah Newren
2022-01-27  7:20       ` [PATCH v4 0/5] Sparse checkout: fix bug with worktree of bare repo Elijah Newren
2022-01-27 14:29         ` Derrick Stolee
2022-01-31 15:00       ` [PATCH v5 " Derrick Stolee via GitGitGadget
2022-01-31 15:00         ` [PATCH v5 1/5] Documentation: add extensions.worktreeConfig details Derrick Stolee via GitGitGadget
2022-02-06  9:17           ` Eric Sunshine
2022-01-31 15:00         ` [PATCH v5 2/5] worktree: create init_worktree_config() Derrick Stolee via GitGitGadget
2022-02-06  9:32           ` Eric Sunshine
2022-01-31 15:00         ` [PATCH v5 3/5] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2022-01-31 15:00         ` [PATCH v5 4/5] sparse-checkout: set worktree-config correctly Derrick Stolee via GitGitGadget
2022-02-06 10:21           ` Eric Sunshine
2022-01-31 15:00         ` [PATCH v5 5/5] worktree: copy sparse-checkout patterns and config on add Derrick Stolee via GitGitGadget
2022-02-06 10:36           ` Jean-Noël AVILA
2022-02-07 14:10             ` Derrick Stolee
2022-02-09  7:53               ` Jean-Noël Avila
2022-02-09 14:45                 ` Derrick Stolee
2022-02-06 11:30           ` Eric Sunshine
2022-02-06 19:36             ` Eric Sunshine
2022-02-07 14:30             ` Derrick Stolee
2022-02-15 22:01               ` Eric Sunshine
2022-02-16 13:58                 ` Derrick Stolee
2022-01-31 16:17         ` [PATCH v5 0/5] Sparse checkout: fix bug with worktree of bare repo Elijah Newren
2022-02-07 21:32         ` [PATCH v6 0/6] " Derrick Stolee via GitGitGadget
2022-02-07 21:32           ` [PATCH v6 1/6] Documentation: add extensions.worktreeConfig details Derrick Stolee via GitGitGadget
2022-02-08 22:20             ` Junio C Hamano
2022-02-09  2:34               ` Derrick Stolee
2022-02-09 17:19                 ` Junio C Hamano
2022-02-09 17:26                   ` Derrick Stolee
2022-02-09 17:51                   ` Elijah Newren
2022-02-09 18:40                     ` Junio C Hamano
2022-02-15 20:37                 ` Eric Sunshine
2022-02-16  1:51                   ` Junio C Hamano
2022-02-09 18:04               ` Elijah Newren
2022-02-09 18:41                 ` Junio C Hamano
2022-02-07 21:32           ` [PATCH v6 2/6] worktree: create init_worktree_config() Derrick Stolee via GitGitGadget
2022-02-08 22:09             ` Junio C Hamano
2022-02-09  2:21               ` Derrick Stolee
2022-02-09 17:34                 ` Junio C Hamano
2022-02-09 16:43               ` Elijah Newren
2022-02-07 21:33           ` [PATCH v6 3/6] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2022-02-08 22:18             ` Junio C Hamano
2022-02-09  2:27               ` Derrick Stolee
2022-02-09 17:49                 ` Junio C Hamano
2022-02-10 14:48                   ` Derrick Stolee
2022-02-10 16:45                     ` Junio C Hamano
2022-02-07 21:33           ` [PATCH v6 4/6] sparse-checkout: set worktree-config correctly Derrick Stolee via GitGitGadget
2022-02-07 21:33           ` [PATCH v6 5/6] worktree: copy sparse-checkout patterns and config on add Derrick Stolee via GitGitGadget
2022-02-15 22:23             ` Eric Sunshine
2022-02-07 21:33           ` [PATCH v6 6/6] config: make git_configset_get_string_tmp() private Derrick Stolee via GitGitGadget
2022-02-08  4:14           ` [PATCH v6 0/6] Sparse checkout: fix bug with worktree of bare repo Elijah Newren
2022-02-08  5:02             ` Eric Sunshine
2022-02-08  5:18               ` Elijah Newren
2022-02-08  5:42                 ` Eric Sunshine
2022-02-16  0:56                   ` Eric Sunshine
2022-02-08 14:33               ` Derrick Stolee

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=53f3531d-29ee-f16e-1d60-21ca7b4a3fbd@gmail.com \
    --to=stolee@gmail.com \
    --cc=allred.sean@gmail.com \
    --cc=derrickstolee@github.com \
    --cc=dstolee@microsoft.com \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=gitster@pobox.com \
    --cc=sunshine@sunshineco.com \
    /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).