Subject: [PATCH 3/5] setup.c: remove special case of core.worktree and core.bare

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Wed, 2 Dec 2015 20:13:44 +0100

core.worktree and core.bare, which are treated specially in 31e26eb [1],
are now moved to info/core.worktree and the special treatment
reverted. The test "$GIT_DIR/common overrides core.worktree" in t1501
from 31e26eb verifies that the behavior is still correct after this
change.

A note about core.bare. On the surface it does not make sense for
core.bare to be worktree specific. It's made so in order to "grow" new
worktrees from a bare repo. In these new linked worktrees, core.bare
will be hidden away and worktree-related commands won't complain about
bare repository.

[1] 31e26eb (setup.c: support multi-checkout repo setup - 2014-11-30)

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 Documentation/config.txt |  4 ++++
 config.c                 |  8 +++++++
 setup.c                  | 62 ++++++++++++++++++++++--------------------------
 3 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5c6cd4b..09a8b57 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -454,6 +454,8 @@ linkgit:git-init[1] when the repository was created.  By default a
 repository that ends in "/.git" is assumed to be not bare (bare =
 false), while all other repositories are assumed to be bare (bare
 = true).
++
+This variable is per-worktree in multiple working tree setup.
 
 core.worktree::
 	Set the path to the root of the working tree.
@@ -478,6 +480,8 @@ still use "/different/path" as the root of the work tree and can cause
 confusion unless you know what you are doing (e.g. you are creating a
 read-only snapshot of the same index to a location different from the
 repository's usual working tree).
++
+This variable is per-worktree in multiple working tree setup.
 
 core.logAllRefUpdates::
 	Enable the reflog. Updates to a ref <ref> is logged to the file
diff --git a/config.c b/config.c
index 75c45e1..54a6219 100644
--- a/config.c
+++ b/config.c
@@ -91,6 +91,11 @@ static long config_buf_ftell(struct config_source *conf)
 	return conf->u.buf.pos;
 }
 
+static const char* default_config_worktree[] = {
+	"core/bare",
+	"core/worktree"
+};
+
 static void load_info_config_worktree(void)
 {
 	struct exclude_list *el = &config_local;
@@ -101,6 +106,9 @@ static void load_info_config_worktree(void)
 
 	clear_exclude_list(el);
 
+	for (i = 0; i < ARRAY_SIZE(default_config_worktree); i++)
+		add_exclude(default_config_worktree[i], "", 0, el, 0);
+
 	if (strbuf_read_file(&sb,
 			     git_path("info/config.worktree"),
 			     128) <= 0) {
diff --git a/setup.c b/setup.c
index 0047d40..c088d45 100644
--- a/setup.c
+++ b/setup.c
@@ -355,43 +355,20 @@ void setup_work_tree(void)
 	initialized = 1;
 }
 
-static int check_repo_format(const char *var, const char *value, void *cb)
-{
-	const char *ext;
-
-	if (strcmp(var, "core.repositoryformatversion") == 0)
-		repository_format_version = git_config_int(var, value);
-	else if (strcmp(var, "core.sharedrepository") == 0)
-		shared_repository = git_config_perm(var, value);
-	else if (skip_prefix(var, "extensions.", &ext)) {
-		/*
-		 * record any known extensions here; otherwise,
-		 * we fall through to recording it as unknown, and
-		 * check_repository_format will complain
-		 */
-		if (!strcmp(ext, "noop"))
-			;
-		else if (!strcmp(ext, "preciousobjects"))
-			repository_format_precious_objects = git_config_bool(var, value);
-		else
-			string_list_append(&unknown_extensions, ext);
-	}
-	return 0;
-}
-
 static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
 {
 	struct strbuf sb = STRBUF_INIT;
+	struct strbuf sb2 = STRBUF_INIT;
 	const char *repo_config;
-	config_fn_t fn;
+	const char *worktree_config = NULL;
 	int ret = 0;
 
 	string_list_clear(&unknown_extensions, 0);
 
-	if (get_common_dir(&sb, gitdir))
-		fn = check_repo_format;
-	else
-		fn = check_repository_format_version;
+	if (get_common_dir(&sb, gitdir)) {
+		strbuf_addf(&sb2, "%s/config.worktree", gitdir);
+		worktree_config = sb2.buf;
+	}
 	strbuf_addstr(&sb, "/config");
 	repo_config = sb.buf;
 
@@ -404,7 +381,8 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
 	 * Use a gentler version of git_config() to check if this repo
 	 * is a good one.
 	 */
-	git_config_early(fn, NULL, repo_config, NULL);
+	git_config_early(check_repository_format_version, NULL,
+			 repo_config, worktree_config);
 	if (GIT_REPO_VERSION_READ < repository_format_version) {
 		if (!nongit_ok)
 			die ("Expected git repo version <= %d, found %d",
@@ -431,6 +409,7 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
 	}
 
 	strbuf_release(&sb);
+	strbuf_release(&sb2);
 	return ret;
 }
 
@@ -963,10 +942,25 @@ int git_config_perm(const char *var, const char *value)
 
 int check_repository_format_version(const char *var, const char *value, void *cb)
 {
-	int ret = check_repo_format(var, value, cb);
-	if (ret)
-		return ret;
-	if (strcmp(var, "core.bare") == 0) {
+	const char *ext;
+
+	if (strcmp(var, "core.repositoryformatversion") == 0)
+		repository_format_version = git_config_int(var, value);
+	else if (strcmp(var, "core.sharedrepository") == 0)
+		shared_repository = git_config_perm(var, value);
+	else if (skip_prefix(var, "extensions.", &ext)) {
+		/*
+		 * record any known extensions here; otherwise,
+		 * we fall through to recording it as unknown, and
+		 * check_repository_format will complain
+		 */
+		if (!strcmp(ext, "noop"))
+			;
+		else if (!strcmp(ext, "preciousobjects"))
+			repository_format_precious_objects = git_config_bool(var, value);
+		else
+			string_list_append(&unknown_extensions, ext);
+	} else if (strcmp(var, "core.bare") == 0) {
 		is_bare_repository_cfg = git_config_bool(var, value);
 		if (is_bare_repository_cfg == 1)
 			inside_work_tree = -1;
-- 
2.2.0.513.g477eb31