summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ignore.c2
-rw-r--r--src/iterator.c431
-rw-r--r--src/path.c20
-rw-r--r--src/path.h6
-rw-r--r--src/repository.c10
-rw-r--r--src/vector.c33
-rw-r--r--src/vector.h3
7 files changed, 221 insertions, 284 deletions
diff --git a/src/ignore.c b/src/ignore.c
index ecdd76005..30f86b822 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -147,7 +147,7 @@ int git_ignore__pop_dir(git_ignores *ign)
if (ign->ign_path.length > 0) {
git_attr_file *file = git_vector_last(&ign->ign_path);
if (git__suffixcmp(ign->dir.ptr, file->path) == 0)
- git_vector_pop(&ign->ign_path, NULL);
+ git_vector_pop(&ign->ign_path);
git_buf_rtruncate_at_char(&ign->dir, '/');
}
return GIT_SUCCESS;
diff --git a/src/iterator.c b/src/iterator.c
index 805ff643e..c2b88ab84 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -10,36 +10,33 @@
#include "ignore.h"
#include "buffer.h"
-#define IDX_AS_PTR(I) (void *)((uint64_t)(I))
-#define PTR_AS_IDX(P) (unsigned int)((uint64_t)(P))
+typedef struct tree_iterator_frame tree_iterator_frame;
+struct tree_iterator_frame {
+ tree_iterator_frame *next;
+ git_tree *tree;
+ unsigned int index;
+};
typedef struct {
- git_iterator cb;
+ git_iterator base;
git_repository *repo;
- git_vector tree_stack;
- git_vector idx_stack;
+ tree_iterator_frame *stack;
git_index_entry entry;
git_buf path;
-} git_iterator_tree;
+} tree_iterator;
-static const git_tree_entry *git_iterator__tree_entry(git_iterator_tree *ti)
+static const git_tree_entry *tree_iterator__tree_entry(tree_iterator *ti)
{
- git_tree *tree;
- unsigned int tree_idx;
-
- if ((tree = git_vector_last(&ti->tree_stack)) == NULL)
- return NULL;
-
- tree_idx = PTR_AS_IDX(git_vector_last(&ti->idx_stack));
- return git_tree_entry_byindex(tree, tree_idx);
+ return (ti->stack == NULL) ? NULL :
+ git_tree_entry_byindex(ti->stack->tree, ti->stack->index);
}
-static int git_iterator__tree_current(
+static int tree_iterator__current(
git_iterator *self, const git_index_entry **entry)
{
int error;
- git_iterator_tree *ti = (git_iterator_tree *)self;
- const git_tree_entry *te = git_iterator__tree_entry(ti);
+ tree_iterator *ti = (tree_iterator *)self;
+ const git_tree_entry *te = tree_iterator__tree_entry(ti);
*entry = NULL;
@@ -58,132 +55,111 @@ static int git_iterator__tree_current(
return GIT_SUCCESS;
}
-static int git_iterator__tree_at_end(git_iterator *self)
+static int tree_iterator__at_end(git_iterator *self)
{
- git_iterator_tree *ti = (git_iterator_tree *)self;
- git_tree *tree;
- return ((tree = git_vector_last(&ti->tree_stack)) == NULL ||
- git_tree_entry_byindex(
- tree, PTR_AS_IDX(git_vector_last(&ti->idx_stack))) == NULL);
+ return (tree_iterator__tree_entry((tree_iterator *)self) == NULL);
}
-static int expand_tree_if_needed(git_iterator_tree *ti)
+static tree_iterator_frame *tree_iterator__alloc_frame(git_tree *tree)
{
- int error;
- git_tree *tree, *subtree;
- unsigned int tree_idx;
- const git_tree_entry *te;
-
- while (1) {
- tree = git_vector_last(&ti->tree_stack);
- tree_idx = PTR_AS_IDX(git_vector_last(&ti->idx_stack));
- te = git_tree_entry_byindex(tree, tree_idx);
+ tree_iterator_frame *tf = git__calloc(1, sizeof(tree_iterator_frame));
+ tf->tree = tree;
+ return tf;
+}
- if (!entry_is_tree(te))
- break;
+static int tree_iterator__expand_tree(tree_iterator *ti)
+{
+ int error;
+ git_tree *subtree;
+ const git_tree_entry *te = tree_iterator__tree_entry(ti);
+ tree_iterator_frame *tf;
+ while (te != NULL && entry_is_tree(te)) {
error = git_tree_lookup(&subtree, ti->repo, &te->oid);
if (error != GIT_SUCCESS)
return error;
- if ((error = git_vector_insert(&ti->tree_stack, subtree)) < GIT_SUCCESS ||
- (error = git_vector_insert(&ti->idx_stack, IDX_AS_PTR(0))) < GIT_SUCCESS ||
- (error = git_buf_joinpath(&ti->path, ti->path.ptr, te->filename)) < GIT_SUCCESS)
- {
- git_tree_free(subtree);
+ if ((tf = tree_iterator__alloc_frame(subtree)) == NULL)
+ return GIT_ENOMEM;
+
+ tf->next = ti->stack;
+ ti->stack = tf;
+
+ error = git_buf_joinpath(&ti->path, ti->path.ptr, te->filename);
+ if (error < GIT_SUCCESS)
return error;
- }
+
+ te = tree_iterator__tree_entry(ti);
}
return GIT_SUCCESS;
}
-static int git_iterator__tree_advance(
+static void tree_iterator__pop_frame(tree_iterator *ti)
+{
+ tree_iterator_frame *tf = ti->stack;
+ ti->stack = tf->next;
+ if (ti->stack != NULL) /* don't free the initial tree */
+ git_tree_free(tf->tree);
+ git__free(tf);
+}
+
+static int tree_iterator__advance(
git_iterator *self, const git_index_entry **entry)
{
int error = GIT_SUCCESS;
- git_iterator_tree *ti = (git_iterator_tree *)self;
- git_tree *tree = git_vector_last(&ti->tree_stack);
- unsigned int tree_idx = PTR_AS_IDX(git_vector_last(&ti->idx_stack));
- const git_tree_entry *te = git_tree_entry_byindex(tree, tree_idx);
+ tree_iterator *ti = (tree_iterator *)self;
+ const git_tree_entry *te;
if (entry != NULL)
*entry = NULL;
- if (te == NULL)
- return GIT_SUCCESS;
-
- while (1) {
- /* advance this tree */
- tree_idx++;
- ti->idx_stack.contents[ti->idx_stack.length - 1] = IDX_AS_PTR(tree_idx);
-
+ while (ti->stack != NULL) {
/* remove old entry filename */
git_buf_rtruncate_at_char(&ti->path, '/');
- if ((te = git_tree_entry_byindex(tree, tree_idx)) != NULL)
+ te = git_tree_entry_byindex(ti->stack->tree, ++ti->stack->index);
+ if (te != NULL)
break;
- /* no entry - either we are done or we are done with this subtree */
- if (ti->tree_stack.length == 1)
- return GIT_SUCCESS;
-
- git_tree_free(tree);
- git_vector_remove(&ti->tree_stack, ti->tree_stack.length - 1);
- git_vector_remove(&ti->idx_stack, ti->idx_stack.length - 1);
+ tree_iterator__pop_frame(ti);
git_buf_rtruncate_at_char(&ti->path, '/');
-
- tree = git_vector_last(&ti->tree_stack);
- tree_idx = PTR_AS_IDX(git_vector_last(&ti->idx_stack));
}
if (te && entry_is_tree(te))
- error = expand_tree_if_needed(ti);
+ error = tree_iterator__expand_tree(ti);
if (error == GIT_SUCCESS && entry != NULL)
- error = git_iterator__tree_current(self, entry);
+ error = tree_iterator__current(self, entry);
return error;
}
-static void git_iterator__tree_free(git_iterator *self)
+static void tree_iterator__free(git_iterator *self)
{
- git_iterator_tree *ti = (git_iterator_tree *)self;
-
- while (ti->tree_stack.length > 1) {
- git_tree *tree = git_vector_last(&ti->tree_stack);
- git_tree_free(tree);
- git_vector_remove(&ti->tree_stack, ti->tree_stack.length - 1);
- }
-
- git_vector_clear(&ti->tree_stack);
- git_vector_clear(&ti->idx_stack);
+ tree_iterator *ti = (tree_iterator *)self;
+ while (ti->stack != NULL)
+ tree_iterator__pop_frame(ti);
git_buf_free(&ti->path);
}
-int git_iterator_for_tree(git_repository *repo, git_tree *tree, git_iterator **iter)
+int git_iterator_for_tree(
+ git_repository *repo, git_tree *tree, git_iterator **iter)
{
int error;
- git_iterator_tree *ti = git__calloc(1, sizeof(git_iterator_tree));
+ tree_iterator *ti = git__calloc(1, sizeof(tree_iterator));
if (!ti)
return GIT_ENOMEM;
- ti->cb.type = GIT_ITERATOR_TREE;
- ti->cb.current = git_iterator__tree_current;
- ti->cb.at_end = git_iterator__tree_at_end;
- ti->cb.advance = git_iterator__tree_advance;
- ti->cb.free = git_iterator__tree_free;
- ti->repo = repo;
-
- if (!(error = git_vector_init(&ti->tree_stack, 0, NULL)) &&
- !(error = git_vector_insert(&ti->tree_stack, tree)) &&
- !(error = git_vector_init(&ti->idx_stack, 0, NULL)))
- error = git_vector_insert(&ti->idx_stack, IDX_AS_PTR(0));
+ ti->base.type = GIT_ITERATOR_TREE;
+ ti->base.current = tree_iterator__current;
+ ti->base.at_end = tree_iterator__at_end;
+ ti->base.advance = tree_iterator__advance;
+ ti->base.free = tree_iterator__free;
+ ti->repo = repo;
+ ti->stack = tree_iterator__alloc_frame(tree);
- if (error == GIT_SUCCESS)
- error = expand_tree_if_needed(ti);
-
- if (error != GIT_SUCCESS)
+ if ((error = tree_iterator__expand_tree(ti)) < GIT_SUCCESS)
git_iterator_free((git_iterator *)ti);
else
*iter = (git_iterator *)ti;
@@ -193,29 +169,29 @@ int git_iterator_for_tree(git_repository *repo, git_tree *tree, git_iterator **i
typedef struct {
- git_iterator cb;
+ git_iterator base;
git_index *index;
unsigned int current;
-} git_iterator_index;
+} index_iterator;
-static int git_iterator__index_current(
+static int index_iterator__current(
git_iterator *self, const git_index_entry **entry)
{
- git_iterator_index *ii = (git_iterator_index *)self;
+ index_iterator *ii = (index_iterator *)self;
*entry = git_index_get(ii->index, ii->current);
return GIT_SUCCESS;
}
-static int git_iterator__index_at_end(git_iterator *self)
+static int index_iterator__at_end(git_iterator *self)
{
- git_iterator_index *ii = (git_iterator_index *)self;
+ index_iterator *ii = (index_iterator *)self;
return (ii->current >= git_index_entrycount(ii->index));
}
-static int git_iterator__index_advance(
+static int index_iterator__advance(
git_iterator *self, const git_index_entry **entry)
{
- git_iterator_index *ii = (git_iterator_index *)self;
+ index_iterator *ii = (index_iterator *)self;
if (ii->current < git_index_entrycount(ii->index))
ii->current++;
if (entry)
@@ -223,9 +199,9 @@ static int git_iterator__index_advance(
return GIT_SUCCESS;
}
-static void git_iterator__index_free(git_iterator *self)
+static void index_iterator__free(git_iterator *self)
{
- git_iterator_index *ii = (git_iterator_index *)self;
+ index_iterator *ii = (index_iterator *)self;
git_index_free(ii->index);
ii->index = NULL;
}
@@ -233,16 +209,16 @@ static void git_iterator__index_free(git_iterator *self)
int git_iterator_for_index(git_repository *repo, git_iterator **iter)
{
int error;
- git_iterator_index *ii = git__calloc(1, sizeof(git_iterator_index));
+ index_iterator *ii = git__calloc(1, sizeof(index_iterator));
if (!ii)
return GIT_ENOMEM;
- ii->cb.type = GIT_ITERATOR_INDEX;
- ii->cb.current = git_iterator__index_current;
- ii->cb.at_end = git_iterator__index_at_end;
- ii->cb.advance = git_iterator__index_advance;
- ii->cb.free = git_iterator__index_free;
- ii->current = 0;
+ ii->base.type = GIT_ITERATOR_INDEX;
+ ii->base.current = index_iterator__current;
+ ii->base.at_end = index_iterator__at_end;
+ ii->base.advance = index_iterator__advance;
+ ii->base.free = index_iterator__free;
+ ii->current = 0;
if ((error = git_repository_index(&ii->index, repo)) < GIT_SUCCESS)
git__free(ii);
@@ -252,101 +228,107 @@ int git_iterator_for_index(git_repository *repo, git_iterator **iter)
}
+typedef struct workdir_iterator_frame workdir_iterator_frame;
+struct workdir_iterator_frame {
+ workdir_iterator_frame *next;
+ git_vector entries;
+ unsigned int index;
+};
+
typedef struct {
- git_iterator cb;
+ git_iterator base;
git_repository *repo;
size_t root_len;
- git_vector dir_stack; /* vector of vectors of paths */
- git_vector idx_stack;
+ workdir_iterator_frame *stack;
git_ignores ignores;
git_index_entry entry;
git_buf path;
int is_ignored;
-} git_iterator_workdir;
+} workdir_iterator;
+
+static workdir_iterator_frame *workdir_iterator__alloc_frame(void)
+{
+ workdir_iterator_frame *wf = git__calloc(1, sizeof(workdir_iterator_frame));
+ if (wf == NULL)
+ return wf;
+ if (git_vector_init(&wf->entries, 0, git__strcmp_cb) != GIT_SUCCESS) {
+ git__free(wf);
+ return NULL;
+ }
+ return wf;
+}
-static void free_directory(git_vector *dir)
+static void workdir_iterator__free_frame(workdir_iterator_frame *wf)
{
unsigned int i;
char *path;
- git_vector_foreach(dir, i, path)
+ git_vector_foreach(&wf->entries, i, path)
git__free(path);
- git_vector_free(dir);
- git__free(dir);
+ git_vector_free(&wf->entries);
+ git__free(wf);
}
-static int load_workdir_entry(git_iterator_workdir *wi);
+static int workdir_iterator__update_entry(workdir_iterator *wi);
-static int push_directory(git_iterator_workdir *wi)
+static int workdir_iterator__expand_dir(workdir_iterator *wi)
{
int error;
- git_vector *dir = NULL;
-
- error = git_vector_alloc(&dir, 0, git__strcmp_cb);
- if (error < GIT_SUCCESS)
- return error;
+ workdir_iterator_frame *wf = workdir_iterator__alloc_frame();
+ if (wf == NULL)
+ return GIT_ENOMEM;
- /* allocate dir entries with extra byte (the "1" param) so later on we
- * can suffix directories with a "/" as needed.
+ /* allocate dir entries with extra byte (the "1" param) so we
+ * can suffix directory names with a "/".
*/
- error = git_path_dirload(wi->path.ptr, wi->root_len, 1, dir);
- if (error < GIT_SUCCESS || dir->length == 0) {
- free_directory(dir);
+ error = git_path_dirload(wi->path.ptr, wi->root_len, 1, &wf->entries);
+ if (error < GIT_SUCCESS || wf->entries.length == 0) {
+ workdir_iterator__free_frame(wf);
return GIT_ENOTFOUND;
}
- if ((error = git_vector_insert(&wi->dir_stack, dir)) ||
- (error = git_vector_insert(&wi->idx_stack, IDX_AS_PTR(0))))
- {
- free_directory(dir);
- return error;
- }
-
- git_vector_sort(dir);
+ git_vector_sort(&wf->entries);
+ wf->next = wi->stack;
+ wi->stack = wf;
- if (wi->dir_stack.length > 1) {
+ /* only push new ignores if this is not top level directory */
+ if (wi->stack->next != NULL) {
int slash_pos = git_buf_rfind_next(&wi->path, '/');
(void)git_ignore__push_dir(&wi->ignores, &wi->path.ptr[slash_pos + 1]);
}
- return load_workdir_entry(wi);
+ return workdir_iterator__update_entry(wi);
}
-static int git_iterator__workdir_current(
+static int workdir_iterator__current(
git_iterator *self, const git_index_entry **entry)
{
- git_iterator_workdir *wi = (git_iterator_workdir *)self;
+ workdir_iterator *wi = (workdir_iterator *)self;
*entry = (wi->entry.path == NULL) ? NULL : &wi->entry;
return GIT_SUCCESS;
}
-static int git_iterator__workdir_at_end(git_iterator *self)
+static int workdir_iterator__at_end(git_iterator *self)
{
- git_iterator_workdir *wi = (git_iterator_workdir *)self;
- return (wi->entry.path == NULL);
+ return (((workdir_iterator *)self)->entry.path == NULL);
}
-static int git_iterator__workdir_advance(
+static int workdir_iterator__advance(
git_iterator *self, const git_index_entry **entry)
{
int error;
- git_iterator_workdir *wi = (git_iterator_workdir *)self;
- git_vector *dir;
- unsigned int pos;
+ workdir_iterator *wi = (workdir_iterator *)self;
+ workdir_iterator_frame *wf;
const char *next;
- if (entry)
+ if (entry != NULL)
*entry = NULL;
if (wi->entry.path == NULL)
return GIT_SUCCESS;
- while (1) {
- dir = git_vector_last(&wi->dir_stack);
- pos = 1 + PTR_AS_IDX(git_vector_last(&wi->idx_stack));
- wi->idx_stack.contents[wi->idx_stack.length - 1] = IDX_AS_PTR(pos);
-
- next = git_vector_get(dir, pos);
+ while ((wf = wi->stack) != NULL) {
+ next = git_vector_get(&wf->entries, ++wf->index);
if (next != NULL) {
if (strcmp(next, DOT_GIT) == 0)
continue;
@@ -354,69 +336,45 @@ static int git_iterator__workdir_advance(
break;
}
- memset(&wi->entry, 0, sizeof(wi->entry));
- if (wi->dir_stack.length == 1)
- return GIT_SUCCESS;
-
- free_directory(dir);
- git_vector_remove(&wi->dir_stack, wi->dir_stack.length - 1);
- git_vector_remove(&wi->idx_stack, wi->idx_stack.length - 1);
+ /* pop workdir directory stack */
+ wi->stack = wf->next;
+ workdir_iterator__free_frame(wf);
git_ignore__pop_dir(&wi->ignores);
+
+ if (wi->stack == NULL) {
+ memset(&wi->entry, 0, sizeof(wi->entry));
+ return GIT_SUCCESS;
+ }
}
- error = load_workdir_entry(wi);
+ error = workdir_iterator__update_entry(wi);
- if (error == GIT_SUCCESS && entry)
- return git_iterator__workdir_current(self, entry);
+ if (error == GIT_SUCCESS && entry != NULL)
+ error = workdir_iterator__current(self, entry);
return error;
}
-int git_iterator_advance_into_directory(
- git_iterator *iter, const git_index_entry **entry)
+static void workdir_iterator__free(git_iterator *self)
{
- git_iterator_workdir *wi = (git_iterator_workdir *)iter;
-
- if (iter->type != GIT_ITERATOR_WORKDIR)
- return git_iterator_current(iter, entry);
+ workdir_iterator *wi = (workdir_iterator *)self;
- /* Loop because the first entry in the ignored directory could itself be
- * an ignored directory, but we want to descend to find an actual entry.
- */
- if (wi->entry.path && S_ISDIR(wi->entry.mode)) {
- if (push_directory(wi) < GIT_SUCCESS)
- /* If error loading or if empty, skip the directory. */
- return git_iterator__workdir_advance((git_iterator *)wi, entry);
+ while (wi->stack != NULL) {
+ workdir_iterator_frame *wf = wi->stack;
+ wi->stack = wf->next;
+ workdir_iterator__free_frame(wf);
}
- return git_iterator__workdir_current(iter, entry);
-}
-
-static void git_iterator__workdir_free(git_iterator *self)
-{
- git_iterator_workdir *wi = (git_iterator_workdir *)self;
-
- while (wi->dir_stack.length) {
- git_vector *dir = git_vector_last(&wi->dir_stack);
- free_directory(dir);
- git_vector_remove(&wi->dir_stack, wi->dir_stack.length - 1);
- }
-
- git_vector_clear(&wi->dir_stack);
- git_vector_clear(&wi->idx_stack);
git_ignore__free(&wi->ignores);
git_buf_free(&wi->path);
}
-static int load_workdir_entry(git_iterator_workdir *wi)
+static int workdir_iterator__update_entry(workdir_iterator *wi)
{
int error;
- char *relpath;
- git_vector *dir = git_vector_last(&wi->dir_stack);
- unsigned int pos = PTR_AS_IDX(git_vector_last(&wi->idx_stack));
struct stat st;
+ char *relpath = git_vector_get(&wi->stack->entries, wi->stack->index);
- relpath = git_vector_get(dir, pos);
error = git_buf_joinpath(
&wi->path, git_repository_workdir(wi->repo), relpath);
if (error < GIT_SUCCESS)
@@ -425,14 +383,12 @@ static int load_workdir_entry(git_iterator_workdir *wi)
memset(&wi->entry, 0, sizeof(wi->entry));
wi->entry.path = relpath;
+ /* skip over .git directory */
if (strcmp(relpath, DOT_GIT) == 0)
- return git_iterator__workdir_advance((git_iterator *)wi, NULL);
+ return workdir_iterator__advance((git_iterator *)wi, NULL);
/* if there is an error processing the entry, treat as ignored */
wi->is_ignored = 1;
- error = git_ignore__lookup(&wi->ignores, wi->entry.path, &wi->is_ignored);
- if (error != GIT_SUCCESS)
- return GIT_SUCCESS;
if (p_lstat(wi->path.ptr, &st) < 0)
return GIT_SUCCESS;
@@ -451,6 +407,11 @@ static int load_workdir_entry(git_iterator_workdir *wi)
if (st.st_mode == 0)
return GIT_SUCCESS;
+ /* okay, we are far enough along to look up real ignore rule */
+ error = git_ignore__lookup(&wi->ignores, wi->entry.path, &wi->is_ignored);
+ if (error != GIT_SUCCESS)
+ return GIT_SUCCESS;
+
if (S_ISDIR(st.st_mode)) {
if (git_path_contains(&wi->path, DOT_GIT) == GIT_SUCCESS) {
/* create submodule entry */
@@ -470,30 +431,28 @@ static int load_workdir_entry(git_iterator_workdir *wi)
int git_iterator_for_workdir(git_repository *repo, git_iterator **iter)
{
int error;
- git_iterator_workdir *wi = git__calloc(1, sizeof(git_iterator_workdir));
+ workdir_iterator *wi = git__calloc(1, sizeof(workdir_iterator));
if (!wi)
return GIT_ENOMEM;
- wi->cb.type = GIT_ITERATOR_WORKDIR;
- wi->cb.current = git_iterator__workdir_current;
- wi->cb.at_end = git_iterator__workdir_at_end;
- wi->cb.advance = git_iterator__workdir_advance;
- wi->cb.free = git_iterator__workdir_free;
- wi->repo = repo;
-
- if ((error = git_buf_sets(
- &wi->path, git_repository_workdir(repo))) < GIT_SUCCESS ||
- (error = git_vector_init(&wi->dir_stack, 0, NULL)) < GIT_SUCCESS ||
- (error = git_vector_init(&wi->idx_stack, 0, NULL)) < GIT_SUCCESS ||
- (error = git_ignore__for_path(repo, "", &wi->ignores)) < GIT_SUCCESS)
- {
+ wi->base.type = GIT_ITERATOR_WORKDIR;
+ wi->base.current = workdir_iterator__current;
+ wi->base.at_end = workdir_iterator__at_end;
+ wi->base.advance = workdir_iterator__advance;
+ wi->base.free = workdir_iterator__free;
+ wi->repo = repo;
+
+ error = git_buf_sets(&wi->path, git_repository_workdir(repo));
+ if (error == GIT_SUCCESS)
+ error = git_ignore__for_path(repo, "", &wi->ignores);
+ if (error != GIT_SUCCESS) {
git__free(wi);
return error;
}
wi->root_len = wi->path.size;
- if ((error = push_directory(wi)) < GIT_SUCCESS)
+ if ((error = workdir_iterator__expand_dir(wi)) < GIT_SUCCESS)
git_iterator_free((git_iterator *)wi);
else
*iter = (git_iterator *)wi;
@@ -501,21 +460,33 @@ int git_iterator_for_workdir(git_repository *repo, git_iterator **iter)
return error;
}
+
int git_iterator_current_tree_entry(
git_iterator *iter, const git_tree_entry **tree_entry)
{
- if (iter->type != GIT_ITERATOR_TREE)
- *tree_entry = NULL;
- else
- *tree_entry = git_iterator__tree_entry((git_iterator_tree *)iter);
-
+ *tree_entry = (iter->type != GIT_ITERATOR_TREE) ? NULL :
+ tree_iterator__tree_entry((tree_iterator *)iter);
return GIT_SUCCESS;
}
int git_iterator_current_is_ignored(git_iterator *iter)
{
- if (iter->type != GIT_ITERATOR_WORKDIR)
- return 0;
- else
- return ((git_iterator_workdir *)iter)->is_ignored;
+ return (iter->type != GIT_ITERATOR_WORKDIR) ? 0 :
+ ((workdir_iterator *)iter)->is_ignored;
+}
+
+int git_iterator_advance_into_directory(
+ git_iterator *iter, const git_index_entry **entry)
+{
+ workdir_iterator *wi = (workdir_iterator *)iter;
+
+ if (iter->type == GIT_ITERATOR_WORKDIR &&
+ wi->entry.path && S_ISDIR(wi->entry.mode))
+ {
+ if (workdir_iterator__expand_dir(wi) < GIT_SUCCESS)
+ /* if error loading or if empty, skip the directory. */
+ return workdir_iterator__advance(iter, entry);
+ }
+
+ return entry ? git_iterator_current(iter, entry) : GIT_SUCCESS;
}
diff --git a/src/path.c b/src/path.c
index 6f46dc95e..88ea95a97 100644
--- a/src/path.c
+++ b/src/path.c
@@ -398,42 +398,38 @@ int git_path_isfile(const char *path)
static int _check_dir_contents(
git_buf *dir,
const char *sub,
- int append_on_success,
int (*predicate)(const char *))
{
int error = GIT_SUCCESS;
size_t dir_size = dir->size;
size_t sub_size = strlen(sub);
- /* leave base valid even if we could not make space for subdir */
+ /* separate allocation and join, so we can always leave git_buf valid */
if ((error = git_buf_try_grow(dir, dir_size + sub_size + 2)) < GIT_SUCCESS)
return error;
-
- /* save excursion */
git_buf_joinpath(dir, dir->ptr, sub);
error = (*predicate)(dir->ptr);
- /* restore excursion */
- if (!append_on_success || error != GIT_SUCCESS)
- git_buf_truncate(dir, dir_size);
+ /* restore path */
+ git_buf_truncate(dir, dir_size);
return error;
}
int git_path_contains(git_buf *dir, const char *item)
{
- return _check_dir_contents(dir, item, 0, &git_path_exists);
+ return _check_dir_contents(dir, item, &git_path_exists);
}
-int git_path_contains_dir(git_buf *base, const char *subdir, int append_if_exists)
+int git_path_contains_dir(git_buf *base, const char *subdir)
{
- return _check_dir_contents(base, subdir, append_if_exists, &git_path_isdir);
+ return _check_dir_contents(base, subdir, &git_path_isdir);
}
-int git_path_contains_file(git_buf *base, const char *file, int append_if_exists)
+int git_path_contains_file(git_buf *base, const char *file)
{
- return _check_dir_contents(base, file, append_if_exists, &git_path_isfile);
+ return _check_dir_contents(base, file, &git_path_isfile);
}
int git_path_find_dir(git_buf *dir, const char *path, const char *base)
diff --git a/src/path.h b/src/path.h
index 7a4f1f4fd..abe6c2217 100644
--- a/src/path.h
+++ b/src/path.h
@@ -143,20 +143,18 @@ extern int git_path_contains(git_buf *dir, const char *item);
*
* @param parent Directory path that might contain subdir
* @param subdir Subdirectory name to look for in parent
- * @param append_if_exists If true, then subdir will be appended to the parent path if it does exist
* @return GIT_SUCCESS if subdirectory exists, < 0 otherwise.
*/
-extern int git_path_contains_dir(git_buf *parent, const char *subdir, int append_if_exists);
+extern int git_path_contains_dir(git_buf *parent, const char *subdir);
/**
* Check if the given path contains the given file.
*
* @param dir Directory path that might contain file
* @param file File name to look for in parent
- * @param append_if_exists If true, then file will be appended to the path if it does exist
* @return GIT_SUCCESS if file exists, < 0 otherwise.
*/
-extern int git_path_contains_file(git_buf *dir, const char *file, int append_if_exists);
+extern int git_path_contains_file(git_buf *dir, const char *file);
/**
* Clean up path, prepending base if it is not already rooted.
diff --git a/src/repository.c b/src/repository.c
index 13ad7eb02..f394d06fe 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -81,14 +81,14 @@ void git_repository_free(git_repository *repo)
static int quickcheck_repository_dir(git_buf *repository_path)
{
/* Check OBJECTS_DIR first, since it will generate the longest path name */
- if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR, 0) < 0)
+ if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR) < 0)
return GIT_ERROR;
/* Ensure HEAD file exists */
- if (git_path_contains_file(repository_path, GIT_HEAD_FILE, 0) < 0)
+ if (git_path_contains_file(repository_path, GIT_HEAD_FILE) < 0)
return GIT_ERROR;
- if (git_path_contains_dir(repository_path, GIT_REFS_DIR, 0) < 0)
+ if (git_path_contains_dir(repository_path, GIT_REFS_DIR) < 0)
return GIT_ERROR;
return GIT_SUCCESS;
@@ -166,8 +166,8 @@ int git_repository_open(git_repository **repo_out, const char *path)
* of the working dir, by testing if it contains a `.git`
* folder inside of it.
*/
- git_path_contains_dir(&path_buf, GIT_DIR, 1); /* append on success */
- /* ignore error, since it just means `path/.git` doesn't exist */
+ if (git_path_contains_dir(&path_buf, GIT_DIR) == GIT_SUCCESS)
+ git_buf_joinpath(&path_buf, path_buf.ptr, GIT_DIR);
if (quickcheck_repository_dir(&path_buf) < GIT_SUCCESS) {
error = git__throw(GIT_ENOTAREPO,
diff --git a/src/vector.c b/src/vector.c
index 49909bbad..e109704ab 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -25,24 +25,6 @@ static int resize_vector(git_vector *v)
return GIT_SUCCESS;
}
-int git_vector_alloc(
- git_vector **vptr, unsigned int initial_size, git_vector_cmp cmp)
-{
- int error;
- git_vector *v = git__malloc(sizeof(git_vector));
- if (!v) {
- *vptr = NULL;
- return GIT_ENOMEM;
- }
-
- if ((error = git_vector_init(v, initial_size, cmp)) < GIT_SUCCESS) {
- git__free(v);
- v = NULL;
- }
- *vptr = v;
- return error;
-}
-
void git_vector_free(git_vector *v)
{
assert(v);
@@ -205,19 +187,10 @@ int git_vector_remove(git_vector *v, unsigned int idx)
return GIT_SUCCESS;
}
-int git_vector_pop(git_vector *v, void **element)
+void git_vector_pop(git_vector *v)
{
- assert(v);
-
- if (v->length == 0)
- return git__throw(GIT_ENOTFOUND, "Can't remove element from empty list");
-
- if (element != NULL)
- *element = v->contents[v->length - 1];
-
- v->length--;
-
- return GIT_SUCCESS;
+ if (v->length > 0)
+ v->length--;
}
void git_vector_uniq(git_vector *v)
diff --git a/src/vector.h b/src/vector.h
index c11e801cc..44635ae14 100644
--- a/src/vector.h
+++ b/src/vector.h
@@ -22,7 +22,6 @@ typedef struct git_vector {
#define GIT_VECTOR_INIT {0}
int git_vector_init(git_vector *v, unsigned int initial_size, git_vector_cmp cmp);
-int git_vector_alloc(git_vector **v, unsigned int initial_size, git_vector_cmp cmp);
void git_vector_free(git_vector *v);
void git_vector_clear(git_vector *v);
@@ -54,7 +53,7 @@ int git_vector_insert(git_vector *v, void *element);
int git_vector_insert_sorted(git_vector *v, void *element,
int (*on_dup)(void **old, void *new));
int git_vector_remove(git_vector *v, unsigned int idx);
-int git_vector_pop(git_vector *v, void **element);
+void git_vector_pop(git_vector *v);
void git_vector_uniq(git_vector *v);
#endif