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
a5ddae68
Unverified
Commit
a5ddae68
authored
Jun 13, 2019
by
Edward Thomson
Committed by
GitHub
Jun 13, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5097 from pks-t/pks/ignore-escapes
gitignore with escapes
parents
e277ff4d
3b517351
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
221 additions
and
1356 deletions
+221
-1356
src/attr_file.c
+60
-19
src/path.c
+4
-1
tests/ignore/path.c
+107
-28
tests/ignore/status.c
+40
-40
tests/path/core.c
+10
-0
tests/status/ignore.c.bak
+0
-1268
No files found.
src/attr_file.c
View file @
a5ddae68
...
...
@@ -565,15 +565,55 @@ void git_attr_path__free(git_attr_path *info)
*/
static
size_t
trailing_space_length
(
const
char
*
p
,
size_t
len
)
{
size_t
n
;
size_t
n
,
i
;
for
(
n
=
len
;
n
;
n
--
)
{
if
((
p
[
n
-
1
]
!=
' '
&&
p
[
n
-
1
]
!=
'\t'
)
||
(
n
>
1
&&
p
[
n
-
2
]
==
'\\'
))
if
(
p
[
n
-
1
]
!=
' '
&&
p
[
n
-
1
]
!=
'\t'
)
break
;
/*
* Count escape-characters before space. In case where it's an
* even number of escape characters, then the escape char itself
* is escaped and the whitespace is an unescaped whitespace.
* Otherwise, the last escape char is not escaped and the
* whitespace in an escaped whitespace.
*/
i
=
n
;
while
(
i
>
1
&&
p
[
i
-
2
]
==
'\\'
)
i
--
;
if
((
n
-
i
)
%
2
)
break
;
}
return
len
-
n
;
}
static
size_t
unescape_spaces
(
char
*
str
)
{
char
*
scan
,
*
pos
=
str
;
bool
escaped
=
false
;
if
(
!
str
)
return
0
;
for
(
scan
=
str
;
*
scan
;
scan
++
)
{
if
(
!
escaped
&&
*
scan
==
'\\'
)
{
escaped
=
true
;
continue
;
}
/* Only insert the escape character for escaped non-spaces */
if
(
escaped
&&
!
git__isspace
(
*
scan
))
*
pos
++
=
'\\'
;
*
pos
++
=
*
scan
;
escaped
=
false
;
}
if
(
pos
!=
scan
)
*
pos
=
'\0'
;
return
(
pos
-
str
);
}
/*
* This will return 0 if the spec was filled out,
* GIT_ENOTFOUND if the fnmatch does not require matching, or
...
...
@@ -587,6 +627,7 @@ int git_attr_fnmatch__parse(
{
const
char
*
pattern
,
*
scan
;
int
slash_count
,
allow_space
;
bool
escaped
;
assert
(
spec
&&
base
&&
*
base
);
...
...
@@ -623,30 +664,31 @@ int git_attr_fnmatch__parse(
}
slash_count
=
0
;
escaped
=
false
;
/* Scan until a non-escaped whitespace. */
for
(
scan
=
pattern
;
*
scan
!=
'\0'
;
++
scan
)
{
/*
* Scan until a non-escaped whitespace: find a whitespace, then look
* one char backward to ensure that it's not prefixed by a `\`.
* Only look backward if we're not at the first position (`pattern`).
*/
if
(
git__isspace
(
*
scan
)
&&
scan
>
pattern
&&
*
(
scan
-
1
)
!=
'\\'
)
{
if
(
!
allow_space
||
(
*
scan
!=
' '
&&
*
scan
!=
'\t'
&&
*
scan
!=
'\r'
))
break
;
}
char
c
=
*
scan
;
if
(
*
scan
==
'/'
)
{
if
(
c
==
'\\'
&&
!
escaped
)
{
escaped
=
true
;
continue
;
}
else
if
(
git__isspace
(
c
)
&&
!
escaped
)
{
if
(
!
allow_space
||
(
c
!=
' '
&&
c
!=
'\t'
&&
c
!=
'\r'
))
break
;
}
else
if
(
c
==
'/'
)
{
spec
->
flags
=
spec
->
flags
|
GIT_ATTR_FNMATCH_FULLPATH
;
slash_count
++
;
if
(
slash_count
==
1
&&
pattern
==
scan
)
pattern
++
;
}
}
else
if
(
git__iswildcard
(
c
)
&&
!
escaped
)
{
/* remember if we see an unescaped wildcard in pattern */
else
if
(
git__iswildcard
(
*
scan
)
&&
(
scan
==
pattern
||
(
*
(
scan
-
1
)
!=
'\\'
)))
spec
->
flags
=
spec
->
flags
|
GIT_ATTR_FNMATCH_HASWILD
;
}
escaped
=
false
;
}
*
base
=
scan
;
if
((
spec
->
length
=
scan
-
pattern
)
==
0
)
...
...
@@ -699,9 +741,8 @@ int git_attr_fnmatch__parse(
*
base
=
git__next_line
(
pattern
);
return
-
1
;
}
else
{
/* strip '\' that might have be used for internal whitespace */
spec
->
length
=
git__unescape
(
spec
->
pattern
);
/* TODO: convert remaining '\' into '/' for POSIX ??? */
/* strip '\' that might have been used for internal whitespace */
spec
->
length
=
unescape_spaces
(
spec
->
pattern
);
}
return
0
;
...
...
src/path.c
View file @
a5ddae68
...
...
@@ -276,9 +276,12 @@ int git_path_root(const char *path)
while
(
path
[
offset
]
&&
path
[
offset
]
!=
'/'
&&
path
[
offset
]
!=
'\\'
)
offset
++
;
}
if
(
path
[
offset
]
==
'\\'
)
return
offset
;
#endif
if
(
path
[
offset
]
==
'/'
||
path
[
offset
]
==
'\\'
)
if
(
path
[
offset
]
==
'/'
)
return
offset
;
return
-
1
;
/* Not a real error - signals that path is not rooted */
...
...
tests/
attr/ignore
.c
→
tests/
ignore/path
.c
View file @
a5ddae68
...
...
@@ -5,12 +5,12 @@
static
git_repository
*
g_repo
=
NULL
;
void
test_
attr_ignore
__initialize
(
void
)
void
test_
ignore_path
__initialize
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"attr"
);
}
void
test_
attr_ignore
__cleanup
(
void
)
void
test_
ignore_path
__cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
g_repo
=
NULL
;
...
...
@@ -31,7 +31,7 @@ static void assert_is_ignored_(
#define assert_is_ignored(expected, filepath) \
assert_is_ignored_(expected, filepath, __FILE__, __LINE__)
void
test_
attr_ignore
__honor_temporary_rules
(
void
)
void
test_
ignore_path
__honor_temporary_rules
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"/NewFolder
\n
/NewFolder/NewFolder"
);
...
...
@@ -41,7 +41,7 @@ void test_attr_ignore__honor_temporary_rules(void)
assert_is_ignored
(
true
,
"NewFolder/NewFolder/File.txt"
);
}
void
test_
attr_ignore
__allow_root
(
void
)
void
test_
ignore_path
__allow_root
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"/"
);
...
...
@@ -51,7 +51,7 @@ void test_attr_ignore__allow_root(void)
assert_is_ignored
(
false
,
"NewFolder/NewFolder/File.txt"
);
}
void
test_
attr_ignore
__ignore_space
(
void
)
void
test_
ignore_path
__ignore_space
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"/
\n\n
/NewFolder
\n
/NewFolder/NewFolder"
);
...
...
@@ -61,7 +61,7 @@ void test_attr_ignore__ignore_space(void)
assert_is_ignored
(
true
,
"NewFolder/NewFolder/File.txt"
);
}
void
test_
attr_ignore
__intermittent_space
(
void
)
void
test_
ignore_path
__intermittent_space
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"foo bar
\n
"
);
...
...
@@ -70,7 +70,7 @@ void test_attr_ignore__intermittent_space(void)
assert_is_ignored
(
true
,
"foo bar"
);
}
void
test_
attr_ignore
__trailing_space
(
void
)
void
test_
ignore_path
__trailing_space
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
...
...
@@ -85,7 +85,7 @@ void test_attr_ignore__trailing_space(void)
assert_is_ignored
(
false
,
"bar "
);
}
void
test_
attr_ignore
__escaped_trailing_spaces
(
void
)
void
test_
ignore_path
__escaped_trailing_spaces
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
...
...
@@ -107,7 +107,7 @@ void test_attr_ignore__escaped_trailing_spaces(void)
assert_is_ignored
(
false
,
"qux "
);
}
void
test_
attr_ignore
__ignore_dir
(
void
)
void
test_
ignore_path
__ignore_dir
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"dir/
\n
"
);
...
...
@@ -115,7 +115,7 @@ void test_attr_ignore__ignore_dir(void)
assert_is_ignored
(
true
,
"dir/file"
);
}
void
test_
attr_ignore
__ignore_dir_with_trailing_space
(
void
)
void
test_
ignore_path
__ignore_dir_with_trailing_space
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"dir/
\n
"
);
...
...
@@ -123,7 +123,7 @@ void test_attr_ignore__ignore_dir_with_trailing_space(void)
assert_is_ignored
(
true
,
"dir/file"
);
}
void
test_
attr_ignore
__ignore_root
(
void
)
void
test_
ignore_path
__ignore_root
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"/
\n\n
/NewFolder
\n
/NewFolder/NewFolder"
);
...
...
@@ -133,7 +133,7 @@ void test_attr_ignore__ignore_root(void)
assert_is_ignored
(
true
,
"NewFolder/NewFolder/File.txt"
);
}
void
test_
attr_ignore
__full_paths
(
void
)
void
test_
ignore_path
__full_paths
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"Folder/*/Contained"
);
...
...
@@ -153,7 +153,7 @@ void test_attr_ignore__full_paths(void)
assert_is_ignored
(
false
,
"Folder/Middle/More/More/Contained/Not/Happy/Child"
);
}
void
test_
attr_ignore
__more_starstar_cases
(
void
)
void
test_
ignore_path
__more_starstar_cases
(
void
)
{
cl_must_pass
(
p_unlink
(
"attr/.gitignore"
));
cl_git_mkfile
(
...
...
@@ -171,7 +171,7 @@ void test_attr_ignore__more_starstar_cases(void)
assert_is_ignored
(
false
,
"sub/sub2/aaa.html"
);
}
void
test_
attr_ignore
__leading_stars
(
void
)
void
test_
ignore_path
__leading_stars
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
...
...
@@ -204,7 +204,7 @@ void test_attr_ignore__leading_stars(void)
assert_is_ignored
(
false
,
"dir1/kid2/file"
);
}
void
test_
attr_ignore
__globs_and_path_delimiters
(
void
)
void
test_
ignore_path
__globs_and_path_delimiters
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"foo/bar/**"
);
assert_is_ignored
(
true
,
"foo/bar/baz"
);
...
...
@@ -230,7 +230,7 @@ void test_attr_ignore__globs_and_path_delimiters(void)
assert_is_ignored
(
false
,
"_test/foo/bar/code/file"
);
}
void
test_
attr_ignore
__skip_gitignore_directory
(
void
)
void
test_
ignore_path
__skip_gitignore_directory
(
void
)
{
cl_git_rewritefile
(
"attr/.git/info/exclude"
,
"/NewFolder
\n
/NewFolder/NewFolder"
);
p_unlink
(
"attr/.gitignore"
);
...
...
@@ -244,7 +244,7 @@ void test_attr_ignore__skip_gitignore_directory(void)
assert_is_ignored
(
true
,
"NewFolder/NewFolder/File.txt"
);
}
void
test_
attr_ignore
__subdirectory_gitignore
(
void
)
void
test_
ignore_path
__subdirectory_gitignore
(
void
)
{
p_unlink
(
"attr/.gitignore"
);
cl_assert
(
!
git_path_exists
(
"attr/.gitignore"
));
...
...
@@ -262,7 +262,7 @@ void test_attr_ignore__subdirectory_gitignore(void)
assert_is_ignored
(
false
,
"dir/file3"
);
}
void
test_
attr_ignore
__expand_tilde_to_homedir
(
void
)
void
test_
ignore_path
__expand_tilde_to_homedir
(
void
)
{
git_config
*
cfg
;
...
...
@@ -292,7 +292,7 @@ void test_attr_ignore__expand_tilde_to_homedir(void)
/* Ensure that the .gitignore in the subdirectory only affects
* items in the subdirectory. */
void
test_
attr_ignore
__gitignore_in_subdir
(
void
)
void
test_
ignore_path
__gitignore_in_subdir
(
void
)
{
cl_git_rmfile
(
"attr/.gitignore"
);
...
...
@@ -320,7 +320,7 @@ void test_attr_ignore__gitignore_in_subdir(void)
}
/* Ensure that files do not match folder cases */
void
test_
attr_ignore
__dont_ignore_files_for_folder
(
void
)
void
test_
ignore_path
__dont_ignore_files_for_folder
(
void
)
{
cl_git_rmfile
(
"attr/.gitignore"
);
...
...
@@ -351,7 +351,7 @@ void test_attr_ignore__dont_ignore_files_for_folder(void)
assert_is_ignored
(
false
,
"dir/TeSt"
);
}
void
test_
attr_ignore
__symlink_to_outside
(
void
)
void
test_
ignore_path
__symlink_to_outside
(
void
)
{
#ifdef GIT_WIN32
cl_skip
();
...
...
@@ -364,7 +364,7 @@ void test_attr_ignore__symlink_to_outside(void)
assert_is_ignored
(
true
,
"lala/../symlink"
);
}
void
test_
attr_ignore
__test
(
void
)
void
test_
ignore_path
__test
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"/*/
\n
"
...
...
@@ -376,7 +376,7 @@ void test_attr_ignore__test(void)
assert_is_ignored
(
true
,
"bin/foo"
);
}
void
test_
attr_ignore
__unignore_dir_succeeds
(
void
)
void
test_
ignore_path
__unignore_dir_succeeds
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"*.c
\n
"
...
...
@@ -385,7 +385,7 @@ void test_attr_ignore__unignore_dir_succeeds(void)
assert_is_ignored
(
true
,
"src/foo/foo.c"
);
}
void
test_
attr_ignore
__case_insensitive_unignores_previous_rule
(
void
)
void
test_
ignore_path
__case_insensitive_unignores_previous_rule
(
void
)
{
git_config
*
cfg
;
...
...
@@ -402,7 +402,7 @@ void test_attr_ignore__case_insensitive_unignores_previous_rule(void)
assert_is_ignored
(
false
,
"case/file"
);
}
void
test_
attr_ignore
__case_sensitive_unignore_does_nothing
(
void
)
void
test_
ignore_path
__case_sensitive_unignore_does_nothing
(
void
)
{
git_config
*
cfg
;
...
...
@@ -419,7 +419,7 @@ void test_attr_ignore__case_sensitive_unignore_does_nothing(void)
assert_is_ignored
(
true
,
"case/file"
);
}
void
test_
attr_ignore
__ignored_subdirfiles_with_subdir_rule
(
void
)
void
test_
ignore_path
__ignored_subdirfiles_with_subdir_rule
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
...
...
@@ -431,7 +431,7 @@ void test_attr_ignore__ignored_subdirfiles_with_subdir_rule(void)
assert_is_ignored
(
true
,
"dir/sub1/sub2"
);
}
void
test_
attr_ignore
__ignored_subdirfiles_with_negations
(
void
)
void
test_
ignore_path
__ignored_subdirfiles_with_negations
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
...
...
@@ -443,7 +443,7 @@ void test_attr_ignore__ignored_subdirfiles_with_negations(void)
assert_is_ignored
(
true
,
"dir/sub1/c.test"
);
}
void
test_
attr_ignore
__negative_directory_rules_only_match_directories
(
void
)
void
test_
ignore_path
__negative_directory_rules_only_match_directories
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
...
...
@@ -459,3 +459,82 @@ void test_attr_ignore__negative_directory_rules_only_match_directories(void)
assert_is_ignored
(
false
,
"src/A.keep"
);
assert_is_ignored
(
false
,
".gitignore"
);
}
void
test_ignore_path__escaped_character
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"
\\
c
\n
"
);
assert_is_ignored
(
true
,
"c"
);
assert_is_ignored
(
false
,
"
\\
c"
);
}
void
test_ignore_path__escaped_newline
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"
\\\n
newline
\n
"
);
assert_is_ignored
(
true
,
"
\n
newline"
);
}
void
test_ignore_path__escaped_glob
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"
\\
*
\n
"
);
assert_is_ignored
(
true
,
"*"
);
assert_is_ignored
(
false
,
"foo"
);
}
void
test_ignore_path__escaped_comments
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"#foo
\n
"
"
\\
#bar
\n
"
"
\\
##baz
\n
"
"
\\
#
\\\\
#qux
\n
"
);
assert_is_ignored
(
false
,
"#foo"
);
assert_is_ignored
(
true
,
"#bar"
);
assert_is_ignored
(
false
,
"
\\
#bar"
);
assert_is_ignored
(
true
,
"##baz"
);
assert_is_ignored
(
false
,
"
\\
##baz"
);
assert_is_ignored
(
true
,
"#
\\
#qux"
);
assert_is_ignored
(
false
,
"##qux"
);
assert_is_ignored
(
false
,
"
\\
##qux"
);
}
void
test_ignore_path__escaped_slash
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"
\\\\\n
"
"
\\\\
preceding
\n
"
"inter
\\\\
mittent
\n
"
"trailing
\\\\\n
"
);
#ifndef GIT_WIN32
assert_is_ignored
(
true
,
"
\\
"
);
assert_is_ignored
(
true
,
"
\\
preceding"
);
#endif
assert_is_ignored
(
true
,
"inter
\\
mittent"
);
assert_is_ignored
(
true
,
"trailing
\\
"
);
}
void
test_ignore_path__escaped_space
(
void
)
{
cl_git_rewritefile
(
"attr/.gitignore"
,
"foo
\\\\
\n
"
"bar
\\\\\\
\n
"
);
assert_is_ignored
(
true
,
"foo
\\
"
);
assert_is_ignored
(
false
,
"foo
\\
"
);
assert_is_ignored
(
false
,
"foo
\\\\
"
);
assert_is_ignored
(
false
,
"foo
\\\\
"
);
assert_is_ignored
(
true
,
"bar
\\
"
);
assert_is_ignored
(
false
,
"bar
\\\\
"
);
assert_is_ignored
(
false
,
"bar
\\\\
"
);
assert_is_ignored
(
false
,
"bar
\\\\\\
"
);
assert_is_ignored
(
false
,
"bar
\\\\\\
"
);
}
tests/
status/ignore
.c
→
tests/
ignore/status
.c
View file @
a5ddae68
...
...
@@ -3,15 +3,15 @@
#include "git2/attr.h"
#include "ignore.h"
#include "attr.h"
#include "status_helpers.h"
#include "status
/status
_helpers.h"
static
git_repository
*
g_repo
=
NULL
;
void
test_
status_ignore
__initialize
(
void
)
void
test_
ignore_status
__initialize
(
void
)
{
}
void
test_
status_ignore
__cleanup
(
void
)
void
test_
ignore_status
__cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
}
...
...
@@ -33,7 +33,7 @@ static void assert_ignored_(
#define refute_is_ignored(filepath) \
assert_ignored_(false, filepath, __FILE__, __LINE__)
void
test_
status_ignore
__0
(
void
)
void
test_
ignore_status
__0
(
void
)
{
struct
{
const
char
*
path
;
...
...
@@ -75,7 +75,7 @@ void test_status_ignore__0(void)
}
void
test_
status_ignore
__1
(
void
)
void
test_
ignore_status
__1
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"attr"
);
...
...
@@ -90,7 +90,7 @@ void test_status_ignore__1(void)
refute_is_ignored
(
"sub/dir/"
);
}
void
test_
status_ignore
__empty_repo_with_gitignore_rewrite
(
void
)
void
test_
ignore_status
__empty_repo_with_gitignore_rewrite
(
void
)
{
status_entry_single
st
;
...
...
@@ -134,7 +134,7 @@ void test_status_ignore__empty_repo_with_gitignore_rewrite(void)
assert_is_ignored
(
"look-ma.txt"
);
}
void
test_
status_ignore
__ignore_pattern_contains_space
(
void
)
void
test_
ignore_status
__ignore_pattern_contains_space
(
void
)
{
unsigned
int
flags
;
const
mode_t
mode
=
0777
;
...
...
@@ -155,7 +155,7 @@ void test_status_ignore__ignore_pattern_contains_space(void)
cl_assert
(
flags
==
GIT_STATUS_WT_NEW
);
}
void
test_
status_ignore
__ignore_pattern_ignorecase
(
void
)
void
test_
ignore_status
__ignore_pattern_ignorecase
(
void
)
{
unsigned
int
flags
;
bool
ignore_case
;
...
...
@@ -174,7 +174,7 @@ void test_status_ignore__ignore_pattern_ignorecase(void)
cl_assert
(
flags
==
ignore_case
?
GIT_STATUS_IGNORED
:
GIT_STATUS_WT_NEW
);
}
void
test_
status_ignore
__subdirectories
(
void
)
void
test_
ignore_status
__subdirectories
(
void
)
{
status_entry_single
st
;
...
...
@@ -250,7 +250,7 @@ static const char *test_files_1[] = {
NULL
};
void
test_
status_ignore
__subdirectories_recursion
(
void
)
void
test_
ignore_status
__subdirectories_recursion
(
void
)
{
/* Let's try again with recursing into ignored dirs turned on */
git_status_options
opts
=
GIT_STATUS_OPTIONS_INIT
;
...
...
@@ -319,7 +319,7 @@ void test_status_ignore__subdirectories_recursion(void)
cl_assert_equal_i
(
0
,
counts
.
wrong_sorted_path
);
}
void
test_
status_ignore
__subdirectories_not_at_root
(
void
)
void
test_
ignore_status
__subdirectories_not_at_root
(
void
)
{
git_status_options
opts
=
GIT_STATUS_OPTIONS_INIT
;
status_entry_counts
counts
;
...
...
@@ -360,7 +360,7 @@ void test_status_ignore__subdirectories_not_at_root(void)
cl_assert_equal_i
(
0
,
counts
.
wrong_sorted_path
);
}
void
test_
status_ignore
__leading_slash_ignores
(
void
)
void
test_
ignore_status
__leading_slash_ignores
(
void
)
{
git_status_options
opts
=
GIT_STATUS_OPTIONS_INIT
;
status_entry_counts
counts
;
...
...
@@ -413,7 +413,7 @@ void test_status_ignore__leading_slash_ignores(void)
cl_assert_equal_i
(
0
,
counts
.
wrong_sorted_path
);
}
void
test_
status_ignore
__multiple_leading_slash
(
void
)
void
test_
ignore_status
__multiple_leading_slash
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/a.test"
,
...
...
@@ -437,7 +437,7 @@ void test_status_ignore__multiple_leading_slash(void)
refute_is_ignored
(
"d.test"
);
}
void
test_
status_ignore
__contained_dir_with_matching_name
(
void
)
void
test_
ignore_status
__contained_dir_with_matching_name
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/subdir_match/aaa/subdir_match/file"
,
...
...
@@ -477,7 +477,7 @@ void test_status_ignore__contained_dir_with_matching_name(void)
cl_assert_equal_i
(
0
,
counts
.
wrong_sorted_path
);
}
void
test_
status_ignore
__trailing_slash_star
(
void
)
void
test_
ignore_status
__trailing_slash_star
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/file"
,
...
...
@@ -495,7 +495,7 @@ void test_status_ignore__trailing_slash_star(void)
assert_is_ignored
(
"subdir/file"
);
}
void
test_
status_ignore
__adding_internal_ignores
(
void
)
void
test_
ignore_status
__adding_internal_ignores
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
...
...
@@ -529,7 +529,7 @@ void test_status_ignore__adding_internal_ignores(void)
assert_is_ignored
(
"two.bar"
);
}
void
test_
status_ignore
__add_internal_as_first_thing
(
void
)
void
test_
ignore_status
__add_internal_as_first_thing
(
void
)
{
const
char
*
add_me
=
"
\n
#################
\n
## Eclipse
\n
#################
\n\n
*.pydevproject
\n
.project
\n
.metadata
\n
bin/
\n
tmp/
\n
*.tmp
\n\n
"
;
...
...
@@ -541,7 +541,7 @@ void test_status_ignore__add_internal_as_first_thing(void)
refute_is_ignored
(
"two.bar"
);
}
void
test_
status_ignore
__internal_ignores_inside_deep_paths
(
void
)
void
test_
ignore_status
__internal_ignores_inside_deep_paths
(
void
)
{
const
char
*
add_me
=
"Debug
\n
this/is/deep
\n
patterned*/dir
\n
"
;
...
...
@@ -571,7 +571,7 @@ void test_status_ignore__internal_ignores_inside_deep_paths(void)
refute_is_ignored
(
"xthis/is/deep"
);
}
void
test_
status_ignore
__automatically_ignore_bad_files
(
void
)
void
test_
ignore_status
__automatically_ignore_bad_files
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
...
...
@@ -595,7 +595,7 @@ void test_status_ignore__automatically_ignore_bad_files(void)
refute_is_ignored
(
"path/whatever.c"
);
}
void
test_
status_ignore
__filenames_with_special_prefixes_do_not_interfere_with_status_retrieval
(
void
)
void
test_
ignore_status
__filenames_with_special_prefixes_do_not_interfere_with_status_retrieval
(
void
)
{
status_entry_single
st
;
char
*
test_cases
[]
=
{
...
...
@@ -629,7 +629,7 @@ void test_status_ignore__filenames_with_special_prefixes_do_not_interfere_with_s
}
}
void
test_
status_ignore
__issue_1766_negated_ignores
(
void
)
void
test_
ignore_status
__issue_1766_negated_ignores
(
void
)
{
unsigned
int
status
;
...
...
@@ -714,7 +714,7 @@ static void add_one_to_index(const char *file)
}
/* Some further broken scenarios that have been reported */
void
test_
status_ignore
__more_breakage
(
void
)
void
test_
ignore_status
__more_breakage
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/d1/pfx-d2/d3/d4/d5/tracked"
,
...
...
@@ -770,7 +770,7 @@ void test_status_ignore__more_breakage(void)
refute_is_ignored
(
"d1/pfx-d2/d3/d4/untracked"
);
}
void
test_
status_ignore
__negative_ignores_inside_ignores
(
void
)
void
test_
ignore_status
__negative_ignores_inside_ignores
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/top/mid/btm/tracked"
,
...
...
@@ -822,7 +822,7 @@ void test_status_ignore__negative_ignores_inside_ignores(void)
refute_is_ignored
(
"foo/bar"
);
}
void
test_
status_ignore
__negative_ignores_in_slash_star
(
void
)
void
test_
ignore_status
__negative_ignores_in_slash_star
(
void
)
{
git_status_options
status_opts
=
GIT_STATUS_OPTIONS_INIT
;
git_status_list
*
list
;
...
...
@@ -860,7 +860,7 @@ void test_status_ignore__negative_ignores_in_slash_star(void)
cl_assert
(
found_what_about
);
}
void
test_
status_ignore
__negative_ignores_without_trailing_slash_inside_ignores
(
void
)
void
test_
ignore_status
__negative_ignores_without_trailing_slash_inside_ignores
(
void
)
{
git_status_options
status_opts
=
GIT_STATUS_OPTIONS_INIT
;
git_status_list
*
list
;
...
...
@@ -916,7 +916,7 @@ void test_status_ignore__negative_ignores_without_trailing_slash_inside_ignores(
cl_assert
(
found_parent_child2_file
);
}
void
test_
status_ignore
__negative_directory_ignores
(
void
)
void
test_
ignore_status
__negative_directory_ignores
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/parent/child1/bar.txt"
,
...
...
@@ -969,7 +969,7 @@ void test_status_ignore__negative_directory_ignores(void)
assert_is_ignored
(
"padded_parent/child8/bar.txt"
);
}
void
test_
status_ignore
__unignore_entry_in_ignored_dir
(
void
)
void
test_
ignore_status
__unignore_entry_in_ignored_dir
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/bar.txt"
,
...
...
@@ -991,7 +991,7 @@ void test_status_ignore__unignore_entry_in_ignored_dir(void)
assert_is_ignored
(
"nested/parent/child/bar.txt"
);
}
void
test_
status_ignore
__do_not_unignore_basename_prefix
(
void
)
void
test_
ignore_status
__do_not_unignore_basename_prefix
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/foo_bar.txt"
,
...
...
@@ -1007,7 +1007,7 @@ void test_status_ignore__do_not_unignore_basename_prefix(void)
assert_is_ignored
(
"foo_bar.txt"
);
}
void
test_
status_ignore
__filename_with_cr
(
void
)
void
test_
ignore_status
__filename_with_cr
(
void
)
{
int
ignored
;
...
...
@@ -1040,7 +1040,7 @@ void test_status_ignore__filename_with_cr(void)
cl_assert_equal_i
(
1
,
ignored
);
}
void
test_
status_ignore
__subdir_doesnt_match_above
(
void
)
void
test_
ignore_status
__subdir_doesnt_match_above
(
void
)
{
int
ignored
,
icase
=
0
,
error
;
git_config
*
cfg
;
...
...
@@ -1073,7 +1073,7 @@ void test_status_ignore__subdir_doesnt_match_above(void)
cl_assert_equal_i
(
icase
,
ignored
);
}
void
test_
status_ignore
__negate_exact_previous
(
void
)
void
test_
ignore_status
__negate_exact_previous
(
void
)
{
int
ignored
;
...
...
@@ -1085,7 +1085,7 @@ void test_status_ignore__negate_exact_previous(void)
cl_assert_equal_i
(
1
,
ignored
);
}
void
test_
status_ignore
__negate_starstar
(
void
)
void
test_
ignore_status
__negate_starstar
(
void
)
{
int
ignored
;
...
...
@@ -1102,7 +1102,7 @@ void test_status_ignore__negate_starstar(void)
cl_assert_equal_i
(
0
,
ignored
);
}
void
test_
status_ignore
__ignore_all_toplevel_dirs_include_files
(
void
)
void
test_
ignore_status
__ignore_all_toplevel_dirs_include_files
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/README.md"
,
...
...
@@ -1127,7 +1127,7 @@ void test_status_ignore__ignore_all_toplevel_dirs_include_files(void)
refute_is_ignored
(
"src/foo/foo.c"
);
}
void
test_
status_ignore
__subdir_ignore_all_toplevel_dirs_include_files
(
void
)
void
test_
ignore_status
__subdir_ignore_all_toplevel_dirs_include_files
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/project/README.md"
,
...
...
@@ -1152,7 +1152,7 @@ void test_status_ignore__subdir_ignore_all_toplevel_dirs_include_files(void)
refute_is_ignored
(
"project/README.md"
);
}
void
test_
status_ignore
__subdir_ignore_everything_except_certain_files
(
void
)
void
test_
ignore_status
__subdir_ignore_everything_except_certain_files
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/project/README.md"
,
...
...
@@ -1180,7 +1180,7 @@ void test_status_ignore__subdir_ignore_everything_except_certain_files(void)
refute_is_ignored
(
"project/src/foo/foo.c"
);
}
void
test_
status_ignore
__deeper
(
void
)
void
test_
ignore_status
__deeper
(
void
)
{
const
char
*
test_files
[]
=
{
"empty_standard_repo/foo.data"
,
...
...
@@ -1202,7 +1202,7 @@ void test_status_ignore__deeper(void)
refute_is_ignored
(
"dont_ignore/bar.data"
);
}
void
test_
status_ignore
__unignored_dir_with_ignored_contents
(
void
)
void
test_
ignore_status
__unignored_dir_with_ignored_contents
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/dir/a.test"
,
...
...
@@ -1220,7 +1220,7 @@ void test_status_ignore__unignored_dir_with_ignored_contents(void)
assert_is_ignored
(
"dir/subdir/a.test"
);
}
void
test_
status_ignore
__unignored_subdirs
(
void
)
void
test_
ignore_status
__unignored_subdirs
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/dir/a.test"
,
...
...
@@ -1238,7 +1238,7 @@ void test_status_ignore__unignored_subdirs(void)
refute_is_ignored
(
"dir/subdir/a.test"
);
}
void
test_
status_ignore
__skips_bom
(
void
)
void
test_
ignore_status
__skips_bom
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/a.test"
,
...
...
@@ -1261,7 +1261,7 @@ void test_status_ignore__skips_bom(void)
refute_is_ignored
(
"bar.txt"
);
}
void
test_
status_ignore
__leading_spaces_are_significant
(
void
)
void
test_
ignore_status
__leading_spaces_are_significant
(
void
)
{
static
const
char
*
test_files
[]
=
{
"empty_standard_repo/a.test"
,
...
...
tests/path/core.c
View file @
a5ddae68
...
...
@@ -343,6 +343,16 @@ void test_path_core__join_unrooted(void)
test_join_unrooted
(
"c:/foo"
,
2
,
"c:/foo"
,
"c:/asdf"
);
test_join_unrooted
(
"c:/foo/bar"
,
2
,
"c:/foo/bar"
,
"c:/asdf"
);
#ifdef GIT_WIN32
/* Paths starting with '\\' are absolute */
test_join_unrooted
(
"
\\
bar"
,
0
,
"
\\
bar"
,
"c:/foo/"
);
test_join_unrooted
(
"
\\\\
network
\\
bar"
,
9
,
"
\\\\
network
\\
bar"
,
"c:/foo/"
);
#else
/* Paths starting with '\\' are not absolute on non-Windows systems */
test_join_unrooted
(
"/foo/
\\
bar"
,
4
,
"
\\
bar"
,
"/foo"
);
test_join_unrooted
(
"c:/foo/
\\
bar"
,
7
,
"
\\
bar"
,
"c:/foo/"
);
#endif
/* Base is returned when it's provided and is the prefix */
test_join_unrooted
(
"c:/foo/bar/foobar"
,
6
,
"c:/foo/bar/foobar"
,
"c:/foo"
);
test_join_unrooted
(
"c:/foo/bar/foobar"
,
10
,
"c:/foo/bar/foobar"
,
"c:/foo/bar"
);
...
...
tests/status/ignore.c.bak
deleted
100644 → 0
View file @
e277ff4d
#include "clar_libgit2.h"
#include "fileops.h"
#include "git2/attr.h"
#include "ignore.h"
#include "attr.h"
#include "status_helpers.h"
static git_repository *g_repo = NULL;
void test_status_ignore__initialize(void)
{
}
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_expect(
git_status_should_ignore(&is_ignored, g_repo, filepath), 0, 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 {
const char *path;
int expected;
} test_cases[] = {
/* pattern "ign" from .gitignore */
{ "file", 0 },
{ "ign", 1 },
{ "sub", 0 },
{ "sub/file", 0 },
{ "sub/ign", 1 },
{ "sub/ign/file", 1 },
{ "sub/ign/sub", 1 },
{ "sub/ign/sub/file", 1 },
{ "sub/sub", 0 },
{ "sub/sub/file", 0 },
{ "sub/sub/ign", 1 },
{ "sub/sub/sub", 0 },
/* pattern "dir/" from .gitignore */
{ "dir", 1 },
{ "dir/", 1 },
{ "sub/dir", 1 },
{ "sub/dir/", 1 },
{ "sub/dir/file", 1 }, /* contained in ignored parent */
{ "sub/sub/dir", 0 }, /* dir is not actually a dir, but a file */
{ NULL, 0 }
}, *one_test;
g_repo = cl_git_sandbox_init("attr");
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(
g_repo, GIT_ATTR_FILE__FROM_FILE, ".git/info/exclude"));
cl_assert(git_attr_cache__is_cached(
g_repo, GIT_ATTR_FILE__FROM_FILE, ".gitignore"));
}
void test_status_ignore__1(void)
{
g_repo = cl_git_sandbox_init("attr");
cl_git_rewritefile("attr/.gitignore", "/*.txt\n/dir/\n");
git_attr_cache_flush(g_repo);
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;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_mkfile(
"empty_standard_repo/look-ma.txt", "I'm going to be ignored!");
memset(&st, 0, sizeof(st));
cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st));
cl_assert(st.count == 1);
cl_assert(st.status == GIT_STATUS_WT_NEW);
cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt"));
cl_assert(st.status == GIT_STATUS_WT_NEW);
refute_is_ignored("look-ma.txt");
cl_git_rewritefile("empty_standard_repo/.gitignore", "*.nomatch\n");
memset(&st, 0, sizeof(st));
cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st));
cl_assert(st.count == 2);
cl_assert(st.status == GIT_STATUS_WT_NEW);
cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt"));
cl_assert(st.status == GIT_STATUS_WT_NEW);
refute_is_ignored("look-ma.txt");
cl_git_rewritefile("empty_standard_repo/.gitignore", "*.txt\n");
memset(&st, 0, sizeof(st));
cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st));
cl_assert(st.count == 2);
cl_assert(st.status == GIT_STATUS_IGNORED);
cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt"));
cl_assert(st.status == GIT_STATUS_IGNORED);
assert_is_ignored("look-ma.txt");
}
void test_status_ignore__ignore_pattern_contains_space(void)
{
unsigned int flags;
const mode_t mode = 0777;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_rewritefile("empty_standard_repo/.gitignore", "foo bar.txt\n");
cl_git_mkfile(
"empty_standard_repo/foo bar.txt", "I'm going to be ignored!");
cl_git_pass(git_status_file(&flags, g_repo, "foo bar.txt"));
cl_assert(flags == GIT_STATUS_IGNORED);
cl_git_pass(git_futils_mkdir_r("empty_standard_repo/foo", mode));
cl_git_mkfile("empty_standard_repo/foo/look-ma.txt", "I'm not going to be ignored!");
cl_git_pass(git_status_file(&flags, g_repo, "foo/look-ma.txt"));
cl_assert(flags == GIT_STATUS_WT_NEW);
}
void test_status_ignore__ignore_pattern_ignorecase(void)
{
unsigned int flags;
bool ignore_case;
git_index *index;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_rewritefile("empty_standard_repo/.gitignore", "a.txt\n");
cl_git_mkfile("empty_standard_repo/A.txt", "Differs in case");
cl_git_pass(git_repository_index(&index, g_repo));
ignore_case = (git_index_caps(index) & GIT_INDEX_CAPABILITY_IGNORE_CASE) != 0;
git_index_free(index);
cl_git_pass(git_status_file(&flags, g_repo, "A.txt"));
cl_assert(flags == ignore_case ? GIT_STATUS_IGNORED : GIT_STATUS_WT_NEW);
}
void test_status_ignore__subdirectories(void)
{
status_entry_single st;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_mkfile(
"empty_standard_repo/ignore_me", "I'm going to be ignored!");
cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n");
memset(&st, 0, sizeof(st));
cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st));
cl_assert_equal_i(2, st.count);
cl_assert(st.status == GIT_STATUS_IGNORED);
cl_git_pass(git_status_file(&st.status, g_repo, "ignore_me"));
cl_assert(st.status == GIT_STATUS_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
* items are skipped completed, even if --ignored is passed to status.
* It you mirror these steps and run "git status -uall --ignored" then
* you will not see "test/ignore_me/" in the results.
*
* However, we had a couple reports of this as a bug, plus there is a
* similar circumstance where we were differing for core git when you
* used a rooted path for an ignore, so I changed this behavior.
*/
cl_git_pass(git_futils_mkdir_r(
"empty_standard_repo/test/ignore_me", 0775));
cl_git_mkfile(
"empty_standard_repo/test/ignore_me/file", "I'm going to be ignored!");
cl_git_mkfile(
"empty_standard_repo/test/ignore_me/file2", "Me, too!");
memset(&st, 0, sizeof(st));
cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st));
cl_assert_equal_i(3, st.count);
cl_git_pass(git_status_file(&st.status, g_repo, "test/ignore_me/file"));
cl_assert(st.status == GIT_STATUS_IGNORED);
assert_is_ignored("test/ignore_me/file");
}
static void make_test_data(const char *reponame, const char **files)
{
const char **scan;
size_t repolen = strlen(reponame) + 1;
g_repo = cl_git_sandbox_init(reponame);
for (scan = files; *scan != NULL; ++scan) {
cl_git_pass(git_futils_mkdir_relative(
*scan + repolen, reponame,
0777, GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST, NULL));
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 */
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts;
static const char *paths_r[] = {
".gitignore",
"dir/a/ignore_me",
"dir/b/ignore_me",
"dir/ignore_me",
"ignore_also/file",
"ignore_me",
"test/ignore_me/and_me/file",
"test/ignore_me/file",
"test/ignore_me/file2",
};
static const unsigned int statuses_r[] = {
GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED,
GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED,
GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED,
};
static const char *paths_nr[] = {
".gitignore",
"dir/a/ignore_me",
"dir/b/ignore_me",
"dir/ignore_me",
"ignore_also/",
"ignore_me",
"test/ignore_me/",
};
static const unsigned int statuses_nr[] = {
GIT_STATUS_WT_NEW,
GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED,
GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED,
};
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));
counts.expected_entry_count = 9;
counts.expected_paths = paths_r;
counts.expected_statuses = statuses_r;
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);
memset(&counts, 0x0, sizeof(status_entry_counts));
counts.expected_entry_count = 7;
counts.expected_paths = paths_nr;
counts.expected_statuses = statuses_nr;
opts.flags = GIT_STATUS_OPT_DEFAULTS;
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__subdirectories_not_at_root(void)
{
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts;
static const char *paths_1[] = {
"dir/.gitignore",
"dir/a/ignore_me",
"dir/b/ignore_me",
"dir/ignore_me",
"ignore_also/file",
"ignore_me",
"test/.gitignore",
"test/ignore_me/and_me/file",
"test/ignore_me/file",
"test/ignore_me/file2",
};
static const unsigned int statuses_1[] = {
GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED,
GIT_STATUS_IGNORED, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW,
GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW,
};
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");
memset(&counts, 0x0, sizeof(status_entry_counts));
counts.expected_entry_count = 10;
counts.expected_paths = paths_1;
counts.expected_statuses = statuses_1;
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__leading_slash_ignores(void)
{
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts;
static const char *paths_2[] = {
"dir/.gitignore",
"dir/a/ignore_me",
"dir/b/ignore_me",
"dir/ignore_me",
"ignore_also/file",
"ignore_me",
"test/.gitignore",
"test/ignore_me/and_me/file",
"test/ignore_me/file",
"test/ignore_me/file2",
};
static const unsigned int statuses_2[] = {
GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW,
GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED,
GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW,
};
make_test_data(test_repo_1, test_files_1);
cl_fake_home();
cl_git_mkfile("home/.gitignore", "/ignore_me\n");
{
git_config *cfg;
cl_git_pass(git_repository_config(&cfg, g_repo));
cl_git_pass(git_config_set_string(
cfg, "core.excludesfile", "~/.gitignore"));
git_config_free(cfg);
}
cl_git_rewritefile("empty_standard_repo/.git/info/exclude", "/ignore_also\n");
cl_git_rewritefile("empty_standard_repo/dir/.gitignore", "/ignore_me\n");
cl_git_rewritefile("empty_standard_repo/test/.gitignore", "/and_me\n");
memset(&counts, 0x0, sizeof(status_entry_counts));
counts.expected_entry_count = 10;
counts.expected_paths = paths_2;
counts.expected_statuses = statuses_2;
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__contained_dir_with_matching_name(void)
{
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");
refute_is_ignored("one.txt");
refute_is_ignored("two.bar");
cl_git_pass(git_ignore_add_rule(g_repo, "*.nomatch\n"));
refute_is_ignored("one.txt");
refute_is_ignored("two.bar");
cl_git_pass(git_ignore_add_rule(g_repo, "*.txt\n"));
assert_is_ignored("one.txt");
refute_is_ignored("two.bar");
cl_git_pass(git_ignore_add_rule(g_repo, "*.bar\n"));
assert_is_ignored("one.txt");
assert_is_ignored("two.bar");
cl_git_pass(git_ignore_clear_internal_rules(g_repo));
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"));
refute_is_ignored("one.txt");
assert_is_ignored("two.bar");
}
void test_status_ignore__add_internal_as_first_thing(void)
{
const char *add_me = "\n#################\n## Eclipse\n#################\n\n*.pydevproject\n.project\n.metadata\nbin/\ntmp/\n*.tmp\n\n";
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_pass(git_ignore_add_rule(g_repo, add_me));
assert_is_ignored("one.tmp");
refute_is_ignored("two.bar");
}
void test_status_ignore__internal_ignores_inside_deep_paths(void)
{
const char *add_me = "Debug\nthis/is/deep\npatterned*/dir\n";
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_pass(git_ignore_add_rule(g_repo, add_me));
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 */
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 */
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)
{
g_repo = cl_git_sandbox_init("empty_standard_repo");
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"));
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));
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)
{
status_entry_single st;
char *test_cases[] = {
"!file",
"#blah",
"[blah]",
"[attr]",
"[attr]blah",
NULL
};
int i;
for (i = 0; *(test_cases + i) != NULL; i++) {
git_buf file = GIT_BUF_INIT;
char *file_name = *(test_cases + i);
git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_pass(git_buf_joinpath(&file, "empty_standard_repo", file_name));
cl_git_mkfile(git_buf_cstr(&file), "Please don't ignore me!");
memset(&st, 0, sizeof(st));
cl_git_pass(git_status_foreach(repo, cb_status__single, &st));
cl_assert(st.count == 1);
cl_assert(st.status == GIT_STATUS_WT_NEW);
cl_git_pass(git_status_file(&st.status, repo, file_name));
cl_assert(st.status == GIT_STATUS_WT_NEW);
cl_git_sandbox_cleanup();
git_buf_dispose(&file);
}
}
void test_status_ignore__issue_1766_negated_ignores(void)
{
unsigned int status;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_pass(git_futils_mkdir_r(
"empty_standard_repo/a", 0775));
cl_git_mkfile(
"empty_standard_repo/a/.gitignore", "*\n!.gitignore\n");
cl_git_mkfile(
"empty_standard_repo/a/ignoreme", "I should be ignored\n");
refute_is_ignored("a/.gitignore");
assert_is_ignored("a/ignoreme");
cl_git_pass(git_futils_mkdir_r(
"empty_standard_repo/b", 0775));
cl_git_mkfile(
"empty_standard_repo/b/.gitignore", "*\n!.gitignore\n");
cl_git_mkfile(
"empty_standard_repo/b/ignoreme", "I should be ignored\n");
refute_is_ignored("b/.gitignore");
assert_is_ignored("b/ignoreme");
/* shouldn't have changed results from first couple either */
refute_is_ignored("a/.gitignore");
assert_is_ignored("a/ignoreme");
/* status should find the two ignore files and nothing else */
cl_git_pass(git_status_file(&status, g_repo, "a/.gitignore"));
cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status);
cl_git_pass(git_status_file(&status, g_repo, "a/ignoreme"));
cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status);
cl_git_pass(git_status_file(&status, g_repo, "b/.gitignore"));
cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status);
cl_git_pass(git_status_file(&status, g_repo, "b/ignoreme"));
cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status);
{
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts;
static const char *paths[] = {
"a/.gitignore",
"a/ignoreme",
"b/.gitignore",
"b/ignoreme",
};
static const unsigned int statuses[] = {
GIT_STATUS_WT_NEW,
GIT_STATUS_IGNORED,
GIT_STATUS_WT_NEW,
GIT_STATUS_IGNORED,
};
memset(&counts, 0x0, sizeof(status_entry_counts));
counts.expected_entry_count = 4;
counts.expected_paths = paths;
counts.expected_statuses = statuses;
opts.flags = GIT_STATUS_OPT_DEFAULTS;
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);
}
}
static void add_one_to_index(const char *file)
{
git_index *index;
cl_git_pass(git_repository_index(&index, g_repo));
cl_git_pass(git_index_add_bypath(index, file));
git_index_free(index);
}
/* Some further broken scenarios that have been reported */
void test_status_ignore__more_breakage(void)
{
static const char *test_files[] = {
"empty_standard_repo/d1/pfx-d2/d3/d4/d5/tracked",
"empty_standard_repo/d1/pfx-d2/d3/d4/d5/untracked",
"empty_standard_repo/d1/pfx-d2/d3/d4/untracked",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"/d1/pfx-*\n"
"!/d1/pfx-d2/\n"
"/d1/pfx-d2/*\n"
"!/d1/pfx-d2/d3/\n"
"/d1/pfx-d2/d3/*\n"
"!/d1/pfx-d2/d3/d4/\n");
add_one_to_index("d1/pfx-d2/d3/d4/d5/tracked");
{
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts;
static const char *files[] = {
".gitignore",
"d1/pfx-d2/d3/d4/d5/tracked",
"d1/pfx-d2/d3/d4/d5/untracked",
"d1/pfx-d2/d3/d4/untracked",
};
static const unsigned int statuses[] = {
GIT_STATUS_WT_NEW,
GIT_STATUS_INDEX_NEW,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_NEW,
};
memset(&counts, 0x0, sizeof(status_entry_counts));
counts.expected_entry_count = 4;
counts.expected_paths = files;
counts.expected_statuses = statuses;
opts.flags = GIT_STATUS_OPT_DEFAULTS |
GIT_STATUS_OPT_INCLUDE_IGNORED |
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);
}
refute_is_ignored("d1/pfx-d2/d3/d4/d5/tracked");
refute_is_ignored("d1/pfx-d2/d3/d4/d5/untracked");
refute_is_ignored("d1/pfx-d2/d3/d4/untracked");
}
void test_status_ignore__negative_ignores_inside_ignores(void)
{
static const char *test_files[] = {
"empty_standard_repo/top/mid/btm/tracked",
"empty_standard_repo/top/mid/btm/untracked",
"empty_standard_repo/zoo/bar",
"empty_standard_repo/zoo/foo/bar",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"top\n"
"!top/mid/btm\n"
"zoo/*\n"
"!zoo/bar\n"
"!zoo/foo/bar\n");
add_one_to_index("top/mid/btm/tracked");
{
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts;
static const char *files[] = {
".gitignore", "top/mid/btm/tracked", "top/mid/btm/untracked",
"zoo/bar", "zoo/foo/bar",
};
static const unsigned int statuses[] = {
GIT_STATUS_WT_NEW, GIT_STATUS_INDEX_NEW, GIT_STATUS_IGNORED,
GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED,
};
memset(&counts, 0x0, sizeof(status_entry_counts));
counts.expected_entry_count = 5;
counts.expected_paths = files;
counts.expected_statuses = statuses;
opts.flags = GIT_STATUS_OPT_DEFAULTS |
GIT_STATUS_OPT_INCLUDE_IGNORED |
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);
}
assert_is_ignored("top/mid/btm/tracked");
assert_is_ignored("top/mid/btm/untracked");
refute_is_ignored("foo/bar");
}
void test_status_ignore__negative_ignores_in_slash_star(void)
{
git_status_options status_opts = GIT_STATUS_OPTIONS_INIT;
git_status_list *list;
int found_look_ma = 0, found_what_about = 0;
size_t i;
static const char *test_files[] = {
"empty_standard_repo/bin/look-ma.txt",
"empty_standard_repo/bin/what-about-me.txt",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"bin/*\n"
"!bin/w*\n");
assert_is_ignored("bin/look-ma.txt");
refute_is_ignored("bin/what-about-me.txt");
status_opts.flags = GIT_STATUS_OPT_DEFAULTS;
cl_git_pass(git_status_list_new(&list, g_repo, &status_opts));
for (i = 0; i < git_status_list_entrycount(list); i++) {
const git_status_entry *entry = git_status_byindex(list, i);
if (!strcmp("bin/look-ma.txt", entry->index_to_workdir->new_file.path))
found_look_ma = 1;
if (!strcmp("bin/what-about-me.txt", entry->index_to_workdir->new_file.path))
found_what_about = 1;
}
git_status_list_free(list);
cl_assert(found_look_ma);
cl_assert(found_what_about);
}
void test_status_ignore__negative_ignores_without_trailing_slash_inside_ignores(void)
{
git_status_options status_opts = GIT_STATUS_OPTIONS_INIT;
git_status_list *list;
int found_parent_file = 0, found_parent_child1_file = 0, found_parent_child2_file = 0;
size_t i;
static const char *test_files[] = {
"empty_standard_repo/parent/file.txt",
"empty_standard_repo/parent/force.txt",
"empty_standard_repo/parent/child1/file.txt",
"empty_standard_repo/parent/child2/file.txt",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"parent/*\n"
"!parent/force.txt\n"
"!parent/child1\n"
"!parent/child2/\n");
add_one_to_index("parent/force.txt");
assert_is_ignored("parent/file.txt");
refute_is_ignored("parent/force.txt");
refute_is_ignored("parent/child1/file.txt");
refute_is_ignored("parent/child2/file.txt");
status_opts.flags = GIT_STATUS_OPT_DEFAULTS;
cl_git_pass(git_status_list_new(&list, g_repo, &status_opts));
for (i = 0; i < git_status_list_entrycount(list); i++) {
const git_status_entry *entry = git_status_byindex(list, i);
if (!entry->index_to_workdir)
continue;
if (!strcmp("parent/file.txt", entry->index_to_workdir->new_file.path))
found_parent_file = 1;
if (!strcmp("parent/force.txt", entry->index_to_workdir->new_file.path))
found_parent_file = 1;
if (!strcmp("parent/child1/file.txt", entry->index_to_workdir->new_file.path))
found_parent_child1_file = 1;
if (!strcmp("parent/child2/file.txt", entry->index_to_workdir->new_file.path))
found_parent_child2_file = 1;
}
git_status_list_free(list);
cl_assert(found_parent_file);
cl_assert(found_parent_child1_file);
cl_assert(found_parent_child2_file);
}
void test_status_ignore__negative_directory_ignores(void)
{
static const char *test_files[] = {
"empty_standard_repo/parent/child1/bar.txt",
"empty_standard_repo/parent/child2/bar.txt",
"empty_standard_repo/parent/child3/foo.txt",
"empty_standard_repo/parent/child4/bar.txt",
"empty_standard_repo/parent/nested/child5/bar.txt",
"empty_standard_repo/parent/nested/child6/bar.txt",
"empty_standard_repo/parent/nested/child7/bar.txt",
"empty_standard_repo/padded_parent/child8/bar.txt",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"foo.txt\n"
"parent/child1\n"
"parent/child2\n"
"parent/child4\n"
"parent/nested/child5\n"
"nested/child6\n"
"nested/child7\n"
"padded_parent/child8\n"
/* test simple exact match */
"!parent/child1\n"
/* test negating file without negating dir */
"!parent/child2/bar.txt\n"
/* test negative pattern on dir with its content
* being ignored */
"!parent/child3\n"
/* test with partial match at end */
"!child4\n"
/* test with partial match with '/' at end */
"!nested/child5\n"
/* test with complete match */
"!nested/child6\n"
/* test with trailing '/' */
"!child7/\n"
/* test with partial dir match */
"!_parent/child8\n");
refute_is_ignored("parent/child1/bar.txt");
assert_is_ignored("parent/child2/bar.txt");
assert_is_ignored("parent/child3/foo.txt");
refute_is_ignored("parent/child4/bar.txt");
assert_is_ignored("parent/nested/child5/bar.txt");
refute_is_ignored("parent/nested/child6/bar.txt");
refute_is_ignored("parent/nested/child7/bar.txt");
assert_is_ignored("padded_parent/child8/bar.txt");
}
void test_status_ignore__unignore_entry_in_ignored_dir(void)
{
static const char *test_files[] = {
"empty_standard_repo/bar.txt",
"empty_standard_repo/parent/bar.txt",
"empty_standard_repo/parent/child/bar.txt",
"empty_standard_repo/nested/parent/child/bar.txt",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"bar.txt\n"
"!parent/child/bar.txt\n");
assert_is_ignored("bar.txt");
assert_is_ignored("parent/bar.txt");
refute_is_ignored("parent/child/bar.txt");
assert_is_ignored("nested/parent/child/bar.txt");
}
void test_status_ignore__do_not_unignore_basename_prefix(void)
{
static const char *test_files[] = {
"empty_standard_repo/foo_bar.txt",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"foo_bar.txt\n"
"!bar.txt\n");
assert_is_ignored("foo_bar.txt");
}
void test_status_ignore__filename_with_cr(void)
{
int ignored;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_mkfile("empty_standard_repo/.gitignore", "Icon\r\r\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r"));
cl_assert_equal_i(1, ignored);
cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn"));
cl_assert_equal_i(1, ignored);
cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\r\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn"));
cl_assert_equal_i(1, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn\r"));
cl_assert_equal_i(0, ignored);
cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\r\r\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn\r"));
cl_assert_equal_i(1, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r"));
cl_assert_equal_i(0, ignored);
cl_git_mkfile("empty_standard_repo/.gitignore", "Icon\r\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r"));
cl_assert_equal_i(0, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon"));
cl_assert_equal_i(1, ignored);
}
void test_status_ignore__subdir_doesnt_match_above(void)
{
int ignored, icase = 0, error;
git_config *cfg;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_pass(git_repository_config_snapshot(&cfg, g_repo));
error = git_config_get_bool(&icase, cfg, "core.ignorecase");
git_config_free(cfg);
if (error == GIT_ENOTFOUND)
error = 0;
cl_git_pass(error);
cl_git_pass(p_mkdir("empty_standard_repo/src", 0777));
cl_git_pass(p_mkdir("empty_standard_repo/src/src", 0777));
cl_git_mkfile("empty_standard_repo/src/.gitignore", "src\n");
cl_git_mkfile("empty_standard_repo/.gitignore", "");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/test.txt"));
cl_assert_equal_i(0, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/src/test.txt"));
cl_assert_equal_i(1, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/foo/test.txt"));
cl_assert_equal_i(0, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "SRC/src/test.txt"));
cl_assert_equal_i(icase, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/SRC/test.txt"));
cl_assert_equal_i(icase, ignored);
}
void test_status_ignore__negate_exact_previous(void)
{
int ignored;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_mkfile("empty_standard_repo/.gitignore", "*.com\ntags\n!tags/\n.buildpath");
cl_git_mkfile("empty_standard_repo/.buildpath", "");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, ".buildpath"));
cl_assert_equal_i(1, ignored);
}
void test_status_ignore__negate_starstar(void)
{
int ignored;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_mkfile("empty_standard_repo/.gitignore",
"code/projects/**/packages/*\n"
"!code/projects/**/packages/repositories.config");
cl_git_pass(git_futils_mkdir_r("empty_standard_repo/code/projects/foo/bar/packages", 0777));
cl_git_mkfile("empty_standard_repo/code/projects/foo/bar/packages/repositories.config", "");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "code/projects/foo/bar/packages/repositories.config"));
cl_assert_equal_i(0, ignored);
}
void test_status_ignore__ignore_all_toplevel_dirs_include_files(void)
{
static const char *test_files[] = {
"empty_standard_repo/README.md",
"empty_standard_repo/src/main.c",
"empty_standard_repo/src/foo/foo.c",
"empty_standard_repo/dist/foo.o",
"empty_standard_repo/dist/main.o",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"/*/\n"
"!/src\n");
assert_is_ignored("dist/foo.o");
assert_is_ignored("dist/main.o");
refute_is_ignored("README.md");
refute_is_ignored("src/foo.c");
refute_is_ignored("src/foo/foo.c");
}
void test_status_ignore__subdir_ignore_all_toplevel_dirs_include_files(void)
{
static const char *test_files[] = {
"empty_standard_repo/project/README.md",
"empty_standard_repo/project/src/main.c",
"empty_standard_repo/project/src/foo/foo.c",
"empty_standard_repo/project/dist/foo.o",
"empty_standard_repo/project/dist/main.o",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/project/.gitignore",
"/*/\n"
"!/src\n");
assert_is_ignored("project/dist/foo.o");
assert_is_ignored("project/dist/main.o");
refute_is_ignored("project/src/foo.c");
refute_is_ignored("project/src/foo/foo.c");
refute_is_ignored("project/README.md");
}
void test_status_ignore__subdir_ignore_everything_except_certain_files(void)
{
static const char *test_files[] = {
"empty_standard_repo/project/README.md",
"empty_standard_repo/project/some_file",
"empty_standard_repo/project/src/main.c",
"empty_standard_repo/project/src/foo/foo.c",
"empty_standard_repo/project/dist/foo.o",
"empty_standard_repo/project/dist/main.o",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/project/.gitignore",
"/*\n"
"!/src\n"
"!README.md\n");
assert_is_ignored("project/some_file");
assert_is_ignored("project/dist/foo.o");
assert_is_ignored("project/dist/main.o");
refute_is_ignored("project/README.md");
refute_is_ignored("project/src/foo.c");
refute_is_ignored("project/src/foo/foo.c");
}
void test_status_ignore__deeper(void)
{
const char *test_files[] = {
"empty_standard_repo/foo.data",
"empty_standard_repo/bar.data",
"empty_standard_repo/dont_ignore/foo.data",
"empty_standard_repo/dont_ignore/bar.data",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile("empty_standard_repo/.gitignore",
"*.data\n"
"!dont_ignore/*.data\n");
assert_is_ignored("foo.data");
assert_is_ignored("bar.data");
refute_is_ignored("dont_ignore/foo.data");
refute_is_ignored("dont_ignore/bar.data");
}
void test_status_ignore__unignored_dir_with_ignored_contents(void)
{
static const char *test_files[] = {
"empty_standard_repo/dir/a.test",
"empty_standard_repo/dir/subdir/a.test",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"*.test\n"
"!dir/*\n");
refute_is_ignored("dir/a.test");
assert_is_ignored("dir/subdir/a.test");
}
void test_status_ignore__unignored_subdirs(void)
{
static const char *test_files[] = {
"empty_standard_repo/dir/a.test",
"empty_standard_repo/dir/subdir/a.test",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"dir/*\n"
"!dir/*/\n");
assert_is_ignored("dir/a.test");
refute_is_ignored("dir/subdir/a.test");
}
void test_status_ignore__skips_bom(void)
{
static const char *test_files[] = {
"empty_standard_repo/a.test",
"empty_standard_repo/b.test",
"empty_standard_repo/c.test",
"empty_standard_repo/foo.txt",
"empty_standard_repo/bar.txt",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"\xEF\xBB\xBF*.test\n");
assert_is_ignored("a.test");
assert_is_ignored("b.test");
assert_is_ignored("c.test");
refute_is_ignored("foo.txt");
refute_is_ignored("bar.txt");
}
void test_status_ignore__leading_spaces_are_significant(void)
{
static const char *test_files[] = {
"empty_standard_repo/a.test",
"empty_standard_repo/b.test",
"empty_standard_repo/c.test",
"empty_standard_repo/d.test",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
" a.test\n"
"# this is a comment\n"
"b.test\n"
"\tc.test\n"
" # not a comment\n"
"d.test\n");
refute_is_ignored("a.test");
assert_is_ignored(" a.test");
refute_is_ignored("# this is a comment");
assert_is_ignored("b.test");
refute_is_ignored("c.test");
assert_is_ignored("\tc.test");
assert_is_ignored(" # not a comment");
assert_is_ignored("d.test");
}
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