From b6c93aef4276051f9c4536ecbed48f4cd093bd1b Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 21 Feb 2012 14:46:24 -0800 Subject: Uniform iterators for trees, index, and workdir This create a new git_iterator type of object that provides a uniform interface for iterating over the index, an arbitrary tree, or the working directory of a repository. As part of this, git ignore support was extended to support push and pop of directory-based ignore files as the working directory is being traversed (so the array of ignores does not have to be recreated at each directory during traveral). There are a number of other small utility functions in buffer, path, vector, and fileops that are included in this patch that made the iterator implementation cleaner. --- src/iterator.h | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/iterator.h (limited to 'src/iterator.h') diff --git a/src/iterator.h b/src/iterator.h new file mode 100644 index 000000000..4aa1df52d --- /dev/null +++ b/src/iterator.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_iterator_h__ +#define INCLUDE_iterator_h__ + +#include "common.h" +#include "git2/index.h" + +typedef struct git_iterator git_iterator; + +typedef enum { + GIT_ITERATOR_TREE = 1, + GIT_ITERATOR_INDEX = 2, + GIT_ITERATOR_WORKDIR = 3 +} git_iterator_type_t; + +struct git_iterator { + git_iterator_type_t type; + int (*current)(git_iterator *, const git_index_entry **); + int (*at_end)(git_iterator *); + int (*advance)(git_iterator *); + void (*free)(git_iterator *); +}; + +int git_iterator_for_tree( + git_repository *repo, git_tree *tree, git_iterator **iter); + +int git_iterator_for_index( + git_repository *repo, git_iterator **iter); + +int git_iterator_for_workdir( + git_repository *repo, 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. + * + * 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. + */ +GIT_INLINE(int) git_iterator_current( + git_iterator *iter, const git_index_entry **entry) +{ + return iter->current(iter, entry); +} + +GIT_INLINE(int) git_iterator_at_end(git_iterator *iter) +{ + return iter->at_end(iter); +} + +GIT_INLINE(int) git_iterator_advance(git_iterator *iter) +{ + return iter->advance(iter); +} + +GIT_INLINE(void) git_iterator_free(git_iterator *iter) +{ + iter->free(iter); + git__free(iter); +} + +GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter) +{ + return iter->type; +} + +extern int git_iterator_current_tree_entry( + git_iterator *iter, const git_tree_entry **tree_entry); + +extern int git_iterator_current_is_ignored(git_iterator *iter); + +/** + * Iterate into an ignored workdir directory. + * + * When a workdir iterator encounters a directory that is ignored, it will + * just return a current entry for the directory with is_ignored returning + * true. If you are iterating over the index or a tree in parallel and a + * file in the ignored directory has been added to the index/tree already, + * then it may be necessary to iterate into the directory even though it is + * ignored. Call this function to do that. + * + * Note that if the tracked file in the ignored directory has been deleted, + * this may end up acting like a full "advance" call and advance past the + * directory completely. You must handle that case. + */ +extern int git_iterator_advance_into_ignored_directory(git_iterator *iter); + +#endif -- cgit v1.2.3