diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/checkout.c | 2 | ||||
-rw-r--r-- | src/diff.c | 50 | ||||
-rw-r--r-- | src/index.c | 3 | ||||
-rw-r--r-- | src/pathspec.c | 17 | ||||
-rw-r--r-- | src/pathspec.h | 12 |
5 files changed, 65 insertions, 19 deletions
diff --git a/src/checkout.c b/src/checkout.c index 40f5732ed..0ce283beb 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -224,7 +224,7 @@ static int checkout_action_wd_only( if (!git_pathspec_match_path( pathspec, wd->path, (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, - git_iterator_ignore_case(workdir))) + git_iterator_ignore_case(workdir), NULL)) return 0; /* check if item is tracked in the index but not in the checkout diff */ diff --git a/src/diff.c b/src/diff.c index 4b60935f0..d9bc32a37 100644 --- a/src/diff.c +++ b/src/diff.c @@ -41,12 +41,26 @@ static git_diff_delta *diff_delta__alloc( return delta; } +static int diff_notify( + const git_diff_list *diff, + const git_diff_delta *delta, + const char *matched_pathspec) +{ + if (!diff->opts.notify_cb) + return 0; + + return diff->opts.notify_cb( + diff, delta, matched_pathspec, diff->opts.notify_payload); +} + static int diff_delta__from_one( git_diff_list *diff, git_delta_t status, const git_index_entry *entry) { git_diff_delta *delta; + const char *matched_pathspec; + int notify_res; if (status == GIT_DELTA_IGNORED && (diff->opts.flags & GIT_DIFF_INCLUDE_IGNORED) == 0) @@ -59,7 +73,7 @@ static int diff_delta__from_one( if (!git_pathspec_match_path( &diff->pathspec, entry->path, (diff->opts.flags & GIT_DIFF_DISABLE_PATHSPEC_MATCH) != 0, - (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0)) + (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0, &matched_pathspec)) return 0; delta = diff_delta__alloc(diff, status, entry->path); @@ -84,12 +98,16 @@ static int diff_delta__from_one( !git_oid_iszero(&delta->new_file.oid)) delta->new_file.flags |= GIT_DIFF_FILE_VALID_OID; - if (git_vector_insert(&diff->deltas, delta) < 0) { + notify_res = diff_notify(diff, delta, matched_pathspec); + + if (notify_res) + git__free(delta); + else if (git_vector_insert(&diff->deltas, delta) < 0) { git__free(delta); return -1; } - return 0; + return notify_res < 0 ? GIT_EUSER : 0; } static int diff_delta__from_two( @@ -99,9 +117,11 @@ static int diff_delta__from_two( uint32_t old_mode, const git_index_entry *new_entry, uint32_t new_mode, - git_oid *new_oid) + git_oid *new_oid, + const char *matched_pathspec) { git_diff_delta *delta; + int notify_res; if (status == GIT_DELTA_UNMODIFIED && (diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0) @@ -138,12 +158,16 @@ static int diff_delta__from_two( if (new_oid || !git_oid_iszero(&new_entry->oid)) delta->new_file.flags |= GIT_DIFF_FILE_VALID_OID; - if (git_vector_insert(&diff->deltas, delta) < 0) { + notify_res = diff_notify(diff, delta, matched_pathspec); + + if (notify_res) + git__free(delta); + else if (git_vector_insert(&diff->deltas, delta) < 0) { git__free(delta); return -1; } - return 0; + return notify_res < 0 ? GIT_EUSER : 0; } static git_diff_delta *diff_delta__last_for_item( @@ -419,13 +443,14 @@ static int maybe_modified( unsigned int omode = oitem->mode; unsigned int nmode = nitem->mode; bool new_is_workdir = (new_iter->type == GIT_ITERATOR_TYPE_WORKDIR); + const char *matched_pathspec; GIT_UNUSED(old_iter); if (!git_pathspec_match_path( &diff->pathspec, oitem->path, (diff->opts.flags & GIT_DIFF_DISABLE_PATHSPEC_MATCH) != 0, - (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0)) + (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0, &matched_pathspec)) return 0; /* on platforms with no symlinks, preserve mode of existing symlinks */ @@ -526,7 +551,7 @@ static int maybe_modified( } return diff_delta__from_two( - diff, status, oitem, omode, nitem, nmode, use_noid); + diff, status, oitem, omode, nitem, nmode, use_noid, matched_pathspec); } static bool entry_is_prefixed( @@ -747,10 +772,11 @@ int git_diff__from_iterators( else { assert(oitem && nitem && cmp == 0); - if (maybe_modified(old_iter, oitem, new_iter, nitem, diff) < 0 || - git_iterator_advance(old_iter, &oitem) < 0 || - git_iterator_advance(new_iter, &nitem) < 0) - goto fail; + if (maybe_modified( + old_iter, oitem, new_iter, nitem, diff) < 0 || + git_iterator_advance(old_iter, &oitem) < 0 || + git_iterator_advance(new_iter, &nitem) < 0) + goto fail; } } diff --git a/src/index.c b/src/index.c index 1e00dd3fa..f5bf954a8 100644 --- a/src/index.c +++ b/src/index.c @@ -1710,7 +1710,8 @@ int git_index_read_tree_match( goto cleanup; while (entry != NULL) { - if (git_pathspec_match_path(&pathspec, entry->path, false, false) && + if (git_pathspec_match_path( + &pathspec, entry->path, false, false, NULL) && (error = git_index_add(index, entry)) < 0) goto cleanup; diff --git a/src/pathspec.c b/src/pathspec.c index 2bde3ba5f..732180248 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -106,14 +106,21 @@ void git_pathspec_free(git_vector *vspec) /* match a path against the vectorized pathspec */ bool git_pathspec_match_path( - git_vector *vspec, const char *path, bool disable_fnmatch, bool casefold) + git_vector *vspec, + const char *path, + bool disable_fnmatch, + bool casefold, + const char **matched_pathspec) { - unsigned int i; + size_t i; git_attr_fnmatch *match; int fnmatch_flags = 0; int (*use_strcmp)(const char *, const char *); int (*use_strncmp)(const char *, const char *, size_t); + if (matched_pathspec) + *matched_pathspec = NULL; + if (!vspec || !vspec->length) return true; @@ -143,8 +150,12 @@ bool git_pathspec_match_path( path[match->length] == '/') result = 0; - if (result == 0) + if (result == 0) { + if (matched_pathspec) + *matched_pathspec = match->pattern; + return (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) ? false : true; + } } return false; diff --git a/src/pathspec.h b/src/pathspec.h index dde63c7d0..c44561520 100644 --- a/src/pathspec.h +++ b/src/pathspec.h @@ -25,8 +25,16 @@ extern int git_pathspec_init( /* free data from the pathspec vector */ extern void git_pathspec_free(git_vector *vspec); -/* match a path against the vectorized pathspec */ +/* + * Match a path against the vectorized pathspec. + * The matched pathspec is passed back into the `matched_pathspec` parameter, + * unless it is passed as NULL by the caller. + */ extern bool git_pathspec_match_path( - git_vector *vspec, const char *path, bool disable_fnmatch, bool casefold); + git_vector *vspec, + const char *path, + bool disable_fnmatch, + bool casefold, + const char **matched_pathspec); #endif |