From da37654d04617b4dacce6e7a4796007d2854624d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 27 Oct 2011 22:33:31 -0700 Subject: tree: Add traversal in post-order --- src/tree.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'src/tree.c') diff --git a/src/tree.c b/src/tree.c index 00aefc295..77034fa43 100644 --- a/src/tree.c +++ b/src/tree.c @@ -15,6 +15,8 @@ #define MAX_FILEMODE 0777777 #define MAX_FILEMODE_BYTES 6 +#define ENTRY_IS_TREE(e) ((e)->attr & 040000) + static int valid_attributes(const int attributes) { return attributes >= 0 && attributes <= MAX_FILEMODE; @@ -31,8 +33,8 @@ static int entry_sort_cmp(const void *a, const void *b) const git_tree_entry *entry_b = (const git_tree_entry *)(b); return git_futils_cmp_path( - entry_a->filename, entry_a->filename_len, entry_a->attr & 040000, - entry_b->filename, entry_b->filename_len, entry_b->attr & 040000); + entry_a->filename, entry_a->filename_len, ENTRY_IS_TREE(entry_a), + entry_b->filename, entry_b->filename_len, ENTRY_IS_TREE(entry_b)); } @@ -654,3 +656,53 @@ int git_tree_frompath(git_tree **parent_out, git_tree *root, const char *treeent strcpy(buffer, treeentry_path); return tree_frompath(parent_out, root, buffer, 0); } + +static int tree_walk_post(git_tree *tree, git_treewalk_cb callback, char *root, size_t root_len) +{ + int error; + unsigned int i; + + for (i = 0; i < tree->entries.length; ++i) { + git_tree_entry *entry = tree->entries.contents[i]; + + root[root_len] = '\0'; + + if (callback(root, entry) < 0) + continue; + + if (ENTRY_IS_TREE(entry)) { + git_tree *subtree; + + if ((error = git_tree_lookup(&subtree, tree->object.repo, &entry->oid)) < 0) + return error; + + strcpy(root + root_len, entry->filename); + root[root_len + entry->filename_len] = '/'; + + tree_walk_post(subtree, callback, root, root_len + entry->filename_len + 1); + + git_tree_close(subtree); + } + } + + return GIT_SUCCESS; +} + +int git_tree_walk(git_tree *tree, git_treewalk_cb callback, int mode) +{ + char root_path[GIT_PATH_MAX]; + + root_path[0] = '\0'; + switch (mode) { + case GIT_TREEWALK_POST: + return tree_walk_post(tree, callback, root_path, 0); + + case GIT_TREEWALK_PRE: + return git__throw(GIT_ENOTIMPLEMENTED, + "Preorder tree walking is still not implemented"); + + default: + return git__throw(GIT_EINVALIDARGS, + "Invalid walking mode for tree walk"); + } +} -- cgit v1.2.1 From 3286c408eccb18c525ca123383f3ebf5097441bc Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 28 Oct 2011 14:51:13 -0700 Subject: global: Properly use `git__` memory wrappers Ensure that all memory related functions (malloc, calloc, strdup, free, etc) are using their respective `git__` wrappers. --- src/tree.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/tree.c') diff --git a/src/tree.c b/src/tree.c index 77034fa43..6efedcff5 100644 --- a/src/tree.c +++ b/src/tree.c @@ -130,12 +130,12 @@ void git_tree__free(git_tree *tree) git_tree_entry *e; e = git_vector_get(&tree->entries, i); - free(e->filename); - free(e); + git__free(e->filename); + git__free(e); } git_vector_free(&tree->entries); - free(tree); + git__free(tree); } const git_oid *git_tree_id(git_tree *c) @@ -378,7 +378,7 @@ static int write_tree(git_oid *oid, git_index *index, const char *dirname, unsig last_comp = subdir; } error = append_entry(bld, last_comp, &sub_oid, S_IFDIR); - free(subdir); + git__free(subdir); if (error < GIT_SUCCESS) { error = git__rethrow(error, "Failed to insert dir"); goto cleanup; @@ -441,7 +441,7 @@ int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source) source_entries = source->entries.length; if (git_vector_init(&bld->entries, source_entries, entry_sort_cmp) < GIT_SUCCESS) { - free(bld); + git__free(bld); return GIT_ENOMEM; } @@ -596,8 +596,8 @@ void git_treebuilder_clear(git_treebuilder *bld) for (i = 0; i < bld->entries.length; ++i) { git_tree_entry *e = bld->entries.contents[i]; - free(e->filename); - free(e); + git__free(e->filename); + git__free(e); } git_vector_clear(&bld->entries); @@ -607,7 +607,7 @@ void git_treebuilder_free(git_treebuilder *bld) { git_treebuilder_clear(bld); git_vector_free(&bld->entries); - free(bld); + git__free(bld); } static int tree_frompath(git_tree **parent_out, git_tree *root, const char *treeentry_path, int offset) -- cgit v1.2.1 From 9432af36fc62ee22d76fb927b8be73e123ba3f3c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 17 Nov 2011 01:23:19 +0100 Subject: Rename `git_tree_frompath` to `git_tree_get_subtree` That makes more sense to me. --- src/tree.c | 56 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 14 deletions(-) (limited to 'src/tree.c') diff --git a/src/tree.c b/src/tree.c index 6efedcff5..458689196 100644 --- a/src/tree.c +++ b/src/tree.c @@ -610,7 +610,11 @@ void git_treebuilder_free(git_treebuilder *bld) git__free(bld); } -static int tree_frompath(git_tree **parent_out, git_tree *root, const char *treeentry_path, int offset) +static int tree_frompath( + git_tree **parent_out, + git_tree *root, + const char *treeentry_path, + int offset) { char *slash_pos = NULL; const git_tree_entry* entry; @@ -618,15 +622,21 @@ static int tree_frompath(git_tree **parent_out, git_tree *root, const char *tree git_tree *subtree; if (!*(treeentry_path + offset)) - return git__rethrow(GIT_EINVALIDPATH, "Invalid relative path to a tree entry '%s'.", treeentry_path); + return git__rethrow(GIT_EINVALIDPATH, + "Invalid relative path to a tree entry '%s'.", treeentry_path); slash_pos = (char *)strchr(treeentry_path + offset, '/'); if (slash_pos == NULL) - return git_tree_lookup(parent_out, root->object.repo, git_object_id((const git_object *)root)); + return git_tree_lookup( + parent_out, + root->object.repo, + git_object_id((const git_object *)root) + ); if (slash_pos == treeentry_path + offset) - return git__rethrow(GIT_EINVALIDPATH, "Invalid relative path to a tree entry '%s'.", treeentry_path); + return git__rethrow(GIT_EINVALIDPATH, + "Invalid relative path to a tree entry '%s'.", treeentry_path); *slash_pos = '\0'; @@ -636,28 +646,44 @@ static int tree_frompath(git_tree **parent_out, git_tree *root, const char *tree *slash_pos = '/'; if (entry == NULL) - return git__rethrow(GIT_ENOTFOUND, "No tree entry can be found from the given tree and relative path '%s'.", treeentry_path); + return git__rethrow(GIT_ENOTFOUND, + "No tree entry can be found from " + "the given tree and relative path '%s'.", treeentry_path); - if ((error = git_tree_lookup(&subtree, root->object.repo, &entry->oid)) < GIT_SUCCESS) + + error = git_tree_lookup(&subtree, root->object.repo, &entry->oid); + if (error < GIT_SUCCESS) return error; - error = tree_frompath(parent_out, subtree, treeentry_path, slash_pos - treeentry_path + 1); + error = tree_frompath( + parent_out, + subtree, + treeentry_path, + slash_pos - treeentry_path + 1 + ); git_tree_close(subtree); return error; } -int git_tree_frompath(git_tree **parent_out, git_tree *root, const char *treeentry_path) +int git_tree_get_subtree( + git_tree **subtree, + git_tree *root, + const char *subtree_path) { char buffer[GIT_PATH_MAX]; - assert(root && treeentry_path); + assert(subtree && root && subtree_path); - strcpy(buffer, treeentry_path); - return tree_frompath(parent_out, root, buffer, 0); + strncpy(buffer, subtree_path, GIT_PATH_MAX); + return tree_frompath(subtree, root, buffer, 0); } -static int tree_walk_post(git_tree *tree, git_treewalk_cb callback, char *root, size_t root_len) +static int tree_walk_post( + git_tree *tree, + git_treewalk_cb callback, + char *root, + size_t root_len) { int error; unsigned int i; @@ -673,13 +699,15 @@ static int tree_walk_post(git_tree *tree, git_treewalk_cb callback, char *root, if (ENTRY_IS_TREE(entry)) { git_tree *subtree; - if ((error = git_tree_lookup(&subtree, tree->object.repo, &entry->oid)) < 0) + if ((error = git_tree_lookup( + &subtree, tree->object.repo, &entry->oid)) < 0) return error; strcpy(root + root_len, entry->filename); root[root_len + entry->filename_len] = '/'; - tree_walk_post(subtree, callback, root, root_len + entry->filename_len + 1); + tree_walk_post(subtree, + callback, root, root_len + entry->filename_len + 1); git_tree_close(subtree); } -- cgit v1.2.1 From 2ba14f2367b14187e1714f32c11236476c22ddfa Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 17 Nov 2011 02:13:46 +0100 Subject: tree: Add payload to `git_tree_walk` --- src/tree.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/tree.c') diff --git a/src/tree.c b/src/tree.c index 458689196..92ca5ab77 100644 --- a/src/tree.c +++ b/src/tree.c @@ -683,7 +683,8 @@ static int tree_walk_post( git_tree *tree, git_treewalk_cb callback, char *root, - size_t root_len) + size_t root_len, + void *payload) { int error; unsigned int i; @@ -693,7 +694,7 @@ static int tree_walk_post( root[root_len] = '\0'; - if (callback(root, entry) < 0) + if (callback(root, entry, payload) < 0) continue; if (ENTRY_IS_TREE(entry)) { @@ -707,7 +708,10 @@ static int tree_walk_post( root[root_len + entry->filename_len] = '/'; tree_walk_post(subtree, - callback, root, root_len + entry->filename_len + 1); + callback, root, + root_len + entry->filename_len + 1, + payload + ); git_tree_close(subtree); } @@ -716,14 +720,14 @@ static int tree_walk_post( return GIT_SUCCESS; } -int git_tree_walk(git_tree *tree, git_treewalk_cb callback, int mode) +int git_tree_walk(git_tree *tree, git_treewalk_cb callback, int mode, void *payload) { char root_path[GIT_PATH_MAX]; root_path[0] = '\0'; switch (mode) { case GIT_TREEWALK_POST: - return tree_walk_post(tree, callback, root_path, 0); + return tree_walk_post(tree, callback, root_path, 0, payload); case GIT_TREEWALK_PRE: return git__throw(GIT_ENOTIMPLEMENTED, -- cgit v1.2.1