File Coverage

deps/libgit2/src/iterator.h
Criterion Covered Total %
statement 10 10 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 10 10 100.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright (C) the libgit2 contributors. All rights reserved.
3             *
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.
6             */
7             #ifndef INCLUDE_iterator_h__
8             #define INCLUDE_iterator_h__
9              
10             #include "common.h"
11              
12             #include "git2/index.h"
13             #include "vector.h"
14             #include "buffer.h"
15             #include "ignore.h"
16              
17             typedef struct git_iterator git_iterator;
18              
19             typedef enum {
20             GIT_ITERATOR_EMPTY = 0,
21             GIT_ITERATOR_TREE = 1,
22             GIT_ITERATOR_INDEX = 2,
23             GIT_ITERATOR_WORKDIR = 3,
24             GIT_ITERATOR_FS = 4,
25             } git_iterator_t;
26              
27             typedef enum {
28             /** ignore case for entry sort order */
29             GIT_ITERATOR_IGNORE_CASE = (1u << 0),
30             /** force case sensitivity for entry sort order */
31             GIT_ITERATOR_DONT_IGNORE_CASE = (1u << 1),
32             /** return tree items in addition to blob items */
33             GIT_ITERATOR_INCLUDE_TREES = (1u << 2),
34             /** don't flatten trees, requiring advance_into (implies INCLUDE_TREES) */
35             GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3),
36             /** convert precomposed unicode to decomposed unicode */
37             GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4),
38             /** never convert precomposed unicode to decomposed unicode */
39             GIT_ITERATOR_DONT_PRECOMPOSE_UNICODE = (1u << 5),
40             /** include conflicts */
41             GIT_ITERATOR_INCLUDE_CONFLICTS = (1u << 6),
42             /** descend into symlinked directories */
43             GIT_ITERATOR_DESCEND_SYMLINKS = (1u << 7),
44             /** hash files in workdir or filesystem iterators */
45             GIT_ITERATOR_INCLUDE_HASH = (1u << 8),
46             } git_iterator_flag_t;
47              
48             typedef enum {
49             GIT_ITERATOR_STATUS_NORMAL = 0,
50             GIT_ITERATOR_STATUS_IGNORED = 1,
51             GIT_ITERATOR_STATUS_EMPTY = 2,
52             GIT_ITERATOR_STATUS_FILTERED = 3
53             } git_iterator_status_t;
54              
55             typedef struct {
56             const char *start;
57             const char *end;
58              
59             /* paths to include in the iterator (literal). if set, any paths not
60             * listed here will be excluded from iteration.
61             */
62             git_strarray pathlist;
63              
64             /* flags, from above */
65             unsigned int flags;
66             } git_iterator_options;
67              
68             #define GIT_ITERATOR_OPTIONS_INIT {0}
69              
70             typedef struct {
71             int (*current)(const git_index_entry **, git_iterator *);
72             int (*advance)(const git_index_entry **, git_iterator *);
73             int (*advance_into)(const git_index_entry **, git_iterator *);
74             int (*advance_over)(
75             const git_index_entry **, git_iterator_status_t *, git_iterator *);
76             int (*reset)(git_iterator *);
77             void (*free)(git_iterator *);
78             } git_iterator_callbacks;
79              
80             struct git_iterator {
81             git_iterator_t type;
82             git_iterator_callbacks *cb;
83              
84             git_repository *repo;
85             git_index *index;
86              
87             char *start;
88             size_t start_len;
89              
90             char *end;
91             size_t end_len;
92              
93             bool started;
94             bool ended;
95             git_vector pathlist;
96             size_t pathlist_walk_idx;
97             int (*strcomp)(const char *a, const char *b);
98             int (*strncomp)(const char *a, const char *b, size_t n);
99             int (*prefixcomp)(const char *str, const char *prefix);
100             int (*entry_srch)(const void *key, const void *array_member);
101             size_t stat_calls;
102             unsigned int flags;
103             };
104              
105             extern int git_iterator_for_nothing(
106             git_iterator **out,
107             git_iterator_options *options);
108              
109             /* tree iterators will match the ignore_case value from the index of the
110             * repository, unless you override with a non-zero flag value
111             */
112             extern int git_iterator_for_tree(
113             git_iterator **out,
114             git_tree *tree,
115             git_iterator_options *options);
116              
117             /* index iterators will take the ignore_case value from the index; the
118             * ignore_case flags are not used
119             */
120             extern int git_iterator_for_index(
121             git_iterator **out,
122             git_repository *repo,
123             git_index *index,
124             git_iterator_options *options);
125              
126             extern int git_iterator_for_workdir_ext(
127             git_iterator **out,
128             git_repository *repo,
129             const char *repo_workdir,
130             git_index *index,
131             git_tree *tree,
132             git_iterator_options *options);
133              
134             /* workdir iterators will match the ignore_case value from the index of the
135             * repository, unless you override with a non-zero flag value
136             */
137 6           GIT_INLINE(int) git_iterator_for_workdir(
138             git_iterator **out,
139             git_repository *repo,
140             git_index *index,
141             git_tree *tree,
142             git_iterator_options *options)
143             {
144 6           return git_iterator_for_workdir_ext(out, repo, NULL, index, tree, options);
145             }
146              
147             /* for filesystem iterators, you have to explicitly pass in the ignore_case
148             * behavior that you desire
149             */
150             extern int git_iterator_for_filesystem(
151             git_iterator **out,
152             const char *root,
153             git_iterator_options *options);
154              
155             extern void git_iterator_free(git_iterator *iter);
156              
157             /* Return a git_index_entry structure for the current value the iterator
158             * is looking at or NULL if the iterator is at the end.
159             *
160             * The entry may noy be fully populated. Tree iterators will only have a
161             * value mode, OID, and path. Workdir iterators will not have an OID (but
162             * you can use `git_iterator_current_oid()` to calculate it on demand).
163             *
164             * You do not need to free the entry. It is still "owned" by the iterator.
165             * Once you call `git_iterator_advance()` then the old entry is no longer
166             * guaranteed to be valid - it may be freed or just overwritten in place.
167             */
168             GIT_INLINE(int) git_iterator_current(
169             const git_index_entry **entry, git_iterator *iter)
170             {
171             return iter->cb->current(entry, iter);
172             }
173              
174             /**
175             * Advance to the next item for the iterator.
176             *
177             * If GIT_ITERATOR_INCLUDE_TREES is set, this may be a tree item. If
178             * GIT_ITERATOR_DONT_AUTOEXPAND is set, calling this again when on a tree
179             * item will skip over all the items under that tree.
180             */
181 32           GIT_INLINE(int) git_iterator_advance(
182             const git_index_entry **entry, git_iterator *iter)
183             {
184 32           return iter->cb->advance(entry, iter);
185             }
186              
187             /**
188             * Iterate into a tree item (when GIT_ITERATOR_DONT_AUTOEXPAND is set).
189             *
190             * git_iterator_advance() steps through all items being iterated over
191             * (either with or without trees, depending on GIT_ITERATOR_INCLUDE_TREES),
192             * but if GIT_ITERATOR_DONT_AUTOEXPAND is set, it will skip to the next
193             * sibling of a tree instead of going to the first child of the tree. In
194             * that case, use this function to advance to the first child of the tree.
195             *
196             * If the current item is not a tree, this is a no-op.
197             *
198             * For filesystem and working directory iterators, a tree (i.e. directory)
199             * can be empty. In that case, this function returns GIT_ENOTFOUND and
200             * does not advance. That can't happen for tree and index iterators.
201             */
202             GIT_INLINE(int) git_iterator_advance_into(
203             const git_index_entry **entry, git_iterator *iter)
204             {
205             return iter->cb->advance_into(entry, iter);
206             }
207              
208             /* Advance over a directory and check if it contains no files or just
209             * ignored files.
210             *
211             * In a tree or the index, all directories will contain files, but in the
212             * working directory it is possible to have an empty directory tree or a
213             * tree that only contains ignored files. Many Git operations treat these
214             * cases specially. This advances over a directory (presumably an
215             * untracked directory) but checks during the scan if there are any files
216             * and any non-ignored files.
217             */
218             GIT_INLINE(int) git_iterator_advance_over(
219             const git_index_entry **entry,
220             git_iterator_status_t *status,
221             git_iterator *iter)
222             {
223             return iter->cb->advance_over(entry, status, iter);
224             }
225              
226             /**
227             * Go back to the start of the iteration.
228             */
229             GIT_INLINE(int) git_iterator_reset(git_iterator *iter)
230             {
231             return iter->cb->reset(iter);
232             }
233              
234             /**
235             * Go back to the start of the iteration after updating the `start` and
236             * `end` pathname boundaries of the iteration.
237             */
238             extern int git_iterator_reset_range(
239             git_iterator *iter, const char *start, const char *end);
240              
241 11           GIT_INLINE(git_iterator_t) git_iterator_type(git_iterator *iter)
242             {
243 11           return iter->type;
244             }
245              
246 6           GIT_INLINE(git_repository *) git_iterator_owner(git_iterator *iter)
247             {
248 6           return iter->repo;
249             }
250              
251             GIT_INLINE(git_index *) git_iterator_index(git_iterator *iter)
252             {
253             return iter->index;
254             }
255              
256             GIT_INLINE(git_iterator_flag_t) git_iterator_flags(git_iterator *iter)
257             {
258             return iter->flags;
259             }
260              
261 11           GIT_INLINE(bool) git_iterator_ignore_case(git_iterator *iter)
262             {
263 11           return ((iter->flags & GIT_ITERATOR_IGNORE_CASE) != 0);
264             }
265              
266             extern void git_iterator_set_ignore_case(
267             git_iterator *iter, bool ignore_case);
268              
269             extern int git_iterator_current_tree_entry(
270             const git_tree_entry **entry_out, git_iterator *iter);
271              
272             extern int git_iterator_current_parent_tree(
273             const git_tree **tree_out, git_iterator *iter, size_t depth);
274              
275             extern bool git_iterator_current_is_ignored(git_iterator *iter);
276              
277             extern bool git_iterator_current_tree_is_ignored(git_iterator *iter);
278              
279             /**
280             * Get full path of the current item from a workdir iterator. This will
281             * return NULL for a non-workdir iterator. The git_buf is still owned by
282             * the iterator; this is exposed just for efficiency.
283             */
284             extern int git_iterator_current_workdir_path(
285             git_buf **path, git_iterator *iter);
286              
287             /**
288             * Retrieve the index stored in the iterator.
289             *
290             * Only implemented for the workdir and index iterators.
291             */
292             extern git_index *git_iterator_index(git_iterator *iter);
293              
294             typedef int (*git_iterator_foreach_cb)(
295             const git_index_entry *entry,
296             void *data);
297              
298             /**
299             * Walk the given iterator and invoke the callback for each path
300             * contained in the iterator.
301             */
302             extern int git_iterator_foreach(
303             git_iterator *iterator,
304             git_iterator_foreach_cb cb,
305             void *data);
306              
307             typedef int (*git_iterator_walk_cb)(
308             const git_index_entry **entries,
309             void *data);
310              
311             /**
312             * Walk the given iterators in lock-step. The given callback will be
313             * called for each unique path, with the index entry in each iterator
314             * (or NULL if the given iterator does not contain that path).
315             */
316             extern int git_iterator_walk(
317             git_iterator **iterators,
318             size_t cnt,
319             git_iterator_walk_cb cb,
320             void *data);
321              
322             #endif