Skip to content

Commit 2b672d5

Browse files
arrbeeVicent Marti
authored andcommitted
Add git_pathspec_match_diff API
This adds an additional pathspec API that will match a pathspec against a diff object. This is convenient if you want to handle renames (so you need the whole diff and can't use the pathspec constraint built into the diff API) but still want to tell if the diff had any files that matched the pathspec. When the pathspec is matched against a diff, instead of keeping a list of filenames that matched, instead the API keeps the list of git_diff_deltas that matched and they can be retrieved via a new API git_pathspec_match_list_diff_entry. There are a couple of other minor API extensions here that were mostly for the sake of convenience and to reduce dependencies on knowing the internal data structure between files inside the library.
1 parent 6fc5a58 commit 2b672d5

File tree

8 files changed

+404
-77
lines changed

8 files changed

+404
-77
lines changed

include/git2/diff.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,14 @@ GIT_EXTERN(size_t) git_diff_num_deltas_of_type(
797797
git_diff_list *diff,
798798
git_delta_t type);
799799

800+
/**
801+
* Check if deltas are sorted case sensitively or insensitively.
802+
*
803+
* @param diff Diff list to check
804+
* @return 0 if case sensitive, 1 if case is ignored
805+
*/
806+
GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff_list *diff);
807+
800808
/**
801809
* Return the diff delta and patch for an entry in the diff list.
802810
*

include/git2/pathspec.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "common.h"
1111
#include "types.h"
1212
#include "strarray.h"
13+
#include "diff.h"
1314

1415
/**
1516
* Compiled pathspec
@@ -166,6 +167,30 @@ GIT_EXTERN(int) git_pathspec_match_tree(
166167
uint32_t flags,
167168
git_pathspec *ps);
168169

170+
/**
171+
* Match a pathspec against files in a diff list.
172+
*
173+
* This matches the pathspec against the files in the given diff list.
174+
*
175+
* If `out` is not NULL, this returns a `git_patchspec_match_list`. That
176+
* contains the list of all matched filenames (unless you pass the
177+
* `GIT_PATHSPEC_FAILURES_ONLY` flag) and may also contain the list of
178+
* pathspecs with no match (if you used the `GIT_PATHSPEC_FIND_FAILURES`
179+
* flag). You must call `git_pathspec_match_list_free()` on this object.
180+
*
181+
* @param out Output list of matches; pass NULL to just get return value
182+
* @param diff A generated diff list
183+
* @param flags Combination of git_pathspec_flag_t options to control match
184+
* @param ps Pathspec to be matched
185+
* @return 0 on success, -1 on error, GIT_ENOTFOUND if no matches and
186+
* the GIT_PATHSPEC_NO_MATCH_ERROR flag is used
187+
*/
188+
GIT_EXTERN(int) git_pathspec_match_diff(
189+
git_pathspec_match_list **out,
190+
git_diff_list *diff,
191+
uint32_t flags,
192+
git_pathspec *ps);
193+
169194
/**
170195
* Free memory associates with a git_pathspec_match_list
171196
*
@@ -185,13 +210,29 @@ GIT_EXTERN(size_t) git_pathspec_match_list_entrycount(
185210
/**
186211
* Get a matching filename by position.
187212
*
213+
* This routine cannot be used if the match list was generated by
214+
* `git_pathspec_match_diff`. If so, it will always return NULL.
215+
*
188216
* @param m The git_pathspec_match_list object
189217
* @param pos The index into the list
190218
* @return The filename of the match
191219
*/
192220
GIT_EXTERN(const char *) git_pathspec_match_list_entry(
193221
const git_pathspec_match_list *m, size_t pos);
194222

223+
/**
224+
* Get a matching diff delta by position.
225+
*
226+
* This routine can only be used if the match list was generated by
227+
* `git_pathspec_match_diff`. Otherwise it will always return NULL.
228+
*
229+
* @param m The git_pathspec_match_list object
230+
* @param pos The index into the list
231+
* @return The filename of the match
232+
*/
233+
GIT_EXTERN(const git_diff_delta *) git_pathspec_match_list_diff_entry(
234+
const git_pathspec_match_list *m, size_t pos);
235+
195236
/**
196237
* Get the number of pathspec items that did not match.
197238
*

src/array.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,6 @@ GIT_INLINE(void *) git_array_grow(git_array_generic_t *a, size_t item_size)
6666

6767
#define git_array_size(a) (a).size
6868

69+
#define git_array_valid_index(a, i) ((i) < (a).size)
70+
6971
#endif

src/diff.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ GIT_INLINE(const char *) diff_delta__path(const git_diff_delta *delta)
247247
return str;
248248
}
249249

250+
const char *git_diff_delta__path(const git_diff_delta *delta)
251+
{
252+
return diff_delta__path(delta);
253+
}
254+
250255
int git_diff_delta__cmp(const void *a, const void *b)
251256
{
252257
const git_diff_delta *da = a, *db = b;
@@ -1235,6 +1240,11 @@ size_t git_diff_num_deltas_of_type(git_diff_list *diff, git_delta_t type)
12351240
return count;
12361241
}
12371242

1243+
int git_diff_is_sorted_icase(const git_diff_list *diff)
1244+
{
1245+
return (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0;
1246+
}
1247+
12381248
int git_diff__paired_foreach(
12391249
git_diff_list *head2idx,
12401250
git_diff_list *idx2wd,

src/diff.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ extern void git_diff_list_addref(git_diff_list *diff);
7676
extern int git_diff_delta__cmp(const void *a, const void *b);
7777
extern int git_diff_delta__casecmp(const void *a, const void *b);
7878

79+
extern const char *git_diff_delta__path(const git_diff_delta *delta);
80+
7981
extern bool git_diff_delta__should_skip(
8082
const git_diff_options *opts, const git_diff_delta *delta);
8183

0 commit comments

Comments
 (0)