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
7779437f
Commit
7779437f
authored
Jul 24, 2012
by
Russell Belfer
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #799 from yorah/fix/issue-787
Fix/issue 787
parents
944d250f
a1773f9d
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
207 additions
and
20 deletions
+207
-20
include/git2/diff.h
+1
-0
include/git2/status.h
+3
-0
src/attr_file.c
+1
-11
src/buffer.c
+4
-0
src/buffer.h
+3
-0
src/diff.c
+17
-7
src/status.c
+6
-2
src/util.c
+18
-0
src/util.h
+9
-0
tests-clar/core/buffer.c
+20
-0
tests-clar/status/worktree.c
+125
-0
No files found.
include/git2/diff.h
View file @
7779437f
...
...
@@ -46,6 +46,7 @@ enum {
GIT_DIFF_INCLUDE_UNTRACKED
=
(
1
<<
8
),
GIT_DIFF_INCLUDE_UNMODIFIED
=
(
1
<<
9
),
GIT_DIFF_RECURSE_UNTRACKED_DIRS
=
(
1
<<
10
),
GIT_DIFF_DISABLE_PATHSPEC_MATCH
=
(
1
<<
11
),
};
/**
...
...
include/git2/status.h
View file @
7779437f
...
...
@@ -96,6 +96,8 @@ typedef enum {
* the top-level directory will be included (with a trailing
* slash on the entry name). Given this flag, the directory
* itself will not be included, but all the files in it will.
* - GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH indicates that the given
* path will be treated as a literal path, and not as a pathspec.
*/
enum
{
...
...
@@ -104,6 +106,7 @@ enum {
GIT_STATUS_OPT_INCLUDE_UNMODIFIED
=
(
1
<<
2
),
GIT_STATUS_OPT_EXCLUDE_SUBMODULES
=
(
1
<<
3
),
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
=
(
1
<<
4
),
GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH
=
(
1
<<
5
),
};
/**
...
...
src/attr_file.c
View file @
7779437f
...
...
@@ -426,17 +426,7 @@ int git_attr_fnmatch__parse(
return
-
1
;
}
else
{
/* strip '\' that might have be used for internal whitespace */
char
*
to
=
spec
->
pattern
;
for
(
scan
=
spec
->
pattern
;
*
scan
;
to
++
,
scan
++
)
{
if
(
*
scan
==
'\\'
)
scan
++
;
/* skip '\' but include next char */
if
(
to
!=
scan
)
*
to
=
*
scan
;
}
if
(
to
!=
scan
)
{
*
to
=
'\0'
;
spec
->
length
=
(
to
-
spec
->
pattern
);
}
spec
->
length
=
git__unescape
(
spec
->
pattern
);
}
return
0
;
...
...
src/buffer.c
View file @
7779437f
...
...
@@ -496,3 +496,7 @@ bool git_buf_is_binary(const git_buf *buf)
return
((
printable
>>
7
)
<
nonprintable
);
}
void
git_buf_unescape
(
git_buf
*
buf
)
{
buf
->
size
=
git__unescape
(
buf
->
ptr
);
}
src/buffer.h
View file @
7779437f
...
...
@@ -151,4 +151,7 @@ int git_buf_common_prefix(git_buf *buf, const git_strarray *strings);
/* Check if buffer looks like it contains binary data */
bool
git_buf_is_binary
(
const
git_buf
*
buf
);
/* Unescape all characters in a buffer */
void
git_buf_unescape
(
git_buf
*
buf
);
#endif
src/diff.c
View file @
7779437f
...
...
@@ -20,14 +20,21 @@ static char *diff_prefix_from_pathspec(const git_strarray *pathspec)
return
NULL
;
/* diff prefix will only be leading non-wildcards */
for
(
scan
=
prefix
.
ptr
;
*
scan
&&
!
git__iswildcard
(
*
scan
);
++
scan
);
for
(
scan
=
prefix
.
ptr
;
*
scan
;
++
scan
)
{
if
(
git__iswildcard
(
*
scan
)
&&
(
scan
==
prefix
.
ptr
||
(
*
(
scan
-
1
)
!=
'\\'
)))
break
;
}
git_buf_truncate
(
&
prefix
,
scan
-
prefix
.
ptr
);
if
(
prefix
.
size
>
0
)
return
git_buf_detach
(
&
prefix
);
if
(
prefix
.
size
<=
0
)
{
git_buf_free
(
&
prefix
);
return
NULL
;
}
git_buf_free
(
&
prefix
);
return
NULL
;
git_buf_unescape
(
&
prefix
);
return
git_buf_detach
(
&
prefix
);
}
static
bool
diff_pathspec_is_interesting
(
const
git_strarray
*
pathspec
)
...
...
@@ -54,7 +61,11 @@ static bool diff_path_matches_pathspec(git_diff_list *diff, const char *path)
return
true
;
git_vector_foreach
(
&
diff
->
pathspec
,
i
,
match
)
{
int
result
=
p_fnmatch
(
match
->
pattern
,
path
,
0
);
int
result
=
strcmp
(
match
->
pattern
,
path
)
?
FNM_NOMATCH
:
0
;
if
(((
diff
->
opts
.
flags
&
GIT_DIFF_DISABLE_PATHSPEC_MATCH
)
==
0
)
&&
result
==
FNM_NOMATCH
)
result
=
p_fnmatch
(
match
->
pattern
,
path
,
0
);
/* if we didn't match, look for exact dirname prefix match */
if
(
result
==
FNM_NOMATCH
&&
...
...
@@ -826,4 +837,3 @@ int git_diff_merge(
return
error
;
}
src/status.c
View file @
7779437f
...
...
@@ -99,6 +99,8 @@ int git_status_foreach_ext(
diffopt
.
flags
=
diffopt
.
flags
|
GIT_DIFF_INCLUDE_UNMODIFIED
;
if
((
opts
->
flags
&
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
)
!=
0
)
diffopt
.
flags
=
diffopt
.
flags
|
GIT_DIFF_RECURSE_UNTRACKED_DIRS
;
if
((
opts
->
flags
&
GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH
)
!=
0
)
diffopt
.
flags
=
diffopt
.
flags
|
GIT_DIFF_DISABLE_PATHSPEC_MATCH
;
/* TODO: support EXCLUDE_SUBMODULES flag */
if
(
show
!=
GIT_STATUS_SHOW_WORKDIR_ONLY
&&
...
...
@@ -176,10 +178,12 @@ static int get_one_status(const char *path, unsigned int status, void *data)
sfi
->
count
++
;
sfi
->
status
=
status
;
if
(
sfi
->
count
>
1
||
strcmp
(
sfi
->
expected
,
path
)
!=
0
)
{
if
(
sfi
->
count
>
1
||
(
strcmp
(
sfi
->
expected
,
path
)
!=
0
&&
p_fnmatch
(
sfi
->
expected
,
path
,
0
)
!=
0
))
{
giterr_set
(
GITERR_INVALID
,
"Ambiguous path '%s' given to git_status_file"
,
sfi
->
expected
);
return
-
1
;
return
GIT_EAMBIGUOUS
;
}
return
0
;
...
...
src/util.c
View file @
7779437f
...
...
@@ -435,3 +435,21 @@ int git__parse_bool(int *out, const char *value)
return
-
1
;
}
size_t
git__unescape
(
char
*
str
)
{
char
*
scan
,
*
pos
=
str
;
for
(
scan
=
str
;
*
scan
;
pos
++
,
scan
++
)
{
if
(
*
scan
==
'\\'
&&
*
(
scan
+
1
)
!=
'\0'
)
scan
++
;
/* skip '\' but include next char */
if
(
pos
!=
scan
)
*
pos
=
*
scan
;
}
if
(
pos
!=
scan
)
{
*
pos
=
'\0'
;
}
return
(
pos
-
str
);
}
src/util.h
View file @
7779437f
...
...
@@ -238,4 +238,13 @@ extern int git__parse_bool(int *out, const char *value);
*/
int
git__date_parse
(
git_time_t
*
out
,
const
char
*
date
);
/*
* Unescapes a string in-place.
*
* Edge cases behavior:
* - "jackie\" -> "jacky\"
* - "chan\\" -> "chan\"
*/
extern
size_t
git__unescape
(
char
*
str
);
#endif
/* INCLUDE_util_h__ */
tests-clar/core/buffer.c
View file @
7779437f
...
...
@@ -658,3 +658,23 @@ void test_core_buffer__puts_escaped(void)
git_buf_free
(
&
a
);
}
static
void
assert_unescape
(
char
*
expected
,
char
*
to_unescape
)
{
git_buf
buf
=
GIT_BUF_INIT
;
cl_git_pass
(
git_buf_sets
(
&
buf
,
to_unescape
));
git_buf_unescape
(
&
buf
);
cl_assert_equal_s
(
expected
,
buf
.
ptr
);
cl_assert_equal_i
(
strlen
(
expected
),
buf
.
size
);
git_buf_free
(
&
buf
);
}
void
test_core_buffer__unescape
(
void
)
{
assert_unescape
(
"Escaped
\\
"
,
"Es
\\
ca
\\
ped
\\
"
);
assert_unescape
(
"Es
\\
caped
\\
"
,
"Es
\\\\
ca
\\
ped
\\\\
"
);
assert_unescape
(
"
\\
"
,
"
\\
"
);
assert_unescape
(
"
\\
"
,
"
\\\\
"
);
assert_unescape
(
""
,
""
);
}
tests-clar/status/worktree.c
View file @
7779437f
...
...
@@ -517,6 +517,85 @@ void test_status_worktree__status_file_with_clean_index_and_empty_workdir(void)
cl_git_pass
(
p_unlink
(
"my-index"
));
}
void
test_status_worktree__bracket_in_filename
(
void
)
{
git_repository
*
repo
;
git_index
*
index
;
status_entry_single
result
;
unsigned
int
status_flags
;
int
error
;
#define FILE_WITH_BRACKET "LICENSE[1].md"
#define FILE_WITHOUT_BRACKET "LICENSE1.md"
cl_git_pass
(
git_repository_init
(
&
repo
,
"with_bracket"
,
0
));
cl_git_mkfile
(
"with_bracket/"
FILE_WITH_BRACKET
,
"I have a bracket in my name
\n
"
);
/* file is new to working directory */
memset
(
&
result
,
0
,
sizeof
(
result
));
cl_git_pass
(
git_status_foreach
(
repo
,
cb_status__single
,
&
result
));
cl_assert_equal_i
(
1
,
result
.
count
);
cl_assert
(
result
.
status
==
GIT_STATUS_WT_NEW
);
cl_git_pass
(
git_status_file
(
&
status_flags
,
repo
,
FILE_WITH_BRACKET
));
cl_assert
(
status_flags
==
GIT_STATUS_WT_NEW
);
/* ignore the file */
cl_git_rewritefile
(
"with_bracket/.gitignore"
,
"*.md
\n
.gitignore
\n
"
);
memset
(
&
result
,
0
,
sizeof
(
result
));
cl_git_pass
(
git_status_foreach
(
repo
,
cb_status__single
,
&
result
));
cl_assert_equal_i
(
2
,
result
.
count
);
cl_assert
(
result
.
status
==
GIT_STATUS_IGNORED
);
cl_git_pass
(
git_status_file
(
&
status_flags
,
repo
,
FILE_WITH_BRACKET
));
cl_assert
(
status_flags
==
GIT_STATUS_IGNORED
);
/* don't ignore the file */
cl_git_rewritefile
(
"with_bracket/.gitignore"
,
".gitignore
\n
"
);
memset
(
&
result
,
0
,
sizeof
(
result
));
cl_git_pass
(
git_status_foreach
(
repo
,
cb_status__single
,
&
result
));
cl_assert_equal_i
(
2
,
result
.
count
);
cl_assert
(
result
.
status
==
GIT_STATUS_WT_NEW
);
cl_git_pass
(
git_status_file
(
&
status_flags
,
repo
,
FILE_WITH_BRACKET
));
cl_assert
(
status_flags
==
GIT_STATUS_WT_NEW
);
/* add the file to the index */
cl_git_pass
(
git_repository_index
(
&
index
,
repo
));
cl_git_pass
(
git_index_add
(
index
,
FILE_WITH_BRACKET
,
0
));
cl_git_pass
(
git_index_write
(
index
));
memset
(
&
result
,
0
,
sizeof
(
result
));
cl_git_pass
(
git_status_foreach
(
repo
,
cb_status__single
,
&
result
));
cl_assert_equal_i
(
2
,
result
.
count
);
cl_assert
(
result
.
status
==
GIT_STATUS_INDEX_NEW
);
cl_git_pass
(
git_status_file
(
&
status_flags
,
repo
,
FILE_WITH_BRACKET
));
cl_assert
(
status_flags
==
GIT_STATUS_INDEX_NEW
);
/* Create file without bracket */
cl_git_mkfile
(
"with_bracket/"
FILE_WITHOUT_BRACKET
,
"I have no bracket in my name!
\n
"
);
cl_git_pass
(
git_status_file
(
&
status_flags
,
repo
,
FILE_WITHOUT_BRACKET
));
cl_assert
(
status_flags
==
GIT_STATUS_WT_NEW
);
cl_git_pass
(
git_status_file
(
&
status_flags
,
repo
,
"LICENSE
\\
[1
\\
].md"
));
cl_assert
(
status_flags
==
GIT_STATUS_INDEX_NEW
);
error
=
git_status_file
(
&
status_flags
,
repo
,
FILE_WITH_BRACKET
);
cl_git_fail
(
error
);
cl_assert
(
error
==
GIT_EAMBIGUOUS
);
git_index_free
(
index
);
git_repository_free
(
repo
);
}
void
test_status_worktree__space_in_filename
(
void
)
{
...
...
@@ -647,3 +726,49 @@ void test_status_worktree__filemode_changes(void)
git_config_free
(
cfg
);
}
int
cb_status__expected_path
(
const
char
*
p
,
unsigned
int
s
,
void
*
payload
)
{
const
char
*
expected_path
=
(
const
char
*
)
payload
;
GIT_UNUSED
(
s
);
if
(
payload
==
NULL
)
cl_fail
(
"Unexpected path"
);
cl_assert_equal_s
(
expected_path
,
p
);
return
0
;
}
void
test_status_worktree__disable_pathspec_match
(
void
)
{
git_repository
*
repo
;
git_status_options
opts
;
char
*
file_with_bracket
=
"LICENSE[1].md"
,
*
imaginary_file_with_bracket
=
"LICENSE[1-2].md"
;
cl_git_pass
(
git_repository_init
(
&
repo
,
"pathspec"
,
0
));
cl_git_mkfile
(
"pathspec/LICENSE[1].md"
,
"screaming bracket
\n
"
);
cl_git_mkfile
(
"pathspec/LICENSE1.md"
,
"no bracket
\n
"
);
memset
(
&
opts
,
0
,
sizeof
(
opts
));
opts
.
flags
=
GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH
;
opts
.
pathspec
.
count
=
1
;
opts
.
pathspec
.
strings
=
&
file_with_bracket
;
cl_git_pass
(
git_status_foreach_ext
(
repo
,
&
opts
,
cb_status__expected_path
,
file_with_bracket
)
);
/* Test passing a pathspec matching files in the workdir. */
/* Must not match because pathspecs are disabled. */
opts
.
pathspec
.
strings
=
&
imaginary_file_with_bracket
;
cl_git_pass
(
git_status_foreach_ext
(
repo
,
&
opts
,
cb_status__expected_path
,
NULL
)
);
git_repository_free
(
repo
);
}
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