diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2015-07-28 19:55:37 -0500 |
---|---|---|
committer | Edward Thomson <ethomson@microsoft.com> | 2015-08-28 18:39:52 -0400 |
commit | ef206124de957408c8d867e2f923d0611a7274fc (patch) | |
tree | bc9a45937d109c6c7d3b1c2052a486d28b4ae470 | |
parent | ed1c64464a4e3126eef5d74d2c14c19133fa9cd8 (diff) | |
download | libgit2-ef206124de957408c8d867e2f923d0611a7274fc.tar.gz |
Move filelist into the iterator handling itself.
-rw-r--r-- | include/git2/diff.h | 7 | ||||
-rw-r--r-- | src/diff.c | 46 | ||||
-rw-r--r-- | src/iterator.c | 115 | ||||
-rw-r--r-- | src/iterator.h | 7 | ||||
-rw-r--r-- | src/merge.c | 5 | ||||
-rw-r--r-- | tests/repo/iterator.c | 248 |
6 files changed, 405 insertions, 23 deletions
diff --git a/include/git2/diff.h b/include/git2/diff.h index 0abbc7f06..c3589bb13 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -163,6 +163,13 @@ typedef enum { /** Include unreadable files in the diff */ GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED = (1u << 17), + /** Use literal path matching in the iterators. This is more broad + * than the DISABLE_PATHSPEC_MATCH flag. The caller must provide an + * array of paths (no patterns or prefixes). Only values included in + * that list will be returned. + */ + GIT_DIFF_ENABLE_FILELIST_MATCH = (1u << 18), + /* * Options controlling how output will be generated */ diff --git a/src/diff.c b/src/diff.c index 58004db21..d87738fb3 100644 --- a/src/diff.c +++ b/src/diff.c @@ -74,6 +74,24 @@ static int diff_insert_delta( return error; } +static bool diff_pathspec_match( + const char **matched_pathspec, git_diff *diff, const char *path) +{ + /* The iterator has filtered out paths for us, so the fact that we're + * seeing this patch means that it must match the given path list. + */ + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_ENABLE_FILELIST_MATCH)) { + *matched_pathspec = path; + return true; + } + + return git_pathspec__match( + &diff->pathspec, path, + DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), + DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE), + matched_pathspec, NULL); +} + static int diff_delta__from_one( git_diff *diff, git_delta_t status, @@ -110,11 +128,7 @@ static int diff_delta__from_one( DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNREADABLE)) return 0; - if (!git_pathspec__match( - &diff->pathspec, entry->path, - DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), - DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE), - &matched_pathspec, NULL)) + if (!diff_pathspec_match(&matched_pathspec, diff, entry->path)) return 0; delta = diff_delta__alloc(diff, status, entry->path); @@ -755,11 +769,7 @@ static int maybe_modified( const char *matched_pathspec; int error = 0; - if (!git_pathspec__match( - &diff->pathspec, oitem->path, - DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), - DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE), - &matched_pathspec, NULL)) + if (!diff_pathspec_match(&matched_pathspec, diff, oitem->path)) return 0; memset(&noid, 0, sizeof(noid)); @@ -1266,7 +1276,9 @@ cleanup: #define DIFF_FROM_ITERATORS(MAKE_FIRST, FLAGS_FIRST, MAKE_SECOND, FLAGS_SECOND) do { \ git_iterator *a = NULL, *b = NULL; \ - char *pfx = opts ? git_pathspec_prefix(&opts->pathspec) : NULL; \ + git_vector pathlist = GIT_VECTOR_INIT; \ + char *pfx = (opts && !(opts->flags & GIT_DIFF_ENABLE_FILELIST_MATCH)) ? \ + git_pathspec_prefix(&opts->pathspec) : NULL; \ git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT, \ b_opts = GIT_ITERATOR_OPTIONS_INIT; \ a_opts.flags = FLAGS_FIRST; \ @@ -1276,9 +1288,19 @@ cleanup: b_opts.start = pfx; \ b_opts.end = pfx; \ GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); \ - if (!(error = MAKE_FIRST) && !(error = MAKE_SECOND)) \ + if (opts && (opts->flags & GIT_DIFF_ENABLE_FILELIST_MATCH) && opts->pathspec.count) { \ + size_t __i; \ + error = git_vector_init(&pathlist, opts->pathspec.count, NULL); \ + for (__i = 0; !error && __i < opts->pathspec.count; __i++) { \ + error = git_vector_insert(&pathlist, opts->pathspec.strings[__i]); \ + } \ + a_opts.pathlist = &pathlist; \ + b_opts.pathlist = &pathlist; \ + } \ + if (!error && !(error = MAKE_FIRST) && !(error = MAKE_SECOND)) \ error = git_diff__from_iterators(diff, repo, a, b, opts); \ git__free(pfx); git_iterator_free(a); git_iterator_free(b); \ + git_vector_free(&pathlist); \ } while (0) int git_diff_tree_to_tree( diff --git a/src/iterator.c b/src/iterator.c index 374caf96d..28629c708 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -42,6 +42,8 @@ (P)->base.flags = options ? options->flags & ~ITERATOR_CASE_FLAGS : 0; \ if ((P)->base.flags & GIT_ITERATOR_DONT_AUTOEXPAND) \ (P)->base.flags |= GIT_ITERATOR_INCLUDE_TREES; \ + if (options && options->pathlist) \ + (P)->base.pathlist = options->pathlist; \ } while (0) #define iterator__flag(I,F) ((((git_iterator *)(I))->flags & GIT_ITERATOR_ ## F) != 0) @@ -106,6 +108,12 @@ static int iterator__update_ignore_case( iter->prefixcomp = iterator__ignore_case(iter) ? git__prefixcmp_icase : git__prefixcmp; + if (iter->pathlist) { + git_vector_set_cmp(iter->pathlist, iterator__ignore_case(iter) ? + git__strcasecmp : git__strcmp); + git_vector_sort(iter->pathlist); + } + return error; } @@ -616,6 +624,9 @@ int git_iterator_for_tree( if (tree == NULL) return git_iterator_for_nothing(iter, options); + /* not yet supported */ + assert (!options || !options->pathlist); + if ((error = git_object_dup((git_object **)&tree, (git_object *)tree)) < 0) return error; @@ -668,15 +679,47 @@ static const git_index_entry *index_iterator__index_entry(index_iterator *ii) return ie; } -static const git_index_entry *index_iterator__advance_over_conflicts(index_iterator *ii) +static const git_index_entry *index_iterator__advance_over_unwanted(index_iterator *ii) { const git_index_entry *ie = index_iterator__index_entry(ii); + const char *p; + int cmp; - if (!iterator__include_conflicts(ii)) { - while (ie && git_index_entry_is_conflict(ie)) { + while (ie) { + if (!iterator__include_conflicts(ii) && + git_index_entry_is_conflict(ie)) { ii->current++; ie = index_iterator__index_entry(ii); + continue; } + + /* if we have a pathlist, this entry's path must be in it to be + * returned. otherwise, advance the pathlist entry or the iterator + * until we find the next path that we want to return. + */ + if (ii->base.pathlist) { + if (ii->base.pathlist_idx >= ii->base.pathlist->length) { + ii->current = SIZE_MAX; + ie = NULL; + break; + } + + p = ii->base.pathlist->contents[ii->base.pathlist_idx]; + cmp = ii->base.pathlist->_cmp(p, ie->path); + + if (cmp < 0) { + ii->base.pathlist_idx++; + continue; + } + + if (cmp > 0) { + ii->current++; + ie = index_iterator__index_entry(ii); + continue; + } + } + + break; } return ie; @@ -705,7 +748,7 @@ static void index_iterator__next_prefix_tree(index_iterator *ii) static int index_iterator__first_prefix_tree(index_iterator *ii) { - const git_index_entry *ie = index_iterator__advance_over_conflicts(ii); + const git_index_entry *ie = index_iterator__advance_over_unwanted(ii); const char *scan, *prior, *slash; if (!ie || !iterator__include_trees(ii)) @@ -818,17 +861,22 @@ static int index_iterator__reset( { index_iterator *ii = (index_iterator *)self; const git_index_entry *ie; + size_t pathlist_idx = 0; if (iterator__reset_range(self, start, end) < 0) return -1; ii->current = 0; + ii->base.pathlist_idx = 0; + /* if we're given a start prefix, find it; if we're given a pathlist, find + * the first of those. start at the later of the two. + */ if (ii->base.start) git_index_snapshot_find( &ii->current, &ii->entries, ii->entry_srch, ii->base.start, 0, 0); - if ((ie = index_iterator__advance_over_conflicts(ii)) == NULL) + if ((ie = index_iterator__advance_over_unwanted(ii)) == NULL) return 0; if (git_buf_sets(&ii->partial, ie->path) < 0) @@ -1004,25 +1052,60 @@ static void fs_iterator__seek_frame_start( ff->index = 0; } +typedef enum { + DIRLOAD_PATHLIST_NONE = 0, + DIRLOAD_PATHLIST_EXACT = 1, + DIRLOAD_PATHLIST_DIRECTORY = 2, +} dirload_pathlist_match_t; + +static dirload_pathlist_match_t dirload_pathlist_match( + git_vector *pathlist, + const char *path, + size_t path_len, + int (*prefixcomp)(const char *a, const char *b)) +{ + const char *matched; + size_t idx; + + if (git_vector_bsearch2( + &idx, pathlist, pathlist->_cmp, path) != GIT_ENOTFOUND) + return DIRLOAD_PATHLIST_EXACT; + + /* the explicit path we searched for was not found, but this may be + * a directory and the pathlist contains a file in it. check. + */ + if ((matched = git_vector_get(pathlist, idx)) != NULL && + prefixcomp(matched, path) == 0 && + matched[path_len] == '/') + return DIRLOAD_PATHLIST_DIRECTORY; + + return DIRLOAD_PATHLIST_NONE; +} + static int dirload_with_stat( + git_vector *contents, const char *dirpath, size_t prefix_len, unsigned int flags, const char *start_stat, const char *end_stat, - git_vector *contents) + git_vector *pathlist) { git_path_diriter diriter = GIT_PATH_DIRITER_INIT; const char *path; int (*strncomp)(const char *a, const char *b, size_t sz); + int (*prefixcomp)(const char *a, const char *b); size_t start_len = start_stat ? strlen(start_stat) : 0; size_t end_len = end_stat ? strlen(end_stat) : 0; fs_iterator_path_with_stat *ps; size_t path_len, cmp_len, ps_size; + dirload_pathlist_match_t pathlist_match = DIRLOAD_PATHLIST_EXACT; int error; strncomp = (flags & GIT_PATH_DIR_IGNORE_CASE) != 0 ? git__strncasecmp : git__strncmp; + prefixcomp = (flags & GIT_PATH_DIR_IGNORE_CASE) != 0 ? + git__prefixcmp_icase : git__prefixcmp; /* Any error here is equivalent to the dir not existing, skip over it */ if ((error = git_path_diriter_init(&diriter, dirpath, flags)) < 0) { @@ -1044,10 +1127,20 @@ static int dirload_with_stat( cmp_len = min(start_len, path_len); if (cmp_len && strncomp(path, start_stat, cmp_len) < 0) continue; + /* skip if after end_stat */ cmp_len = min(end_len, path_len); if (cmp_len && strncomp(path, end_stat, cmp_len) > 0) continue; + /* skip if we have a pathlist and this isn't in it. note that we + * haven't stat'd yet to know if it's a file or a directory, so this + * match for files like `foo` when we're looking for `foo/bar` + */ + if (pathlist && + !(pathlist_match = dirload_pathlist_match( + pathlist, path, path_len, prefixcomp))) + continue; + /* Make sure to append two bytes, one for the path's null * termination, one for a possible trailing '/' for folders. */ @@ -1068,6 +1161,12 @@ static int dirload_with_stat( continue; } + if (pathlist_match == DIRLOAD_PATHLIST_DIRECTORY) { + /* were looking for a directory, but this is a file */ + git__free(ps); + continue; + } + /* Treat the file as unreadable if we get any other error */ memset(&ps->st, 0, sizeof(ps->st)); ps->st.st_mode = GIT_FILEMODE_UNREADABLE; @@ -1113,9 +1212,9 @@ static int fs_iterator__expand_dir(fs_iterator *fi) ff = fs_iterator__alloc_frame(fi); GITERR_CHECK_ALLOC(ff); - error = dirload_with_stat( + error = dirload_with_stat(&ff->entries, fi->path.ptr, fi->root_len, fi->dirload_flags, - fi->base.start, fi->base.end, &ff->entries); + fi->base.start, fi->base.end, fi->base.pathlist); if (error < 0) { git_error_state last_error = { 0 }; diff --git a/src/iterator.h b/src/iterator.h index 46e96f044..0ea2bc053 100644 --- a/src/iterator.h +++ b/src/iterator.h @@ -43,6 +43,11 @@ typedef struct { const char *start; const char *end; + /* paths to include in the iterator (literal). any paths not listed + * will be excluded. note that this vector may be resorted! + */ + git_vector *pathlist; + /* flags, from above */ unsigned int flags; } git_iterator_options; @@ -65,6 +70,8 @@ struct git_iterator { git_repository *repo; char *start; char *end; + git_vector *pathlist; + size_t pathlist_idx; int (*prefixcomp)(const char *str, const char *prefix); size_t stat_calls; unsigned int flags; diff --git a/src/merge.c b/src/merge.c index 16cd2aee0..1460a5040 100644 --- a/src/merge.c +++ b/src/merge.c @@ -2356,10 +2356,8 @@ static int merge_check_index(size_t *conflicts, git_repository *repo, git_index goto done; } - opts.pathspec.count = staged_paths.length; - opts.pathspec.strings = (char **)staged_paths.contents; - iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE; + iter_opts.pathlist = &staged_paths; if ((error = git_iterator_for_index(&iter_repo, index_repo, &iter_opts)) < 0 || (error = git_iterator_for_index(&iter_new, index_new, &iter_opts)) < 0 || @@ -2406,6 +2404,7 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde * will be applied by the merge (including conflicts). Ensure that there * are no changes in the workdir to these paths. */ + opts.flags |= GIT_DIFF_ENABLE_FILELIST_MATCH; opts.pathspec.count = merged_paths->length; opts.pathspec.strings = (char **)merged_paths->contents; diff --git a/tests/repo/iterator.c b/tests/repo/iterator.c index 4d0d12be1..8af7bc533 100644 --- a/tests/repo/iterator.c +++ b/tests/repo/iterator.c @@ -1073,3 +1073,251 @@ void test_repo_iterator__skips_fifos_and_such(void) git_iterator_free(i); #endif } + +void test_repo_iterator__indexfilelist(void) +{ + git_iterator *i; + git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT; + git_index *index; + git_vector filelist; + int default_icase; + int expect; + + cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb)); + cl_git_pass(git_vector_insert(&filelist, "a")); + cl_git_pass(git_vector_insert(&filelist, "B")); + cl_git_pass(git_vector_insert(&filelist, "c")); + cl_git_pass(git_vector_insert(&filelist, "D")); + cl_git_pass(git_vector_insert(&filelist, "e")); + cl_git_pass(git_vector_insert(&filelist, "k/1")); + cl_git_pass(git_vector_insert(&filelist, "k/a")); + cl_git_pass(git_vector_insert(&filelist, "L/1")); + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_repository_index(&index, g_repo)); + /* In this test we DO NOT force a case setting on the index. */ + default_icase = ((git_index_caps(index) & GIT_INDEXCAP_IGNORE_CASE) != 0); + + i_opts.pathlist = &filelist; + + /* All indexfilelist iterator tests are "autoexpand with no tree entries" */ + + cl_git_pass(git_iterator_for_index(&i, index, &i_opts)); + expect_iterator_items(i, 8, NULL, 8, NULL); + git_iterator_free(i); + + i_opts.start = "c"; + i_opts.end = NULL; + + cl_git_pass(git_iterator_for_index(&i, index, &i_opts)); + /* (c D e k/1 k/a L ==> 6) vs (c e k/1 k/a ==> 4) */ + expect = ((default_icase) ? 6 : 4); + expect_iterator_items(i, expect, NULL, expect, NULL); + git_iterator_free(i); + + i_opts.start = NULL; + i_opts.end = "e"; + + cl_git_pass(git_iterator_for_index(&i, index, &i_opts)); + /* (a B c D e ==> 5) vs (B D L/1 a c e ==> 6) */ + expect = ((default_icase) ? 5 : 6); + expect_iterator_items(i, expect, NULL, expect, NULL); + git_iterator_free(i); + + git_index_free(index); + git_vector_free(&filelist); +} + +void test_repo_iterator__indexfilelist_2(void) +{ + git_iterator *i; + git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT; + git_index *index; + git_vector filelist = GIT_VECTOR_INIT; + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb)); + cl_git_pass(git_vector_insert(&filelist, "0")); + cl_git_pass(git_vector_insert(&filelist, "c")); + cl_git_pass(git_vector_insert(&filelist, "D")); + cl_git_pass(git_vector_insert(&filelist, "e")); + cl_git_pass(git_vector_insert(&filelist, "k/a")); + + i_opts.pathlist = &filelist; + + i_opts.start = "b"; + i_opts.end = "k/D"; + + cl_git_pass(git_iterator_for_index(&i, index, &i_opts)); + expect_iterator_items(i, 4, NULL, 4, NULL); + git_iterator_free(i); + + git_index_free(index); + git_vector_free(&filelist); +} + +void test_repo_iterator__indexfilelist_icase(void) +{ + git_iterator *i; + git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT; + git_index *index; + int caps; + git_vector filelist; + + cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb)); + cl_git_pass(git_vector_insert(&filelist, "a")); + cl_git_pass(git_vector_insert(&filelist, "B")); + cl_git_pass(git_vector_insert(&filelist, "c")); + cl_git_pass(git_vector_insert(&filelist, "D")); + cl_git_pass(git_vector_insert(&filelist, "e")); + cl_git_pass(git_vector_insert(&filelist, "k/1")); + cl_git_pass(git_vector_insert(&filelist, "k/a")); + cl_git_pass(git_vector_insert(&filelist, "L/1")); + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_repository_index(&index, g_repo)); + caps = git_index_caps(index); + + /* force case sensitivity */ + cl_git_pass(git_index_set_caps(index, caps & ~GIT_INDEXCAP_IGNORE_CASE)); + + /* All indexfilelist iterator tests are "autoexpand with no tree entries" */ + + i_opts.pathlist = &filelist; + + i_opts.start = "c"; + i_opts.end = "k/D"; + cl_git_pass(git_iterator_for_index(&i, index, &i_opts)); + expect_iterator_items(i, 3, NULL, 3, NULL); + git_iterator_free(i); + + i_opts.start = "k"; + i_opts.end = "k/Z"; + cl_git_pass(git_iterator_for_index(&i, index, &i_opts)); + expect_iterator_items(i, 1, NULL, 1, NULL); + git_iterator_free(i); + + /* force case insensitivity */ + cl_git_pass(git_index_set_caps(index, caps | GIT_INDEXCAP_IGNORE_CASE)); + + i_opts.start = "c"; + i_opts.end = "k/D"; + cl_git_pass(git_iterator_for_index(&i, index, &i_opts)); + expect_iterator_items(i, 5, NULL, 5, NULL); + git_iterator_free(i); + + i_opts.start = "k"; + i_opts.end = "k/Z"; + cl_git_pass(git_iterator_for_index(&i, index, &i_opts)); + expect_iterator_items(i, 2, NULL, 2, NULL); + git_iterator_free(i); + + cl_git_pass(git_index_set_caps(index, caps)); + git_index_free(index); + git_vector_free(&filelist); +} + +void test_repo_iterator__workdirfilelist(void) +{ + git_iterator *i; + git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT; + git_vector filelist; + bool default_icase; + int expect; + + cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb)); + cl_git_pass(git_vector_insert(&filelist, "a")); + cl_git_pass(git_vector_insert(&filelist, "B")); + cl_git_pass(git_vector_insert(&filelist, "c")); + cl_git_pass(git_vector_insert(&filelist, "D")); + cl_git_pass(git_vector_insert(&filelist, "e")); + cl_git_pass(git_vector_insert(&filelist, "k/1")); + cl_git_pass(git_vector_insert(&filelist, "k/a")); + cl_git_pass(git_vector_insert(&filelist, "L/1")); + + g_repo = cl_git_sandbox_init("icase"); + + /* All indexfilelist iterator tests are "autoexpand with no tree entries" */ + /* In this test we DO NOT force a case on the iteratords and verify default behavior. */ + + i_opts.pathlist = &filelist; + + cl_git_pass(git_iterator_for_workdir(&i, g_repo, NULL, NULL, &i_opts)); + expect_iterator_items(i, 8, NULL, 8, NULL); + git_iterator_free(i); + + i_opts.start = "c"; + i_opts.end = NULL; + cl_git_pass(git_iterator_for_workdir(&i, g_repo, NULL, NULL, &i_opts)); + default_icase = git_iterator_ignore_case(i); + /* (c D e k/1 k/a L ==> 6) vs (c e k/1 k/a ==> 4) */ + expect = ((default_icase) ? 6 : 4); + expect_iterator_items(i, expect, NULL, expect, NULL); + git_iterator_free(i); + + i_opts.start = NULL; + i_opts.end = "e"; + cl_git_pass(git_iterator_for_workdir(&i, g_repo, NULL, NULL, &i_opts)); + default_icase = git_iterator_ignore_case(i); + /* (a B c D e ==> 5) vs (B D L/1 a c e ==> 6) */ + expect = ((default_icase) ? 5 : 6); + expect_iterator_items(i, expect, NULL, expect, NULL); + git_iterator_free(i); + + git_vector_free(&filelist); +} + +void test_repo_iterator__workdirfilelist_icase(void) +{ + git_iterator *i; + git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT; + git_vector filelist; + + cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb)); + cl_git_pass(git_vector_insert(&filelist, "a")); + cl_git_pass(git_vector_insert(&filelist, "B")); + cl_git_pass(git_vector_insert(&filelist, "c")); + cl_git_pass(git_vector_insert(&filelist, "D")); + cl_git_pass(git_vector_insert(&filelist, "e")); + cl_git_pass(git_vector_insert(&filelist, "k/1")); + cl_git_pass(git_vector_insert(&filelist, "k/a")); + cl_git_pass(git_vector_insert(&filelist, "L/1")); + + g_repo = cl_git_sandbox_init("icase"); + + i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE; + i_opts.pathlist = &filelist; + + i_opts.start = "c"; + i_opts.end = "k/D"; + cl_git_pass(git_iterator_for_workdir(&i, g_repo, NULL, NULL, &i_opts)); + expect_iterator_items(i, 3, NULL, 3, NULL); + git_iterator_free(i); + + i_opts.start = "k"; + i_opts.end = "k/Z"; + cl_git_pass(git_iterator_for_workdir(&i, g_repo, NULL, NULL, &i_opts)); + expect_iterator_items(i, 1, NULL, 1, NULL); + git_iterator_free(i); + + i_opts.flags = GIT_ITERATOR_IGNORE_CASE; + + i_opts.start = "c"; + i_opts.end = "k/D"; + cl_git_pass(git_iterator_for_workdir(&i, g_repo, NULL, NULL, &i_opts)); + expect_iterator_items(i, 5, NULL, 5, NULL); + git_iterator_free(i); + + i_opts.start = "k"; + i_opts.end = "k/Z"; + cl_git_pass(git_iterator_for_workdir(&i, g_repo, NULL, NULL, &i_opts)); + expect_iterator_items(i, 2, NULL, 2, NULL); + git_iterator_free(i); + + git_vector_free(&filelist); +} |