Merge branch 'nd/per-worktree-config'

A fourth class of configuration files (in addition to the
traditional "system wide", "per user in the $HOME directory" and
"per repository in the $GIT_DIR/config") has been introduced so
that different worktrees that share the same repository (hence the
same $GIT_DIR/config file) can use different customization.

* nd/per-worktree-config:
  worktree: add per-worktree config files
  t1300: extract and use test_cmp_config()
maint
Junio C Hamano 2018-11-13 22:37:18 +09:00
commit 8c758f9a67
12 changed files with 255 additions and 78 deletions

View File

@ -2,8 +2,9 @@ CONFIGURATION FILE
------------------ ------------------


The Git configuration file contains a number of variables that affect The Git configuration file contains a number of variables that affect
the Git commands' behavior. The `.git/config` file in each repository the Git commands' behavior. The files `.git/config` and optionally
is used to store the configuration for that repository, and `config.worktree` (see `extensions.worktreeConfig` below) in each
repository are used to store the configuration for that repository, and
`$HOME/.gitconfig` is used to store a per-user configuration as `$HOME/.gitconfig` is used to store a per-user configuration as
fallback values for the `.git/config` file. The file `/etc/gitconfig` fallback values for the `.git/config` file. The file `/etc/gitconfig`
can be used to store a system-wide default configuration. can be used to store a system-wide default configuration.
@ -291,6 +292,13 @@ include::config/advice.txt[]


include::config/core.txt[] include::config/core.txt[]


extensions.worktreeConfig::
If set, by default "git config" reads from both "config" and
"config.worktree" file from GIT_DIR in that order. In
multiple working directory mode, "config" file is shared while
"config.worktree" is per-working directory (i.e., it's in
GIT_COMMON_DIR/worktrees/<id>/config.worktree)

include::config/add.txt[] include::config/add.txt[]


include::config/alias.txt[] include::config/alias.txt[]

View File

@ -45,13 +45,15 @@ unset an existing `--type` specifier with `--no-type`.


When reading, the values are read from the system, global and When reading, the values are read from the system, global and
repository local configuration files by default, and options repository local configuration files by default, and options
`--system`, `--global`, `--local` and `--file <filename>` can be `--system`, `--global`, `--local`, `--worktree` and
used to tell the command to read from only that location (see <<FILES>>). `--file <filename>` can be used to tell the command to read from only
that location (see <<FILES>>).


When writing, the new value is written to the repository local When writing, the new value is written to the repository local
configuration file by default, and options `--system`, `--global`, configuration file by default, and options `--system`, `--global`,
`--file <filename>` can be used to tell the command to write to `--worktree`, `--file <filename>` can be used to tell the command to
that location (you can say `--local` but that is the default). write to that location (you can say `--local` but that is the
default).


This command will fail with non-zero status upon error. Some exit This command will fail with non-zero status upon error. Some exit
codes are: codes are:
@ -131,6 +133,11 @@ from all available files.
+ +
See also <<FILES>>. See also <<FILES>>.


--worktree::
Similar to `--local` except that `.git/config.worktree` is
read from or written to if `extensions.worktreeConfig` is
present. If not it's the same as `--local`.

-f config-file:: -f config-file::
--file config-file:: --file config-file::
Use the given config file instead of the one specified by GIT_CONFIG. Use the given config file instead of the one specified by GIT_CONFIG.
@ -281,6 +288,10 @@ $XDG_CONFIG_HOME/git/config::
$GIT_DIR/config:: $GIT_DIR/config::
Repository specific configuration file. Repository specific configuration file.


$GIT_DIR/config.worktree::
This is optional and is only searched when
`extensions.worktreeConfig` is present in $GIT_DIR/config.

If no further options are given, all reading options will read all of these If no further options are given, all reading options will read all of these
files that are available. If the global or the system-wide configuration files that are available. If the global or the system-wide configuration
file are not available they will be ignored. If the repository configuration file are not available they will be ignored. If the repository configuration
@ -299,9 +310,10 @@ configuration file. Note that this also affects options like `--replace-all`
and `--unset`. *'git config' will only ever change one file at a time*. and `--unset`. *'git config' will only ever change one file at a time*.


You can override these rules either by command-line options or by environment You can override these rules either by command-line options or by environment
variables. The `--global` and the `--system` options will limit the file used variables. The `--global`, `--system` and `--worktree` options will limit
to the global or system-wide file respectively. The `GIT_CONFIG` environment the file used to the global, system-wide or per-worktree file respectively.
variable has a similar effect, but you can specify any filename you want. The `GIT_CONFIG` environment variable has a similar effect, but you
can specify any filename you want.




ENVIRONMENT ENVIRONMENT

View File

@ -204,6 +204,36 @@ working trees, it can be used to identify worktrees. For example if
you only have two working trees, at "/abc/def/ghi" and "/abc/def/ggg", you only have two working trees, at "/abc/def/ghi" and "/abc/def/ggg",
then "ghi" or "def/ghi" is enough to point to the former working tree. then "ghi" or "def/ghi" is enough to point to the former working tree.


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.

In order to have configuration specific to working trees, you can turn
on "worktreeConfig" extension, e.g.:

------------
$ git config extensions.worktreeConfig true
------------

In this mode, specific configuration stays in the path pointed by `git
rev-parse --git-path config.worktree`. You can add or update
configuration in this file with `git config --worktree`. Older Git
versions will refuse to access repositories with this extension.

Note that in this file, the exception for `core.bare` and `core.worktree`
is gone. If you have them in $GIT_DIR/config before, you must move
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.sparseCheckout` is recommended per working tree, unless you
are sure you always use sparse checkout for all working trees.

DETAILS DETAILS
------- -------
Each linked working tree has a private sub-directory in the repository's Each linked working tree has a private sub-directory in the repository's
@ -253,6 +283,9 @@ to `/path/main/.git/worktrees/test-next` then a file named
`test-next` entry from being pruned. See `test-next` entry from being pruned. See
linkgit:gitrepository-layout[5] for details. linkgit:gitrepository-layout[5] for details.


When extensions.worktreeConfig is enabled, the config file
`.git/worktrees/<id>/config.worktree` is read after `.git/config` is.

LIST OUTPUT FORMAT LIST OUTPUT FORMAT
------------------ ------------------
The worktree list command has two output formats. The default format shows the The worktree list command has two output formats. The default format shows the

View File

@ -143,6 +143,11 @@ config::
if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/config" will be if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/config" will be
used instead. used instead.


config.worktree::
Working directory specific configuration file for the main
working directory in multiple working directory setup (see
linkgit:git-worktree[1]).

branches:: branches::
A slightly deprecated way to store shorthands to be used A slightly deprecated way to store shorthands to be used
to specify a URL to 'git fetch', 'git pull' and 'git push'. to specify a URL to 'git fetch', 'git pull' and 'git push'.
@ -275,6 +280,9 @@ worktrees/<id>/locked::
or manually by `git worktree prune`. The file may contain a string or manually by `git worktree prune`. The file may contain a string
explaining why the repository is locked. explaining why the repository is locked.


worktrees/<id>/config.worktree::
Working directory specific configuration file.

SEE ALSO SEE ALSO
-------- --------
linkgit:git-init[1], linkgit:git-init[1],

View File

@ -5,6 +5,7 @@
#include "parse-options.h" #include "parse-options.h"
#include "urlmatch.h" #include "urlmatch.h"
#include "quote.h" #include "quote.h"
#include "worktree.h"


static const char *const builtin_config_usage[] = { static const char *const builtin_config_usage[] = {
N_("git config [<options>]"), N_("git config [<options>]"),
@ -24,6 +25,7 @@ static char key_delim = ' ';
static char term = '\n'; static char term = '\n';


static int use_global_config, use_system_config, use_local_config; static int use_global_config, use_system_config, use_local_config;
static int use_worktree_config;
static struct git_config_source given_config_source; static struct git_config_source given_config_source;
static int actions, type; static int actions, type;
static char *default_value; static char *default_value;
@ -123,6 +125,7 @@ static struct option builtin_config_options[] = {
OPT_BOOL(0, "global", &use_global_config, N_("use global config file")), OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
OPT_BOOL(0, "system", &use_system_config, N_("use system config file")), OPT_BOOL(0, "system", &use_system_config, N_("use system config file")),
OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")), OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
OPT_BOOL(0, "worktree", &use_worktree_config, N_("use per-worktree config file")),
OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")), OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")),
OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")), OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")),
OPT_GROUP(N_("Action")), OPT_GROUP(N_("Action")),
@ -602,6 +605,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
PARSE_OPT_STOP_AT_NON_OPTION); PARSE_OPT_STOP_AT_NON_OPTION);


if (use_global_config + use_system_config + use_local_config + if (use_global_config + use_system_config + use_local_config +
use_worktree_config +
!!given_config_source.file + !!given_config_source.blob > 1) { !!given_config_source.file + !!given_config_source.blob > 1) {
error(_("only one config file at a time")); error(_("only one config file at a time"));
usage_builtin_config(); usage_builtin_config();
@ -645,7 +649,20 @@ int cmd_config(int argc, const char **argv, const char *prefix)
given_config_source.file = git_etc_gitconfig(); given_config_source.file = git_etc_gitconfig();
else if (use_local_config) else if (use_local_config)
given_config_source.file = git_pathdup("config"); given_config_source.file = git_pathdup("config");
else if (given_config_source.file) { else if (use_worktree_config) {
struct worktree **worktrees = get_worktrees(0);
if (repository_format_worktree_config)
given_config_source.file = git_pathdup("config.worktree");
else if (worktrees[0] && worktrees[1])
die(_("--worktree cannot be used with multiple "
"working trees unless the config\n"
"extension worktreeConfig is enabled. "
"Please read \"CONFIGURATION FILE\"\n"
"section in \"git help worktree\" for details"));
else
given_config_source.file = git_pathdup("config");
free_worktrees(worktrees);
} else if (given_config_source.file) {
if (!is_absolute_path(given_config_source.file) && prefix) if (!is_absolute_path(given_config_source.file) && prefix)
given_config_source.file = given_config_source.file =
prefix_filename(prefix, given_config_source.file); prefix_filename(prefix, given_config_source.file);

View File

@ -962,11 +962,13 @@ extern int grafts_replace_parents;
extern int repository_format_precious_objects; extern int repository_format_precious_objects;
extern char *repository_format_partial_clone; extern char *repository_format_partial_clone;
extern const char *core_partial_clone_filter_default; extern const char *core_partial_clone_filter_default;
extern int repository_format_worktree_config;


struct repository_format { struct repository_format {
int version; int version;
int precious_objects; int precious_objects;
char *partial_clone; /* value of extensions.partialclone */ char *partial_clone; /* value of extensions.partialclone */
int worktree_config;
int is_bare; int is_bare;
int hash_algo; int hash_algo;
char *work_tree; char *work_tree;

View File

@ -1695,6 +1695,17 @@ static int do_git_config_sequence(const struct config_options *opts,
if (repo_config && !access_or_die(repo_config, R_OK, 0)) if (repo_config && !access_or_die(repo_config, R_OK, 0))
ret += git_config_from_file(fn, repo_config, data); ret += git_config_from_file(fn, repo_config, data);


/*
* Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
* But let's not complicate things before it's actually needed.
*/
if (repository_format_worktree_config) {
char *path = git_pathdup("config.worktree");
if (!access_or_die(path, R_OK, 0))
ret += git_config_from_file(fn, path, data);
free(path);
}

current_parsing_scope = CONFIG_SCOPE_CMDLINE; current_parsing_scope = CONFIG_SCOPE_CMDLINE;
if (git_config_from_parameters(fn, data) < 0) if (git_config_from_parameters(fn, data) < 0)
die(_("unable to parse command-line config")); die(_("unable to parse command-line config"));

View File

@ -33,6 +33,7 @@ int ref_paranoia = -1;
int repository_format_precious_objects; int repository_format_precious_objects;
char *repository_format_partial_clone; char *repository_format_partial_clone;
const char *core_partial_clone_filter_default; const char *core_partial_clone_filter_default;
int repository_format_worktree_config;
const char *git_commit_encoding; const char *git_commit_encoding;
const char *git_log_output_encoding; const char *git_log_output_encoding;
const char *apply_default_whitespace; const char *apply_default_whitespace;

40
setup.c
View File

@ -402,6 +402,20 @@ void setup_work_tree(void)
initialized = 1; initialized = 1;
} }


static int read_worktree_config(const char *var, const char *value, void *vdata)
{
struct repository_format *data = vdata;

if (strcmp(var, "core.bare") == 0) {
data->is_bare = git_config_bool(var, value);
} else if (strcmp(var, "core.worktree") == 0) {
if (!value)
return config_error_nonbool(var);
data->work_tree = xstrdup(value);
}
return 0;
}

static int check_repo_format(const char *var, const char *value, void *vdata) static int check_repo_format(const char *var, const char *value, void *vdata)
{ {
struct repository_format *data = vdata; struct repository_format *data = vdata;
@ -423,16 +437,13 @@ static int check_repo_format(const char *var, const char *value, void *vdata)
if (!value) if (!value)
return config_error_nonbool(var); return config_error_nonbool(var);
data->partial_clone = xstrdup(value); data->partial_clone = xstrdup(value);
} else } else if (!strcmp(ext, "worktreeconfig"))
data->worktree_config = git_config_bool(var, value);
else
string_list_append(&data->unknown_extensions, ext); string_list_append(&data->unknown_extensions, ext);
} else if (strcmp(var, "core.bare") == 0) {
data->is_bare = git_config_bool(var, value);
} else if (strcmp(var, "core.worktree") == 0) {
if (!value)
return config_error_nonbool(var);
data->work_tree = xstrdup(value);
} }
return 0;
return read_worktree_config(var, value, vdata);
} }


static int check_repository_format_gently(const char *gitdir, struct repository_format *candidate, int *nongit_ok) static int check_repository_format_gently(const char *gitdir, struct repository_format *candidate, int *nongit_ok)
@ -466,7 +477,20 @@ static int check_repository_format_gently(const char *gitdir, struct repository_


repository_format_precious_objects = candidate->precious_objects; repository_format_precious_objects = candidate->precious_objects;
repository_format_partial_clone = candidate->partial_clone; repository_format_partial_clone = candidate->partial_clone;
repository_format_worktree_config = candidate->worktree_config;
string_list_clear(&candidate->unknown_extensions, 0); string_list_clear(&candidate->unknown_extensions, 0);

if (repository_format_worktree_config) {
/*
* pick up core.bare and core.worktree from per-worktree
* config if present
*/
strbuf_addf(&sb, "%s/config.worktree", gitdir);
git_config_from_file(read_worktree_config, sb.buf, candidate);
strbuf_release(&sb);
has_common = 0;
}

if (!has_common) { if (!has_common) {
if (candidate->is_bare != -1) { if (candidate->is_bare != -1) {
is_bare_repository_cfg = candidate->is_bare; is_bare_repository_cfg = candidate->is_bare;

View File

@ -76,15 +76,11 @@ EOF
test_expect_success 'non-match result' 'test_cmp expect .git/config' test_expect_success 'non-match result' 'test_cmp expect .git/config'


test_expect_success 'find mixed-case key by canonical name' ' test_expect_success 'find mixed-case key by canonical name' '
echo Second >expect && test_cmp_config Second cores.whatever
git config cores.whatever >actual &&
test_cmp expect actual
' '


test_expect_success 'find mixed-case key by non-canonical name' ' test_expect_success 'find mixed-case key by non-canonical name' '
echo Second >expect && test_cmp_config Second CoReS.WhAtEvEr
git config CoReS.WhAtEvEr >actual &&
test_cmp expect actual
' '


test_expect_success 'subsections are not canonicalized by git-config' ' test_expect_success 'subsections are not canonicalized by git-config' '
@ -94,12 +90,8 @@ test_expect_success 'subsections are not canonicalized by git-config' '
[section "SubSection"] [section "SubSection"]
key = two key = two
EOF EOF
echo one >expect && test_cmp_config one section.subsection.key &&
git config section.subsection.key >actual && test_cmp_config two section.SubSection.key
test_cmp expect actual &&
echo two >expect &&
git config section.SubSection.key >actual &&
test_cmp expect actual
' '


cat > .git/config <<\EOF cat > .git/config <<\EOF
@ -212,9 +204,7 @@ test_expect_success 'really really mean test' '
' '


test_expect_success 'get value' ' test_expect_success 'get value' '
echo alpha >expect && test_cmp_config alpha beta.haha
git config beta.haha >actual &&
test_cmp expect actual
' '


cat > expect << EOF cat > expect << EOF
@ -251,15 +241,11 @@ test_expect_success 'non-match' '
' '


test_expect_success 'non-match value' ' test_expect_success 'non-match value' '
echo wow >expect && test_cmp_config wow --get nextsection.nonewline !for
git config --get nextsection.nonewline !for >actual &&
test_cmp expect actual
' '


test_expect_success 'multi-valued get returns final one' ' test_expect_success 'multi-valued get returns final one' '
echo "wow2 for me" >expect && test_cmp_config "wow2 for me" --get nextsection.nonewline
git config --get nextsection.nonewline >actual &&
test_cmp expect actual
' '


test_expect_success 'multi-valued get-all returns all' ' test_expect_success 'multi-valued get-all returns all' '
@ -520,21 +506,11 @@ test_expect_success 'editing stdin is an error' '


test_expect_success 'refer config from subdirectory' ' test_expect_success 'refer config from subdirectory' '
mkdir x && mkdir x &&
( test_cmp_config -C x strasse --get --file ../other-config ein.bahn
cd x &&
echo strasse >expect &&
git config --get --file ../other-config ein.bahn >actual &&
test_cmp expect actual
)

' '


test_expect_success 'refer config from subdirectory via --file' ' test_expect_success 'refer config from subdirectory via --file' '
( test_cmp_config -C x strasse --file=../other-config --get ein.bahn
cd x &&
git config --file=../other-config --get ein.bahn >actual &&
test_cmp expect actual
)
' '


cat > expect << EOF cat > expect << EOF
@ -688,16 +664,13 @@ test_expect_success numbers '


test_expect_success '--int is at least 64 bits' ' test_expect_success '--int is at least 64 bits' '
git config giga.watts 121g && git config giga.watts 121g &&
echo 129922760704 >expect && echo >expect &&
git config --int --get giga.watts >actual && test_cmp_config 129922760704 --int --get giga.watts
test_cmp expect actual
' '


test_expect_success 'invalid unit' ' test_expect_success 'invalid unit' '
git config aninvalid.unit "1auto" && git config aninvalid.unit "1auto" &&
echo 1auto >expect && test_cmp_config 1auto aninvalid.unit &&
git config aninvalid.unit >actual &&
test_cmp expect actual &&
test_must_fail git config --int --get aninvalid.unit 2>actual && test_must_fail git config --int --get aninvalid.unit 2>actual &&
test_i18ngrep "bad numeric config value .1auto. for .aninvalid.unit. in file .git/config: invalid unit" actual test_i18ngrep "bad numeric config value .1auto. for .aninvalid.unit. in file .git/config: invalid unit" actual
' '
@ -1039,9 +1012,7 @@ test_expect_success '--null --get-regexp' '


test_expect_success 'inner whitespace kept verbatim' ' test_expect_success 'inner whitespace kept verbatim' '
git config section.val "foo bar" && git config section.val "foo bar" &&
echo "foo bar" >expect && test_cmp_config "foo bar" section.val
git config section.val >actual &&
test_cmp expect actual
' '


test_expect_success SYMLINKS 'symlinked configuration' ' test_expect_success SYMLINKS 'symlinked configuration' '
@ -1809,21 +1780,15 @@ big = 1M
EOF EOF


test_expect_success 'identical modern --type specifiers are allowed' ' test_expect_success 'identical modern --type specifiers are allowed' '
git config --type=int --type=int core.big >actual && test_cmp_config 1048576 --type=int --type=int core.big
echo 1048576 >expect &&
test_cmp expect actual
' '


test_expect_success 'identical legacy --type specifiers are allowed' ' test_expect_success 'identical legacy --type specifiers are allowed' '
git config --int --int core.big >actual && test_cmp_config 1048576 --int --int core.big
echo 1048576 >expect &&
test_cmp expect actual
' '


test_expect_success 'identical mixed --type specifiers are allowed' ' test_expect_success 'identical mixed --type specifiers are allowed' '
git config --int --type=int core.big >actual && test_cmp_config 1048576 --int --type=int core.big
echo 1048576 >expect &&
test_cmp expect actual
' '


test_expect_success 'non-identical modern --type specifiers are not allowed' ' test_expect_success 'non-identical modern --type specifiers are not allowed' '
@ -1842,21 +1807,15 @@ test_expect_success 'non-identical mixed --type specifiers are not allowed' '
' '


test_expect_success '--type allows valid type specifiers' ' test_expect_success '--type allows valid type specifiers' '
echo "true" >expect && test_cmp_config true --type=bool core.foo
git config --type=bool core.foo >actual &&
test_cmp expect actual
' '


test_expect_success '--no-type unsets type specifiers' ' test_expect_success '--no-type unsets type specifiers' '
echo "10" >expect && test_cmp_config 10 --type=bool --no-type core.number
git config --type=bool --no-type core.number >actual &&
test_cmp expect actual
' '


test_expect_success 'unset type specifiers may be reset to conflicting ones' ' test_expect_success 'unset type specifiers may be reset to conflicting ones' '
echo 1048576 >expect && test_cmp_config 1048576 --type=bool --no-type --type=int core.big
git config --type=bool --no-type --type=int core.big >actual &&
test_cmp expect actual
' '


test_expect_success '--type rejects unknown specifiers' ' test_expect_success '--type rejects unknown specifiers' '

79
t/t2029-worktree-config.sh Executable file
View File

@ -0,0 +1,79 @@
#!/bin/sh

test_description="config file in multi worktree"

. ./test-lib.sh

test_expect_success 'setup' '
test_commit start
'

test_expect_success 'config --worktree in single worktree' '
git config --worktree foo.bar true &&
test_cmp_config true foo.bar
'

test_expect_success 'add worktrees' '
git worktree add wt1 &&
git worktree add wt2
'

test_expect_success 'config --worktree without extension' '
test_must_fail git config --worktree foo.bar false
'

test_expect_success 'enable worktreeConfig extension' '
git config extensions.worktreeConfig true &&
test_cmp_config true extensions.worktreeConfig
'

test_expect_success 'config is shared as before' '
git config this.is shared &&
test_cmp_config shared this.is &&
test_cmp_config -C wt1 shared this.is &&
test_cmp_config -C wt2 shared this.is
'

test_expect_success 'config is shared (set from another worktree)' '
git -C wt1 config that.is also-shared &&
test_cmp_config also-shared that.is &&
test_cmp_config -C wt1 also-shared that.is &&
test_cmp_config -C wt2 also-shared that.is
'

test_expect_success 'config private to main worktree' '
git config --worktree this.is for-main &&
test_cmp_config for-main this.is &&
test_cmp_config -C wt1 shared this.is &&
test_cmp_config -C wt2 shared this.is
'

test_expect_success 'config private to linked worktree' '
git -C wt1 config --worktree this.is for-wt1 &&
test_cmp_config for-main this.is &&
test_cmp_config -C wt1 for-wt1 this.is &&
test_cmp_config -C wt2 shared this.is
'

test_expect_success 'core.bare no longer for main only' '
test_config core.bare true &&
test "$(git rev-parse --is-bare-repository)" = true &&
test "$(git -C wt1 rev-parse --is-bare-repository)" = true &&
test "$(git -C wt2 rev-parse --is-bare-repository)" = true
'

test_expect_success 'per-worktree core.bare is picked up' '
git -C wt1 config --worktree core.bare true &&
test "$(git rev-parse --is-bare-repository)" = false &&
test "$(git -C wt1 rev-parse --is-bare-repository)" = true &&
test "$(git -C wt2 rev-parse --is-bare-repository)" = false
'

test_expect_success 'config.worktree no longer read without extension' '
git config --unset extensions.worktreeConfig &&
test_cmp_config shared this.is &&
test_cmp_config -C wt1 shared this.is &&
test_cmp_config -C wt2 shared this.is
'

test_done

View File

@ -747,6 +747,29 @@ test_cmp() {
$GIT_TEST_CMP "$@" $GIT_TEST_CMP "$@"
} }


# Check that the given config key has the expected value.
#
# test_cmp_config [-C <dir>] <expected-value>
# [<git-config-options>...] <config-key>
#
# for example to check that the value of core.bar is foo
#
# test_cmp_config foo core.bar
#
test_cmp_config() {
local GD &&
if test "$1" = "-C"
then
shift &&
GD="-C $1" &&
shift
fi &&
printf "%s\n" "$1" >expect.config &&
shift &&
git $GD config "$@" >actual.config &&
test_cmp expect.config actual.config
}

# test_cmp_bin - helper to compare binary files # test_cmp_bin - helper to compare binary files


test_cmp_bin() { test_cmp_bin() {