mirror of
https://git.proxmox.com/git/libgit2
synced 2025-07-09 20:47:48 +00:00
Fix attribute lookup in index for bare repos
When using a bare repo with an index, libgit2 attempts to read files from the index. It caches those files based on the path to the file, specifically the path to the directory that contains the file. If there is no working directory, we use `git_path_dirname_r` to get the path to the containing directory. However, for the `.gitattributes` file in the root of the repository, this ends up normalizing the containing path to `"."` instead of the empty string and the lookup the `.gitattributes` data fails. This adds a test of attribute lookups on bare repos and also fixes the problem by simply rewriting `"."` to be `""`.
This commit is contained in:
parent
910cd2daa6
commit
1fbeb2f04c
@ -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);
|
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
|
GIT_END_DECL
|
||||||
#endif
|
#endif
|
||||||
|
@ -426,6 +426,8 @@ static int collect_attr_files(
|
|||||||
error = git_path_dirname_r(&dir, path);
|
error = git_path_dirname_r(&dir, path);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
if (dir.size == 1 && dir.ptr[0] == '.')
|
||||||
|
git_buf_clear(&dir);
|
||||||
|
|
||||||
/* in precendence order highest to lowest:
|
/* in precendence order highest to lowest:
|
||||||
* - $GIT_DIR/info/attributes
|
* - $GIT_DIR/info/attributes
|
||||||
|
@ -1681,6 +1681,32 @@ int git_repository_is_bare(git_repository *repo)
|
|||||||
return repo->is_bare;
|
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)
|
int git_repository_head_tree(git_tree **tree, git_repository *repo)
|
||||||
{
|
{
|
||||||
git_reference *head;
|
git_reference *head;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "attr.h"
|
#include "attr.h"
|
||||||
|
|
||||||
#include "attr_expect.h"
|
#include "attr_expect.h"
|
||||||
|
#include "git2/sys/repository.h"
|
||||||
|
|
||||||
static git_repository *g_repo = NULL;
|
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);
|
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]));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user