Commit 6259576408520a93f7a3da220454a6b540536d15

Vicent Marti 2014-09-16T13:17:08

Merge pull request #2566 from libgit2/rb/attr-with-bare Fix attribute lookup in index for bare repos

diff --git a/include/git2/sys/repository.h b/include/git2/sys/repository.h
index 36f8b58..dd7b22e 100644
--- a/include/git2/sys/repository.h
+++ b/include/git2/sys/repository.h
@@ -119,6 +119,19 @@ GIT_EXTERN(void) git_repository_set_refdb(git_repository *repo, git_refdb *refdb
  */
 GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
 
+/**
+ * Set a repository to be bare.
+ *
+ * Clear the working directory and set core.bare to true.  You may also
+ * want to call `git_repository_set_index(repo, NULL)` since a bare repo
+ * typically does not have an index, but this function will not do that
+ * for you.
+ *
+ * @param repo Repo to make bare
+ * @return 0 on success, <0 on failure
+ */
+GIT_EXTERN(int) git_repository_set_bare(git_repository *repo);
+
 /** @} */
 GIT_END_DECL
 #endif
diff --git a/src/attr.c b/src/attr.c
index 05b0c1b..1decb5b 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -426,6 +426,8 @@ static int collect_attr_files(
 		error = git_path_dirname_r(&dir, path);
 	if (error < 0)
 		goto cleanup;
+	if (dir.size == 1 && dir.ptr[0] == '.')
+		git_buf_clear(&dir);
 
 	/* in precendence order highest to lowest:
 	 * - $GIT_DIR/info/attributes
diff --git a/src/repository.c b/src/repository.c
index d86d890..39a4f02 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1681,6 +1681,32 @@ int git_repository_is_bare(git_repository *repo)
 	return repo->is_bare;
 }
 
+int git_repository_set_bare(git_repository *repo)
+{
+	int error;
+	git_config *config;
+
+	assert(repo);
+
+	if (repo->is_bare)
+		return 0;
+
+	if ((error = git_repository_config__weakptr(&config, repo)) < 0 ||
+		(error = git_config_set_bool(config, "core.bare", false)) < 0)
+		goto done;
+
+	error = git_config__update_entry(config, "core.worktree", NULL, true, true);
+
+	git__free(repo->workdir);
+	repo->workdir = NULL;
+
+	repo->is_bare = 1;
+
+done:
+	git_config_free(config);
+	return error;
+}
+
 int git_repository_head_tree(git_tree **tree, git_repository *repo)
 {
 	git_reference *head;
diff --git a/tests/attr/repo.c b/tests/attr/repo.c
index 5e812a7..e8b74c0 100644
--- a/tests/attr/repo.c
+++ b/tests/attr/repo.c
@@ -4,6 +4,7 @@
 #include "attr.h"
 
 #include "attr_expect.h"
+#include "git2/sys/repository.h"
 
 static git_repository *g_repo = NULL;
 
@@ -333,3 +334,38 @@ void test_attr_repo__staging_properly_normalizes_line_endings_according_to_gitat
 
 	git_index_free(index);
 }
+
+void test_attr_repo__bare_repo_with_index(void)
+{
+	const char *names[4] = { "test1", "test2", "test3", "test4" };
+	const char *values[4];
+	git_index *index;
+
+	cl_git_pass(git_repository_index(&index, g_repo));
+
+	cl_git_mkfile(
+		"attr/.gitattributes",
+		"*.txt test1 test2=foobar -test3\n"
+		"trial.txt -test1 test2=barfoo !test3 test4\n");
+	cl_git_pass(git_index_add_bypath(index, ".gitattributes"));
+	git_index_free(index);
+
+	cl_must_pass(p_unlink("attr/.gitattributes"));
+	cl_assert(!git_path_exists("attr/.gitattributes"));
+
+	cl_git_pass(git_repository_set_bare(g_repo));
+
+	cl_git_pass(git_attr_get_many(values, g_repo, 0, "file.txt", 4, names));
+
+	cl_assert(GIT_ATTR_TRUE(values[0]));
+	cl_assert_equal_s("foobar", values[1]);
+	cl_assert(GIT_ATTR_FALSE(values[2]));
+	cl_assert(GIT_ATTR_UNSPECIFIED(values[3]));
+
+	cl_git_pass(git_attr_get_many(values, g_repo, 0, "trial.txt", 4, names));
+
+	cl_assert(GIT_ATTR_FALSE(values[0]));
+	cl_assert_equal_s("barfoo", values[1]);
+	cl_assert(GIT_ATTR_UNSPECIFIED(values[2]));
+	cl_assert(GIT_ATTR_TRUE(values[3]));
+}