Merge branch 'ds/sparse-checkout-requires-per-worktree-config'
"git sparse-checkout" wants to work with per-worktree configuration, but did not work well in a worktree attached to a bare repository. * ds/sparse-checkout-requires-per-worktree-config: config: make git_configset_get_string_tmp() private worktree: copy sparse-checkout patterns and config on add sparse-checkout: set worktree-config correctly config: add repo_config_set_worktree_gently() worktree: create init_worktree_config() Documentation: add extensions.worktreeConfig details
This commit is contained in:
commit
6249ce2d1b
@ -6,3 +6,34 @@ extensions.objectFormat::
|
||||
Note that this setting should only be set by linkgit:git-init[1] or
|
||||
linkgit:git-clone[1]. Trying to change it after initialization will not
|
||||
work and will produce hard-to-diagnose issues.
|
||||
|
||||
extensions.worktreeConfig::
|
||||
If enabled, then worktrees will load config settings from the
|
||||
`$GIT_DIR/config.worktree` file in addition to the
|
||||
`$GIT_COMMON_DIR/config` file. Note that `$GIT_COMMON_DIR` and
|
||||
`$GIT_DIR` are the same for the main working tree, while other
|
||||
working trees have `$GIT_DIR` equal to
|
||||
`$GIT_COMMON_DIR/worktrees/<id>/`. The settings in the
|
||||
`config.worktree` file will override settings from any other
|
||||
config files.
|
||||
+
|
||||
When enabling `extensions.worktreeConfig`, you must be careful to move
|
||||
certain values from the common config file to the main working tree's
|
||||
`config.worktree` file, if present:
|
||||
+
|
||||
* `core.worktree` must be moved from `$GIT_COMMON_DIR/config` to
|
||||
`$GIT_COMMON_DIR/config.worktree`.
|
||||
* If `core.bare` is true, then it must be moved from `$GIT_COMMON_DIR/config`
|
||||
to `$GIT_COMMON_DIR/config.worktree`.
|
||||
+
|
||||
It may also be beneficial to adjust the locations of `core.sparseCheckout`
|
||||
and `core.sparseCheckoutCone` depending on your desire for customizable
|
||||
sparse-checkout settings for each worktree. By default, the `git
|
||||
sparse-checkout` builtin enables `extensions.worktreeConfig`, assigns
|
||||
these config values on a per-worktree basis, and uses the
|
||||
`$GIT_DIR/info/sparse-checkout` file to specify the sparsity for each
|
||||
worktree independently. See linkgit:git-sparse-checkout[1] for more
|
||||
details.
|
||||
+
|
||||
For historical reasons, `extensions.worktreeConfig` is respected
|
||||
regardless of the `core.repositoryFormatVersion` setting.
|
||||
|
@ -141,9 +141,13 @@ from all available files.
|
||||
See also <<FILES>>.
|
||||
|
||||
--worktree::
|
||||
Similar to `--local` except that `.git/config.worktree` is
|
||||
Similar to `--local` except that `$GIT_DIR/config.worktree` is
|
||||
read from or written to if `extensions.worktreeConfig` is
|
||||
present. If not it's the same as `--local`.
|
||||
enabled. If not it's the same as `--local`. Note that `$GIT_DIR`
|
||||
is equal to `$GIT_COMMON_DIR` for the main working tree, but is of
|
||||
the form `$GIT_DIR/worktrees/<id>/` for other working trees. See
|
||||
linkgit:git-worktree[1] to learn how to enable
|
||||
`extensions.worktreeConfig`.
|
||||
|
||||
-f <config-file>::
|
||||
--file <config-file>::
|
||||
|
@ -31,13 +31,21 @@ COMMANDS
|
||||
Describe the patterns in the sparse-checkout file.
|
||||
|
||||
'set'::
|
||||
Enable the necessary config settings
|
||||
(extensions.worktreeConfig, core.sparseCheckout,
|
||||
core.sparseCheckoutCone) if they are not already enabled, and
|
||||
write a set of patterns to the sparse-checkout file from the
|
||||
Enable the necessary sparse-checkout config settings
|
||||
(`core.sparseCheckout`, `core.sparseCheckoutCone`, and
|
||||
`index.sparse`) if they are not already set to the desired values,
|
||||
and write a set of patterns to the sparse-checkout file from the
|
||||
list of arguments following the 'set' subcommand. Update the
|
||||
working directory to match the new patterns.
|
||||
+
|
||||
To ensure that adjusting the sparse-checkout settings within a worktree
|
||||
does not alter the sparse-checkout settings in other worktrees, the 'set'
|
||||
subcommand will upgrade your repository config to use worktree-specific
|
||||
config if not already present. The sparsity defined by the arguments to
|
||||
the 'set' subcommand are stored in the worktree-specific sparse-checkout
|
||||
file. See linkgit:git-worktree[1] and the documentation of
|
||||
`extensions.worktreeConfig` in linkgit:git-config[1] for more details.
|
||||
+
|
||||
When the `--stdin` option is provided, the patterns are read from
|
||||
standard in as a newline-delimited list instead of from the arguments.
|
||||
+
|
||||
|
@ -286,8 +286,8 @@ CONFIGURATION FILE
|
||||
------------------
|
||||
By default, the repository `config` file is shared across all working
|
||||
trees. If the config variables `core.bare` or `core.worktree` are
|
||||
already present in the config file, they will be applied to the main
|
||||
working trees only.
|
||||
present in the common config file and `extensions.worktreeConfig` is
|
||||
disabled, then they will be applied to the main working tree only.
|
||||
|
||||
In order to have configuration specific to working trees, you can turn
|
||||
on the `worktreeConfig` extension, e.g.:
|
||||
@ -307,11 +307,16 @@ them to the `config.worktree` of the main working tree. You may also
|
||||
take this opportunity to review and move other configuration that you
|
||||
do not want to share to all working trees:
|
||||
|
||||
- `core.worktree` and `core.bare` should never be shared
|
||||
- `core.worktree` should never be shared.
|
||||
|
||||
- `core.bare` should not be shared if the value is `core.bare=true`.
|
||||
|
||||
- `core.sparseCheckout` is recommended per working tree, unless you
|
||||
are sure you always use sparse checkout for all working trees.
|
||||
|
||||
See the documentation of `extensions.worktreeConfig` in
|
||||
linkgit:git-config[1] for more details.
|
||||
|
||||
DETAILS
|
||||
-------
|
||||
Each linked working tree has a private sub-directory in the repository's
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "wt-status.h"
|
||||
#include "quote.h"
|
||||
#include "sparse-index.h"
|
||||
#include "worktree.h"
|
||||
|
||||
static const char *empty_base = "";
|
||||
|
||||
@ -361,26 +362,23 @@ enum sparse_checkout_mode {
|
||||
|
||||
static int set_config(enum sparse_checkout_mode mode)
|
||||
{
|
||||
const char *config_path;
|
||||
|
||||
if (upgrade_repository_format(1) < 0)
|
||||
die(_("unable to upgrade repository format to enable worktreeConfig"));
|
||||
if (git_config_set_gently("extensions.worktreeConfig", "true")) {
|
||||
error(_("failed to set extensions.worktreeConfig setting"));
|
||||
/* Update to use worktree config, if not already. */
|
||||
if (init_worktree_config(the_repository)) {
|
||||
error(_("failed to initialize worktree config"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
config_path = git_path("config.worktree");
|
||||
git_config_set_in_file_gently(config_path,
|
||||
"core.sparseCheckout",
|
||||
mode ? "true" : NULL);
|
||||
|
||||
git_config_set_in_file_gently(config_path,
|
||||
"core.sparseCheckoutCone",
|
||||
mode == MODE_CONE_PATTERNS ? "true" : NULL);
|
||||
if (repo_config_set_worktree_gently(the_repository,
|
||||
"core.sparseCheckout",
|
||||
mode ? "true" : "false") ||
|
||||
repo_config_set_worktree_gently(the_repository,
|
||||
"core.sparseCheckoutCone",
|
||||
mode == MODE_CONE_PATTERNS ?
|
||||
"true" : "false"))
|
||||
return 1;
|
||||
|
||||
if (mode == MODE_NO_PATTERNS)
|
||||
set_sparse_index_config(the_repository, 0);
|
||||
return set_sparse_index_config(the_repository, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -335,6 +335,69 @@ static int add_worktree(const char *path, const char *refname,
|
||||
strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
|
||||
write_file(sb.buf, "../..");
|
||||
|
||||
/*
|
||||
* If the current worktree has sparse-checkout enabled, then copy
|
||||
* the sparse-checkout patterns from the current worktree.
|
||||
*/
|
||||
if (core_apply_sparse_checkout) {
|
||||
char *from_file = git_pathdup("info/sparse-checkout");
|
||||
char *to_file = xstrfmt("%s/info/sparse-checkout",
|
||||
sb_repo.buf);
|
||||
|
||||
if (file_exists(from_file)) {
|
||||
if (safe_create_leading_directories(to_file) ||
|
||||
copy_file(to_file, from_file, 0666))
|
||||
error(_("failed to copy '%s' to '%s'; sparse-checkout may not work correctly"),
|
||||
from_file, to_file);
|
||||
}
|
||||
|
||||
free(from_file);
|
||||
free(to_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are using worktree config, then copy all current config
|
||||
* values from the current worktree into the new one, that way the
|
||||
* new worktree behaves the same as this one.
|
||||
*/
|
||||
if (repository_format_worktree_config) {
|
||||
char *from_file = git_pathdup("config.worktree");
|
||||
char *to_file = xstrfmt("%s/config.worktree",
|
||||
sb_repo.buf);
|
||||
|
||||
if (file_exists(from_file)) {
|
||||
struct config_set cs = { { 0 } };
|
||||
const char *core_worktree;
|
||||
int bare;
|
||||
|
||||
if (safe_create_leading_directories(to_file) ||
|
||||
copy_file(to_file, from_file, 0666)) {
|
||||
error(_("failed to copy worktree config from '%s' to '%s'"),
|
||||
from_file, to_file);
|
||||
goto worktree_copy_cleanup;
|
||||
}
|
||||
|
||||
git_configset_init(&cs);
|
||||
git_configset_add_file(&cs, from_file);
|
||||
|
||||
if (!git_configset_get_bool(&cs, "core.bare", &bare) &&
|
||||
bare &&
|
||||
git_config_set_multivar_in_file_gently(
|
||||
to_file, "core.bare", NULL, "true", 0))
|
||||
error(_("failed to unset 'core.bare' in '%s'"), to_file);
|
||||
if (!git_configset_get_value(&cs, "core.worktree", &core_worktree) &&
|
||||
git_config_set_in_file_gently(to_file,
|
||||
"core.worktree", NULL))
|
||||
error(_("failed to unset 'core.worktree' in '%s'"), to_file);
|
||||
|
||||
git_configset_clear(&cs);
|
||||
}
|
||||
|
||||
worktree_copy_cleanup:
|
||||
free(from_file);
|
||||
free(to_file);
|
||||
}
|
||||
|
||||
strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
|
||||
strvec_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
|
||||
cp.git_cmd = 1;
|
||||
|
39
config.c
39
config.c
@ -21,6 +21,7 @@
|
||||
#include "dir.h"
|
||||
#include "color.h"
|
||||
#include "refs.h"
|
||||
#include "worktree.h"
|
||||
|
||||
struct config_source {
|
||||
struct config_source *prev;
|
||||
@ -2294,8 +2295,8 @@ int git_configset_get_string(struct config_set *cs, const char *key, char **dest
|
||||
return 1;
|
||||
}
|
||||
|
||||
int git_configset_get_string_tmp(struct config_set *cs, const char *key,
|
||||
const char **dest)
|
||||
static int git_configset_get_string_tmp(struct config_set *cs, const char *key,
|
||||
const char **dest)
|
||||
{
|
||||
const char *value;
|
||||
if (!git_configset_get_value(cs, key, &value)) {
|
||||
@ -3000,6 +3001,20 @@ int git_config_set_gently(const char *key, const char *value)
|
||||
return git_config_set_multivar_gently(key, value, NULL, 0);
|
||||
}
|
||||
|
||||
int repo_config_set_worktree_gently(struct repository *r,
|
||||
const char *key, const char *value)
|
||||
{
|
||||
/* Only use worktree-specific config if it is is already enabled. */
|
||||
if (repository_format_worktree_config) {
|
||||
char *file = repo_git_path(r, "config.worktree");
|
||||
int ret = git_config_set_multivar_in_file_gently(
|
||||
file, key, value, NULL, 0);
|
||||
free(file);
|
||||
return ret;
|
||||
}
|
||||
return repo_config_set_multivar_gently(r, key, value, NULL, 0);
|
||||
}
|
||||
|
||||
void git_config_set(const char *key, const char *value)
|
||||
{
|
||||
git_config_set_multivar(key, value, NULL, 0);
|
||||
@ -3297,14 +3312,28 @@ void git_config_set_multivar_in_file(const char *config_filename,
|
||||
int git_config_set_multivar_gently(const char *key, const char *value,
|
||||
const char *value_pattern, unsigned flags)
|
||||
{
|
||||
return git_config_set_multivar_in_file_gently(NULL, key, value, value_pattern,
|
||||
flags);
|
||||
return repo_config_set_multivar_gently(the_repository, key, value,
|
||||
value_pattern, flags);
|
||||
}
|
||||
|
||||
int repo_config_set_multivar_gently(struct repository *r, const char *key,
|
||||
const char *value,
|
||||
const char *value_pattern, unsigned flags)
|
||||
{
|
||||
char *file = repo_git_path(r, "config");
|
||||
int res = git_config_set_multivar_in_file_gently(file,
|
||||
key, value,
|
||||
value_pattern,
|
||||
flags);
|
||||
free(file);
|
||||
return res;
|
||||
}
|
||||
|
||||
void git_config_set_multivar(const char *key, const char *value,
|
||||
const char *value_pattern, unsigned flags)
|
||||
{
|
||||
git_config_set_multivar_in_file(NULL, key, value, value_pattern,
|
||||
git_config_set_multivar_in_file(git_path("config"),
|
||||
key, value, value_pattern,
|
||||
flags);
|
||||
}
|
||||
|
||||
|
9
config.h
9
config.h
@ -266,6 +266,13 @@ void git_config_set_in_file(const char *, const char *, const char *);
|
||||
|
||||
int git_config_set_gently(const char *, const char *);
|
||||
|
||||
/**
|
||||
* Write a config value that should apply to the current worktree. If
|
||||
* extensions.worktreeConfig is enabled, then the write will happen in the
|
||||
* current worktree's config. Otherwise, write to the common config file.
|
||||
*/
|
||||
int repo_config_set_worktree_gently(struct repository *, const char *, const char *);
|
||||
|
||||
/**
|
||||
* write config values to `.git/config`, takes a key/value pair as parameter.
|
||||
*/
|
||||
@ -294,6 +301,7 @@ int git_config_parse_key(const char *, char **, size_t *);
|
||||
|
||||
int git_config_set_multivar_gently(const char *, const char *, const char *, unsigned);
|
||||
void git_config_set_multivar(const char *, const char *, const char *, unsigned);
|
||||
int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned);
|
||||
int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, unsigned);
|
||||
|
||||
/**
|
||||
@ -466,7 +474,6 @@ void git_configset_clear(struct config_set *cs);
|
||||
int git_configset_get_value(struct config_set *cs, const char *key, const char **dest);
|
||||
|
||||
int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
|
||||
int git_configset_get_string_tmp(struct config_set *cs, const char *key, const char **dest);
|
||||
int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
|
||||
int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest);
|
||||
int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
|
||||
|
@ -99,13 +99,9 @@ static int convert_to_sparse_rec(struct index_state *istate,
|
||||
|
||||
int set_sparse_index_config(struct repository *repo, int enable)
|
||||
{
|
||||
int res;
|
||||
char *config_path = repo_git_path(repo, "config.worktree");
|
||||
res = git_config_set_in_file_gently(config_path,
|
||||
"index.sparse",
|
||||
enable ? "true" : NULL);
|
||||
free(config_path);
|
||||
|
||||
int res = repo_config_set_worktree_gently(repo,
|
||||
"index.sparse",
|
||||
enable ? "true" : "false");
|
||||
prepare_repo_settings(repo);
|
||||
repo->settings.sparse_index = enable;
|
||||
return res;
|
||||
|
@ -126,7 +126,7 @@ test_expect_success 'switching to cone mode with non-cone mode patterns' '
|
||||
cd bad-patterns &&
|
||||
git sparse-checkout init &&
|
||||
git sparse-checkout add dir &&
|
||||
git config core.sparseCheckoutCone true &&
|
||||
git config --worktree core.sparseCheckoutCone true &&
|
||||
test_must_fail git sparse-checkout add dir 2>err &&
|
||||
grep "existing sparse-checkout patterns do not use cone mode" err
|
||||
)
|
||||
@ -155,9 +155,9 @@ test_expect_success 'interaction with clone --no-checkout (unborn index)' '
|
||||
'
|
||||
|
||||
test_expect_success 'set enables config' '
|
||||
git init empty-config &&
|
||||
git init worktree-config &&
|
||||
(
|
||||
cd empty-config &&
|
||||
cd worktree-config &&
|
||||
test_commit test file &&
|
||||
test_path_is_missing .git/config.worktree &&
|
||||
git sparse-checkout set nothing &&
|
||||
@ -210,6 +210,21 @@ test_expect_success 'add to sparse-checkout' '
|
||||
check_files repo "a folder1 folder2"
|
||||
'
|
||||
|
||||
test_expect_success 'worktree: add copies sparse-checkout patterns' '
|
||||
cat repo/.git/info/sparse-checkout >old &&
|
||||
test_when_finished cp old repo/.git/info/sparse-checkout &&
|
||||
test_when_finished git -C repo worktree remove ../worktree &&
|
||||
git -C repo sparse-checkout set --no-cone "/*" &&
|
||||
git -C repo worktree add --quiet ../worktree 2>err &&
|
||||
test_must_be_empty err &&
|
||||
new="$(git -C worktree rev-parse --git-path info/sparse-checkout)" &&
|
||||
test_path_is_file "$new" &&
|
||||
test_cmp repo/.git/info/sparse-checkout "$new" &&
|
||||
git -C worktree sparse-checkout set --cone &&
|
||||
test_cmp_config -C worktree true core.sparseCheckoutCone &&
|
||||
test_must_fail git -C repo core.sparseCheckoutCone
|
||||
'
|
||||
|
||||
test_expect_success 'cone mode: match patterns' '
|
||||
git -C repo config --worktree core.sparseCheckoutCone true &&
|
||||
rm -rf repo/a repo/folder1 repo/folder2 &&
|
||||
@ -261,7 +276,7 @@ test_expect_success 'sparse-index enabled and disabled' '
|
||||
test_cmp expect actual &&
|
||||
|
||||
git -C repo config --list >config &&
|
||||
! grep index.sparse config
|
||||
test_cmp_config -C repo false index.sparse
|
||||
'
|
||||
|
||||
test_expect_success 'cone mode: init and set' '
|
||||
@ -524,13 +539,13 @@ test_expect_success 'interaction with submodules' '
|
||||
'
|
||||
|
||||
test_expect_success 'different sparse-checkouts with worktrees' '
|
||||
git -C repo sparse-checkout set --cone deep folder1 &&
|
||||
git -C repo worktree add --detach ../worktree &&
|
||||
check_files worktree "a deep folder1 folder2" &&
|
||||
git -C worktree sparse-checkout init --cone &&
|
||||
git -C repo sparse-checkout set folder1 &&
|
||||
git -C worktree sparse-checkout set deep/deeper1 &&
|
||||
check_files repo a folder1 &&
|
||||
check_files worktree a deep
|
||||
check_files worktree "a deep folder1" &&
|
||||
git -C repo sparse-checkout set --cone folder1 &&
|
||||
git -C worktree sparse-checkout set --cone deep/deeper1 &&
|
||||
check_files repo "a folder1" &&
|
||||
check_files worktree "a deep"
|
||||
'
|
||||
|
||||
test_expect_success 'set using filename keeps file on-disk' '
|
||||
|
@ -165,8 +165,62 @@ test_expect_success '"add" default branch of a bare repo' '
|
||||
(
|
||||
git clone --bare . bare2 &&
|
||||
cd bare2 &&
|
||||
git worktree add ../there3 main
|
||||
)
|
||||
git worktree add ../there3 main &&
|
||||
cd ../there3 &&
|
||||
# Simple check that a Git command does not
|
||||
# immediately fail with the current setup
|
||||
git status
|
||||
) &&
|
||||
cat >expect <<-EOF &&
|
||||
init.t
|
||||
EOF
|
||||
ls there3 >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success '"add" to bare repo with worktree config' '
|
||||
(
|
||||
git clone --bare . bare3 &&
|
||||
cd bare3 &&
|
||||
git config extensions.worktreeconfig true &&
|
||||
|
||||
# Add config values that are erroneous to have in
|
||||
# a config.worktree file outside of the main
|
||||
# working tree, to check that Git filters them out
|
||||
# when copying config during "git worktree add".
|
||||
git config --worktree core.bare true &&
|
||||
git config --worktree core.worktree "$(pwd)" &&
|
||||
|
||||
# We want to check that bogus.key is copied
|
||||
git config --worktree bogus.key value &&
|
||||
git config --unset core.bare &&
|
||||
git worktree add ../there4 main &&
|
||||
cd ../there4 &&
|
||||
|
||||
# Simple check that a Git command does not
|
||||
# immediately fail with the current setup
|
||||
git status &&
|
||||
git worktree add --detach ../there5 &&
|
||||
cd ../there5 &&
|
||||
git status
|
||||
) &&
|
||||
|
||||
# the worktree has the arbitrary value copied.
|
||||
test_cmp_config -C there4 value bogus.key &&
|
||||
test_cmp_config -C there5 value bogus.key &&
|
||||
|
||||
# however, core.bare and core.worktree were removed.
|
||||
test_must_fail git -C there4 config core.bare &&
|
||||
test_must_fail git -C there4 config core.worktree &&
|
||||
|
||||
cat >expect <<-EOF &&
|
||||
init.t
|
||||
EOF
|
||||
|
||||
ls there4 >actual &&
|
||||
test_cmp expect actual &&
|
||||
ls there5 >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'checkout with grafts' '
|
||||
|
73
worktree.c
73
worktree.c
@ -5,6 +5,7 @@
|
||||
#include "worktree.h"
|
||||
#include "dir.h"
|
||||
#include "wt-status.h"
|
||||
#include "config.h"
|
||||
|
||||
void free_worktrees(struct worktree **worktrees)
|
||||
{
|
||||
@ -821,3 +822,75 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath,
|
||||
*wtpath = path;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int move_config_setting(const char *key, const char *value,
|
||||
const char *from_file, const char *to_file)
|
||||
{
|
||||
if (git_config_set_in_file_gently(to_file, key, value))
|
||||
return error(_("unable to set %s in '%s'"), key, to_file);
|
||||
if (git_config_set_in_file_gently(from_file, key, NULL))
|
||||
return error(_("unable to unset %s in '%s'"), key, from_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_worktree_config(struct repository *r)
|
||||
{
|
||||
int res = 0;
|
||||
int bare = 0;
|
||||
struct config_set cs = { { 0 } };
|
||||
const char *core_worktree;
|
||||
char *common_config_file;
|
||||
char *main_worktree_file;
|
||||
|
||||
/*
|
||||
* If the extension is already enabled, then we can skip the
|
||||
* upgrade process.
|
||||
*/
|
||||
if (repository_format_worktree_config)
|
||||
return 0;
|
||||
if ((res = git_config_set_gently("extensions.worktreeConfig", "true")))
|
||||
return error(_("failed to set extensions.worktreeConfig setting"));
|
||||
|
||||
common_config_file = xstrfmt("%s/config", r->commondir);
|
||||
main_worktree_file = xstrfmt("%s/config.worktree", r->commondir);
|
||||
|
||||
git_configset_init(&cs);
|
||||
git_configset_add_file(&cs, common_config_file);
|
||||
|
||||
/*
|
||||
* If core.bare is true in the common config file, then we need to
|
||||
* move it to the main worktree's config file or it will break all
|
||||
* worktrees. If it is false, then leave it in place because it
|
||||
* _could_ be negating a global core.bare=true.
|
||||
*/
|
||||
if (!git_configset_get_bool(&cs, "core.bare", &bare) && bare) {
|
||||
if ((res = move_config_setting("core.bare", "true",
|
||||
common_config_file,
|
||||
main_worktree_file)))
|
||||
goto cleanup;
|
||||
}
|
||||
/*
|
||||
* If core.worktree is set, then the main worktree is located
|
||||
* somewhere different than the parent of the common Git dir.
|
||||
* Relocate that value to avoid breaking all worktrees with this
|
||||
* upgrade to worktree config.
|
||||
*/
|
||||
if (!git_configset_get_value(&cs, "core.worktree", &core_worktree)) {
|
||||
if ((res = move_config_setting("core.worktree", core_worktree,
|
||||
common_config_file,
|
||||
main_worktree_file)))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that we use worktree config for the remaining lifetime
|
||||
* of the current process.
|
||||
*/
|
||||
repository_format_worktree_config = 1;
|
||||
|
||||
cleanup:
|
||||
git_configset_clear(&cs);
|
||||
free(common_config_file);
|
||||
free(main_worktree_file);
|
||||
return res;
|
||||
}
|
||||
|
21
worktree.h
21
worktree.h
@ -183,4 +183,25 @@ void strbuf_worktree_ref(const struct worktree *wt,
|
||||
struct strbuf *sb,
|
||||
const char *refname);
|
||||
|
||||
/**
|
||||
* Enable worktree config for the first time. This will make the following
|
||||
* adjustments:
|
||||
*
|
||||
* 1. Add extensions.worktreeConfig=true in the common config file.
|
||||
*
|
||||
* 2. If the common config file has a core.worktree value, then that value
|
||||
* is moved to the main worktree's config.worktree file.
|
||||
*
|
||||
* 3. If the common config file has a core.bare enabled, then that value
|
||||
* is moved to the main worktree's config.worktree file.
|
||||
*
|
||||
* If extensions.worktreeConfig is already true, then this method
|
||||
* terminates early without any of the above steps. The existing config
|
||||
* arrangement is assumed to be intentional.
|
||||
*
|
||||
* Returns 0 on success. Reports an error message and returns non-zero
|
||||
* if any of these steps fail.
|
||||
*/
|
||||
int init_worktree_config(struct repository *r);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user