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
e77e53ed
Commit
e77e53ed
authored
Apr 13, 2012
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #627 from arrbee/diff-with-pathspec
Diff with pathspec
parents
d1f33156
14a513e0
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
206 additions
and
7 deletions
+206
-7
include/git2/common.h
+1
-0
src/attr_file.c
+4
-0
src/attr_file.h
+1
-0
src/diff.c
+92
-5
src/diff.h
+1
-0
src/status.c
+1
-0
src/util.c
+29
-0
tests-clar/attr/file.c
+4
-2
tests-clar/diff/workdir.c
+73
-0
No files found.
include/git2/common.h
View file @
e77e53ed
...
...
@@ -87,6 +87,7 @@ typedef struct {
}
git_strarray
;
GIT_EXTERN
(
void
)
git_strarray_free
(
git_strarray
*
array
);
GIT_EXTERN
(
int
)
git_strarray_copy
(
git_strarray
*
tgt
,
const
git_strarray
*
src
);
/**
* Return the version of the libgit2 library
...
...
src/attr_file.c
View file @
e77e53ed
...
...
@@ -334,6 +334,10 @@ int git_attr_fnmatch__parse(
spec
->
flags
=
spec
->
flags
|
GIT_ATTR_FNMATCH_FULLPATH
;
slash_count
++
;
}
/* remember if we see an unescaped wildcard in pattern */
else
if
((
*
scan
==
'*'
||
*
scan
==
'.'
||
*
scan
==
'['
)
&&
(
scan
==
pattern
||
(
*
(
scan
-
1
)
!=
'\\'
)))
spec
->
flags
=
spec
->
flags
|
GIT_ATTR_FNMATCH_HASWILD
;
}
*
base
=
scan
;
...
...
src/attr_file.h
View file @
e77e53ed
...
...
@@ -20,6 +20,7 @@
#define GIT_ATTR_FNMATCH_FULLPATH (1U << 2)
#define GIT_ATTR_FNMATCH_MACRO (1U << 3)
#define GIT_ATTR_FNMATCH_IGNORE (1U << 4)
#define GIT_ATTR_FNMATCH_HASWILD (1U << 5)
typedef
struct
{
char
*
pattern
;
...
...
src/diff.c
View file @
e77e53ed
...
...
@@ -9,6 +9,50 @@
#include "diff.h"
#include "fileops.h"
#include "config.h"
#include "attr_file.h"
static
bool
diff_pathspec_is_interesting
(
const
git_strarray
*
pathspec
)
{
const
char
*
str
;
if
(
pathspec
==
NULL
||
pathspec
->
count
==
0
)
return
false
;
if
(
pathspec
->
count
>
1
)
return
true
;
str
=
pathspec
->
strings
[
0
];
if
(
!
str
||
!
str
[
0
]
||
(
!
str
[
1
]
&&
(
str
[
0
]
==
'*'
||
str
[
0
]
==
'.'
)))
return
false
;
return
true
;
}
static
bool
diff_path_matches_pathspec
(
git_diff_list
*
diff
,
const
char
*
path
)
{
unsigned
int
i
;
git_attr_fnmatch
*
match
;
if
(
!
diff
->
pathspec
.
length
)
return
true
;
git_vector_foreach
(
&
diff
->
pathspec
,
i
,
match
)
{
int
result
=
git__fnmatch
(
match
->
pattern
,
path
,
0
);
/* if we didn't match, look for exact dirname prefix match */
if
(
result
==
GIT_ENOMATCH
&&
(
match
->
flags
&
GIT_ATTR_FNMATCH_HASWILD
)
==
0
&&
strncmp
(
path
,
match
->
pattern
,
match
->
length
)
==
0
&&
path
[
match
->
length
]
==
'/'
)
result
=
0
;
if
(
result
==
0
)
return
(
match
->
flags
&
GIT_ATTR_FNMATCH_NEGATIVE
)
?
false
:
true
;
if
(
result
!=
GIT_ENOMATCH
)
giterr_clear
();
}
return
false
;
}
static
void
diff_delta__free
(
git_diff_delta
*
delta
)
{
...
...
@@ -143,6 +187,9 @@ static int diff_delta__from_one(
(
diff
->
opts
.
flags
&
GIT_DIFF_INCLUDE_UNTRACKED
)
==
0
)
return
0
;
if
(
!
diff_path_matches_pathspec
(
diff
,
entry
->
path
))
return
0
;
delta
=
diff_delta__alloc
(
diff
,
status
,
entry
->
path
);
GITERR_CHECK_ALLOC
(
delta
);
...
...
@@ -246,6 +293,7 @@ static git_diff_list *git_diff_list_alloc(
git_repository
*
repo
,
const
git_diff_options
*
opts
)
{
git_config
*
cfg
;
size_t
i
;
git_diff_list
*
diff
=
git__calloc
(
1
,
sizeof
(
git_diff_list
));
if
(
diff
==
NULL
)
return
NULL
;
...
...
@@ -269,6 +317,7 @@ static git_diff_list *git_diff_list_alloc(
return
diff
;
memcpy
(
&
diff
->
opts
,
opts
,
sizeof
(
git_diff_options
));
memset
(
&
diff
->
opts
.
pathspec
,
0
,
sizeof
(
diff
->
opts
.
pathspec
));
diff
->
opts
.
src_prefix
=
diff_strdup_prefix
(
opts
->
src_prefix
?
opts
->
src_prefix
:
DIFF_SRC_PREFIX_DEFAULT
);
...
...
@@ -287,21 +336,45 @@ static git_diff_list *git_diff_list_alloc(
if
(
git_vector_init
(
&
diff
->
deltas
,
0
,
diff_delta__cmp
)
<
0
)
goto
fail
;
/* TODO: do something safe with the pathspec strarray */
/* only copy pathspec if it is "interesting" so we can test
* diff->pathspec.length > 0 to know if it is worth calling
* fnmatch as we iterate.
*/
if
(
!
diff_pathspec_is_interesting
(
&
opts
->
pathspec
))
return
diff
;
if
(
git_vector_init
(
&
diff
->
pathspec
,
opts
->
pathspec
.
count
,
NULL
)
<
0
)
goto
fail
;
for
(
i
=
0
;
i
<
opts
->
pathspec
.
count
;
++
i
)
{
int
ret
;
const
char
*
pattern
=
opts
->
pathspec
.
strings
[
i
];
git_attr_fnmatch
*
match
=
git__calloc
(
1
,
sizeof
(
git_attr_fnmatch
));
if
(
!
match
)
goto
fail
;
ret
=
git_attr_fnmatch__parse
(
match
,
NULL
,
&
pattern
);
if
(
ret
==
GIT_ENOTFOUND
)
{
git__free
(
match
);
continue
;
}
else
if
(
ret
<
0
)
goto
fail
;
if
(
git_vector_insert
(
&
diff
->
pathspec
,
match
)
<
0
)
goto
fail
;
}
return
diff
;
fail:
git_vector_free
(
&
diff
->
deltas
);
git__free
(
diff
->
opts
.
src_prefix
);
git__free
(
diff
->
opts
.
dst_prefix
);
git__free
(
diff
);
git_diff_list_free
(
diff
);
return
NULL
;
}
void
git_diff_list_free
(
git_diff_list
*
diff
)
{
git_diff_delta
*
delta
;
git_attr_fnmatch
*
match
;
unsigned
int
i
;
if
(
!
diff
)
...
...
@@ -312,6 +385,17 @@ void git_diff_list_free(git_diff_list *diff)
diff
->
deltas
.
contents
[
i
]
=
NULL
;
}
git_vector_free
(
&
diff
->
deltas
);
git_vector_foreach
(
&
diff
->
pathspec
,
i
,
match
)
{
if
(
match
!=
NULL
)
{
git__free
(
match
->
pattern
);
match
->
pattern
=
NULL
;
git__free
(
match
);
diff
->
pathspec
.
contents
[
i
]
=
NULL
;
}
}
git_vector_free
(
&
diff
->
pathspec
);
git__free
(
diff
->
opts
.
src_prefix
);
git__free
(
diff
->
opts
.
dst_prefix
);
git__free
(
diff
);
...
...
@@ -366,6 +450,9 @@ static int maybe_modified(
GIT_UNUSED
(
old
);
if
(
!
diff_path_matches_pathspec
(
diff
,
oitem
->
path
))
return
0
;
/* on platforms with no symlinks, promote plain files to symlinks */
if
(
S_ISLNK
(
omode
)
&&
S_ISREG
(
nmode
)
&&
!
(
diff
->
diffcaps
&
GIT_DIFFCAPS_HAS_SYMLINKS
))
...
...
src/diff.h
View file @
e77e53ed
...
...
@@ -24,6 +24,7 @@ enum {
struct
git_diff_list
{
git_repository
*
repo
;
git_diff_options
opts
;
git_vector
pathspec
;
git_vector
deltas
;
/* vector of git_diff_file_delta */
git_iterator_type_t
old_src
;
git_iterator_type_t
new_src
;
...
...
src/status.c
View file @
e77e53ed
...
...
@@ -205,6 +205,7 @@ int git_status_foreach(
{
git_status_options
opts
;
memset
(
&
opts
,
0
,
sizeof
(
opts
));
opts
.
show
=
GIT_STATUS_SHOW_INDEX_AND_WORKDIR
;
opts
.
flags
=
GIT_STATUS_OPT_INCLUDE_IGNORED
|
GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
...
...
src/util.c
View file @
e77e53ed
...
...
@@ -31,6 +31,35 @@ void git_strarray_free(git_strarray *array)
git__free
(
array
->
strings
);
}
int
git_strarray_copy
(
git_strarray
*
tgt
,
const
git_strarray
*
src
)
{
size_t
i
;
assert
(
tgt
&&
src
);
memset
(
tgt
,
0
,
sizeof
(
*
tgt
));
if
(
!
src
->
count
)
return
0
;
tgt
->
strings
=
git__calloc
(
src
->
count
,
sizeof
(
char
*
));
GITERR_CHECK_ALLOC
(
tgt
->
strings
);
for
(
i
=
0
;
i
<
src
->
count
;
++
i
)
{
tgt
->
strings
[
tgt
->
count
]
=
git__strdup
(
src
->
strings
[
i
]);
if
(
!
tgt
->
strings
[
tgt
->
count
])
{
git_strarray_free
(
tgt
);
memset
(
tgt
,
0
,
sizeof
(
*
tgt
));
return
-
1
;
}
tgt
->
count
++
;
}
return
0
;
}
int
git__fnmatch
(
const
char
*
pattern
,
const
char
*
name
,
int
flags
)
{
int
ret
;
...
...
tests-clar/attr/file.c
View file @
e77e53ed
...
...
@@ -20,7 +20,7 @@ void test_attr_file__simple_read(void)
cl_assert
(
rule
!=
NULL
);
cl_assert_strequal
(
"*"
,
rule
->
match
.
pattern
);
cl_assert
(
rule
->
match
.
length
==
1
);
cl_assert
(
rule
->
match
.
flags
=
=
0
);
cl_assert
(
(
rule
->
match
.
flags
&
GIT_ATTR_FNMATCH_HASWILD
)
!
=
0
);
cl_assert
(
rule
->
assigns
.
length
==
1
);
assign
=
get_assign
(
rule
,
0
);
...
...
@@ -74,14 +74,16 @@ void test_attr_file__match_variants(void)
rule
=
get_rule
(
4
);
cl_assert_strequal
(
"pat4.*"
,
rule
->
match
.
pattern
);
cl_assert
(
rule
->
match
.
flags
=
=
0
);
cl_assert
(
(
rule
->
match
.
flags
&
GIT_ATTR_FNMATCH_HASWILD
)
!
=
0
);
rule
=
get_rule
(
5
);
cl_assert_strequal
(
"*.pat5"
,
rule
->
match
.
pattern
);
cl_assert
((
rule
->
match
.
flags
&
GIT_ATTR_FNMATCH_HASWILD
)
!=
0
);
rule
=
get_rule
(
7
);
cl_assert_strequal
(
"pat7[a-e]??[xyz]"
,
rule
->
match
.
pattern
);
cl_assert
(
rule
->
assigns
.
length
==
1
);
cl_assert
((
rule
->
match
.
flags
&
GIT_ATTR_FNMATCH_HASWILD
)
!=
0
);
assign
=
get_assign
(
rule
,
0
);
cl_assert_strequal
(
"attr7"
,
assign
->
name
);
cl_assert
(
GIT_ATTR_TRUE
(
assign
->
value
));
...
...
tests-clar/diff/workdir.c
View file @
e77e53ed
...
...
@@ -164,6 +164,79 @@ void test_diff_workdir__to_tree(void)
git_tree_free
(
b
);
}
void
test_diff_workdir__to_index_with_pathspec
(
void
)
{
git_diff_options
opts
=
{
0
};
git_diff_list
*
diff
=
NULL
;
diff_expects
exp
;
char
*
pathspec
=
NULL
;
opts
.
context_lines
=
3
;
opts
.
interhunk_lines
=
1
;
opts
.
flags
|=
GIT_DIFF_INCLUDE_IGNORED
|
GIT_DIFF_INCLUDE_UNTRACKED
;
opts
.
pathspec
.
strings
=
&
pathspec
;
opts
.
pathspec
.
count
=
1
;
memset
(
&
exp
,
0
,
sizeof
(
exp
));
cl_git_pass
(
git_diff_workdir_to_index
(
g_repo
,
&
opts
,
&
diff
));
cl_git_pass
(
git_diff_foreach
(
diff
,
&
exp
,
diff_file_fn
,
NULL
,
NULL
));
cl_assert_equal_i
(
12
,
exp
.
files
);
cl_assert_equal_i
(
0
,
exp
.
file_adds
);
cl_assert_equal_i
(
4
,
exp
.
file_dels
);
cl_assert_equal_i
(
4
,
exp
.
file_mods
);
cl_assert_equal_i
(
1
,
exp
.
file_ignored
);
cl_assert_equal_i
(
3
,
exp
.
file_untracked
);
git_diff_list_free
(
diff
);
memset
(
&
exp
,
0
,
sizeof
(
exp
));
pathspec
=
"modified_file"
;
cl_git_pass
(
git_diff_workdir_to_index
(
g_repo
,
&
opts
,
&
diff
));
cl_git_pass
(
git_diff_foreach
(
diff
,
&
exp
,
diff_file_fn
,
NULL
,
NULL
));
cl_assert_equal_i
(
1
,
exp
.
files
);
cl_assert_equal_i
(
0
,
exp
.
file_adds
);
cl_assert_equal_i
(
0
,
exp
.
file_dels
);
cl_assert_equal_i
(
1
,
exp
.
file_mods
);
cl_assert_equal_i
(
0
,
exp
.
file_ignored
);
cl_assert_equal_i
(
0
,
exp
.
file_untracked
);
git_diff_list_free
(
diff
);
memset
(
&
exp
,
0
,
sizeof
(
exp
));
pathspec
=
"subdir"
;
cl_git_pass
(
git_diff_workdir_to_index
(
g_repo
,
&
opts
,
&
diff
));
cl_git_pass
(
git_diff_foreach
(
diff
,
&
exp
,
diff_file_fn
,
NULL
,
NULL
));
cl_assert_equal_i
(
3
,
exp
.
files
);
cl_assert_equal_i
(
0
,
exp
.
file_adds
);
cl_assert_equal_i
(
1
,
exp
.
file_dels
);
cl_assert_equal_i
(
1
,
exp
.
file_mods
);
cl_assert_equal_i
(
0
,
exp
.
file_ignored
);
cl_assert_equal_i
(
1
,
exp
.
file_untracked
);
git_diff_list_free
(
diff
);
memset
(
&
exp
,
0
,
sizeof
(
exp
));
pathspec
=
"*_deleted"
;
cl_git_pass
(
git_diff_workdir_to_index
(
g_repo
,
&
opts
,
&
diff
));
cl_git_pass
(
git_diff_foreach
(
diff
,
&
exp
,
diff_file_fn
,
NULL
,
NULL
));
cl_assert_equal_i
(
2
,
exp
.
files
);
cl_assert_equal_i
(
0
,
exp
.
file_adds
);
cl_assert_equal_i
(
2
,
exp
.
file_dels
);
cl_assert_equal_i
(
0
,
exp
.
file_mods
);
cl_assert_equal_i
(
0
,
exp
.
file_ignored
);
cl_assert_equal_i
(
0
,
exp
.
file_untracked
);
git_diff_list_free
(
diff
);
}
/* PREPARATION OF TEST DATA
*
* Since there is no command line equivalent of git_diff_workdir_to_tree,
...
...
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