diff options
author | Vicent Marti <tanoku@gmail.com> | 2013-04-16 19:46:41 +0400 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2013-04-16 19:46:41 +0400 |
commit | a50086d174658914d4d6462afbc83b02825b1f5b (patch) | |
tree | e8daa1c7bf678222cf351445179837bed7db3a72 /src/iterator.h | |
parent | 5b9fac39d8a76b9139667c26a63e6b3f204b3977 (diff) | |
parent | f124ebd457bfbf43de3516629aaba5a279636e04 (diff) |
Merge branch 'development'v0.18.0
Diffstat (limited to 'src/iterator.h')
-rw-r--r-- | src/iterator.h | 230 |
1 files changed, 142 insertions, 88 deletions
diff --git a/src/iterator.h b/src/iterator.h index b916a9080..4a4e6a9d8 100644 --- a/src/iterator.h +++ b/src/iterator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 the libgit2 contributors + * Copyright (C) the libgit2 contributors. All rights reserved. * * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. @@ -9,143 +9,197 @@ #include "common.h" #include "git2/index.h" +#include "vector.h" +#include "buffer.h" typedef struct git_iterator git_iterator; typedef enum { - GIT_ITERATOR_EMPTY = 0, - GIT_ITERATOR_TREE = 1, - GIT_ITERATOR_INDEX = 2, - GIT_ITERATOR_WORKDIR = 3 + GIT_ITERATOR_TYPE_EMPTY = 0, + GIT_ITERATOR_TYPE_TREE = 1, + GIT_ITERATOR_TYPE_INDEX = 2, + GIT_ITERATOR_TYPE_WORKDIR = 3, } git_iterator_type_t; +typedef enum { + /** ignore case for entry sort order */ + GIT_ITERATOR_IGNORE_CASE = (1 << 0), + /** force case sensitivity for entry sort order */ + GIT_ITERATOR_DONT_IGNORE_CASE = (1 << 1), + /** return tree items in addition to blob items */ + GIT_ITERATOR_INCLUDE_TREES = (1 << 2), + /** don't flatten trees, requiring advance_into (implies INCLUDE_TREES) */ + GIT_ITERATOR_DONT_AUTOEXPAND = (1 << 3), +} git_iterator_flag_t; + +typedef struct { + int (*current)(const git_index_entry **, git_iterator *); + int (*advance)(const git_index_entry **, git_iterator *); + int (*advance_into)(const git_index_entry **, git_iterator *); + int (*seek)(git_iterator *, const char *prefix); + int (*reset)(git_iterator *, const char *start, const char *end); + int (*at_end)(git_iterator *); + void (*free)(git_iterator *); +} git_iterator_callbacks; + struct git_iterator { git_iterator_type_t type; + git_iterator_callbacks *cb; + git_repository *repo; char *start; char *end; - int (*current)(git_iterator *, const git_index_entry **); - int (*at_end)(git_iterator *); - int (*advance)(git_iterator *, const git_index_entry **); - int (*seek)(git_iterator *, const char *prefix); - int (*reset)(git_iterator *); - void (*free)(git_iterator *); + int (*prefixcomp)(const char *str, const char *prefix); + unsigned int flags; }; -extern int git_iterator_for_nothing(git_iterator **iter); - -extern int git_iterator_for_tree_range( - git_iterator **iter, git_repository *repo, git_tree *tree, - const char *start, const char *end); - -GIT_INLINE(int) git_iterator_for_tree( - git_iterator **iter, git_repository *repo, git_tree *tree) -{ - return git_iterator_for_tree_range(iter, repo, tree, NULL, NULL); -} - -extern int git_iterator_for_index_range( - git_iterator **iter, git_repository *repo, - const char *start, const char *end); - -GIT_INLINE(int) git_iterator_for_index( - git_iterator **iter, git_repository *repo) -{ - return git_iterator_for_index_range(iter, repo, NULL, NULL); -} +extern int git_iterator_for_nothing( + git_iterator **out, + git_iterator_flag_t flags, + const char *start, + const char *end); -extern int git_iterator_for_workdir_range( - git_iterator **iter, git_repository *repo, - const char *start, const char *end); - -GIT_INLINE(int) git_iterator_for_workdir( - git_iterator **iter, git_repository *repo) -{ - return git_iterator_for_workdir_range(iter, repo, NULL, NULL); -} +/* tree iterators will match the ignore_case value from the index of the + * repository, unless you override with a non-zero flag value + */ +extern int git_iterator_for_tree( + git_iterator **out, + git_tree *tree, + git_iterator_flag_t flags, + const char *start, + const char *end); + +/* index iterators will take the ignore_case value from the index; the + * ignore_case flags are not used + */ +extern int git_iterator_for_index( + git_iterator **out, + git_index *index, + git_iterator_flag_t flags, + const char *start, + const char *end); + +/* workdir iterators will match the ignore_case value from the index of the + * repository, unless you override with a non-zero flag value + */ +extern int git_iterator_for_workdir( + git_iterator **out, + git_repository *repo, + git_iterator_flag_t flags, + const char *start, + const char *end); +extern void git_iterator_free(git_iterator *iter); -/* Entry is not guaranteed to be fully populated. For a tree iterator, - * we will only populate the mode, oid and path, for example. For a workdir - * iterator, we will not populate the oid. +/* Return a git_index_entry structure for the current value the iterator + * is looking at or NULL if the iterator is at the end. + * + * The entry may noy be fully populated. Tree iterators will only have a + * value mode, OID, and path. Workdir iterators will not have an OID (but + * you can use `git_iterator_current_oid()` to calculate it on demand). * * You do not need to free the entry. It is still "owned" by the iterator. - * Once you call `git_iterator_advance`, then content of the old entry is - * no longer guaranteed to be valid. + * Once you call `git_iterator_advance()` then the old entry is no longer + * guaranteed to be valid - it may be freed or just overwritten in place. */ GIT_INLINE(int) git_iterator_current( - git_iterator *iter, const git_index_entry **entry) + const git_index_entry **entry, git_iterator *iter) { - return iter->current(iter, entry); + return iter->cb->current(entry, iter); } -GIT_INLINE(int) git_iterator_at_end(git_iterator *iter) +/** + * Advance to the next item for the iterator. + * + * If GIT_ITERATOR_INCLUDE_TREES is set, this may be a tree item. If + * GIT_ITERATOR_DONT_AUTOEXPAND is set, calling this again when on a tree + * item will skip over all the items under that tree. + */ +GIT_INLINE(int) git_iterator_advance( + const git_index_entry **entry, git_iterator *iter) { - return iter->at_end(iter); + return iter->cb->advance(entry, iter); } -GIT_INLINE(int) git_iterator_advance( - git_iterator *iter, const git_index_entry **entry) +/** + * Iterate into a tree item (when GIT_ITERATOR_DONT_AUTOEXPAND is set). + * + * git_iterator_advance() steps through all items being iterated over + * (either with or without trees, depending on GIT_ITERATOR_INCLUDE_TREES), + * but if GIT_ITERATOR_DONT_AUTOEXPAND is set, it will skip to the next + * sibling of a tree instead of going to the first child of the tree. In + * that case, use this function to advance to the first child of the tree. + * + * If the current item is not a tree, this is a no-op. + * + * For working directory iterators only, a tree (i.e. directory) can be + * empty. In that case, this function returns GIT_ENOTFOUND and does not + * advance. That can't happen for tree and index iterators. + */ +GIT_INLINE(int) git_iterator_advance_into( + const git_index_entry **entry, git_iterator *iter) { - return iter->advance(iter, entry); + return iter->cb->advance_into(entry, iter); } GIT_INLINE(int) git_iterator_seek( git_iterator *iter, const char *prefix) { - return iter->seek(iter, prefix); + return iter->cb->seek(iter, prefix); } -GIT_INLINE(int) git_iterator_reset(git_iterator *iter) +GIT_INLINE(int) git_iterator_reset( + git_iterator *iter, const char *start, const char *end) { - return iter->reset(iter); + return iter->cb->reset(iter, start, end); } -GIT_INLINE(void) git_iterator_free(git_iterator *iter) +GIT_INLINE(int) git_iterator_at_end(git_iterator *iter) { - if (iter == NULL) - return; - - iter->free(iter); + return iter->cb->at_end(iter); +} - git__free(iter->start); - git__free(iter->end); +GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter) +{ + return iter->type; +} - memset(iter, 0, sizeof(*iter)); +GIT_INLINE(git_repository *) git_iterator_owner(git_iterator *iter) +{ + return iter->repo; +} - git__free(iter); +GIT_INLINE(git_iterator_flag_t) git_iterator_flags(git_iterator *iter) +{ + return iter->flags; } -GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter) +GIT_INLINE(bool) git_iterator_ignore_case(git_iterator *iter) { - return iter->type; + return ((iter->flags & GIT_ITERATOR_IGNORE_CASE) != 0); } +extern int git_iterator_set_ignore_case(git_iterator *iter, bool ignore_case); + extern int git_iterator_current_tree_entry( - git_iterator *iter, const git_tree_entry **tree_entry); + const git_tree_entry **entry_out, git_iterator *iter); -extern int git_iterator_current_is_ignored(git_iterator *iter); +extern int git_iterator_current_parent_tree( + const git_tree **tree_out, git_iterator *iter, const char *parent_path); -/** - * Iterate into a workdir directory. - * - * Workdir iterators do not automatically descend into directories (so that - * when comparing two iterator entries you can detect a newly created - * directory in the workdir). As a result, you may get S_ISDIR items from - * a workdir iterator. If you wish to iterate over the contents of the - * directories you encounter, then call this function when you encounter - * a directory. - * - * If there are no files in the directory, this will end up acting like a - * regular advance and will skip past the directory, so you should be - * prepared for that case. - * - * On non-workdir iterators or if not pointing at a directory, this is a - * no-op and will not advance the iterator. - */ -extern int git_iterator_advance_into_directory( - git_iterator *iter, const git_index_entry **entry); +extern bool git_iterator_current_is_ignored(git_iterator *iter); extern int git_iterator_cmp( git_iterator *iter, const char *path_prefix); +/** + * Get full path of the current item from a workdir iterator. This will + * return NULL for a non-workdir iterator. The git_buf is still owned by + * the iterator; this is exposed just for efficiency. + */ +extern int git_iterator_current_workdir_path( + git_buf **path, git_iterator *iter); + +/* Return index pointer if index iterator, else NULL */ +extern git_index *git_iterator_get_index(git_iterator *iter); + #endif |