/** * ggit_tree_walk: * @tree: a #GgitTree. * @mode: the walking order. * @callback: (scope call): the callback to call for each entry. * @user_data: (closure): user data for the callback. * @error: a #GError for error reporting, or %NULL. * * Walk all the entries of a tree object recursively (resolving and walking * subtrees of the tree as needed). The @error will be set to the error returned * by @callback (if any). * **/ void ggit_tree_walk (GgitTree *tree, GgitTreeWalkMode mode, GgitTreeWalkCallback callback, gpointer user_data, GError **error) { gint ret; WalkInfo info = {0,}; g_return_if_fail (GGIT_IS_TREE (tree)); g_return_if_fail (callback != NULL); g_return_if_fail (error == NULL || *error == NULL); info.callback = callback; info.user_data = user_data; ret = git_tree_walk (_ggit_native_get (tree), (git_treewalk_mode)mode, (git_treewalk_cb)walk_callback_wrapper, &info); if (ret != GIT_OK) { _ggit_error_set (error, ret); } }
/* * call-seq: * tree.walk(mode) { |root, entry| block } * tree.walk(mode) -> Iterator * * Walk +tree+ with the given mode (either +:preorder+ or +:postorder+) and yield * to +block+ every entry in +tree+ and all its subtrees, as a +Hash+. The +block+ * also takes a +root+, the relative path in the traversal, starting from the root * of the original tree. * * If no +block+ is given, an +Iterator+ is returned instead. * * tree.walk(:postorder) { |root, entry| puts "#{root}#{entry[:name]} [#{entry[:oid]}]" } * * generates: * * USAGE.rb [02bae86c91f96b5fdb6b1cf06f5aa3612139e318] * ext [23f135b3c576b6ac4785821888991d7089f35db1] * ext/rugged [25c88faa9302e34e16664eb9c990deb2bcf77849] * ext/rugged/extconf.rb [40c1aa8a8cec8ca444ed5758e3f00ecff093070a] * ... */ static VALUE rb_git_tree_walk(VALUE self, VALUE rb_mode) { git_tree *tree; int error, mode = 0; ID id_mode; Data_Get_Struct(self, git_tree, tree); if (!rb_block_given_p()) return rb_funcall(self, rb_intern("to_enum"), 2, CSTR2SYM("walk"), rb_mode); Check_Type(rb_mode, T_SYMBOL); id_mode = SYM2ID(rb_mode); if (id_mode == rb_intern("preorder")) mode = GIT_TREEWALK_PRE; else if (id_mode == rb_intern("postorder")) mode = GIT_TREEWALK_POST; else rb_raise(rb_eTypeError, "Invalid iteration mode. Expected `:preorder` or `:postorder`"); error = git_tree_walk(tree, &rugged__treewalk_cb, mode, (void *)rb_block_proc()); rugged_exception_check(error); return Qnil; }
/* * call-seq: * tree.count_recursive(limit=nil) -> count * * `limit` - The maximum number of blobs to the count in the repository. * Rugged will stop walking the tree after `limit` items to avoid long * execution times. * * Return the number of blobs (up to the limit) contained in the tree and * all subtrees. */ static VALUE rb_git_tree_entrycount_recursive(int argc, VALUE* argv, VALUE self) { git_tree *tree; int error; struct rugged_treecount_cb_payload payload; VALUE rb_limit; Data_Get_Struct(self, git_tree, tree); rb_scan_args(argc, argv, "01", &rb_limit); payload.limit = -1; payload.count = 0; if (!NIL_P(rb_limit)) { Check_Type(rb_limit, T_FIXNUM); payload.limit = FIX2INT(rb_limit); } error = git_tree_walk(tree, GIT_TREEWALK_PRE, &rugged__treecount_cb, (void *)&payload); if (error && giterr_last()->klass == GITERR_CALLBACK) { giterr_clear(); error = 0; } rugged_exception_check(error); return INT2FIX(payload.count); }
static void mne_git_walk_tree(git_tree *tree, git_reference *ref, mne_git_walk_ctx *ctx) { ctx->distinct_blobs = 0; int ref_name_len = strlen(git_reference_name(ref)); ctx->ref_name = malloc(sizeof(char) * (ref_name_len + 1)); assert(ctx->ref_name != NULL); strncpy(ctx->ref_name, git_reference_name(ref), ref_name_len); ctx->ref_name[ref_name_len] = 0; ref_names[ctx->ref_index] = ctx->ref_name; printf(" * %-22s", ctx->ref_name); fflush(stdout); git_tree_walk(tree, &mne_git_tree_entry_cb, GIT_TREEWALK_POST, ctx); printf(" ✔ +%d\n", ctx->distinct_blobs); }
static gboolean checksum_commit_contents (struct TreeWalkData *twdata, const git_oid *commit_oid, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; int r; git_commit *commit = NULL; git_tree *tree = NULL; r = git_commit_lookup (&commit, twdata->repo, commit_oid); if (!handle_libgit_ret (r, error)) goto out; if (!checksum_object_id (twdata, commit_oid, error)) goto out; r = git_commit_tree (&tree, commit); if (!handle_libgit_ret (r, error)) goto out; if (!checksum_object_id (twdata, git_object_id((git_object*)tree), error)) goto out; r = git_tree_walk (tree, GIT_TREEWALK_PRE, checksum_tree_callback, twdata); if (twdata->caught_error) goto out; if (!handle_libgit_ret (r, error)) goto out; ret = TRUE; out: if (commit) git_commit_free (commit); if (tree) git_tree_free (tree); return ret; }
static int load_dives_from_tree(git_repository *repo, git_tree *tree) { git_tree_walk(tree, GIT_TREEWALK_PRE, walk_tree_cb, repo); return 0; }
int _go_git_treewalk(git_tree *tree, git_treewalk_mode mode, void *ptr) { return git_tree_walk(tree, mode, (git_treewalk_cb)&CallbackGitTreeWalk, ptr); }
static git_commit* FindFileRecentCommit(git_repository* repository, const CString& path) { CAutoRevwalk walk; if (git_revwalk_new(walk.GetPointer(), repository)) return nullptr; CStringA pathA = CUnicodeUtils::GetUTF8(path); if (pathA.GetLength() >= MAX_PATH) return nullptr; const char *pathC = pathA; char folder[MAX_PATH] = {0}, file[MAX_PATH] = {0}; const char *slash = strrchr(pathC, '/'); if (slash) { strncpy(folder, pathC, slash - pathC + 1); folder[slash - pathC + 1] = '\0'; strcpy(file, slash + 1); } else { folder[0] = '\0'; strcpy(file, pathC); } TreewalkStruct treewalkstruct = { folder, file }; if (git_revwalk_push_head(walk)) return nullptr; git_oid oid; CAutoCommit commit; while (!git_revwalk_next(&oid, walk)) { if (git_commit_lookup(commit.GetPointer(), repository, &oid)) return nullptr; CAutoTree tree; if (git_commit_tree(tree.GetPointer(), commit)) return nullptr; memset(&treewalkstruct.oid.id, 0, sizeof(treewalkstruct.oid.id)); int ret = git_tree_walk(tree, GIT_TREEWALK_PRE, TreewalkCB_FindFileRecentCommit, &treewalkstruct); if (ret < 0 && ret != GIT_EUSER) return nullptr; // check if file not found if (git_oid_iszero(&treewalkstruct.oid)) return nullptr; bool diff = true; // for merge point, check if it is different to all parents, if yes then there are real change in the merge point. // if no parent then of course it is different for (unsigned int i = 0; i < git_commit_parentcount(commit); ++i) { CAutoCommit commit2; if (git_commit_parent(commit2.GetPointer(), commit, i)) return nullptr; CAutoTree tree2; if (git_commit_tree(tree2.GetPointer(), commit2)) return nullptr; TreewalkStruct treewalkstruct2 = { folder, file }; memset(&treewalkstruct2.oid.id, 0, sizeof(treewalkstruct2.oid.id)); int ret = git_tree_walk(tree2, GIT_TREEWALK_PRE, TreewalkCB_FindFileRecentCommit, &treewalkstruct2); if (ret < 0 && ret != GIT_EUSER) return nullptr; if (!git_oid_cmp(&treewalkstruct.oid, &treewalkstruct2.oid)) diff = false; else if (git_revwalk_hide(walk, git_commit_parent_id(commit, i))) return nullptr; } if (diff) break; } return commit.Detach(); }