2 * Copyright (C) the libgit2 contributors. All rights reserved.
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
7 #ifndef INCLUDE_iterator_h__
8 #define INCLUDE_iterator_h__
11 #include "git2/index.h"
16 typedef struct git_iterator git_iterator
;
19 GIT_ITERATOR_TYPE_EMPTY
= 0,
20 GIT_ITERATOR_TYPE_TREE
= 1,
21 GIT_ITERATOR_TYPE_INDEX
= 2,
22 GIT_ITERATOR_TYPE_WORKDIR
= 3,
23 GIT_ITERATOR_TYPE_FS
= 4,
24 } git_iterator_type_t
;
27 /** ignore case for entry sort order */
28 GIT_ITERATOR_IGNORE_CASE
= (1u << 0),
29 /** force case sensitivity for entry sort order */
30 GIT_ITERATOR_DONT_IGNORE_CASE
= (1u << 1),
31 /** return tree items in addition to blob items */
32 GIT_ITERATOR_INCLUDE_TREES
= (1u << 2),
33 /** don't flatten trees, requiring advance_into (implies INCLUDE_TREES) */
34 GIT_ITERATOR_DONT_AUTOEXPAND
= (1u << 3),
35 /** convert precomposed unicode to decomposed unicode */
36 GIT_ITERATOR_PRECOMPOSE_UNICODE
= (1u << 4),
37 /** never convert precomposed unicode to decomposed unicode */
38 GIT_ITERATOR_DONT_PRECOMPOSE_UNICODE
= (1u << 5),
39 /** include conflicts */
40 GIT_ITERATOR_INCLUDE_CONFLICTS
= (1u << 6),
41 } git_iterator_flag_t
;
44 GIT_ITERATOR_STATUS_NORMAL
= 0,
45 GIT_ITERATOR_STATUS_IGNORED
= 1,
46 GIT_ITERATOR_STATUS_EMPTY
= 2,
47 GIT_ITERATOR_STATUS_FILTERED
= 3
48 } git_iterator_status_t
;
54 /* paths to include in the iterator (literal). if set, any paths not
55 * listed here will be excluded from iteration.
57 git_strarray pathlist
;
59 /* flags, from above */
61 } git_iterator_options
;
63 #define GIT_ITERATOR_OPTIONS_INIT {0}
66 int (*current
)(const git_index_entry
**, git_iterator
*);
67 int (*advance
)(const git_index_entry
**, git_iterator
*);
68 int (*advance_into
)(const git_index_entry
**, git_iterator
*);
70 const git_index_entry
**, git_iterator_status_t
*, git_iterator
*);
71 int (*reset
)(git_iterator
*);
72 void (*free
)(git_iterator
*);
73 } git_iterator_callbacks
;
76 git_iterator_type_t type
;
77 git_iterator_callbacks
*cb
;
91 size_t pathlist_walk_idx
;
92 int (*strcomp
)(const char *a
, const char *b
);
93 int (*strncomp
)(const char *a
, const char *b
, size_t n
);
94 int (*prefixcomp
)(const char *str
, const char *prefix
);
95 int (*entry_srch
)(const void *key
, const void *array_member
);
100 extern int git_iterator_for_nothing(
102 git_iterator_options
*options
);
104 /* tree iterators will match the ignore_case value from the index of the
105 * repository, unless you override with a non-zero flag value
107 extern int git_iterator_for_tree(
110 git_iterator_options
*options
);
112 /* index iterators will take the ignore_case value from the index; the
113 * ignore_case flags are not used
115 extern int git_iterator_for_index(
117 git_repository
*repo
,
119 git_iterator_options
*options
);
121 extern int git_iterator_for_workdir_ext(
123 git_repository
*repo
,
124 const char *repo_workdir
,
127 git_iterator_options
*options
);
129 /* workdir iterators will match the ignore_case value from the index of the
130 * repository, unless you override with a non-zero flag value
132 GIT_INLINE(int) git_iterator_for_workdir(
134 git_repository
*repo
,
137 git_iterator_options
*options
)
139 return git_iterator_for_workdir_ext(out
, repo
, NULL
, index
, tree
, options
);
142 /* for filesystem iterators, you have to explicitly pass in the ignore_case
143 * behavior that you desire
145 extern int git_iterator_for_filesystem(
148 git_iterator_options
*options
);
150 extern void git_iterator_free(git_iterator
*iter
);
152 /* Return a git_index_entry structure for the current value the iterator
153 * is looking at or NULL if the iterator is at the end.
155 * The entry may noy be fully populated. Tree iterators will only have a
156 * value mode, OID, and path. Workdir iterators will not have an OID (but
157 * you can use `git_iterator_current_oid()` to calculate it on demand).
159 * You do not need to free the entry. It is still "owned" by the iterator.
160 * Once you call `git_iterator_advance()` then the old entry is no longer
161 * guaranteed to be valid - it may be freed or just overwritten in place.
163 GIT_INLINE(int) git_iterator_current(
164 const git_index_entry
**entry
, git_iterator
*iter
)
166 return iter
->cb
->current(entry
, iter
);
170 * Advance to the next item for the iterator.
172 * If GIT_ITERATOR_INCLUDE_TREES is set, this may be a tree item. If
173 * GIT_ITERATOR_DONT_AUTOEXPAND is set, calling this again when on a tree
174 * item will skip over all the items under that tree.
176 GIT_INLINE(int) git_iterator_advance(
177 const git_index_entry
**entry
, git_iterator
*iter
)
179 return iter
->cb
->advance(entry
, iter
);
183 * Iterate into a tree item (when GIT_ITERATOR_DONT_AUTOEXPAND is set).
185 * git_iterator_advance() steps through all items being iterated over
186 * (either with or without trees, depending on GIT_ITERATOR_INCLUDE_TREES),
187 * but if GIT_ITERATOR_DONT_AUTOEXPAND is set, it will skip to the next
188 * sibling of a tree instead of going to the first child of the tree. In
189 * that case, use this function to advance to the first child of the tree.
191 * If the current item is not a tree, this is a no-op.
193 * For filesystem and working directory iterators, a tree (i.e. directory)
194 * can be empty. In that case, this function returns GIT_ENOTFOUND and
195 * does not advance. That can't happen for tree and index iterators.
197 GIT_INLINE(int) git_iterator_advance_into(
198 const git_index_entry
**entry
, git_iterator
*iter
)
200 return iter
->cb
->advance_into(entry
, iter
);
203 /* Advance over a directory and check if it contains no files or just
206 * In a tree or the index, all directories will contain files, but in the
207 * working directory it is possible to have an empty directory tree or a
208 * tree that only contains ignored files. Many Git operations treat these
209 * cases specially. This advances over a directory (presumably an
210 * untracked directory) but checks during the scan if there are any files
211 * and any non-ignored files.
213 GIT_INLINE(int) git_iterator_advance_over(
214 const git_index_entry
**entry
,
215 git_iterator_status_t
*status
,
218 return iter
->cb
->advance_over(entry
, status
, iter
);
222 * Go back to the start of the iteration.
224 GIT_INLINE(int) git_iterator_reset(git_iterator
*iter
)
226 return iter
->cb
->reset(iter
);
230 * Go back to the start of the iteration after updating the `start` and
231 * `end` pathname boundaries of the iteration.
233 extern int git_iterator_reset_range(
234 git_iterator
*iter
, const char *start
, const char *end
);
236 GIT_INLINE(git_iterator_type_t
) git_iterator_type(git_iterator
*iter
)
241 GIT_INLINE(git_repository
*) git_iterator_owner(git_iterator
*iter
)
246 GIT_INLINE(git_index
*) git_iterator_index(git_iterator
*iter
)
251 GIT_INLINE(git_iterator_flag_t
) git_iterator_flags(git_iterator
*iter
)
256 GIT_INLINE(bool) git_iterator_ignore_case(git_iterator
*iter
)
258 return ((iter
->flags
& GIT_ITERATOR_IGNORE_CASE
) != 0);
261 extern void git_iterator_set_ignore_case(
262 git_iterator
*iter
, bool ignore_case
);
264 extern int git_iterator_current_tree_entry(
265 const git_tree_entry
**entry_out
, git_iterator
*iter
);
267 extern int git_iterator_current_parent_tree(
268 const git_tree
**tree_out
, git_iterator
*iter
, size_t depth
);
270 extern bool git_iterator_current_is_ignored(git_iterator
*iter
);
272 extern bool git_iterator_current_tree_is_ignored(git_iterator
*iter
);
275 * Get full path of the current item from a workdir iterator. This will
276 * return NULL for a non-workdir iterator. The git_buf is still owned by
277 * the iterator; this is exposed just for efficiency.
279 extern int git_iterator_current_workdir_path(
280 git_buf
**path
, git_iterator
*iter
);
283 * Retrieve the index stored in the iterator.
285 * Only implemented for the workdir and index iterators.
287 extern git_index
*git_iterator_index(git_iterator
*iter
);
289 typedef int (*git_iterator_walk_cb
)(
290 const git_index_entry
**entries
,
294 * Walk the given iterators in lock-step. The given callback will be
295 * called for each unique path, with the index entry in each iterator
296 * (or NULL if the given iterator does not contain that path).
298 extern int git_iterator_walk(
299 git_iterator
**iterators
,
301 git_iterator_walk_cb cb
,