зеркало из https://github.com/microsoft/git.git
config: learn the "onbranch:" includeIf condition
Currently, if a user wishes to have individual settings per branch, they are required to manually keep track of the settings in their head and manually set the options on the command-line or change the config at each branch. Teach config the "onbranch:" includeIf condition so that it can conditionally include configuration files if the branch that is checked out in the current worktree matches the pattern given. Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
74583d8912
Коммит
07b2c0eaca
|
@ -144,6 +144,20 @@ refer to linkgit:gitignore[5] for details. For convenience:
|
|||
This is the same as `gitdir` except that matching is done
|
||||
case-insensitively (e.g. on case-insensitive file sytems)
|
||||
|
||||
`onbranch`::
|
||||
The data that follows the keyword `onbranch:` is taken to be a
|
||||
pattern with standard globbing wildcards and two additional
|
||||
ones, `**/` and `/**`, that can match multiple path components.
|
||||
If we are in a worktree where the name of the branch that is
|
||||
currently checked out matches the pattern, the include condition
|
||||
is met.
|
||||
+
|
||||
If the pattern ends with `/`, `**` will be automatically added. For
|
||||
example, the pattern `foo/` becomes `foo/**`. In other words, it matches
|
||||
all branches that begin with `foo/`. This is useful if your branches are
|
||||
organized hierarchically and you would like to apply a configuration to
|
||||
all the branches in that hierarchy.
|
||||
|
||||
A few more notes on matching via `gitdir` and `gitdir/i`:
|
||||
|
||||
* Symlinks in `$GIT_DIR` are not resolved before matching.
|
||||
|
@ -206,6 +220,11 @@ Example
|
|||
[includeIf "gitdir:/path/to/group/"]
|
||||
path = foo.inc
|
||||
|
||||
; include only if we are in a worktree where foo-branch is
|
||||
; currently checked out
|
||||
[includeIf "onbranch:foo-branch"]
|
||||
path = foo.inc
|
||||
|
||||
Values
|
||||
~~~~~~
|
||||
|
||||
|
|
31
config.c
31
config.c
|
@ -19,6 +19,7 @@
|
|||
#include "utf8.h"
|
||||
#include "dir.h"
|
||||
#include "color.h"
|
||||
#include "refs.h"
|
||||
|
||||
struct config_source {
|
||||
struct config_source *prev;
|
||||
|
@ -170,6 +171,12 @@ static int handle_path_include(const char *path, struct config_include_data *inc
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void add_trailing_starstar_for_dir(struct strbuf *pat)
|
||||
{
|
||||
if (pat->len && is_dir_sep(pat->buf[pat->len - 1]))
|
||||
strbuf_addstr(pat, "**");
|
||||
}
|
||||
|
||||
static int prepare_include_condition_pattern(struct strbuf *pat)
|
||||
{
|
||||
struct strbuf path = STRBUF_INIT;
|
||||
|
@ -199,8 +206,7 @@ static int prepare_include_condition_pattern(struct strbuf *pat)
|
|||
} else if (!is_absolute_path(pat->buf))
|
||||
strbuf_insert(pat, 0, "**/", 3);
|
||||
|
||||
if (pat->len && is_dir_sep(pat->buf[pat->len - 1]))
|
||||
strbuf_addstr(pat, "**");
|
||||
add_trailing_starstar_for_dir(pat);
|
||||
|
||||
strbuf_release(&path);
|
||||
return prefix;
|
||||
|
@ -264,6 +270,25 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int include_by_branch(const char *cond, size_t cond_len)
|
||||
{
|
||||
int flags;
|
||||
int ret;
|
||||
struct strbuf pattern = STRBUF_INIT;
|
||||
const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
|
||||
const char *shortname;
|
||||
|
||||
if (!refname || !(flags & REF_ISSYMREF) ||
|
||||
!skip_prefix(refname, "refs/heads/", &shortname))
|
||||
return 0;
|
||||
|
||||
strbuf_add(&pattern, cond, cond_len);
|
||||
add_trailing_starstar_for_dir(&pattern);
|
||||
ret = !wildmatch(pattern.buf, shortname, WM_PATHNAME);
|
||||
strbuf_release(&pattern);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int include_condition_is_true(const struct config_options *opts,
|
||||
const char *cond, size_t cond_len)
|
||||
{
|
||||
|
@ -272,6 +297,8 @@ static int include_condition_is_true(const struct config_options *opts,
|
|||
return include_by_gitdir(opts, cond, cond_len, 0);
|
||||
else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len))
|
||||
return include_by_gitdir(opts, cond, cond_len, 1);
|
||||
else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len))
|
||||
return include_by_branch(cond, cond_len);
|
||||
|
||||
/* unknown conditionals are always false */
|
||||
return 0;
|
||||
|
|
|
@ -309,6 +309,45 @@ test_expect_success SYMLINKS 'conditional include, gitdir matching symlink, icas
|
|||
)
|
||||
'
|
||||
|
||||
test_expect_success 'conditional include, onbranch' '
|
||||
echo "[includeIf \"onbranch:foo-branch\"]path=bar9" >>.git/config &&
|
||||
echo "[test]nine=9" >.git/bar9 &&
|
||||
git checkout -b master &&
|
||||
test_must_fail git config test.nine &&
|
||||
git checkout -b foo-branch &&
|
||||
echo 9 >expect &&
|
||||
git config test.nine >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'conditional include, onbranch, wildcard' '
|
||||
echo "[includeIf \"onbranch:?oo-*/**\"]path=bar10" >>.git/config &&
|
||||
echo "[test]ten=10" >.git/bar10 &&
|
||||
git checkout -b not-foo-branch/a &&
|
||||
test_must_fail git config test.ten &&
|
||||
|
||||
echo 10 >expect &&
|
||||
git checkout -b foo-branch/a/b/c &&
|
||||
git config test.ten >actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
git checkout -b moo-bar/a &&
|
||||
git config test.ten >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'conditional include, onbranch, implicit /** for /' '
|
||||
echo "[includeIf \"onbranch:foo-dir/\"]path=bar11" >>.git/config &&
|
||||
echo "[test]eleven=11" >.git/bar11 &&
|
||||
git checkout -b not-foo-dir/a &&
|
||||
test_must_fail git config test.eleven &&
|
||||
|
||||
echo 11 >expect &&
|
||||
git checkout -b foo-dir/a/b/c &&
|
||||
git config test.eleven >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'include cycles are detected' '
|
||||
cat >.gitconfig <<-\EOF &&
|
||||
[test]value = gitconfig
|
||||
|
|
Загрузка…
Ссылка в новой задаче