예제 #1
0
/**
 * 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);
	}
}
예제 #2
0
/*
 *	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;
}
예제 #3
0
/*
 *  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);
}
예제 #4
0
파일: git.c 프로젝트: ileitch/meanie
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);
}
예제 #5
0
파일: git-evtag.c 프로젝트: tyll/git-evtag
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;
}
예제 #6
0
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;
}
예제 #7
0
파일: wrapper.c 프로젝트: Merovius/git2go
int _go_git_treewalk(git_tree *tree, git_treewalk_mode mode, void *ptr)
{
	return git_tree_walk(tree, mode, (git_treewalk_cb)&CallbackGitTreeWalk, ptr);
}
예제 #8
0
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();
}