]> git.proxmox.com Git - libgit2.git/blame - src/iterator.h
Merge pull request #3097 from libgit2/cmn/submodule-config-state
[libgit2.git] / src / iterator.h
CommitLineData
b6c93aef 1/*
359fc2d2 2 * Copyright (C) the libgit2 contributors. All rights reserved.
b6c93aef
RB
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#include "git2/index.h"
ec40b7f9 12#include "vector.h"
dfbff793 13#include "buffer.h"
ff475375 14#include "ignore.h"
ec40b7f9 15
b6c93aef
RB
16typedef struct git_iterator git_iterator;
17
18typedef enum {
134d8c91
RB
19 GIT_ITERATOR_TYPE_EMPTY = 0,
20 GIT_ITERATOR_TYPE_TREE = 1,
21 GIT_ITERATOR_TYPE_INDEX = 2,
22 GIT_ITERATOR_TYPE_WORKDIR = 3,
ff0ddfa4 23 GIT_ITERATOR_TYPE_FS = 4,
b6c93aef
RB
24} git_iterator_type_t;
25
134d8c91 26typedef enum {
169dc616 27 /** ignore case for entry sort order */
2fe54afa 28 GIT_ITERATOR_IGNORE_CASE = (1u << 0),
169dc616 29 /** force case sensitivity for entry sort order */
2fe54afa 30 GIT_ITERATOR_DONT_IGNORE_CASE = (1u << 1),
9bea03ce 31 /** return tree items in addition to blob items */
2fe54afa 32 GIT_ITERATOR_INCLUDE_TREES = (1u << 2),
9bea03ce 33 /** don't flatten trees, requiring advance_into (implies INCLUDE_TREES) */
2fe54afa
RB
34 GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3),
35 /** convert precomposed unicode to decomposed unicode */
36 GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4),
aa3af01d
ET
37 /** include conflicts */
38 GIT_ITERATOR_INCLUDE_CONFLICTS = (1u << 5),
134d8c91
RB
39} git_iterator_flag_t;
40
f616a36b 41typedef struct {
169dc616
RB
42 int (*current)(const git_index_entry **, git_iterator *);
43 int (*advance)(const git_index_entry **, git_iterator *);
9bea03ce 44 int (*advance_into)(const git_index_entry **, git_iterator *);
41a82592 45 int (*seek)(git_iterator *, const char *prefix);
91e7d263 46 int (*reset)(git_iterator *, const char *start, const char *end);
169dc616 47 int (*at_end)(git_iterator *);
b6c93aef 48 void (*free)(git_iterator *);
f616a36b
RB
49} git_iterator_callbacks;
50
51struct git_iterator {
52 git_iterator_type_t type;
53 git_iterator_callbacks *cb;
54 git_repository *repo;
55 char *start;
56 char *end;
25423d03 57 int (*prefixcomp)(const char *str, const char *prefix);
9c8ed499 58 size_t stat_calls;
134d8c91 59 unsigned int flags;
b6c93aef
RB
60};
61
134d8c91 62extern int git_iterator_for_nothing(
169dc616
RB
63 git_iterator **out,
64 git_iterator_flag_t flags,
65 const char *start,
66 const char *end);
7e000ab2 67
134d8c91
RB
68/* tree iterators will match the ignore_case value from the index of the
69 * repository, unless you override with a non-zero flag value
70 */
169dc616 71extern int git_iterator_for_tree(
134d8c91
RB
72 git_iterator **out,
73 git_tree *tree,
74 git_iterator_flag_t flags,
75 const char *start,
76 const char *end);
b6c93aef 77
134d8c91
RB
78/* index iterators will take the ignore_case value from the index; the
79 * ignore_case flags are not used
80 */
169dc616 81extern int git_iterator_for_index(
134d8c91
RB
82 git_iterator **out,
83 git_index *index,
84 git_iterator_flag_t flags,
85 const char *start,
86 const char *end);
41a82592 87
9094ae5a
RB
88extern int git_iterator_for_workdir_ext(
89 git_iterator **out,
90 git_repository *repo,
91 const char *repo_workdir,
62a617dc
CMN
92 git_index *index,
93 git_tree *tree,
9094ae5a
RB
94 git_iterator_flag_t flags,
95 const char *start,
96 const char *end);
97
134d8c91
RB
98/* workdir iterators will match the ignore_case value from the index of the
99 * repository, unless you override with a non-zero flag value
100 */
9094ae5a 101GIT_INLINE(int) git_iterator_for_workdir(
134d8c91
RB
102 git_iterator **out,
103 git_repository *repo,
62a617dc
CMN
104 git_index *index,
105 git_tree *tree,
134d8c91
RB
106 git_iterator_flag_t flags,
107 const char *start,
9094ae5a
RB
108 const char *end)
109{
62a617dc 110 return git_iterator_for_workdir_ext(out, repo, NULL, index, tree, flags, start, end);
9094ae5a 111}
41a82592 112
ff0ddfa4
RB
113/* for filesystem iterators, you have to explicitly pass in the ignore_case
114 * behavior that you desire
115 */
116extern int git_iterator_for_filesystem(
117 git_iterator **out,
118 const char *root,
119 git_iterator_flag_t flags,
120 const char *start,
121 const char *end);
122
4b181037
RB
123extern void git_iterator_free(git_iterator *iter);
124
169dc616
RB
125/* Return a git_index_entry structure for the current value the iterator
126 * is looking at or NULL if the iterator is at the end.
127 *
128 * The entry may noy be fully populated. Tree iterators will only have a
129 * value mode, OID, and path. Workdir iterators will not have an OID (but
130 * you can use `git_iterator_current_oid()` to calculate it on demand).
b6c93aef
RB
131 *
132 * You do not need to free the entry. It is still "owned" by the iterator.
169dc616
RB
133 * Once you call `git_iterator_advance()` then the old entry is no longer
134 * guaranteed to be valid - it may be freed or just overwritten in place.
b6c93aef
RB
135 */
136GIT_INLINE(int) git_iterator_current(
169dc616 137 const git_index_entry **entry, git_iterator *iter)
b6c93aef 138{
169dc616 139 return iter->cb->current(entry, iter);
b6c93aef
RB
140}
141
9bea03ce
RB
142/**
143 * Advance to the next item for the iterator.
144 *
145 * If GIT_ITERATOR_INCLUDE_TREES is set, this may be a tree item. If
146 * GIT_ITERATOR_DONT_AUTOEXPAND is set, calling this again when on a tree
147 * item will skip over all the items under that tree.
148 */
da337c80 149GIT_INLINE(int) git_iterator_advance(
169dc616 150 const git_index_entry **entry, git_iterator *iter)
b6c93aef 151{
169dc616 152 return iter->cb->advance(entry, iter);
b6c93aef
RB
153}
154
9bea03ce
RB
155/**
156 * Iterate into a tree item (when GIT_ITERATOR_DONT_AUTOEXPAND is set).
157 *
158 * git_iterator_advance() steps through all items being iterated over
159 * (either with or without trees, depending on GIT_ITERATOR_INCLUDE_TREES),
160 * but if GIT_ITERATOR_DONT_AUTOEXPAND is set, it will skip to the next
161 * sibling of a tree instead of going to the first child of the tree. In
162 * that case, use this function to advance to the first child of the tree.
163 *
164 * If the current item is not a tree, this is a no-op.
165 *
cee695ae
RB
166 * For filesystem and working directory iterators, a tree (i.e. directory)
167 * can be empty. In that case, this function returns GIT_ENOTFOUND and
168 * does not advance. That can't happen for tree and index iterators.
9bea03ce
RB
169 */
170GIT_INLINE(int) git_iterator_advance_into(
171 const git_index_entry **entry, git_iterator *iter)
172{
173 return iter->cb->advance_into(entry, iter);
174}
175
cee695ae
RB
176/**
177 * Advance into a tree or skip over it if it is empty.
178 *
179 * Because `git_iterator_advance_into` may return GIT_ENOTFOUND if the
180 * directory is empty (only with filesystem and working directory
181 * iterators) and a common response is to just call `git_iterator_advance`
182 * when that happens, this bundles the two into a single simple call.
183 */
184GIT_INLINE(int) git_iterator_advance_into_or_over(
185 const git_index_entry **entry, git_iterator *iter)
186{
187 int error = iter->cb->advance_into(entry, iter);
188 if (error == GIT_ENOTFOUND) {
189 giterr_clear();
190 error = iter->cb->advance(entry, iter);
191 }
192 return error;
193}
194
195/* Seek is currently unimplemented */
41a82592
RB
196GIT_INLINE(int) git_iterator_seek(
197 git_iterator *iter, const char *prefix)
198{
f616a36b 199 return iter->cb->seek(iter, prefix);
41a82592
RB
200}
201
cee695ae
RB
202/**
203 * Go back to the start of the iteration.
204 *
205 * This resets the iterator to the start of the iteration. It also allows
206 * you to reset the `start` and `end` pathname boundaries of the iteration
207 * when doing so.
208 */
91e7d263
RB
209GIT_INLINE(int) git_iterator_reset(
210 git_iterator *iter, const char *start, const char *end)
74fa4bfa 211{
f616a36b 212 return iter->cb->reset(iter, start, end);
74fa4bfa
RB
213}
214
cee695ae
RB
215/**
216 * Check if the iterator is at the end
217 *
218 * @return 0 if not at end, >0 if at end
219 */
169dc616
RB
220GIT_INLINE(int) git_iterator_at_end(git_iterator *iter)
221{
222 return iter->cb->at_end(iter);
223}
224
b6c93aef
RB
225GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter)
226{
227 return iter->type;
228}
229
9950d27a
RB
230GIT_INLINE(git_repository *) git_iterator_owner(git_iterator *iter)
231{
232 return iter->repo;
233}
234
134d8c91
RB
235GIT_INLINE(git_iterator_flag_t) git_iterator_flags(git_iterator *iter)
236{
237 return iter->flags;
238}
239
240GIT_INLINE(bool) git_iterator_ignore_case(git_iterator *iter)
241{
242 return ((iter->flags & GIT_ITERATOR_IGNORE_CASE) != 0);
243}
244
cc216a01
RB
245extern int git_iterator_set_ignore_case(git_iterator *iter, bool ignore_case);
246
b6c93aef 247extern int git_iterator_current_tree_entry(
9bea03ce 248 const git_tree_entry **entry_out, git_iterator *iter);
b6c93aef 249
0d64bef9 250extern int git_iterator_current_parent_tree(
9bea03ce 251 const git_tree **tree_out, git_iterator *iter, const char *parent_path);
0d64bef9 252
169dc616 253extern bool git_iterator_current_is_ignored(git_iterator *iter);
b6c93aef 254
f554611a
RB
255extern bool git_iterator_current_tree_is_ignored(git_iterator *iter);
256
41a82592
RB
257extern int git_iterator_cmp(
258 git_iterator *iter, const char *path_prefix);
259
dfbff793 260/**
169dc616
RB
261 * Get full path of the current item from a workdir iterator. This will
262 * return NULL for a non-workdir iterator. The git_buf is still owned by
263 * the iterator; this is exposed just for efficiency.
dfbff793
RB
264 */
265extern int git_iterator_current_workdir_path(
169dc616 266 git_buf **path, git_iterator *iter);
5cf9875a 267
169dc616
RB
268/* Return index pointer if index iterator, else NULL */
269extern git_index *git_iterator_get_index(git_iterator *iter);
5cf9875a 270
219c89d1
RB
271typedef enum {
272 GIT_ITERATOR_STATUS_NORMAL = 0,
273 GIT_ITERATOR_STATUS_IGNORED = 1,
274 GIT_ITERATOR_STATUS_EMPTY = 2
275} git_iterator_status_t;
276
277/* Advance over a directory and check if it contains no files or just
278 * ignored files.
279 *
280 * In a tree or the index, all directories will contain files, but in the
281 * working directory it is possible to have an empty directory tree or a
282 * tree that only contains ignored files. Many Git operations treat these
283 * cases specially. This advances over a directory (presumably an
284 * untracked directory) but checks during the scan if there are any files
285 * and any non-ignored files.
37da3685 286 */
219c89d1
RB
287extern int git_iterator_advance_over_with_status(
288 const git_index_entry **entry, git_iterator_status_t *status, git_iterator *iter);
37da3685 289
ff475375
CMN
290/**
291 * Retrieve the index stored in the iterator.
292 *
293 * Only implemented for the workdir iterator
294 */
295extern int git_iterator_index(git_index **out, git_iterator *iter);
296
b6c93aef 297#endif