Skip to content

Commit 722ba93

Browse files
committed
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.
1 parent e208b19 commit 722ba93

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

src/config_file.c

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,12 +651,64 @@ static int conditional_match_gitdir_i(
651651
return do_match_gitdir(matches, repo, cfg_file, value, true);
652652
}
653653

654+
static int conditional_match_onbranch(
655+
int *matches,
656+
const git_repository *repo,
657+
const char *cfg_file,
658+
const char *condition)
659+
{
660+
git_buf reference = GIT_BUF_INIT, buf = GIT_BUF_INIT;
661+
int error;
662+
663+
GIT_UNUSED(cfg_file);
664+
665+
/*
666+
* NOTE: you cannot use `git_repository_head` here. Looking up the
667+
* HEAD reference will create the ODB, which causes us to read the
668+
* repo's config for keys like core.precomposeUnicode. As we're
669+
* just parsing the config right now, though, this would result in
670+
* an endless recursion.
671+
*/
672+
673+
if ((error = git_buf_joinpath(&buf, git_repository_path(repo), GIT_HEAD_FILE)) < 0 ||
674+
(error = git_futils_readbuffer(&reference, buf.ptr)) < 0)
675+
goto out;
676+
git_buf_rtrim(&reference);
677+
678+
if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF)))
679+
goto out;
680+
git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF));
681+
682+
if (git__strncmp(reference.ptr, GIT_REFS_HEADS_DIR, strlen(GIT_REFS_HEADS_DIR)))
683+
goto out;
684+
git_buf_consume(&reference, reference.ptr + strlen(GIT_REFS_HEADS_DIR));
685+
686+
/*
687+
* If the condition ends with a '/', then we should treat it as if
688+
* it had '**' appended.
689+
*/
690+
if ((error = git_buf_sets(&buf, condition)) < 0)
691+
goto out;
692+
if (git_path_is_dirsep(condition[strlen(condition) - 1]) &&
693+
(error = git_buf_puts(&buf, "**")) < 0)
694+
goto out;
695+
696+
*matches = wildmatch(buf.ptr, reference.ptr, WM_PATHNAME) == WM_MATCH;
697+
out:
698+
git_buf_dispose(&reference);
699+
git_buf_dispose(&buf);
700+
701+
return error;
702+
703+
}
704+
654705
static const struct {
655706
const char *prefix;
656707
int (*matches)(int *matches, const git_repository *repo, const char *cfg, const char *value);
657708
} conditions[] = {
658709
{ "gitdir:", conditional_match_gitdir },
659-
{ "gitdir/i:", conditional_match_gitdir_i }
710+
{ "gitdir/i:", conditional_match_gitdir_i },
711+
{ "onbranch:", conditional_match_onbranch }
660712
};
661713

662714
static int parse_conditional_include(config_file_parse_data *parse_data, const char *section, const char *file)

tests/config/conditionals.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "clar_libgit2.h"
22
#include "buffer.h"
33
#include "futils.h"
4+
#include "repository.h"
45

56
#ifdef GIT_WIN32
67
# define ROOT_PREFIX "C:"
@@ -106,3 +107,42 @@ void test_config_conditionals__invalid_conditional_fails(void)
106107
{
107108
assert_condition_includes("foobar", ".git", false);
108109
}
110+
111+
static void set_head(git_repository *repo, const char *name)
112+
{
113+
cl_git_pass(git_repository_create_head(git_repository_path(repo), name));
114+
}
115+
116+
void test_config_conditionals__onbranch(void)
117+
{
118+
assert_condition_includes("onbranch", "master", true);
119+
assert_condition_includes("onbranch", "m*", true);
120+
assert_condition_includes("onbranch", "*", true);
121+
assert_condition_includes("onbranch", "master/", false);
122+
assert_condition_includes("onbranch", "foo", false);
123+
124+
set_head(_repo, "foo");
125+
assert_condition_includes("onbranch", "master", false);
126+
assert_condition_includes("onbranch", "foo", true);
127+
assert_condition_includes("onbranch", "f*o", true);
128+
129+
set_head(_repo, "dir/ref");
130+
assert_condition_includes("onbranch", "dir/ref", true);
131+
assert_condition_includes("onbranch", "dir/", true);
132+
assert_condition_includes("onbranch", "dir/*", true);
133+
assert_condition_includes("onbranch", "dir/**", true);
134+
assert_condition_includes("onbranch", "**", true);
135+
assert_condition_includes("onbranch", "dir", false);
136+
assert_condition_includes("onbranch", "dir*", false);
137+
138+
set_head(_repo, "dir/subdir/ref");
139+
assert_condition_includes("onbranch", "dir/subdir/", true);
140+
assert_condition_includes("onbranch", "dir/subdir/*", true);
141+
assert_condition_includes("onbranch", "dir/subdir/ref", true);
142+
assert_condition_includes("onbranch", "dir/", true);
143+
assert_condition_includes("onbranch", "dir/**", true);
144+
assert_condition_includes("onbranch", "**", true);
145+
assert_condition_includes("onbranch", "dir", false);
146+
assert_condition_includes("onbranch", "dir*", false);
147+
assert_condition_includes("onbranch", "dir/*", false);
148+
}

0 commit comments

Comments
 (0)