mirror of
https://git.proxmox.com/git/libgit2
synced 2025-10-19 09:26:43 +00:00
commit
4728b55ac6
11
src/attr.c
11
src/attr.c
@ -403,9 +403,14 @@ int git_attr_cache__push_file(
|
|||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file &&
|
/* if we got here, we have to parse and/or reparse the file */
|
||||||
(error = git_attr_file__new(&file, source, relfile, &cache->pool)) < 0)
|
if (file)
|
||||||
goto finish;
|
git_attr_file__clear_rules(file);
|
||||||
|
else {
|
||||||
|
error = git_attr_file__new(&file, source, relfile, &cache->pool);
|
||||||
|
if (error < 0)
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
if (parse && (error = parse(repo, content, file)) < 0)
|
if (parse && (error = parse(repo, content, file)) < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
@ -139,18 +139,23 @@ int git_attr_file__new_and_load(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_attr_file__free(git_attr_file *file)
|
void git_attr_file__clear_rules(git_attr_file *file)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
git_attr_rule *rule;
|
git_attr_rule *rule;
|
||||||
|
|
||||||
if (!file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
git_vector_foreach(&file->rules, i, rule)
|
git_vector_foreach(&file->rules, i, rule)
|
||||||
git_attr_rule__free(rule);
|
git_attr_rule__free(rule);
|
||||||
|
|
||||||
git_vector_free(&file->rules);
|
git_vector_free(&file->rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
void git_attr_file__free(git_attr_file *file)
|
||||||
|
{
|
||||||
|
if (!file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
git_attr_file__clear_rules(file);
|
||||||
|
|
||||||
if (file->pool_is_allocated) {
|
if (file->pool_is_allocated) {
|
||||||
git_pool_clear(file->pool);
|
git_pool_clear(file->pool);
|
||||||
@ -338,10 +343,13 @@ int git_attr_fnmatch__parse(
|
|||||||
const char **base)
|
const char **base)
|
||||||
{
|
{
|
||||||
const char *pattern, *scan;
|
const char *pattern, *scan;
|
||||||
int slash_count;
|
int slash_count, allow_space;
|
||||||
|
|
||||||
assert(spec && base && *base);
|
assert(spec && base && *base);
|
||||||
|
|
||||||
|
spec->flags = (spec->flags & GIT_ATTR_FNMATCH_ALLOWSPACE);
|
||||||
|
allow_space = (spec->flags != 0);
|
||||||
|
|
||||||
pattern = *base;
|
pattern = *base;
|
||||||
|
|
||||||
while (git__isspace(*pattern)) pattern++;
|
while (git__isspace(*pattern)) pattern++;
|
||||||
@ -350,8 +358,6 @@ int git_attr_fnmatch__parse(
|
|||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
spec->flags = 0;
|
|
||||||
|
|
||||||
if (*pattern == '[') {
|
if (*pattern == '[') {
|
||||||
if (strncmp(pattern, "[attr]", 6) == 0) {
|
if (strncmp(pattern, "[attr]", 6) == 0) {
|
||||||
spec->flags = spec->flags | GIT_ATTR_FNMATCH_MACRO;
|
spec->flags = spec->flags | GIT_ATTR_FNMATCH_MACRO;
|
||||||
@ -368,8 +374,10 @@ int git_attr_fnmatch__parse(
|
|||||||
slash_count = 0;
|
slash_count = 0;
|
||||||
for (scan = pattern; *scan != '\0'; ++scan) {
|
for (scan = pattern; *scan != '\0'; ++scan) {
|
||||||
/* scan until (non-escaped) white space */
|
/* scan until (non-escaped) white space */
|
||||||
if (git__isspace(*scan) && *(scan - 1) != '\\')
|
if (git__isspace(*scan) && *(scan - 1) != '\\') {
|
||||||
break;
|
if (!allow_space || (*scan != ' ' && *scan != '\t'))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (*scan == '/') {
|
if (*scan == '/') {
|
||||||
spec->flags = spec->flags | GIT_ATTR_FNMATCH_FULLPATH;
|
spec->flags = spec->flags | GIT_ATTR_FNMATCH_FULLPATH;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#define GIT_ATTR_FNMATCH_MACRO (1U << 3)
|
#define GIT_ATTR_FNMATCH_MACRO (1U << 3)
|
||||||
#define GIT_ATTR_FNMATCH_IGNORE (1U << 4)
|
#define GIT_ATTR_FNMATCH_IGNORE (1U << 4)
|
||||||
#define GIT_ATTR_FNMATCH_HASWILD (1U << 5)
|
#define GIT_ATTR_FNMATCH_HASWILD (1U << 5)
|
||||||
|
#define GIT_ATTR_FNMATCH_ALLOWSPACE (1U << 6)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *pattern;
|
char *pattern;
|
||||||
@ -88,6 +89,8 @@ extern int git_attr_file__new_and_load(
|
|||||||
|
|
||||||
extern void git_attr_file__free(git_attr_file *file);
|
extern void git_attr_file__free(git_attr_file *file);
|
||||||
|
|
||||||
|
extern void git_attr_file__clear_rules(git_attr_file *file);
|
||||||
|
|
||||||
extern int git_attr_file__parse_buffer(
|
extern int git_attr_file__parse_buffer(
|
||||||
git_repository *repo, const char *buf, git_attr_file *file);
|
git_repository *repo, const char *buf, git_attr_file *file);
|
||||||
|
|
||||||
|
@ -342,6 +342,7 @@ static git_diff_list *git_diff_list_alloc(
|
|||||||
git_attr_fnmatch *match = git__calloc(1, sizeof(git_attr_fnmatch));
|
git_attr_fnmatch *match = git__calloc(1, sizeof(git_attr_fnmatch));
|
||||||
if (!match)
|
if (!match)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE;
|
||||||
ret = git_attr_fnmatch__parse(match, &diff->pool, NULL, &pattern);
|
ret = git_attr_fnmatch__parse(match, &diff->pool, NULL, &pattern);
|
||||||
if (ret == GIT_ENOTFOUND) {
|
if (ret == GIT_ENOTFOUND) {
|
||||||
git__free(match);
|
git__free(match);
|
||||||
|
@ -18,19 +18,20 @@ struct attr_expected {
|
|||||||
GIT_INLINE(void) attr_check_expected(
|
GIT_INLINE(void) attr_check_expected(
|
||||||
enum attr_expect_t expected,
|
enum attr_expect_t expected,
|
||||||
const char *expected_str,
|
const char *expected_str,
|
||||||
|
const char *name,
|
||||||
const char *value)
|
const char *value)
|
||||||
{
|
{
|
||||||
switch (expected) {
|
switch (expected) {
|
||||||
case EXPECT_TRUE:
|
case EXPECT_TRUE:
|
||||||
cl_assert(GIT_ATTR_TRUE(value));
|
cl_assert_(GIT_ATTR_TRUE(value), name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXPECT_FALSE:
|
case EXPECT_FALSE:
|
||||||
cl_assert(GIT_ATTR_FALSE(value));
|
cl_assert_(GIT_ATTR_FALSE(value), name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXPECT_UNDEFINED:
|
case EXPECT_UNDEFINED:
|
||||||
cl_assert(GIT_ATTR_UNSPECIFIED(value));
|
cl_assert_(GIT_ATTR_UNSPECIFIED(value), name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXPECT_STRING:
|
case EXPECT_STRING:
|
||||||
|
@ -114,7 +114,7 @@ static void check_one_assign(
|
|||||||
cl_assert_equal_s(name, assign->name);
|
cl_assert_equal_s(name, assign->name);
|
||||||
cl_assert(assign->name_hash == git_attr_file__name_hash(assign->name));
|
cl_assert(assign->name_hash == git_attr_file__name_hash(assign->name));
|
||||||
|
|
||||||
attr_check_expected(expected, expected_str, assign->value);
|
attr_check_expected(expected, expected_str, assign->name, assign->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_attr_file__assign_variants(void)
|
void test_attr_file__assign_variants(void)
|
||||||
|
@ -44,7 +44,7 @@ static void run_test_cases(git_attr_file *file, struct attr_expected *cases, int
|
|||||||
error = git_attr_file__lookup_one(file,&path,c->attr,&value);
|
error = git_attr_file__lookup_one(file,&path,c->attr,&value);
|
||||||
cl_git_pass(error);
|
cl_git_pass(error);
|
||||||
|
|
||||||
attr_check_expected(c->expected, c->expected_str, value);
|
attr_check_expected(c->expected, c->expected_str, c->attr, value);
|
||||||
|
|
||||||
git_attr_path__free(&path);
|
git_attr_path__free(&path);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ void test_attr_repo__get_one(void)
|
|||||||
for (scan = test_cases; scan->path != NULL; scan++) {
|
for (scan = test_cases; scan->path != NULL; scan++) {
|
||||||
const char *value;
|
const char *value;
|
||||||
cl_git_pass(git_attr_get(&value, g_repo, 0, scan->path, scan->attr));
|
cl_git_pass(git_attr_get(&value, g_repo, 0, scan->path, scan->attr));
|
||||||
attr_check_expected(scan->expected, scan->expected_str, value);
|
attr_check_expected(scan->expected, scan->expected_str, scan->attr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/attributes"));
|
cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/attributes"));
|
||||||
|
@ -52,8 +52,11 @@ static int cl_setenv(const char *name, const char *value)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *env_home = NULL;
|
#ifdef GIT_WIN32
|
||||||
static char *env_userprofile = NULL;
|
static char *env_userprofile = NULL;
|
||||||
|
#else
|
||||||
|
static char *env_home = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
void test_core_env__initialize(void)
|
void test_core_env__initialize(void)
|
||||||
{
|
{
|
||||||
|
@ -516,3 +516,68 @@ void test_status_worktree__status_file_with_clean_index_and_empty_workdir(void)
|
|||||||
cl_git_pass(p_rmdir("wd"));
|
cl_git_pass(p_rmdir("wd"));
|
||||||
cl_git_pass(p_unlink("my-index"));
|
cl_git_pass(p_unlink("my-index"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void test_status_worktree__space_in_filename(void)
|
||||||
|
{
|
||||||
|
git_repository *repo;
|
||||||
|
git_index *index;
|
||||||
|
status_entry_single result;
|
||||||
|
unsigned int status_flags;
|
||||||
|
|
||||||
|
#define FILE_WITH_SPACE "LICENSE - copy.md"
|
||||||
|
|
||||||
|
cl_git_pass(git_repository_init(&repo, "with_space", 0));
|
||||||
|
cl_git_mkfile("with_space/" FILE_WITH_SPACE, "I have a space in my name\n");
|
||||||
|
|
||||||
|
/* file is new to working directory */
|
||||||
|
|
||||||
|
memset(&result, 0, sizeof(result));
|
||||||
|
cl_git_pass(git_status_foreach(repo, cb_status__single, &result));
|
||||||
|
cl_assert_equal_i(1, result.count);
|
||||||
|
cl_assert(result.status == GIT_STATUS_WT_NEW);
|
||||||
|
|
||||||
|
cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE));
|
||||||
|
cl_assert(status_flags == GIT_STATUS_WT_NEW);
|
||||||
|
|
||||||
|
/* ignore the file */
|
||||||
|
|
||||||
|
cl_git_rewritefile("with_space/.gitignore", "*.md\n.gitignore\n");
|
||||||
|
|
||||||
|
memset(&result, 0, sizeof(result));
|
||||||
|
cl_git_pass(git_status_foreach(repo, cb_status__single, &result));
|
||||||
|
cl_assert_equal_i(2, result.count);
|
||||||
|
cl_assert(result.status == GIT_STATUS_IGNORED);
|
||||||
|
|
||||||
|
cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE));
|
||||||
|
cl_assert(status_flags == GIT_STATUS_IGNORED);
|
||||||
|
|
||||||
|
/* don't ignore the file */
|
||||||
|
|
||||||
|
cl_git_rewritefile("with_space/.gitignore", ".gitignore\n");
|
||||||
|
|
||||||
|
memset(&result, 0, sizeof(result));
|
||||||
|
cl_git_pass(git_status_foreach(repo, cb_status__single, &result));
|
||||||
|
cl_assert_equal_i(2, result.count);
|
||||||
|
cl_assert(result.status == GIT_STATUS_WT_NEW);
|
||||||
|
|
||||||
|
cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE));
|
||||||
|
cl_assert(status_flags == GIT_STATUS_WT_NEW);
|
||||||
|
|
||||||
|
/* add the file to the index */
|
||||||
|
|
||||||
|
cl_git_pass(git_repository_index(&index, repo));
|
||||||
|
cl_git_pass(git_index_add(index, FILE_WITH_SPACE, 0));
|
||||||
|
cl_git_pass(git_index_write(index));
|
||||||
|
|
||||||
|
memset(&result, 0, sizeof(result));
|
||||||
|
cl_git_pass(git_status_foreach(repo, cb_status__single, &result));
|
||||||
|
cl_assert_equal_i(2, result.count);
|
||||||
|
cl_assert(result.status == GIT_STATUS_INDEX_NEW);
|
||||||
|
|
||||||
|
cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE));
|
||||||
|
cl_assert(status_flags == GIT_STATUS_INDEX_NEW);
|
||||||
|
|
||||||
|
git_index_free(index);
|
||||||
|
git_repository_free(repo);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user