mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-28 12:13:18 +00:00
iterator: combine fs+workdir iterators more completely
Drop some of the layers of indirection between the workdir and the filesystem iterators. This makes the code a little bit easier to follow, and reduces the number of unnecessary allocations a bit as well. (Prior to this, when we filter entries, we would allocate them, filter them and then free them; now we do the filtering before allocation.) Also, rename `git_iterator_advance_over_with_status` to just `git_iterator_advance_over`. Mostly because it's a fucking long-ass function name otherwise.
This commit is contained in:
parent
d051de243c
commit
0e0589fcc3
@ -394,7 +394,7 @@ static int checkout_action_wd_only(
|
||||
git_buf_sets(&data->tmp, wd->path);
|
||||
saved_wd.path = data->tmp.ptr;
|
||||
|
||||
error = git_iterator_advance_over_with_status(
|
||||
error = git_iterator_advance_over(
|
||||
wditem, &untracked_state, workdir);
|
||||
if (error == GIT_ITEROVER)
|
||||
over = true;
|
||||
@ -930,7 +930,7 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g
|
||||
git_index *index;
|
||||
|
||||
/* Only write conficts from sources that have them: indexes. */
|
||||
if ((index = git_iterator_get_index(data->target)) == NULL)
|
||||
if ((index = git_iterator_index(data->target)) == NULL)
|
||||
return 0;
|
||||
|
||||
data->update_conflicts._cmp = checkout_conflictdata_cmp;
|
||||
@ -1080,7 +1080,7 @@ static int checkout_conflicts_coalesce_renames(
|
||||
size_t i, names;
|
||||
int error = 0;
|
||||
|
||||
if ((index = git_iterator_get_index(data->target)) == NULL)
|
||||
if ((index = git_iterator_index(data->target)) == NULL)
|
||||
return 0;
|
||||
|
||||
/* Juggle entries based on renames */
|
||||
@ -1138,7 +1138,7 @@ static int checkout_conflicts_mark_directoryfile(
|
||||
const char *path;
|
||||
int prefixed, error = 0;
|
||||
|
||||
if ((index = git_iterator_get_index(data->target)) == NULL)
|
||||
if ((index = git_iterator_index(data->target)) == NULL)
|
||||
return 0;
|
||||
|
||||
len = git_index_entrycount(index);
|
||||
@ -2378,7 +2378,7 @@ static int checkout_data_init(
|
||||
if ((error = git_repository_index(&data->index, data->repo)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (data->index != git_iterator_get_index(target)) {
|
||||
if (data->index != git_iterator_index(target)) {
|
||||
if ((error = git_index_read(data->index, true)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
@ -2600,7 +2600,7 @@ int git_checkout_iterator(
|
||||
(error = checkout_create_conflicts(&data)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (data.index != git_iterator_get_index(target) &&
|
||||
if (data.index != git_iterator_index(target) &&
|
||||
(error = checkout_extensions_update_index(&data)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
|
12
src/diff.c
12
src/diff.c
@ -826,8 +826,7 @@ static int maybe_modified(
|
||||
*/
|
||||
} else if (git_oid_iszero(&nitem->id) && new_is_workdir) {
|
||||
bool use_ctime = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) != 0);
|
||||
git_index *index;
|
||||
git_iterator_index(&index, info->new_iter);
|
||||
git_index *index = git_iterator_index(info->new_iter);
|
||||
|
||||
status = GIT_DELTA_UNMODIFIED;
|
||||
|
||||
@ -980,15 +979,14 @@ static int iterator_advance_into(
|
||||
return error;
|
||||
}
|
||||
|
||||
static int iterator_advance_over_with_status(
|
||||
static int iterator_advance_over(
|
||||
const git_index_entry **entry,
|
||||
git_iterator_status_t *status,
|
||||
git_iterator *iterator)
|
||||
{
|
||||
int error;
|
||||
int error = git_iterator_advance_over(entry, status, iterator);
|
||||
|
||||
if ((error = git_iterator_advance_over_with_status(
|
||||
entry, status, iterator)) == GIT_ITEROVER) {
|
||||
if (error == GIT_ITEROVER) {
|
||||
*entry = NULL;
|
||||
error = 0;
|
||||
}
|
||||
@ -1056,7 +1054,7 @@ static int handle_unmatched_new_item(
|
||||
return iterator_advance(&info->nitem, info->new_iter);
|
||||
|
||||
/* iterate into dir looking for an actual untracked file */
|
||||
if ((error = iterator_advance_over_with_status(
|
||||
if ((error = iterator_advance_over(
|
||||
&info->nitem, &untracked_state, info->new_iter)) < 0)
|
||||
return error;
|
||||
|
||||
|
2004
src/iterator.c
2004
src/iterator.c
File diff suppressed because it is too large
Load Diff
@ -34,10 +34,19 @@ typedef enum {
|
||||
GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3),
|
||||
/** convert precomposed unicode to decomposed unicode */
|
||||
GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4),
|
||||
/** never convert precomposed unicode to decomposed unicode */
|
||||
GIT_ITERATOR_DONT_PRECOMPOSE_UNICODE = (1u << 5),
|
||||
/** include conflicts */
|
||||
GIT_ITERATOR_INCLUDE_CONFLICTS = (1u << 5),
|
||||
GIT_ITERATOR_INCLUDE_CONFLICTS = (1u << 6),
|
||||
} git_iterator_flag_t;
|
||||
|
||||
typedef enum {
|
||||
GIT_ITERATOR_STATUS_NORMAL = 0,
|
||||
GIT_ITERATOR_STATUS_IGNORED = 1,
|
||||
GIT_ITERATOR_STATUS_EMPTY = 2,
|
||||
GIT_ITERATOR_STATUS_FILTERED = 3
|
||||
} git_iterator_status_t;
|
||||
|
||||
typedef struct {
|
||||
const char *start;
|
||||
const char *end;
|
||||
@ -57,6 +66,8 @@ 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 (*advance_over)(
|
||||
const git_index_entry **, git_iterator_status_t *, git_iterator *);
|
||||
int (*reset)(git_iterator *);
|
||||
int (*reset_range)(git_iterator *, const char *start, const char *end);
|
||||
int (*at_end)(git_iterator *);
|
||||
@ -67,8 +78,13 @@ struct git_iterator {
|
||||
git_iterator_type_t type;
|
||||
git_iterator_callbacks *cb;
|
||||
git_repository *repo;
|
||||
|
||||
char *start;
|
||||
size_t start_len;
|
||||
|
||||
char *end;
|
||||
size_t end_len;
|
||||
|
||||
bool started;
|
||||
bool ended;
|
||||
git_vector pathlist;
|
||||
@ -76,6 +92,7 @@ struct git_iterator {
|
||||
int (*strcomp)(const char *a, const char *b);
|
||||
int (*strncomp)(const char *a, const char *b, size_t n);
|
||||
int (*prefixcomp)(const char *str, const char *prefix);
|
||||
int (*entry_srch)(const void *key, const void *array_member);
|
||||
size_t stat_calls;
|
||||
unsigned int flags;
|
||||
};
|
||||
@ -183,6 +200,28 @@ GIT_INLINE(int) git_iterator_advance_into(
|
||||
return iter->cb->advance_into(entry, iter);
|
||||
}
|
||||
|
||||
/* Advance over a directory and check if it contains no files or just
|
||||
* ignored files.
|
||||
*
|
||||
* In a tree or the index, all directories will contain files, but in the
|
||||
* working directory it is possible to have an empty directory tree or a
|
||||
* tree that only contains ignored files. Many Git operations treat these
|
||||
* cases specially. This advances over a directory (presumably an
|
||||
* untracked directory) but checks during the scan if there are any files
|
||||
* and any non-ignored files.
|
||||
*/
|
||||
GIT_INLINE(int) git_iterator_advance_over(
|
||||
const git_index_entry **entry,
|
||||
git_iterator_status_t *status,
|
||||
git_iterator *iter)
|
||||
{
|
||||
if (iter->cb->advance_over)
|
||||
return iter->cb->advance_over(entry, status, iter);
|
||||
|
||||
*status = GIT_ITERATOR_STATUS_NORMAL;
|
||||
return git_iterator_advance(entry, iter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance into a tree or skip over it if it is empty.
|
||||
*
|
||||
@ -273,35 +312,12 @@ extern int git_iterator_cmp(
|
||||
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);
|
||||
|
||||
typedef enum {
|
||||
GIT_ITERATOR_STATUS_NORMAL = 0,
|
||||
GIT_ITERATOR_STATUS_IGNORED = 1,
|
||||
GIT_ITERATOR_STATUS_EMPTY = 2,
|
||||
GIT_ITERATOR_STATUS_FILTERED = 3
|
||||
} git_iterator_status_t;
|
||||
|
||||
/* Advance over a directory and check if it contains no files or just
|
||||
* ignored files.
|
||||
*
|
||||
* In a tree or the index, all directories will contain files, but in the
|
||||
* working directory it is possible to have an empty directory tree or a
|
||||
* tree that only contains ignored files. Many Git operations treat these
|
||||
* cases specially. This advances over a directory (presumably an
|
||||
* untracked directory) but checks during the scan if there are any files
|
||||
* and any non-ignored files.
|
||||
*/
|
||||
extern int git_iterator_advance_over_with_status(
|
||||
const git_index_entry **entry, git_iterator_status_t *status, git_iterator *iter);
|
||||
|
||||
/**
|
||||
* Retrieve the index stored in the iterator.
|
||||
*
|
||||
* Only implemented for the workdir iterator
|
||||
* Only implemented for the workdir and index iterators.
|
||||
*/
|
||||
extern int git_iterator_index(git_index **out, git_iterator *iter);
|
||||
extern git_index *git_iterator_index(git_iterator *iter);
|
||||
|
||||
typedef int (*git_iterator_walk_cb)(
|
||||
const git_index_entry **entries,
|
||||
|
Loading…
Reference in New Issue
Block a user