{"thread":{"id":"48012","subject":"feature request: git-config: Add conditional include for gitbranch","startedAt":"2018-03-09T00:23:49Z","lastAt":"2018-03-09T01:41:01Z","messageCount":2,"participants":["Jeremy Bicha","Duy Nguyen"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"341329","messageId":"CAAajCMbFEF+1i8+MOpOfdMgChi0FfdA1CoCjKLjjKMT2m-58KQ@mail.gmail.com","threadId":"48012","inReplyTo":null,"subject":"feature request: git-config: Add conditional include for gitbranch","fromName":"Jeremy Bicha","fromEmail":"jbicha@ubuntu.com","sentAt":"2018-03-09T00:23:00Z","receivedAt":"2018-03-09T00:23:49Z","isPatch":false,"sender":{"key":"jbicha@ubuntu.com","avatar":null},"body":"Use Case\n======\nJeremy is a developer for Debian and Ubuntu. The same repository is\nused for both Debian and Ubuntu packaging but with different branches.\nFor commits to the debian/master branch, Jeremy wants to use his\n@debian.org email address. For commits to the ubuntu/master branch,\nJeremy wants to use his @ubuntu.com email.\n\nProposal\n=======\nThe includeIf feature of git-config could be extended to offer a\ngitbranch conditional include in addition to the gitdir conditional\ninclude it already offers.\n\nThanks,\nJeremy Bicha\n"},{"id":"341330","messageId":"20180309014043.GA9506@duynguyen.dek-tpc.internal","threadId":"48012","inReplyTo":"CAAajCMbFEF+1i8+MOpOfdMgChi0FfdA1CoCjKLjjKMT2m-58KQ@mail.gmail.com","subject":"Re: feature request: git-config: Add conditional include for gitbranch","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-09T01:40:43Z","receivedAt":"2018-03-09T01:41:01Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Mar 08, 2018 at 07:23:00PM -0500, Jeremy Bicha wrote:\n> Use Case\n> ======\n> Jeremy is a developer for Debian and Ubuntu. The same repository is\n> used for both Debian and Ubuntu packaging but with different branches.\n> For commits to the debian/master branch, Jeremy wants to use his\n> @debian.org email address. For commits to the ubuntu/master branch,\n> Jeremy wants to use his @ubuntu.com email.\n> \n> Proposal\n> =======\n> The includeIf feature of git-config could be extended to offer a\n> gitbranch conditional include in addition to the gitdir conditional\n> include it already offers.\n\nInteresting. It looks quite simple to do this. My prototype looks like\nthis.\n\n-- 8< --\nSubject: [PATCH] config: support conditional include by matching ref pattern\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/config.txt  | 12 ++++++++++++\n config.c                  | 30 ++++++++++++++++++++++++++++++\n t/t1305-config-include.sh | 26 ++++++++++++++++++++++++++\n 3 files changed, 68 insertions(+)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex ce9102cea8..4e8fb6d99c 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -143,6 +143,18 @@ refer to linkgit:gitignore[5] for details. For convenience:\n \tThis is the same as `gitdir` except that matching is done\n \tcase-insensitively (e.g. on case-insensitive file sytems)\n \n+`ref`::\n+\tThe data that follows the keyword `ref:` is used as a glob\n+\tpattern that matches against the current branch. `*` in the\n+\tpattern does not match `/` and `**` matches multiple levels,\n+\tthe same as .gitignore syntax. The branch is a full reference\n+\t(i.e. with `refs/heads/` prefix). If HEAD is detached, the\n+\tpattern will be matched against the value \"HEAD\".\n+\n+`ref/i`::\n+\tThis is the same as `ref` except that matching is done\n+\tcase-insensitively\n+\n A few more notes on matching via `gitdir` and `gitdir/i`:\n \n  * Symlinks in `$GIT_DIR` are not resolved before matching.\ndiff --git a/config.c b/config.c\nindex b0c20e6cb8..72ff2da667 100644\n--- a/config.c\n+++ b/config.c\n@@ -16,6 +16,7 @@\n #include \"string-list.h\"\n #include \"utf8.h\"\n #include \"dir.h\"\n+#include \"refs.h\"\n \n struct config_source {\n \tstruct config_source *prev;\n@@ -202,6 +203,31 @@ static int prepare_include_condition_pattern(struct strbuf *pat)\n \treturn prefix;\n }\n \n+static int include_by_ref(const struct config_options *opts,\n+\t\t\t  const char *cond, size_t cond_len, int icase)\n+{\n+\tstruct strbuf pattern = STRBUF_INIT;\n+\tchar *branch;\n+\tunsigned flags = WM_PATHNAME;\n+\tint ret;\n+\n+\tif (!opts->git_dir)\n+\t\treturn 0;\n+\n+\tbranch = resolve_refdup(\"HEAD\", 0, NULL, NULL);\n+\tif (!branch)\n+\t\treturn 0;\n+\n+\tif (icase)\n+\t\tflags |= WM_CASEFOLD;\n+\tstrbuf_add(&pattern,  cond, cond_len);\n+\tret = !wildmatch(pattern.buf, branch, flags);\n+\n+\tfree(branch);\n+\tstrbuf_release(&pattern);\n+\treturn ret;\n+}\n+\n static int include_by_gitdir(const struct config_options *opts,\n \t\t\t     const char *cond, size_t cond_len, int icase)\n {\n@@ -268,6 +294,10 @@ static int include_condition_is_true(const struct config_options *opts,\n \t\treturn include_by_gitdir(opts, cond, cond_len, 0);\n \telse if (skip_prefix_mem(cond, cond_len, \"gitdir/i:\", &cond, &cond_len))\n \t\treturn include_by_gitdir(opts, cond, cond_len, 1);\n+\telse if (skip_prefix_mem(cond, cond_len, \"ref:\", &cond, &cond_len))\n+\t\treturn include_by_ref(opts, cond, cond_len, 0);\n+\telse if (skip_prefix_mem(cond, cond_len, \"ref/i:\", &cond, &cond_len))\n+\t\treturn include_by_ref(opts, cond, cond_len, 1);\n \n \t/* unknown conditionals are always false */\n \treturn 0;\ndiff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh\nindex d9d2f545a4..27ecfc74b7 100755\n--- a/t/t1305-config-include.sh\n+++ b/t/t1305-config-include.sh\n@@ -296,6 +296,32 @@ test_expect_success SYMLINKS 'conditional include, gitdir matching symlink, icas\n \t)\n '\n \n+test_expect_success 'conditional include by refs' '\n+\tgit init inc-by-ref &&\n+\t(\n+\t\tcheck() {\n+\t\t\techo \"ref: $1\" >.git/HEAD &&\n+\t\t\techo \"[includeIf \\\"ref:$2\\\"]path=bar8\" >.git/config &&\n+\t\t\tgit config test.var >actual &&\n+\t\t\ttest_cmp expect actual\n+\t\t}\n+\t\tcd inc-by-ref &&\n+\t\techo \"[test]var=matched\" >.git/bar8 &&\n+\t\techo matched >expect &&\n+\n+\t\tcheck refs/heads/foo refs/heads/foo &&\n+\t\tcheck refs/heads/foo \"refs/heads/*\" &&\n+\t\tcheck refs/heads/foo \"refs/heads/f*\" &&\n+\t\tcheck refs/heads/deep/in/foo \"refs/heads/**/foo\" &&\n+\n+\t\ttest_commit one &&\n+\t\tgit checkout --detach &&\n+\t\techo \"[includeIf \\\"ref:HEAD\\\"]path=bar8\" >.git/config &&\n+\t\tgit config test.var >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n test_expect_success 'include cycles are detected' '\n \tcat >.gitconfig <<-\\EOF &&\n \t[test]value = gitconfig\n-- \n2.16.2.903.gd04caf5039\n\n-- 8< --\n"}]}