Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
7b0f8ba9
Commit
7b0f8ba9
authored
Apr 19, 2014
by
Vicent Marti
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2279 from libgit2/rb/moar-eegnöre-fîxés
Fix several ignore and attribute file behavior bugs
parents
386777fd
ac16bd0a
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
325 additions
and
229 deletions
+325
-229
src/attr.c
+71
-3
src/attr_file.c
+11
-3
src/attr_file.h
+4
-2
src/ignore.c
+8
-5
src/ignore.h
+1
-0
src/path.c
+1
-1
src/pathspec.c
+2
-1
tests/attr/ignore.c
+1
-1
tests/attr/repo.c
+64
-39
tests/status/ignore.c
+159
-164
tests/status/status_helpers.c
+3
-10
No files found.
src/attr.c
View file @
7b0f8ba9
...
...
@@ -217,6 +217,74 @@ cleanup:
return
error
;
}
static
int
preload_attr_file
(
git_repository
*
repo
,
git_attr_file_source
source
,
const
char
*
base
,
const
char
*
file
)
{
int
error
;
git_attr_file
*
preload
=
NULL
;
if
(
!
file
)
return
0
;
if
(
!
(
error
=
git_attr_cache__get
(
&
preload
,
repo
,
source
,
base
,
file
,
git_attr_file__parse_buffer
)))
git_attr_file__free
(
preload
);
return
error
;
}
static
int
attr_setup
(
git_repository
*
repo
)
{
int
error
=
0
;
const
char
*
workdir
=
git_repository_workdir
(
repo
);
git_index
*
idx
=
NULL
;
git_buf
sys
=
GIT_BUF_INIT
;
if
((
error
=
git_attr_cache__init
(
repo
))
<
0
)
return
error
;
/* preload attribute files that could contain macros so the
* definitions will be available for later file parsing
*/
if
(
!
(
error
=
git_sysdir_find_system_file
(
&
sys
,
GIT_ATTR_FILE_SYSTEM
)))
{
error
=
preload_attr_file
(
repo
,
GIT_ATTR_FILE__FROM_FILE
,
NULL
,
sys
.
ptr
);
git_buf_free
(
&
sys
);
}
if
(
error
<
0
)
{
if
(
error
==
GIT_ENOTFOUND
)
{
giterr_clear
();
error
=
0
;
}
else
return
error
;
}
if
((
error
=
preload_attr_file
(
repo
,
GIT_ATTR_FILE__FROM_FILE
,
NULL
,
git_repository_attr_cache
(
repo
)
->
cfg_attr_file
))
<
0
)
return
error
;
if
((
error
=
preload_attr_file
(
repo
,
GIT_ATTR_FILE__FROM_FILE
,
git_repository_path
(
repo
),
GIT_ATTR_FILE_INREPO
))
<
0
)
return
error
;
if
(
workdir
!=
NULL
&&
(
error
=
preload_attr_file
(
repo
,
GIT_ATTR_FILE__FROM_FILE
,
workdir
,
GIT_ATTR_FILE
))
<
0
)
return
error
;
if
((
error
=
git_repository_index__weakptr
(
&
idx
,
repo
))
<
0
||
(
error
=
preload_attr_file
(
repo
,
GIT_ATTR_FILE__FROM_INDEX
,
NULL
,
GIT_ATTR_FILE
))
<
0
)
return
error
;
return
error
;
}
int
git_attr_add_macro
(
git_repository
*
repo
,
const
char
*
name
,
...
...
@@ -226,8 +294,8 @@ int git_attr_add_macro(
git_attr_rule
*
macro
=
NULL
;
git_pool
*
pool
;
if
(
git_attr_cache__init
(
repo
)
<
0
)
return
-
1
;
if
(
(
error
=
git_attr_cache__init
(
repo
)
)
<
0
)
return
error
;
macro
=
git__calloc
(
1
,
sizeof
(
git_attr_rule
));
GITERR_CHECK_ALLOC
(
macro
);
...
...
@@ -348,7 +416,7 @@ static int collect_attr_files(
const
char
*
workdir
=
git_repository_workdir
(
repo
);
attr_walk_up_info
info
=
{
NULL
};
if
((
error
=
git_attr_cache__init
(
repo
))
<
0
)
if
((
error
=
attr_setup
(
repo
))
<
0
)
return
error
;
/* Resolve path in a non-bare repo */
...
...
src/attr_file.c
View file @
7b0f8ba9
...
...
@@ -248,9 +248,7 @@ int git_attr_file__parse_buffer(
repo
,
&
attrs
->
pool
,
&
rule
->
assigns
,
&
scan
)))
{
if
(
rule
->
match
.
flags
&
GIT_ATTR_FNMATCH_MACRO
)
/* should generate error/warning if this is coming from any
* file other than .gitattributes at repo root.
*/
/* TODO: warning if macro found in file below repo root */
error
=
git_attr_cache__insert_macro
(
repo
,
rule
);
else
error
=
git_vector_insert
(
&
attrs
->
rules
,
rule
);
...
...
@@ -355,6 +353,8 @@ bool git_attr_fnmatch__match(
if
(
match
->
flags
&
GIT_ATTR_FNMATCH_ICASE
)
flags
|=
FNM_CASEFOLD
;
if
(
match
->
flags
&
GIT_ATTR_FNMATCH_LEADINGDIR
)
flags
|=
FNM_LEADING_DIR
;
if
(
match
->
flags
&
GIT_ATTR_FNMATCH_FULLPATH
)
{
filename
=
path
->
path
;
...
...
@@ -545,6 +545,14 @@ int git_attr_fnmatch__parse(
if
(
--
slash_count
<=
0
)
spec
->
flags
=
spec
->
flags
&
~
GIT_ATTR_FNMATCH_FULLPATH
;
}
if
((
spec
->
flags
&
GIT_ATTR_FNMATCH_NOLEADINGDIR
)
==
0
&&
spec
->
length
>=
2
&&
pattern
[
spec
->
length
-
1
]
==
'*'
&&
pattern
[
spec
->
length
-
2
]
==
'/'
)
{
spec
->
length
-=
2
;
spec
->
flags
=
spec
->
flags
|
GIT_ATTR_FNMATCH_LEADINGDIR
;
/* leave FULLPATH match on, however */
}
if
((
spec
->
flags
&
GIT_ATTR_FNMATCH_FULLPATH
)
!=
0
&&
context
!=
NULL
&&
git_path_root
(
pattern
)
<
0
)
...
...
src/attr_file.h
View file @
7b0f8ba9
...
...
@@ -30,10 +30,12 @@
#define GIT_ATTR_FNMATCH_MATCH_ALL (1U << 8)
#define GIT_ATTR_FNMATCH_ALLOWNEG (1U << 9)
#define GIT_ATTR_FNMATCH_ALLOWMACRO (1U << 10)
#define GIT_ATTR_FNMATCH_LEADINGDIR (1U << 11)
#define GIT_ATTR_FNMATCH_NOLEADINGDIR (1U << 12)
#define GIT_ATTR_FNMATCH__INCOMING \
(GIT_ATTR_FNMATCH_ALLOWSPACE | \
GIT_ATTR_FNMATCH_ALLOW
NEG | GIT_ATTR_FNMATCH_ALLOWMACRO
)
(GIT_ATTR_FNMATCH_ALLOWSPACE |
GIT_ATTR_FNMATCH_ALLOWNEG |
\
GIT_ATTR_FNMATCH_ALLOW
MACRO | GIT_ATTR_FNMATCH_NOLEADINGDIR
)
typedef
enum
{
GIT_ATTR_FILE__IN_MEMORY
=
0
,
...
...
src/ignore.c
View file @
7b0f8ba9
...
...
@@ -123,7 +123,7 @@ int git_ignore__for_path(
int
error
=
0
;
const
char
*
workdir
=
git_repository_workdir
(
repo
);
assert
(
ignores
);
assert
(
ignores
&&
path
);
memset
(
ignores
,
0
,
sizeof
(
*
ignores
));
ignores
->
repo
=
repo
;
...
...
@@ -140,10 +140,13 @@ int git_ignore__for_path(
if
(
workdir
&&
git_path_root
(
path
)
<
0
)
error
=
git_path_find_dir
(
&
ignores
->
dir
,
path
,
workdir
);
else
error
=
git_buf_
sets
(
&
ignores
->
dir
,
path
);
error
=
git_buf_
joinpath
(
&
ignores
->
dir
,
path
,
""
);
if
(
error
<
0
)
goto
cleanup
;
if
(
workdir
&&
!
git__prefixcmp
(
ignores
->
dir
.
ptr
,
workdir
))
ignores
->
dir_root
=
strlen
(
workdir
);
/* set up internals */
if
((
error
=
get_internal_ignores
(
&
ignores
->
ign_internal
,
repo
))
<
0
)
goto
cleanup
;
...
...
@@ -204,10 +207,10 @@ int git_ignore__pop_dir(git_ignores *ign)
if
((
end
=
strrchr
(
start
,
'/'
))
!=
NULL
)
{
size_t
dirlen
=
(
end
-
start
)
+
1
;
const
char
*
relpath
=
ign
->
dir
.
ptr
+
ign
->
dir_root
;
size_t
pathlen
=
ign
->
dir
.
size
-
ign
->
dir_root
;
if
(
ign
->
dir
.
size
>=
dirlen
&&
!
memcmp
(
ign
->
dir
.
ptr
+
ign
->
dir
.
size
-
dirlen
,
start
,
dirlen
))
{
if
(
pathlen
==
dirlen
&&
!
memcmp
(
relpath
,
start
,
dirlen
))
{
git_vector_pop
(
&
ign
->
ign_path
);
git_attr_file__free
(
file
);
}
...
...
src/ignore.h
View file @
7b0f8ba9
...
...
@@ -28,6 +28,7 @@ typedef struct {
git_attr_file
*
ign_internal
;
git_vector
ign_path
;
git_vector
ign_global
;
size_t
dir_root
;
/* offset in dir to repo root */
int
ignore_case
;
int
depth
;
}
git_ignores
;
...
...
src/path.c
View file @
7b0f8ba9
...
...
@@ -624,7 +624,7 @@ int git_path_find_dir(git_buf *dir, const char *path, const char *base)
/* call dirname if this is not a directory */
if
(
!
error
)
/* && git_path_isdir(dir->ptr) == false) */
error
=
git_path_dirname_r
(
dir
,
dir
->
ptr
)
;
error
=
(
git_path_dirname_r
(
dir
,
dir
->
ptr
)
<
0
)
?
-
1
:
0
;
if
(
!
error
)
error
=
git_path_to_dir
(
dir
);
...
...
src/pathspec.c
View file @
7b0f8ba9
...
...
@@ -83,7 +83,8 @@ int git_pathspec__vinit(
if
(
!
match
)
return
-
1
;
match
->
flags
=
GIT_ATTR_FNMATCH_ALLOWSPACE
|
GIT_ATTR_FNMATCH_ALLOWNEG
;
match
->
flags
=
GIT_ATTR_FNMATCH_ALLOWSPACE
|
GIT_ATTR_FNMATCH_ALLOWNEG
|
GIT_ATTR_FNMATCH_NOLEADINGDIR
;
ret
=
git_attr_fnmatch__parse
(
match
,
strpool
,
NULL
,
&
pattern
);
if
(
ret
==
GIT_ENOTFOUND
)
{
...
...
tests/attr/ignore.c
View file @
7b0f8ba9
...
...
@@ -16,7 +16,7 @@ void test_attr_ignore__cleanup(void)
g_repo
=
NULL
;
}
void
assert_is_ignored_
(
static
void
assert_is_ignored_
(
bool
expected
,
const
char
*
filepath
,
const
char
*
file
,
int
line
)
{
int
is_ignored
=
0
;
...
...
tests/attr/repo.c
View file @
7b0f8ba9
...
...
@@ -23,49 +23,74 @@ void test_attr_repo__cleanup(void)
g_repo
=
NULL
;
}
static
struct
attr_expected
get_one_test_cases
[]
=
{
{
"root_test1"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"root_test1"
,
"rootattr"
,
EXPECT_TRUE
,
NULL
},
{
"root_test1"
,
"missingattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test1"
,
"subattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test1"
,
"negattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test2"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"root_test2"
,
"rootattr"
,
EXPECT_FALSE
,
NULL
},
{
"root_test2"
,
"missingattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test2"
,
"multiattr"
,
EXPECT_FALSE
,
NULL
},
{
"root_test3"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"root_test3"
,
"rootattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test3"
,
"multiattr"
,
EXPECT_STRING
,
"3"
},
{
"root_test3"
,
"multi2"
,
EXPECT_UNDEFINED
,
NULL
},
{
"sub/subdir_test1"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"sub/subdir_test1"
,
"rootattr"
,
EXPECT_TRUE
,
NULL
},
{
"sub/subdir_test1"
,
"missingattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"sub/subdir_test1"
,
"subattr"
,
EXPECT_STRING
,
"yes"
},
{
"sub/subdir_test1"
,
"negattr"
,
EXPECT_FALSE
,
NULL
},
{
"sub/subdir_test1"
,
"another"
,
EXPECT_UNDEFINED
,
NULL
},
{
"sub/subdir_test2.txt"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"sub/subdir_test2.txt"
,
"rootattr"
,
EXPECT_TRUE
,
NULL
},
{
"sub/subdir_test2.txt"
,
"missingattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"sub/subdir_test2.txt"
,
"subattr"
,
EXPECT_STRING
,
"yes"
},
{
"sub/subdir_test2.txt"
,
"negattr"
,
EXPECT_FALSE
,
NULL
},
{
"sub/subdir_test2.txt"
,
"another"
,
EXPECT_STRING
,
"zero"
},
{
"sub/subdir_test2.txt"
,
"reposub"
,
EXPECT_TRUE
,
NULL
},
{
"sub/sub/subdir.txt"
,
"another"
,
EXPECT_STRING
,
"one"
},
{
"sub/sub/subdir.txt"
,
"reposubsub"
,
EXPECT_TRUE
,
NULL
},
{
"sub/sub/subdir.txt"
,
"reposub"
,
EXPECT_UNDEFINED
,
NULL
},
{
"does-not-exist"
,
"foo"
,
EXPECT_STRING
,
"yes"
},
{
"sub/deep/file"
,
"deepdeep"
,
EXPECT_TRUE
,
NULL
},
{
"sub/sub/d/no"
,
"test"
,
EXPECT_STRING
,
"a/b/d/*"
},
{
"sub/sub/d/yes"
,
"test"
,
EXPECT_UNDEFINED
,
NULL
},
};
void
test_attr_repo__get_one
(
void
)
{
struct
attr_expected
test_cases
[]
=
{
{
"root_test1"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"root_test1"
,
"rootattr"
,
EXPECT_TRUE
,
NULL
},
{
"root_test1"
,
"missingattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test1"
,
"subattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test1"
,
"negattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test2"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"root_test2"
,
"rootattr"
,
EXPECT_FALSE
,
NULL
},
{
"root_test2"
,
"missingattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test2"
,
"multiattr"
,
EXPECT_FALSE
,
NULL
},
{
"root_test3"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"root_test3"
,
"rootattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"root_test3"
,
"multiattr"
,
EXPECT_STRING
,
"3"
},
{
"root_test3"
,
"multi2"
,
EXPECT_UNDEFINED
,
NULL
},
{
"sub/subdir_test1"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"sub/subdir_test1"
,
"rootattr"
,
EXPECT_TRUE
,
NULL
},
{
"sub/subdir_test1"
,
"missingattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"sub/subdir_test1"
,
"subattr"
,
EXPECT_STRING
,
"yes"
},
{
"sub/subdir_test1"
,
"negattr"
,
EXPECT_FALSE
,
NULL
},
{
"sub/subdir_test1"
,
"another"
,
EXPECT_UNDEFINED
,
NULL
},
{
"sub/subdir_test2.txt"
,
"repoattr"
,
EXPECT_TRUE
,
NULL
},
{
"sub/subdir_test2.txt"
,
"rootattr"
,
EXPECT_TRUE
,
NULL
},
{
"sub/subdir_test2.txt"
,
"missingattr"
,
EXPECT_UNDEFINED
,
NULL
},
{
"sub/subdir_test2.txt"
,
"subattr"
,
EXPECT_STRING
,
"yes"
},
{
"sub/subdir_test2.txt"
,
"negattr"
,
EXPECT_FALSE
,
NULL
},
{
"sub/subdir_test2.txt"
,
"another"
,
EXPECT_STRING
,
"zero"
},
{
"sub/subdir_test2.txt"
,
"reposub"
,
EXPECT_TRUE
,
NULL
},
{
"sub/sub/subdir.txt"
,
"another"
,
EXPECT_STRING
,
"one"
},
{
"sub/sub/subdir.txt"
,
"reposubsub"
,
EXPECT_TRUE
,
NULL
},
{
"sub/sub/subdir.txt"
,
"reposub"
,
EXPECT_UNDEFINED
,
NULL
},
{
"does-not-exist"
,
"foo"
,
EXPECT_STRING
,
"yes"
},
{
"sub/deep/file"
,
"deepdeep"
,
EXPECT_TRUE
,
NULL
},
{
"sub/sub/d/no"
,
"test"
,
EXPECT_STRING
,
"a/b/d/*"
},
{
"sub/sub/d/yes"
,
"test"
,
EXPECT_UNDEFINED
,
NULL
},
{
NULL
,
NULL
,
0
,
NULL
}
},
*
scan
;
for
(
scan
=
test_cases
;
scan
->
path
!=
NULL
;
scan
++
)
{
int
i
;
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
get_one_test_cases
);
++
i
)
{
struct
attr_expected
*
scan
=
&
get_one_test_cases
[
i
];
const
char
*
value
;
cl_git_pass
(
git_attr_get
(
&
value
,
g_repo
,
0
,
scan
->
path
,
scan
->
attr
));
attr_check_expected
(
scan
->
expected
,
scan
->
expected_str
,
scan
->
attr
,
value
);
}
cl_assert
(
git_attr_cache__is_cached
(
g_repo
,
GIT_ATTR_FILE__FROM_FILE
,
".git/info/attributes"
));
cl_assert
(
git_attr_cache__is_cached
(
g_repo
,
GIT_ATTR_FILE__FROM_FILE
,
".gitattributes"
));
cl_assert
(
git_attr_cache__is_cached
(
g_repo
,
GIT_ATTR_FILE__FROM_FILE
,
"sub/.gitattributes"
));
}
void
test_attr_repo__get_one_start_deep
(
void
)
{
int
i
;
for
(
i
=
(
int
)
ARRAY_SIZE
(
get_one_test_cases
)
-
1
;
i
>=
0
;
--
i
)
{
struct
attr_expected
*
scan
=
&
get_one_test_cases
[
i
];
const
char
*
value
;
cl_git_pass
(
git_attr_get
(
&
value
,
g_repo
,
0
,
scan
->
path
,
scan
->
attr
));
attr_check_expected
(
scan
->
expected
,
scan
->
expected_str
,
scan
->
attr
,
value
);
attr_check_expected
(
scan
->
expected
,
scan
->
expected_str
,
scan
->
attr
,
value
);
}
cl_assert
(
git_attr_cache__is_cached
(
...
...
tests/status/ignore.c
View file @
7b0f8ba9
...
...
@@ -16,6 +16,23 @@ void test_status_ignore__cleanup(void)
cl_git_sandbox_cleanup
();
}
static
void
assert_ignored_
(
bool
expected
,
const
char
*
filepath
,
const
char
*
file
,
int
line
)
{
int
is_ignored
=
0
;
cl_git_pass_
(
git_status_should_ignore
(
&
is_ignored
,
g_repo
,
filepath
),
file
,
line
);
clar__assert
(
(
expected
!=
0
)
==
(
is_ignored
!=
0
),
file
,
line
,
"expected != is_ignored"
,
filepath
,
1
);
}
#define assert_ignored(expected, filepath) \
assert_ignored_(expected, filepath, __FILE__, __LINE__)
#define assert_is_ignored(filepath) \
assert_ignored_(true, filepath, __FILE__, __LINE__)
#define refute_is_ignored(filepath) \
assert_ignored_(false, filepath, __FILE__, __LINE__)
void
test_status_ignore__0
(
void
)
{
struct
{
...
...
@@ -47,11 +64,8 @@ void test_status_ignore__0(void)
g_repo
=
cl_git_sandbox_init
(
"attr"
);
for
(
one_test
=
test_cases
;
one_test
->
path
!=
NULL
;
one_test
++
)
{
int
ignored
;
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
one_test
->
path
));
cl_assert_
(
ignored
==
one_test
->
expected
,
one_test
->
path
);
}
for
(
one_test
=
test_cases
;
one_test
->
path
!=
NULL
;
one_test
++
)
assert_ignored
(
one_test
->
expected
,
one_test
->
path
);
/* confirm that ignore files were cached */
cl_assert
(
git_attr_cache__is_cached
(
...
...
@@ -63,37 +77,22 @@ void test_status_ignore__0(void)
void
test_status_ignore__1
(
void
)
{
int
ignored
;
g_repo
=
cl_git_sandbox_init
(
"attr"
);
cl_git_rewritefile
(
"attr/.gitignore"
,
"/*.txt
\n
/dir/
\n
"
);
git_attr_cache_flush
(
g_repo
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"root_test4.txt"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"sub/subdir_test2.txt"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"dir"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"dir/"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"sub/dir"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"sub/dir/"
));
cl_assert
(
!
ignored
);
assert_is_ignored
(
"root_test4.txt"
);
refute_is_ignored
(
"sub/subdir_test2.txt"
);
assert_is_ignored
(
"dir"
);
assert_is_ignored
(
"dir/"
);
refute_is_ignored
(
"sub/dir"
);
refute_is_ignored
(
"sub/dir/"
);
}
void
test_status_ignore__empty_repo_with_gitignore_rewrite
(
void
)
{
status_entry_single
st
;
int
ignored
;
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
...
...
@@ -108,8 +107,7 @@ void test_status_ignore__empty_repo_with_gitignore_rewrite(void)
cl_git_pass
(
git_status_file
(
&
st
.
status
,
g_repo
,
"look-ma.txt"
));
cl_assert
(
st
.
status
==
GIT_STATUS_WT_NEW
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"look-ma.txt"
));
cl_assert
(
!
ignored
);
refute_is_ignored
(
"look-ma.txt"
);
cl_git_rewritefile
(
"empty_standard_repo/.gitignore"
,
"*.nomatch
\n
"
);
...
...
@@ -121,8 +119,7 @@ void test_status_ignore__empty_repo_with_gitignore_rewrite(void)
cl_git_pass
(
git_status_file
(
&
st
.
status
,
g_repo
,
"look-ma.txt"
));
cl_assert
(
st
.
status
==
GIT_STATUS_WT_NEW
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"look-ma.txt"
));
cl_assert
(
!
ignored
);
refute_is_ignored
(
"look-ma.txt"
);
cl_git_rewritefile
(
"empty_standard_repo/.gitignore"
,
"*.txt
\n
"
);
...
...
@@ -134,8 +131,7 @@ void test_status_ignore__empty_repo_with_gitignore_rewrite(void)
cl_git_pass
(
git_status_file
(
&
st
.
status
,
g_repo
,
"look-ma.txt"
));
cl_assert
(
st
.
status
==
GIT_STATUS_IGNORED
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"look-ma.txt"
));
cl_assert
(
ignored
);
assert_is_ignored
(
"look-ma.txt"
);
}
void
test_status_ignore__ignore_pattern_contains_space
(
void
)
...
...
@@ -181,7 +177,6 @@ void test_status_ignore__ignore_pattern_ignorecase(void)
void
test_status_ignore__subdirectories
(
void
)
{
status_entry_single
st
;
int
ignored
;
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
...
...
@@ -198,8 +193,7 @@ void test_status_ignore__subdirectories(void)
cl_git_pass
(
git_status_file
(
&
st
.
status
,
g_repo
,
"ignore_me"
));
cl_assert
(
st
.
status
==
GIT_STATUS_IGNORED
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"ignore_me"
));
cl_assert
(
ignored
);
assert_is_ignored
(
"ignore_me"
);
/* I've changed libgit2 so that the behavior here now differs from
* core git but seems to make more sense. In core git, the following
...
...
@@ -225,37 +219,37 @@ void test_status_ignore__subdirectories(void)
cl_git_pass
(
git_status_file
(
&
st
.
status
,
g_repo
,
"test/ignore_me/file"
));
cl_assert
(
st
.
status
==
GIT_STATUS_IGNORED
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"test/ignore_me/file"
));
cl_assert
(
ignored
);
assert_is_ignored
(
"test/ignore_me/file"
);
}
static
void
make_test_data
(
void
)
static
void
make_test_data
(
const
char
*
reponame
,
const
char
**
files
)
{
static
const
char
*
files
[]
=
{
"empty_standard_repo/dir/a/ignore_me"
,
"empty_standard_repo/dir/b/ignore_me"
,
"empty_standard_repo/dir/ignore_me"
,
"empty_standard_repo/ignore_also/file"
,
"empty_standard_repo/ignore_me"
,
"empty_standard_repo/test/ignore_me/file"
,
"empty_standard_repo/test/ignore_me/file2"
,
"empty_standard_repo/test/ignore_me/and_me/file"
,
NULL
};
static
const
char
*
repo
=
"empty_standard_repo"
;
const
char
**
scan
;
size_t
repolen
=
strlen
(
repo
)
+
1
;
size_t
repolen
=
strlen
(
repo
name
)
+
1
;
g_repo
=
cl_git_sandbox_init
(
repo
);
g_repo
=
cl_git_sandbox_init
(
repo
name
);
for
(
scan
=
files
;
*
scan
!=
NULL
;
++
scan
)
{
cl_git_pass
(
git_futils_mkdir
(
*
scan
+
repolen
,
repo
,
0777
,
GIT_MKDIR_PATH
|
GIT_MKDIR_SKIP_LAST
));
*
scan
+
repolen
,
reponame
,
0777
,
GIT_MKDIR_PATH
|
GIT_MKDIR_SKIP_LAST
));
cl_git_mkfile
(
*
scan
,
"contents"
);
}
}
static
const
char
*
test_repo_1
=
"empty_standard_repo"
;
static
const
char
*
test_files_1
[]
=
{
"empty_standard_repo/dir/a/ignore_me"
,
"empty_standard_repo/dir/b/ignore_me"
,
"empty_standard_repo/dir/ignore_me"
,
"empty_standard_repo/ignore_also/file"
,
"empty_standard_repo/ignore_me"
,
"empty_standard_repo/test/ignore_me/file"
,
"empty_standard_repo/test/ignore_me/file2"
,
"empty_standard_repo/test/ignore_me/and_me/file"
,
NULL
};
void
test_status_ignore__subdirectories_recursion
(
void
)
{
/* Let's try again with recursing into ignored dirs turned on */
...
...
@@ -292,7 +286,7 @@ void test_status_ignore__subdirectories_recursion(void)
GIT_STATUS_IGNORED
,
GIT_STATUS_IGNORED
,
GIT_STATUS_IGNORED
,
};
make_test_data
();
make_test_data
(
test_repo_1
,
test_files_1
);
cl_git_rewritefile
(
"empty_standard_repo/.gitignore"
,
"ignore_me
\n
/ignore_also
\n
"
);
memset
(
&
counts
,
0x0
,
sizeof
(
status_entry_counts
));
...
...
@@ -347,7 +341,7 @@ void test_status_ignore__subdirectories_not_at_root(void)
GIT_STATUS_WT_NEW
,
GIT_STATUS_IGNORED
,
GIT_STATUS_WT_NEW
,
GIT_STATUS_WT_NEW
,
};
make_test_data
();
make_test_data
(
test_repo_1
,
test_files_1
);
cl_git_rewritefile
(
"empty_standard_repo/dir/.gitignore"
,
"ignore_me
\n
/ignore_also
\n
"
);
cl_git_rewritefile
(
"empty_standard_repo/test/.gitignore"
,
"and_me
\n
"
);
...
...
@@ -389,7 +383,7 @@ void test_status_ignore__leading_slash_ignores(void)
GIT_STATUS_WT_NEW
,
GIT_STATUS_WT_NEW
,
GIT_STATUS_WT_NEW
,
GIT_STATUS_WT_NEW
,
};
make_test_data
();
make_test_data
(
test_repo_1
,
test_files_1
);
cl_fake_home
(
&
home
);
cl_git_mkfile
(
"home/.gitignore"
,
"/ignore_me
\n
"
);
...
...
@@ -422,151 +416,162 @@ void test_status_ignore__leading_slash_ignores(void)
cl_fake_home_cleanup
(
&
home
);
}
void
test_status_ignore__
adding_internal_ignores
(
void
)
void
test_status_ignore__
contained_dir_with_matching_name
(
void
)
{
int
ignored
;
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/subdir_match/aaa/subdir_match/file"
,
"empty_standard_repo/subdir_match/zzz_ignoreme"
,
NULL
};
static
const
char
*
expected_paths
[]
=
{
"subdir_match/.gitignore"
,
"subdir_match/aaa/subdir_match/file"
,
"subdir_match/zzz_ignoreme"
,
};
static
const
unsigned
int
expected_statuses
[]
=
{
GIT_STATUS_WT_NEW
,
GIT_STATUS_WT_NEW
,
GIT_STATUS_IGNORED
};
git_status_options
opts
=
GIT_STATUS_OPTIONS_INIT
;
status_entry_counts
counts
;
make_test_data
(
"empty_standard_repo"
,
test_files
);
cl_git_mkfile
(
"empty_standard_repo/subdir_match/.gitignore"
,
"*_ignoreme
\n
"
);
refute_is_ignored
(
"subdir_match/aaa/subdir_match/file"
);
assert_is_ignored
(
"subdir_match/zzz_ignoreme"
);
memset
(
&
counts
,
0x0
,
sizeof
(
status_entry_counts
));
counts
.
expected_entry_count
=
3
;
counts
.
expected_paths
=
expected_paths
;
counts
.
expected_statuses
=
expected_statuses
;
opts
.
flags
=
GIT_STATUS_OPT_DEFAULTS
|
GIT_STATUS_OPT_RECURSE_IGNORED_DIRS
;
cl_git_pass
(
git_status_foreach_ext
(
g_repo
,
&
opts
,
cb_status__normal
,
&
counts
));
cl_assert_equal_i
(
counts
.
expected_entry_count
,
counts
.
entry_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_status_flags_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_sorted_path
);
}
void
test_status_ignore__trailing_slash_star
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/file"
,
"empty_standard_repo/subdir/file"
,
"empty_standard_repo/subdir/sub2/sub3/file"
,
NULL
};
make_test_data
(
"empty_standard_repo"
,
test_files
);
cl_git_mkfile
(
"empty_standard_repo/subdir/.gitignore"
,
"/**/*
\n
"
);
refute_is_ignored
(
"file"
);
assert_is_ignored
(
"subdir/sub2/sub3/file"
);
assert_is_ignored
(
"subdir/file"
);
}
void
test_status_ignore__adding_internal_ignores
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"one.txt"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"two.bar"
));
cl_assert
(
!
ignored
);
refute_is_ignored
(
"one.txt"
);
refute_is_ignored
(
"two.bar"
);
cl_git_pass
(
git_ignore_add_rule
(
g_repo
,
"*.nomatch
\n
"
));
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"one.txt"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"two.bar"
));
cl_assert
(
!
ignored
);
refute_is_ignored
(
"one.txt"
);
refute_is_ignored
(
"two.bar"
);
cl_git_pass
(
git_ignore_add_rule
(
g_repo
,
"*.txt
\n
"
));
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"one.txt"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"two.bar"
));
cl_assert
(
!
ignored
);
assert_is_ignored
(
"one.txt"
);
refute_is_ignored
(
"two.bar"
);
cl_git_pass
(
git_ignore_add_rule
(
g_repo
,
"*.bar
\n
"
));
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"one.txt"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"two.bar"
));
cl_assert
(
ignored
);
assert_is_ignored
(
"one.txt"
);
assert_is_ignored
(
"two.bar"
);
cl_git_pass
(
git_ignore_clear_internal_rules
(
g_repo
));
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"one.txt"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"two.bar"
));
cl_assert
(
!
ignored
);
refute_is_ignored
(
"one.txt"
);
refute_is_ignored
(
"two.bar"
);
cl_git_pass
(
git_ignore_add_rule
(
g_repo
,
"multiple
\n
*.rules
\n
# comment line
\n
*.bar
\n
"
));
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"one.txt"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"two.bar"
));
cl_assert
(
ignored
);
refute_is_ignored
(
"one.txt"
);
assert_is_ignored
(
"two.bar"
);
}
void
test_status_ignore__add_internal_as_first_thing
(
void
)
{
int
ignored
;
const
char
*
add_me
=
"
\n
#################
\n
## Eclipse
\n
#################
\n\n
*.pydevproject
\n
.project
\n
.metadata
\n
bin/
\n
tmp/
\n
*.tmp
\n\n
"
;
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
cl_git_pass
(
git_ignore_add_rule
(
g_repo
,
add_me
));
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"one.tmp"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"two.bar"
));
cl_assert
(
!
ignored
);
assert_is_ignored
(
"one.tmp"
);
refute_is_ignored
(
"two.bar"
);
}
void
test_status_ignore__internal_ignores_inside_deep_paths
(
void
)
{
int
ignored
;
const
char
*
add_me
=
"Debug
\n
this/is/deep
\n
patterned*/dir
\n
"
;
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
cl_git_pass
(
git_ignore_add_rule
(
g_repo
,
add_me
));
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"Debug"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"and/Debug"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"really/Debug/this/file"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"Debug/what/I/say"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"and/NoDebug"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"NoDebug/this"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"please/NoDebug/this"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"this/is/deep"
));
cl_assert
(
ignored
);
assert_is_ignored
(
"Debug"
);
assert_is_ignored
(
"and/Debug"
);
assert_is_ignored
(
"really/Debug/this/file"
);
assert_is_ignored
(
"Debug/what/I/say"
);
refute_is_ignored
(
"and/NoDebug"
);
refute_is_ignored
(
"NoDebug/this"
);
refute_is_ignored
(
"please/NoDebug/this"
);
assert_is_ignored
(
"this/is/deep"
);
/* pattern containing slash gets FNM_PATHNAME so all slashes must match */
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"and/this/is/deep"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"this/is/deep/too"
));
cl_assert
(
ignored
);
refute_is_ignored
(
"and/this/is/deep"
);
assert_is_ignored
(
"this/is/deep/too"
);
/* pattern containing slash gets FNM_PATHNAME so all slashes must match */
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"but/this/is/deep/and/ignored"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"this/is/not/deep"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"is/this/not/as/deep"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"this/is/deepish"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"xthis/is/deep"
));
cl_assert
(
!
ignored
);
refute_is_ignored
(
"but/this/is/deep/and/ignored"
);
refute_is_ignored
(
"this/is/not/deep"
);
refute_is_ignored
(
"is/this/not/as/deep"
);
refute_is_ignored
(
"this/is/deepish"
);
refute_is_ignored
(
"xthis/is/deep"
);
}
void
test_status_ignore__automatically_ignore_bad_files
(
void
)
{
int
ignored
;
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
".git"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"this/file/."
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"path/../funky"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"path/whatever.c"
));
cl_assert
(
!
ignored
);
assert_is_ignored
(
".git"
);
assert_is_ignored
(
"this/file/."
);
assert_is_ignored
(
"path/../funky"
);
refute_is_ignored
(
"path/whatever.c"
);
cl_git_pass
(
git_ignore_add_rule
(
g_repo
,
"*.c
\n
"
));
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
".git"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"this/file/."
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"path/../funky"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"path/whatever.c"
));
cl_assert
(
ignored
);
assert_is_ignored
(
".git"
);
assert_is_ignored
(
"this/file/."
);
assert_is_ignored
(
"path/../funky"
);
assert_is_ignored
(
"path/whatever.c"
);
cl_git_pass
(
git_ignore_clear_internal_rules
(
g_repo
));
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
".git"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"this/file/."
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"path/../funky"
));
cl_assert
(
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"path/whatever.c"
));
cl_assert
(
!
ignored
);
assert_is_ignored
(
".git"
);
assert_is_ignored
(
"this/file/."
);
assert_is_ignored
(
"path/../funky"
);
refute_is_ignored
(
"path/whatever.c"
);
}
void
test_status_ignore__filenames_with_special_prefixes_do_not_interfere_with_status_retrieval
(
void
)
...
...
@@ -605,7 +610,6 @@ void test_status_ignore__filenames_with_special_prefixes_do_not_interfere_with_s
void
test_status_ignore__issue_1766_negated_ignores
(
void
)
{
int
ignored
=
0
;
unsigned
int
status
;
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
...
...
@@ -617,11 +621,8 @@ void test_status_ignore__issue_1766_negated_ignores(void)
cl_git_mkfile
(
"empty_standard_repo/a/ignoreme"
,
"I should be ignored
\n
"
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"a/.gitignore"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"a/ignoreme"
));
cl_assert
(
ignored
);
refute_is_ignored
(
"a/.gitignore"
);
assert_is_ignored
(
"a/ignoreme"
);
cl_git_pass
(
git_futils_mkdir_r
(
"empty_standard_repo/b"
,
NULL
,
0775
));
...
...
@@ -630,18 +631,12 @@ void test_status_ignore__issue_1766_negated_ignores(void)
cl_git_mkfile
(
"empty_standard_repo/b/ignoreme"
,
"I should be ignored
\n
"
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"b/.gitignore"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"b/ignoreme"
));
cl_assert
(
ignored
);
refute_is_ignored
(
"b/.gitignore"
);
assert_is_ignored
(
"b/ignoreme"
);
/* shouldn't have changed results from first couple either */
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"a/.gitignore"
));
cl_assert
(
!
ignored
);
cl_git_pass
(
git_status_should_ignore
(
&
ignored
,
g_repo
,
"a/ignoreme"
));
cl_assert
(
ignored
);
refute_is_ignored
(
"a/.gitignore"
);
assert_is_ignored
(
"a/ignoreme"
);
/* status should find the two ignore files and nothing else */
...
...
tests/status/status_helpers.c
View file @
7b0f8ba9
...
...
@@ -9,20 +9,13 @@ int cb_status__normal(
if
(
counts
->
debug
)
cb_status__print
(
path
,
status_flags
,
NULL
);
if
(
counts
->
entry_count
>=
counts
->
expected_entry_count
)
{
if
(
counts
->
entry_count
>=
counts
->
expected_entry_count
)
counts
->
wrong_status_flags_count
++
;
goto
exit
;
}
if
(
strcmp
(
path
,
counts
->
expected_paths
[
counts
->
entry_count
]))
{
else
if
(
strcmp
(
path
,
counts
->
expected_paths
[
counts
->
entry_count
]))
counts
->
wrong_sorted_path
++
;
goto
exit
;
}
if
(
status_flags
!=
counts
->
expected_statuses
[
counts
->
entry_count
])
else
if
(
status_flags
!=
counts
->
expected_statuses
[
counts
->
entry_count
])
counts
->
wrong_status_flags_count
++
;
exit:
counts
->
entry_count
++
;
return
0
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment