diff options
author | Patrick Steinhardt <ps@pks.im> | 2019-08-01 15:14:06 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2019-08-01 15:57:16 +0200 |
commit | 722ba93f6f813669ff9ea2359d3dfbbd662283fc (patch) | |
tree | 9058ff55a0226b87032b90b860186045c47c0795 | |
parent | e208b1953853f27f2de23f429e9518480a2d51e2 (diff) | |
download | libgit2-722ba93f6f813669ff9ea2359d3dfbbd662283fc.tar.gz |
config: implement "onbranch" conditional
With Git v2.23.0, the conditional include mechanism gained another new
conditional "onbranch". As the name says, it will cause a file to be
included if the "onbranch" pattern matches the currently checked out
branch.
Implement this new condition and add a bunch of tests.
-rw-r--r-- | src/config_file.c | 54 | ||||
-rw-r--r-- | tests/config/conditionals.c | 40 |
2 files changed, 93 insertions, 1 deletions
diff --git a/src/config_file.c b/src/config_file.c index 3e8e30cbd..849096d0f 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -651,12 +651,64 @@ static int conditional_match_gitdir_i( return do_match_gitdir(matches, repo, cfg_file, value, true); } +static int conditional_match_onbranch( + int *matches, + const git_repository *repo, + const char *cfg_file, + const char *condition) +{ + git_buf reference = GIT_BUF_INIT, buf = GIT_BUF_INIT; + int error; + + GIT_UNUSED(cfg_file); + + /* + * NOTE: you cannot use `git_repository_head` here. Looking up the + * HEAD reference will create the ODB, which causes us to read the + * repo's config for keys like core.precomposeUnicode. As we're + * just parsing the config right now, though, this would result in + * an endless recursion. + */ + + if ((error = git_buf_joinpath(&buf, git_repository_path(repo), GIT_HEAD_FILE)) < 0 || + (error = git_futils_readbuffer(&reference, buf.ptr)) < 0) + goto out; + git_buf_rtrim(&reference); + + if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF))) + goto out; + git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF)); + + if (git__strncmp(reference.ptr, GIT_REFS_HEADS_DIR, strlen(GIT_REFS_HEADS_DIR))) + goto out; + git_buf_consume(&reference, reference.ptr + strlen(GIT_REFS_HEADS_DIR)); + + /* + * If the condition ends with a '/', then we should treat it as if + * it had '**' appended. + */ + if ((error = git_buf_sets(&buf, condition)) < 0) + goto out; + if (git_path_is_dirsep(condition[strlen(condition) - 1]) && + (error = git_buf_puts(&buf, "**")) < 0) + goto out; + + *matches = wildmatch(buf.ptr, reference.ptr, WM_PATHNAME) == WM_MATCH; +out: + git_buf_dispose(&reference); + git_buf_dispose(&buf); + + return error; + +} + static const struct { const char *prefix; int (*matches)(int *matches, const git_repository *repo, const char *cfg, const char *value); } conditions[] = { { "gitdir:", conditional_match_gitdir }, - { "gitdir/i:", conditional_match_gitdir_i } + { "gitdir/i:", conditional_match_gitdir_i }, + { "onbranch:", conditional_match_onbranch } }; static int parse_conditional_include(config_file_parse_data *parse_data, const char *section, const char *file) diff --git a/tests/config/conditionals.c b/tests/config/conditionals.c index e2c74c1f5..5858782c1 100644 --- a/tests/config/conditionals.c +++ b/tests/config/conditionals.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "buffer.h" #include "futils.h" +#include "repository.h" #ifdef GIT_WIN32 # define ROOT_PREFIX "C:" @@ -106,3 +107,42 @@ void test_config_conditionals__invalid_conditional_fails(void) { assert_condition_includes("foobar", ".git", false); } + +static void set_head(git_repository *repo, const char *name) +{ + cl_git_pass(git_repository_create_head(git_repository_path(repo), name)); +} + +void test_config_conditionals__onbranch(void) +{ + assert_condition_includes("onbranch", "master", true); + assert_condition_includes("onbranch", "m*", true); + assert_condition_includes("onbranch", "*", true); + assert_condition_includes("onbranch", "master/", false); + assert_condition_includes("onbranch", "foo", false); + + set_head(_repo, "foo"); + assert_condition_includes("onbranch", "master", false); + assert_condition_includes("onbranch", "foo", true); + assert_condition_includes("onbranch", "f*o", true); + + set_head(_repo, "dir/ref"); + assert_condition_includes("onbranch", "dir/ref", true); + assert_condition_includes("onbranch", "dir/", true); + assert_condition_includes("onbranch", "dir/*", true); + assert_condition_includes("onbranch", "dir/**", true); + assert_condition_includes("onbranch", "**", true); + assert_condition_includes("onbranch", "dir", false); + assert_condition_includes("onbranch", "dir*", false); + + set_head(_repo, "dir/subdir/ref"); + assert_condition_includes("onbranch", "dir/subdir/", true); + assert_condition_includes("onbranch", "dir/subdir/*", true); + assert_condition_includes("onbranch", "dir/subdir/ref", true); + assert_condition_includes("onbranch", "dir/", true); + assert_condition_includes("onbranch", "dir/**", true); + assert_condition_includes("onbranch", "**", true); + assert_condition_includes("onbranch", "dir", false); + assert_condition_includes("onbranch", "dir*", false); + assert_condition_includes("onbranch", "dir/*", false); +} |