[RFC PATCH] config: learn the "onbranch:" includeIf condition

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 is checked out
in the current worktree.

Signed-off-by: Denton Liu <liu.denton@xxxxxxxxx>
---

I decided to go ahead and implement the includeIf onbranch semantics for
fun. For completeness, I'm sending it to the list but I'm not really
sure if this should get merged, since I don't really have a use-case for
this, especially if we go the branch-specific format-patch config route.

Another thing to note is that this change doesn't completely cover all
the use-cases that the branch-specific format-patch does. In particular,
if I run

	$ git checkout foo
	$ git format-patch master..bar

with the `format.bar.*`, we'd get bar-specific configs, whereas with
`includeIf "onbranch:bar"`, we'd fail to include bar-specific configs
and, more dangerously, we'd be including foo's configs.

But let's see how it goes.

 Documentation/config.txt  | 10 ++++++++++
 config.c                  | 16 ++++++++++++++++
 t/t1305-config-include.sh | 13 +++++++++++++
 3 files changed, 39 insertions(+)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 7e2a6f61f5..3b9fbe1860 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -144,6 +144,11 @@ 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
+	name of a local branch. If we are in a worktree where that
+	branch is currently checked out, the include condition is met.
+
 A few more notes on matching via `gitdir` and `gitdir/i`:
 
  * Symlinks in `$GIT_DIR` are not resolved before matching.
@@ -206,6 +211,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
 ~~~~~~
 
diff --git a/config.c b/config.c
index 296a6d9cc4..954e84e13a 100644
--- a/config.c
+++ b/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;
@@ -264,6 +265,19 @@ static int include_by_gitdir(const struct config_options *opts,
 	return ret;
 }
 
+static int include_by_branch(const char *cond, size_t cond_len)
+{
+	int flags;
+	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;
+
+	return !strncmp(cond, shortname, cond_len);
+}
+
 static int include_condition_is_true(const struct config_options *opts,
 				     const char *cond, size_t cond_len)
 {
@@ -272,6 +286,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;
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index 579a86b7f8..062db08ad9 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -309,6 +309,19 @@ test_expect_success SYMLINKS 'conditional include, gitdir matching symlink, icas
 	)
 '
 
+test_expect_success 'conditional include, onbranch' '
+	(
+		cd bar &&
+		echo "[includeIf \"onbranch:foo-branch\"]path=bar9" >>.git/config &&
+		echo "[test]nine=9" >.git/bar9 &&
+		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 'include cycles are detected' '
 	cat >.gitconfig <<-\EOF &&
 	[test]value = gitconfig
-- 
2.22.0.rc1.169.g49223abbf8




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux