diff options
author | Russell Belfer <rb@github.com> | 2012-11-13 14:02:59 -0800 |
---|---|---|
committer | Russell Belfer <rb@github.com> | 2012-11-14 22:55:40 -0800 |
commit | bad68c0a998116685ad75cab84210004dd2c5be1 (patch) | |
tree | d8b6db9be06ea1fcc150b5a7d2ba4cd635a174aa | |
parent | 5735bf5e6ab4da347b601d4b85c09c5c701dc002 (diff) | |
download | libgit2-bad68c0a998116685ad75cab84210004dd2c5be1.tar.gz |
Add iterator for git_index object
The index iterator could previously only be created from a repo
object, but this allows creating an iterator from a `git_index`
object instead (while keeping, though renaming, the old function).
-rw-r--r-- | src/diff.c | 17 | ||||
-rw-r--r-- | src/diff.h | 6 | ||||
-rw-r--r-- | src/index.c | 4 | ||||
-rw-r--r-- | src/iterator.c | 49 | ||||
-rw-r--r-- | src/iterator.h | 14 | ||||
-rw-r--r-- | src/submodule.c | 2 | ||||
-rw-r--r-- | src/vector.h | 9 | ||||
-rw-r--r-- | tests-clar/diff/iterator.c | 2 |
8 files changed, 78 insertions, 25 deletions
diff --git a/src/diff.c b/src/diff.c index b75ada1e0..e6634e6d2 100644 --- a/src/diff.c +++ b/src/diff.c @@ -777,6 +777,19 @@ int git_diff_tree_to_tree( ); } +int git_diff__tree_to_index( + git_diff_list **diff, + git_tree *tree, + git_index *index, + const git_diff_options *opts) +{ + DIFF_FROM_ITERATORS( + git_repository *repo = git_index_owner(index), + git_iterator_for_index_range(&a, index, pfx, pfx), + git_iterator_for_tree_range(&b, repo, tree, pfx, pfx) + ); +} + int git_diff_index_to_tree( git_diff_list **diff, git_repository *repo, @@ -786,7 +799,7 @@ int git_diff_index_to_tree( DIFF_FROM_ITERATORS( assert(repo && diff), git_iterator_for_tree_range(&a, repo, old_tree, pfx, pfx), - git_iterator_for_index_range(&b, repo, pfx, pfx) + git_iterator_for_repo_index_range(&b, repo, pfx, pfx) ); } @@ -797,7 +810,7 @@ int git_diff_workdir_to_index( { DIFF_FROM_ITERATORS( assert(repo && diff), - git_iterator_for_index_range(&a, repo, pfx, pfx), + git_iterator_for_repo_index_range(&a, repo, pfx, pfx), git_iterator_for_workdir_range(&b, repo, pfx, pfx) ); } diff --git a/src/diff.h b/src/diff.h index 1e3be7593..3df7ce6d6 100644 --- a/src/diff.h +++ b/src/diff.h @@ -61,5 +61,11 @@ extern bool git_diff_delta__should_skip( extern int git_diff__oid_for_file( git_repository *, const char *, uint16_t, git_off_t, git_oid *); +extern int git_diff__tree_to_index( + git_diff_list **diff, + git_tree *tree, + git_index *index, + const git_diff_options *opts); + #endif diff --git a/src/index.c b/src/index.c index 007f19a43..128dd18cf 100644 --- a/src/index.c +++ b/src/index.c @@ -835,7 +835,9 @@ unsigned int git_index__prefix_position(git_index *index, const char *path) srch_key.path = path; srch_key.stage = 0; - git_vector_bsearch3(&pos, &index->entries, index->entries_search, &srch_key); + git_vector_sort(&index->entries); + git_vector_bsearch3( + &pos, &index->entries, index->entries_search, &srch_key); return pos; } diff --git a/src/iterator.c b/src/iterator.c index 33b775ce1..ee83a4fda 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -330,6 +330,7 @@ typedef struct { git_iterator base; git_index *index; unsigned int current; + bool free_index; } index_iterator; static int index_iterator__current( @@ -387,32 +388,47 @@ static int index_iterator__reset(git_iterator *self) static void index_iterator__free(git_iterator *self) { index_iterator *ii = (index_iterator *)self; - git_index_free(ii->index); + if (ii->free_index) + git_index_free(ii->index); ii->index = NULL; } int git_iterator_for_index_range( git_iterator **iter, - git_repository *repo, + git_index *index, const char *start, const char *end) { - int error; index_iterator *ii; ITERATOR_BASE_INIT(ii, index, INDEX); - if ((error = git_repository_index(&ii->index, repo)) < 0) - git__free(ii); - else { - ii->base.ignore_case = ii->index->ignore_case; - ii->current = start ? git_index__prefix_position(ii->index, start) : 0; - *iter = (git_iterator *)ii; - } + ii->index = index; + ii->base.ignore_case = ii->index->ignore_case; + ii->current = start ? git_index__prefix_position(ii->index, start) : 0; - return error; + *iter = (git_iterator *)ii; + + return 0; } +int git_iterator_for_repo_index_range( + git_iterator **iter, + git_repository *repo, + const char *start, + const char *end) +{ + int error; + git_index *index; + + if ((error = git_repository_index(&index, repo)) < 0) + return error; + + if (!(error = git_iterator_for_index_range(iter, index, start, end))) + ((index_iterator *)(*iter))->free_index = true; + + return error; +} typedef struct workdir_iterator_frame workdir_iterator_frame; struct workdir_iterator_frame { @@ -690,24 +706,21 @@ int git_iterator_for_workdir_range( assert(iter && repo); - if ((error = git_repository__ensure_not_bare(repo, "scan working directory")) < 0) + if ((error = git_repository__ensure_not_bare( + repo, "scan working directory")) < 0) return error; ITERATOR_BASE_INIT(wi, workdir, WORKDIR); - wi->repo = repo; - if ((error = git_repository_index(&index, repo)) < 0) { + if ((error = git_repository_index__weakptr(&index, repo)) < 0) { git__free(wi); return error; } - /* Set the ignore_case flag for the workdir iterator to match - * that of the index. */ + /* Match ignore_case flag for iterator to that of the index */ wi->base.ignore_case = index->ignore_case; - git_index_free(index); - if (git_buf_sets(&wi->path, git_repository_workdir(repo)) < 0 || git_path_to_dir(&wi->path) < 0 || git_ignore__for_path(repo, "", &wi->ignores) < 0) diff --git a/src/iterator.h b/src/iterator.h index d7df50137..77ead76cc 100644 --- a/src/iterator.h +++ b/src/iterator.h @@ -52,13 +52,23 @@ GIT_INLINE(int) git_iterator_for_tree( } extern int git_iterator_for_index_range( - git_iterator **iter, git_repository *repo, + git_iterator **iter, git_index *index, const char *start, const char *end); GIT_INLINE(int) git_iterator_for_index( + git_iterator **iter, git_index *index) +{ + return git_iterator_for_index_range(iter, index, NULL, NULL); +} + +extern int git_iterator_for_repo_index_range( + git_iterator **iter, git_repository *repo, + const char *start, const char *end); + +GIT_INLINE(int) git_iterator_for_repo_index( git_iterator **iter, git_repository *repo) { - return git_iterator_for_index_range(iter, repo, NULL, NULL); + return git_iterator_for_repo_index_range(iter, repo, NULL, NULL); } extern int git_iterator_for_workdir_range( diff --git a/src/submodule.c b/src/submodule.c index 1bd8c42da..527d9e453 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1118,7 +1118,7 @@ static int load_submodule_config_from_index( git_iterator *i; const git_index_entry *entry; - if ((error = git_iterator_for_index(&i, repo)) < 0) + if ((error = git_iterator_for_repo_index(&i, repo)) < 0) return error; error = git_iterator_current(i, &entry); diff --git a/src/vector.h b/src/vector.h index 5061f7846..6d820b8fc 100644 --- a/src/vector.h +++ b/src/vector.h @@ -29,17 +29,26 @@ void git_vector_swap(git_vector *a, git_vector *b); void git_vector_sort(git_vector *v); +/** Linear search for matching entry using internal comparison function */ int git_vector_search(git_vector *v, const void *entry); + +/** Linear search for matching entry using explicit comparison function */ int git_vector_search2(git_vector *v, git_vector_cmp cmp, const void *key); +/** + * Binary search for matching entry using explicit comparison function that + * returns position where item would go if not found. + */ int git_vector_bsearch3( unsigned int *at_pos, git_vector *v, git_vector_cmp cmp, const void *key); +/** Binary search for matching entry using internal comparison function */ GIT_INLINE(int) git_vector_bsearch(git_vector *v, const void *key) { return git_vector_bsearch3(NULL, v, v->_cmp, key); } +/** Binary search for matching entry using explicit comparison function */ GIT_INLINE(int) git_vector_bsearch2( git_vector *v, git_vector_cmp cmp, const void *key) { diff --git a/tests-clar/diff/iterator.c b/tests-clar/diff/iterator.c index c2ab9940b..368903200 100644 --- a/tests-clar/diff/iterator.c +++ b/tests-clar/diff/iterator.c @@ -350,7 +350,7 @@ static void index_iterator_test( int count = 0; git_repository *repo = cl_git_sandbox_init(sandbox); - cl_git_pass(git_iterator_for_index_range(&i, repo, start, end)); + cl_git_pass(git_iterator_for_repo_index_range(&i, repo, start, end)); cl_git_pass(git_iterator_current(i, &entry)); while (entry != NULL) { |