mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 19:04:05 +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);
|
git_buf_sets(&data->tmp, wd->path);
|
||||||
saved_wd.path = data->tmp.ptr;
|
saved_wd.path = data->tmp.ptr;
|
||||||
|
|
||||||
error = git_iterator_advance_over_with_status(
|
error = git_iterator_advance_over(
|
||||||
wditem, &untracked_state, workdir);
|
wditem, &untracked_state, workdir);
|
||||||
if (error == GIT_ITEROVER)
|
if (error == GIT_ITEROVER)
|
||||||
over = true;
|
over = true;
|
||||||
@ -930,7 +930,7 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g
|
|||||||
git_index *index;
|
git_index *index;
|
||||||
|
|
||||||
/* Only write conficts from sources that have them: indexes. */
|
/* 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;
|
return 0;
|
||||||
|
|
||||||
data->update_conflicts._cmp = checkout_conflictdata_cmp;
|
data->update_conflicts._cmp = checkout_conflictdata_cmp;
|
||||||
@ -1080,7 +1080,7 @@ static int checkout_conflicts_coalesce_renames(
|
|||||||
size_t i, names;
|
size_t i, names;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if ((index = git_iterator_get_index(data->target)) == NULL)
|
if ((index = git_iterator_index(data->target)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Juggle entries based on renames */
|
/* Juggle entries based on renames */
|
||||||
@ -1138,7 +1138,7 @@ static int checkout_conflicts_mark_directoryfile(
|
|||||||
const char *path;
|
const char *path;
|
||||||
int prefixed, error = 0;
|
int prefixed, error = 0;
|
||||||
|
|
||||||
if ((index = git_iterator_get_index(data->target)) == NULL)
|
if ((index = git_iterator_index(data->target)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
len = git_index_entrycount(index);
|
len = git_index_entrycount(index);
|
||||||
@ -2378,7 +2378,7 @@ static int checkout_data_init(
|
|||||||
if ((error = git_repository_index(&data->index, data->repo)) < 0)
|
if ((error = git_repository_index(&data->index, data->repo)) < 0)
|
||||||
goto cleanup;
|
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)
|
if ((error = git_index_read(data->index, true)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -2600,7 +2600,7 @@ int git_checkout_iterator(
|
|||||||
(error = checkout_create_conflicts(&data)) < 0)
|
(error = checkout_create_conflicts(&data)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (data.index != git_iterator_get_index(target) &&
|
if (data.index != git_iterator_index(target) &&
|
||||||
(error = checkout_extensions_update_index(&data)) < 0)
|
(error = checkout_extensions_update_index(&data)) < 0)
|
||||||
goto cleanup;
|
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) {
|
} else if (git_oid_iszero(&nitem->id) && new_is_workdir) {
|
||||||
bool use_ctime = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) != 0);
|
bool use_ctime = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) != 0);
|
||||||
git_index *index;
|
git_index *index = git_iterator_index(info->new_iter);
|
||||||
git_iterator_index(&index, info->new_iter);
|
|
||||||
|
|
||||||
status = GIT_DELTA_UNMODIFIED;
|
status = GIT_DELTA_UNMODIFIED;
|
||||||
|
|
||||||
@ -980,15 +979,14 @@ static int iterator_advance_into(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iterator_advance_over_with_status(
|
static int iterator_advance_over(
|
||||||
const git_index_entry **entry,
|
const git_index_entry **entry,
|
||||||
git_iterator_status_t *status,
|
git_iterator_status_t *status,
|
||||||
git_iterator *iterator)
|
git_iterator *iterator)
|
||||||
{
|
{
|
||||||
int error;
|
int error = git_iterator_advance_over(entry, status, iterator);
|
||||||
|
|
||||||
if ((error = git_iterator_advance_over_with_status(
|
if (error == GIT_ITEROVER) {
|
||||||
entry, status, iterator)) == GIT_ITEROVER) {
|
|
||||||
*entry = NULL;
|
*entry = NULL;
|
||||||
error = 0;
|
error = 0;
|
||||||
}
|
}
|
||||||
@ -1056,7 +1054,7 @@ static int handle_unmatched_new_item(
|
|||||||
return iterator_advance(&info->nitem, info->new_iter);
|
return iterator_advance(&info->nitem, info->new_iter);
|
||||||
|
|
||||||
/* iterate into dir looking for an actual untracked file */
|
/* 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)
|
&info->nitem, &untracked_state, info->new_iter)) < 0)
|
||||||
return error;
|
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),
|
GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3),
|
||||||
/** convert precomposed unicode to decomposed unicode */
|
/** convert precomposed unicode to decomposed unicode */
|
||||||
GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4),
|
GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4),
|
||||||
|
/** never convert precomposed unicode to decomposed unicode */
|
||||||
|
GIT_ITERATOR_DONT_PRECOMPOSE_UNICODE = (1u << 5),
|
||||||
/** include conflicts */
|
/** include conflicts */
|
||||||
GIT_ITERATOR_INCLUDE_CONFLICTS = (1u << 5),
|
GIT_ITERATOR_INCLUDE_CONFLICTS = (1u << 6),
|
||||||
} git_iterator_flag_t;
|
} 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 {
|
typedef struct {
|
||||||
const char *start;
|
const char *start;
|
||||||
const char *end;
|
const char *end;
|
||||||
@ -57,6 +66,8 @@ typedef struct {
|
|||||||
int (*current)(const git_index_entry **, git_iterator *);
|
int (*current)(const git_index_entry **, git_iterator *);
|
||||||
int (*advance)(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_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)(git_iterator *);
|
||||||
int (*reset_range)(git_iterator *, const char *start, const char *end);
|
int (*reset_range)(git_iterator *, const char *start, const char *end);
|
||||||
int (*at_end)(git_iterator *);
|
int (*at_end)(git_iterator *);
|
||||||
@ -67,8 +78,13 @@ struct git_iterator {
|
|||||||
git_iterator_type_t type;
|
git_iterator_type_t type;
|
||||||
git_iterator_callbacks *cb;
|
git_iterator_callbacks *cb;
|
||||||
git_repository *repo;
|
git_repository *repo;
|
||||||
|
|
||||||
char *start;
|
char *start;
|
||||||
|
size_t start_len;
|
||||||
|
|
||||||
char *end;
|
char *end;
|
||||||
|
size_t end_len;
|
||||||
|
|
||||||
bool started;
|
bool started;
|
||||||
bool ended;
|
bool ended;
|
||||||
git_vector pathlist;
|
git_vector pathlist;
|
||||||
@ -76,6 +92,7 @@ struct git_iterator {
|
|||||||
int (*strcomp)(const char *a, const char *b);
|
int (*strcomp)(const char *a, const char *b);
|
||||||
int (*strncomp)(const char *a, const char *b, size_t n);
|
int (*strncomp)(const char *a, const char *b, size_t n);
|
||||||
int (*prefixcomp)(const char *str, const char *prefix);
|
int (*prefixcomp)(const char *str, const char *prefix);
|
||||||
|
int (*entry_srch)(const void *key, const void *array_member);
|
||||||
size_t stat_calls;
|
size_t stat_calls;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
@ -183,6 +200,28 @@ GIT_INLINE(int) git_iterator_advance_into(
|
|||||||
return iter->cb->advance_into(entry, iter);
|
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.
|
* 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(
|
extern int git_iterator_current_workdir_path(
|
||||||
git_buf **path, git_iterator *iter);
|
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.
|
* 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)(
|
typedef int (*git_iterator_walk_cb)(
|
||||||
const git_index_entry **entries,
|
const git_index_entry **entries,
|
||||||
|
Loading…
Reference in New Issue
Block a user