Пример #1
0
static int read_tree_recursive(git_tree_cache *cache, const git_tree *tree, git_pool *pool)
{
	git_repository *repo;
	size_t i, j, nentries, ntrees;
	int error;

	repo = git_tree_owner(tree);

	git_oid_cpy(&cache->oid, git_tree_id(tree));
	nentries = git_tree_entrycount(tree);

	/*
	 * We make sure we know how many trees we need to allocate for
	 * so we don't have to realloc and change the pointers for the
	 * parents.
	 */
	ntrees = 0;
	for (i = 0; i < nentries; i++) {
		const git_tree_entry *entry;

		entry = git_tree_entry_byindex(tree, i);
		if (git_tree_entry_filemode(entry) == GIT_FILEMODE_TREE)
			ntrees++;
	}

	cache->children_count = ntrees;
	cache->children = git_pool_mallocz(pool, ntrees * sizeof(git_tree_cache *));
	GITERR_CHECK_ALLOC(cache->children);

	j = 0;
	for (i = 0; i < nentries; i++) {
		const git_tree_entry *entry;
		git_tree *subtree;

		entry = git_tree_entry_byindex(tree, i);
		if (git_tree_entry_filemode(entry) != GIT_FILEMODE_TREE)
			continue;

		if ((error = git_tree_cache_new(&cache->children[j], git_tree_entry_name(entry), pool)) < 0)
			return error;

		if ((error = git_tree_lookup(&subtree, repo, git_tree_entry_id(entry))) < 0)
			return error;

		error = read_tree_recursive(cache->children[j], subtree, pool);
		git_tree_free(subtree);
		j++;

		if (error < 0)
			return error;
	}

	return 0;
}
Пример #2
0
static int find_subtree_in_current_level(
	git_tree **out,
	git_repository *repo,
	git_tree *parent,
	const char *annotated_object_sha,
	int fanout)
{
	size_t i;
	const git_tree_entry *entry;

	*out = NULL;

	if (parent == NULL)
		return GIT_ENOTFOUND;

	for (i = 0; i < git_tree_entrycount(parent); i++) {
		entry = git_tree_entry_byindex(parent, i);

		if (!git__ishex(git_tree_entry_name(entry)))
			continue;

		if (S_ISDIR(git_tree_entry_filemode(entry))
			&& strlen(git_tree_entry_name(entry)) == 2
			&& !strncmp(git_tree_entry_name(entry), annotated_object_sha + fanout, 2))
			return git_tree_lookup(out, repo, git_tree_entry_id(entry));

		/* Not a DIR, so do we have an already existing blob? */
		if (!strcmp(git_tree_entry_name(entry), annotated_object_sha + fanout))
			return GIT_EEXISTS;
	}

	return GIT_ENOTFOUND;
}
Пример #3
0
static int print_tree(git_repository *repo, const git_oid *tree_oid, int depth)
{
	static const char *indent = "                              ";
	git_tree *tree;
	unsigned int i;

	if (git_tree_lookup(&tree, repo, tree_oid) < GIT_SUCCESS)
		return GIT_ERROR;

	for (i = 0; i < git_tree_entrycount(tree); ++i) {
		const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
		char entry_oid[40];

		git_oid_fmt(entry_oid, &entry->oid);
		printf("%.*s%o [%.*s] %s\n", depth*2, indent, entry->attr, 40, entry_oid, entry->filename);

		if (entry->attr == S_IFDIR) {
			if (print_tree(repo, &entry->oid, depth + 1) < GIT_SUCCESS) {
				git_tree_close(tree);
				return GIT_ERROR;
			}
		}
	}

	git_tree_close(tree);
	return GIT_SUCCESS;
}
Пример #4
0
int CRepositoryBrowser::ReadTreeRecursive(git_repository &repo, git_tree * tree, CShadowFilesTree * treeroot)
{
	size_t count = git_tree_entrycount(tree);

	for (size_t i = 0; i < count; ++i)
	{
		const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
		if (entry == NULL)
			continue;

		const int mode = git_tree_entry_filemode(entry);

		CString base = CUnicodeUtils::GetUnicode(git_tree_entry_name(entry), CP_UTF8);

		const git_oid *oid = git_tree_entry_id(entry);
		CShadowFilesTree * pNextTree = &treeroot->m_ShadowTree[base];
		pNextTree->m_sName = base;
		pNextTree->m_pParent = treeroot;
		pNextTree->m_hash = CGitHash((char *)oid->id);

		if (mode == GIT_FILEMODE_COMMIT)
			pNextTree->m_bSubmodule = true;
		else if (mode & S_IFDIR)
		{
			pNextTree->m_bFolder = true;

			TVINSERTSTRUCT tvinsert = {0};
			tvinsert.hParent = treeroot->m_hTree;
			tvinsert.hInsertAfter = TVI_SORT;
			tvinsert.itemex.mask = TVIF_DI_SETITEM | TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE;
			tvinsert.itemex.pszText = base.GetBuffer(base.GetLength());
			tvinsert.itemex.lParam = (LPARAM)pNextTree;
			tvinsert.itemex.iImage = m_nIconFolder;
			tvinsert.itemex.iSelectedImage = m_nOpenIconFolder;
			pNextTree->m_hTree = m_RepoTree.InsertItem(&tvinsert);
			base.ReleaseBuffer();

			git_object *object = nullptr;
			git_tree_entry_to_object(&object, &repo, entry);
			if (object == nullptr)
				continue;

			ReadTreeRecursive(repo, (git_tree*)object, pNextTree);

			git_object_free(object);
		}
		else
		{
			git_blob * blob = nullptr;
			git_blob_lookup(&blob, &repo, oid);
			if (blob == NULL)
				continue;

			pNextTree->m_iSize = git_blob_rawsize(blob);
			git_blob_free(blob);
		}
	}

	return 0;
}
Пример #5
0
static void assert_workdir_matches_tree(
    git_repository *repo, const git_oid *id, const char *root, bool recurse)
{
    git_object *obj;
    git_tree *tree;
    size_t i, max_i;
    git_buf path = GIT_BUF_INIT;

    if (!root)
        root = git_repository_workdir(repo);
    cl_assert(root);

    cl_git_pass(git_object_lookup(&obj, repo, id, GIT_OBJ_ANY));
    cl_git_pass(git_object_peel((git_object **)&tree, obj, GIT_OBJ_TREE));
    git_object_free(obj);

    max_i = git_tree_entrycount(tree);

    for (i = 0; i < max_i; ++i) {
        const git_tree_entry *te = git_tree_entry_byindex(tree, i);
        cl_assert(te);

        cl_git_pass(git_buf_joinpath(&path, root, git_tree_entry_name(te)));

        switch (git_tree_entry_type(te)) {
        case GIT_OBJ_COMMIT:
            assert_dir_exists(path.ptr);
            break;
        case GIT_OBJ_TREE:
            assert_dir_exists(path.ptr);
            if (recurse)
                assert_workdir_matches_tree(
                    repo, git_tree_entry_id(te), path.ptr, true);
            break;
        case GIT_OBJ_BLOB:
            switch (git_tree_entry_filemode(te)) {
            case GIT_FILEMODE_BLOB:
            case GIT_FILEMODE_BLOB_EXECUTABLE:
                assert_file_exists(path.ptr);
                /* because of cross-platform, don't confirm exec bit yet */
                break;
            case GIT_FILEMODE_LINK:
                cl_assert_(git_path_exists(path.ptr), path.ptr);
                /* because of cross-platform, don't confirm link yet */
                break;
            default:
                cl_assert(false); /* really?! */
            }
            break;
        default:
            cl_assert(false); /* really?!! */
        }
    }

    git_tree_free(tree);
    git_buf_free(&path);
}
Пример #6
0
static size_t copy_entries(AGBMergeEntry * entries, const git_tree * tree, enum AGBMergeIndex idx) {
	size_t n = git_tree_entrycount(tree);
	size_t i;
	for(i=0; i<n; ++i) {
		const git_tree_entry * gte = git_tree_entry_byindex(tree,i);
		entries[i].name = git_tree_entry_name(gte);
		entries[i].treeentries[idx] = gte;
	}
	return n;
}
Пример #7
0
int
read_repo(const char *repo_name)
{
	int i;
	int r;
	int n;
	git_repository *repo;
	git_reference *head;
	git_oid oid;
	git_commit *commit;
	git_tree *tree;
	git_tree_entry *tree_entry;
	char out[41];
	out[40] = '\0';

	// opening the repository
	r = git_repository_open(&repo, repo_name);
	if (r)
		printf("error in opening the repository\n");
	printf("Opened the repository successfully.\n");

	// obtaining the head
	r = git_repository_head(&head, repo);
	if (r)
		printf("error in obtaining the head\n");
	r = git_reference_name_to_oid(&oid, repo, git_reference_name(head));
	if (r)
		printf("error in obtaining the ref id of head\n");
	printf("Obtained the head id %s\n", git_oid_tostr(out, 41, &oid));

	// obtaining the commit from commit id
	r = git_commit_lookup(&commit, repo, &oid);
	if (r)
		printf("error in obtaining the commit from oid\n");
	printf("Obtained the commit.\n");

	// obtaining the tree id from the commit
	oid = *git_commit_tree_oid(commit);

	// get the tree
	r = git_tree_lookup(&tree, repo, &oid);
	if (r)
		printf("error in looking up the tree for oid\n");
	printf("Lookup for tree of oid successful.\n");

	n = git_tree_entrycount(tree);
	for (i=0; i<n; i++) {
		tree_entry = git_tree_entry_byindex(tree, i);
		printf("entry >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %s %s\n", git_tree_entry_name(tree_entry), git_object_type2string(git_tree_entry_type(tree_entry)));
	}

	git_repository_free(repo);
	return 0;
}
Пример #8
0
void test_object_tree_read__loaded(void)
{
	/* acces randomly the entries on a loaded tree */
	git_oid id;
	git_tree *tree;

	git_oid_fromstr(&id, tree_oid);

	cl_git_pass(git_tree_lookup(&tree, g_repo, &id));

	cl_assert(git_tree_entry_byname(tree, "README") != NULL);
	cl_assert(git_tree_entry_byname(tree, "NOTEXISTS") == NULL);
	cl_assert(git_tree_entry_byname(tree, "") == NULL);
	cl_assert(git_tree_entry_byindex(tree, 0) != NULL);
	cl_assert(git_tree_entry_byindex(tree, 2) != NULL);
	cl_assert(git_tree_entry_byindex(tree, 3) == NULL);
	cl_assert(git_tree_entry_byindex(tree, (unsigned int)-1) == NULL);

	git_tree_free(tree);
}
Пример #9
0
TreeEntry *
TreeIter_iternext(TreeIter *self)
{
    const git_tree_entry *tree_entry;

    tree_entry = git_tree_entry_byindex(self->owner->tree, self->i);
    if (!tree_entry)
        return NULL;

    self->i += 1;
    return (TreeEntry*)wrap_tree_entry(git_tree_entry_dup(tree_entry), self->owner);
}
Пример #10
0
/*
 *	call-seq:
 *		tree[e] -> entry
 *		tree.get_entry(e) -> entry
 *
 *	Return one of the entries from a tree as a +Hash+. If +e+ is a number, the +e+nth entry
 *	from the tree will be returned. If +e+ is a string, the entry with that name
 *	will be returned.
 *
 *	If the entry doesn't exist, +nil+ will be returned.
 *
 *		tree[3] #=> {:name => "foo.txt", :type => :blob, :oid => "d8786bfc97485e8d7b19b21fb88c8ef1f199fc3f", :filemode => 0}
 *
 *		tree['bar.txt'] #=> {:name => "bar.txt", :type => :blob, :oid => "de5ba987198bcf2518885f0fc1350e5172cded78", :filemode => 0}
 *
 *		tree['baz.txt'] #=> nil
 */
static VALUE rb_git_tree_get_entry(VALUE self, VALUE entry_id)
{
	git_tree *tree;
	Data_Get_Struct(self, git_tree, tree);

	if (TYPE(entry_id) == T_FIXNUM)
		return rb_git_treeentry_fromC(git_tree_entry_byindex(tree, FIX2INT(entry_id)));

	else if (TYPE(entry_id) == T_STRING)
		return rb_git_treeentry_fromC(git_tree_entry_byname(tree, StringValueCStr(entry_id)));

	else
		rb_raise(rb_eTypeError, "entry_id must be either an index or a filename");
}
Пример #11
0
static VALUE rb_git_tree_get_entry(VALUE self, VALUE entry_id)
{
	git_tree *tree;
	RUGGED_OBJ_UNWRAP(self, git_tree, tree);

	if (TYPE(entry_id) == T_FIXNUM)
		return rb_git_createentry(self, git_tree_entry_byindex(tree, FIX2INT(entry_id)));

	else if (TYPE(entry_id) == T_STRING)
		return rb_git_createentry(self, git_tree_entry_byname(tree, RSTRING_PTR(entry_id)));

	else
		rb_raise(rb_eTypeError, "entry_id must be either an index or a filename");
}
Пример #12
0
/**
 * ggit_tree_get:
 * @tree: a #GgitTree.
 * @i: the index of the entry.
 *
 * Get a tree entry by index.
 *
 * Returns: (transfer full): a #GgitTreeEntry.
 *
 **/
GgitTreeEntry *
ggit_tree_get (GgitTree *tree,
               guint     i)
{
	git_tree *t;
	const git_tree_entry *entry;

	g_return_val_if_fail (GGIT_IS_TREE (tree), NULL);

	t = _ggit_native_get (tree);

	entry = git_tree_entry_byindex (t, i);

	return _ggit_tree_entry_wrap ((git_tree_entry *)entry, FALSE);
}
Пример #13
0
TreeEntry *
Tree_getitem_by_index(Tree *self, PyObject *py_index)
{
    int index;
    const git_tree_entry *entry;

    index = Tree_fix_index(self, py_index);
    if (PyErr_Occurred())
        return NULL;

    entry = git_tree_entry_byindex(self->tree, index);
    if (!entry) {
        PyErr_SetObject(PyExc_IndexError, py_index);
        return NULL;
    }
    return wrap_tree_entry(git_tree_entry_dup(entry), self);
}
Пример #14
0
void add_tree_to_index(git_tree * tree, const char * prefix) {
	for (size_t i = 0; i < git_tree_entrycount(tree); i++) {
		/* Get the tree entry */
		const git_tree_entry *tree_entry;
		tree_entry = git_tree_entry_byindex(tree,(unsigned int)i);
		
		if (tree_entry == NULL) {
			printf("Tree entry not found");
			libgit_error();
		}

		/* Get the oid of a tree entry */
		const git_oid *entry_oid = git_tree_entry_id (tree_entry);

		/* is a sub directory ? */
		git_tree * subtree;
		if (git_tree_lookup(&subtree, repo, entry_oid) == 0) {
			char * subprefix = xmalloc(sizeof(char)*1024);
			const char * dirname = git_tree_entry_name (tree_entry);
			git2__joinpath(subprefix, prefix, dirname);
			add_tree_to_index(subtree, subprefix);
			continue;
		}
		
		char * completename = xmalloc(sizeof(char)*1024);
		git2__joinpath(completename, prefix, git_tree_entry_name (tree_entry));
		git_index_entry source_entry = {
			{0,0},//git_index_time 	ctime
			{0,0},//git_index_time 	mtime
			0,//unsigned int 	dev
			0,//unsigned int 	ino
			git_tree_entry_attributes(tree_entry),//unsigned int 	mode
			0,//unsigned int 	uid
			0,//unsigned int 	gid
			0,//git_off_t 	file_size
			*entry_oid,
			0,
			0,//unsigned short 	flags_extended
			completename
		};
		
		
		git_index_append2(index_cur, &source_entry);
		
	}
}
Пример #15
0
static int find_blob(git_oid *blob, git_tree *tree, const char *target)
{
	size_t i;
	const git_tree_entry *entry;

	for (i=0; i<git_tree_entrycount(tree); i++) {
		entry = git_tree_entry_byindex(tree, i);

		if (!strcmp(git_tree_entry_name(entry), target)) {
			/* found matching note object - return */

			git_oid_cpy(blob, git_tree_entry_id(entry));
			return 0;
		}
	}
	return GIT_ENOTFOUND;
}
Пример #16
0
/** Show each entry with its type, id and attributes */
static void show_tree(const git_tree *tree)
{
	size_t i, max_i = (int)git_tree_entrycount(tree);
	char oidstr[GIT_OID_HEXSZ + 1];
	const git_tree_entry *te;

	for (i = 0; i < max_i; ++i) {
		te = git_tree_entry_byindex(tree, i);

		git_oid_tostr(oidstr, sizeof(oidstr), git_tree_entry_id(te));

		printf("%06o %s %s\t%s\n",
			git_tree_entry_filemode(te),
			git_object_type2string(git_tree_entry_type(te)),
			oidstr, git_tree_entry_name(te));
	}
}
Пример #17
0
TreeEntry *
TreeIter_iternext(TreeIter *self)
{
    const git_tree_entry *entry_src;
    git_tree_entry *entry;

    entry_src = git_tree_entry_byindex(self->owner->tree, self->i);
    if (!entry_src)
        return NULL;

    self->i += 1;

    if (git_tree_entry_dup(&entry, entry_src) < 0) {
        PyErr_SetNone(PyExc_MemoryError);
        return NULL;
    }
    return wrap_tree_entry(entry);
}
Пример #18
0
/*
 *	call-seq:
 *		tree.each { |entry| block }
 *		tree.each -> Iterator
 *
 *	Call +block+ with each of the entries of the subtree as a +Hash+. If no +block+
 *	is given, an +Iterator+ is returned instead.
 *
 *	Note that only the entries in the root of the tree are yielded; if you need to
 *	list also entries in subfolders, use +tree.walk+ instead.
 *
 *		tree.each { |entry| puts entry.inspect }
 *
 *	generates:
 *
 *		{:name => "foo.txt", :type => :blob, :oid => "d8786bfc97485e8d7b19b21fb88c8ef1f199fc3f", :filemode => 0}
 *		{:name => "bar.txt", :type => :blob, :oid => "de5ba987198bcf2518885f0fc1350e5172cded78", :filemode => 0}
 *		...
 */
static VALUE rb_git_tree_each(VALUE self)
{
	git_tree *tree;
	unsigned int i, count;
	Data_Get_Struct(self, git_tree, tree);

	if (!rb_block_given_p())
		return rb_funcall(self, rb_intern("to_enum"), 0);

	count = git_tree_entrycount(tree);

	for (i = 0; i < count; ++i) {
		const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
		rb_yield(rb_git_treeentry_fromC(entry));
	}

	return Qnil;
}
Пример #19
0
int ReadTreeRecursive(git_repository &repo, git_tree * tree, CStringA base, int (*CallBack) (const unsigned char *, const char *, int, const char *, unsigned int, int, void *),void *data)
{
	size_t count = git_tree_entrycount(tree);
	for (int i = 0; i < count; i++)
	{
		const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
		if (entry == NULL)
			continue;
		int mode = git_tree_entry_attributes(entry);
		if( CallBack(git_tree_entry_id(entry)->id,
			base,
			base.GetLength(),
			git_tree_entry_name(entry),
			mode,
			0,
			data) == READ_TREE_RECURSIVE
		  )
		{
			if(mode&S_IFDIR)
			{
				git_object *object = NULL;
				git_tree_entry_2object(&object, &repo, entry);
				if (object == NULL)
					continue;
				CStringA parent = base;
				parent += git_tree_entry_name(entry);
				parent += "/";
				ReadTreeRecursive(repo, (git_tree*)object, parent, CallBack, data);
				git_object_free(object);
			}
		}

	}

	return 0;
}
Пример #20
0
TreeEntry *
Tree_getitem_by_index(Tree *self, PyObject *py_index)
{
    int index;
    const git_tree_entry *entry_src;
    git_tree_entry *entry;

    index = Tree_fix_index(self, py_index);
    if (PyErr_Occurred())
        return NULL;

    entry_src = git_tree_entry_byindex(self->tree, index);
    if (!entry_src) {
        PyErr_SetObject(PyExc_IndexError, py_index);
        return NULL;
    }

    if (git_tree_entry_dup(&entry, entry_src) < 0) {
        PyErr_SetNone(PyExc_MemoryError);
        return NULL;
    }

    return wrap_tree_entry(entry);
}
Пример #21
0
QGitTreeEntry QGitTree::entryByIndex(int idx) const
{
    return QGitTreeEntry(git_tree_entry_byindex(data(), idx));
}
Пример #22
0
/**
 * Merges two tree objects, producing a third tree.
 * The base tree allows the algorithm to distinguish between adds and deletes.
 * The algorithm always prefers the item from tree 1 when there is a conflict.
 */
static int sync_merge_trees(git_oid *out,
                            git_repository *repo,
                            const git_oid *base_id,
                            const git_oid *id1,
                            const git_oid *id2)
{
    int e = 0;
    git_tree *base_tree = NULL;
    git_tree *tree1 = NULL;
    git_tree *tree2 = NULL;
    git_treebuilder *tb = NULL;
    size_t size1, size2;
    size_t i1 = 0;
    size_t i2 = 0;
    const git_tree_entry *e1 = NULL;
    const git_tree_entry *e2 = NULL;
    enum { ONLY1 = 1, ONLY2 = 2, BOTH = 3 } state = BOTH;

    git_check(git_tree_lookup(&base_tree, repo, base_id));
    git_check(git_tree_lookup(&tree1, repo, id1));
    git_check(git_tree_lookup(&tree2, repo, id2));
    git_check(git_treebuilder_new(&tb, repo, NULL));
    size1 = git_tree_entrycount(tree1);
    size2 = git_tree_entrycount(tree2);

    while (1)
    {
        // Advance to next file:
        if (state == ONLY1 || state == BOTH)
        {
            e1 = i1 < size1 ? git_tree_entry_byindex(tree1, i1++) : NULL;
        }
        if (state == ONLY2 || state == BOTH)
        {
            e2 = i2 < size2 ? git_tree_entry_byindex(tree2, i2++) : NULL;
        }

        // Determine state:
        if (e1 && e2)
        {
            int s = strcmp(git_tree_entry_name(e1), git_tree_entry_name(e2));
            state = s < 0 ? ONLY1 :
                    s > 0 ? ONLY2 :
                    BOTH;
        }
        else if (e1 && !e2)
        {
            state = ONLY1;
        }
        else if (!e1 && e2)
        {
            state = ONLY2;
        }
        else
        {
            break;
        }

        // Grab the entry in question:
        const git_tree_entry *entry =
            (state == ONLY1 || state == BOTH) ? e1 : e2;
        const git_tree_entry *base_entry =
            git_tree_entry_byname(base_tree, git_tree_entry_name(entry));

        // Decide what to do with the entry:
        if (state == BOTH && base_entry &&
            GIT_OBJ_TREE == git_tree_entry_type(e1) &&
            GIT_OBJ_TREE == git_tree_entry_type(e2) &&
            GIT_OBJ_TREE == git_tree_entry_type(base_entry))
        {
            // Merge sub-trees:
            git_oid new_tree;
            git_check(sync_merge_trees(&new_tree, repo,
                git_tree_entry_id(base_entry),
                git_tree_entry_id(e1),
                git_tree_entry_id(e2)));
            git_check(git_treebuilder_insert(NULL, tb,
                git_tree_entry_name(e1),
                &new_tree,
                git_tree_entry_filemode(e1)));
        }
        else if (state == BOTH && base_entry)
        {
            if (git_oid_cmp(git_tree_entry_id(base_entry), git_tree_entry_id(e1)))
            {
                // Entry `e1` has changes, so use that:
                git_check(git_treebuilder_insert(NULL, tb,
                    git_tree_entry_name(e1),
                    git_tree_entry_id(e1),
                    git_tree_entry_filemode(e1)));
            }
            else
            {
                // Entry `e1` has no changes, so use `e2`:
                git_check(git_treebuilder_insert(NULL, tb,
                    git_tree_entry_name(e2),
                    git_tree_entry_id(e2),
                    git_tree_entry_filemode(e2)));
            }
        }
        else if (state == BOTH || !base_entry)
        {
            // Entry was added, or already present:
            git_check(git_treebuilder_insert(NULL, tb,
                git_tree_entry_name(entry),
                git_tree_entry_id(entry),
                git_tree_entry_filemode(entry)));
        }
        // Otherwise, the entry was deleted.
    }

    // Write tree:
    git_check(git_treebuilder_write(out, tb));

exit:
    if (base_tree)      git_tree_free(base_tree);
    if (tree1)          git_tree_free(tree1);
    if (tree2)          git_tree_free(tree2);
    if (tb)             git_treebuilder_free(tb);
    return e;
}
Пример #23
0
int main (int argc, char** argv)
{
  // ### Opening the Repository

  // There are a couple of methods for opening a repository, this being the simplest.
  // There are also [methods][me] for specifying the index file and work tree locations, here
  // we are assuming they are in the normal places.
  //
  // [me]: http://libgit2.github.com/libgit2/#HEAD/group/repository
  git_repository *repo;
  if (argc > 1) {
    git_repository_open(&repo, argv[1]);
  } else {
    git_repository_open(&repo, "/opt/libgit2-test/.git");
  }

  // ### SHA-1 Value Conversions

  // For our first example, we will convert a 40 character hex value to the 20 byte raw SHA1 value.
  printf("*Hex to Raw*\n");
  char hex[] = "fd6e612585290339ea8bf39c692a7ff6a29cb7c3";

  // The `git_oid` is the structure that keeps the SHA value. We will use this throughout the example
  // for storing the value of the current SHA key we're working with.
  git_oid oid;
  git_oid_fromstr(&oid, hex);

  // Once we've converted the string into the oid value, we can get the raw value of the SHA.
  printf("Raw 20 bytes: [%.20s]\n", (&oid)->id);

  // Next we will convert the 20 byte raw SHA1 value to a human readable 40 char hex value.
  printf("\n*Raw to Hex*\n");
  char out[41];
  out[40] = '\0';

  // If you have a oid, you can easily get the hex value of the SHA as well.
  git_oid_fmt(out, &oid);
  printf("SHA hex string: %s\n", out);

  // ### Working with the Object Database
  // **libgit2** provides [direct access][odb] to the object database.
  // The object database is where the actual objects are stored in Git. For
  // working with raw objects, we'll need to get this structure from the
  // repository.
  // [odb]: http://libgit2.github.com/libgit2/#HEAD/group/odb
  git_odb *odb;
  git_repository_odb(&odb, repo);

  // #### Raw Object Reading

  printf("\n*Raw Object Read*\n");
  git_odb_object *obj;
  git_otype otype;
  const unsigned char *data;
  const char *str_type;
  int error;

  // We can read raw objects directly from the object database if we have the oid (SHA)
  // of the object.  This allows us to access objects without knowing thier type and inspect
  // the raw bytes unparsed.
  error = git_odb_read(&obj, odb, &oid);

  // A raw object only has three properties - the type (commit, blob, tree or tag), the size
  // of the raw data and the raw, unparsed data itself.  For a commit or tag, that raw data
  // is human readable plain ASCII text. For a blob it is just file contents, so it could be
  // text or binary data. For a tree it is a special binary format, so it's unlikely to be
  // hugely helpful as a raw object.
  data = (const unsigned char *)git_odb_object_data(obj);
  otype = git_odb_object_type(obj);

  // We provide methods to convert from the object type which is an enum, to a string
  // representation of that value (and vice-versa).
  str_type = git_object_type2string(otype);
  printf("object length and type: %d, %s\n",
      (int)git_odb_object_size(obj),
      str_type);

  // For proper memory management, close the object when you are done with it or it will leak
  // memory.
  git_odb_object_free(obj);

  // #### Raw Object Writing

  printf("\n*Raw Object Write*\n");

  // You can also write raw object data to Git. This is pretty cool because it gives you
  // direct access to the key/value properties of Git.  Here we'll write a new blob object
  // that just contains a simple string.  Notice that we have to specify the object type as
  // the `git_otype` enum.
  git_odb_write(&oid, odb, "test data", sizeof("test data") - 1, GIT_OBJ_BLOB);

  // Now that we've written the object, we can check out what SHA1 was generated when the
  // object was written to our database.
  git_oid_fmt(out, &oid);
  printf("Written Object: %s\n", out);

  // ### Object Parsing
  // libgit2 has methods to parse every object type in Git so you don't have to work directly
  // with the raw data. This is much faster and simpler than trying to deal with the raw data
  // yourself.

  // #### Commit Parsing
  // [Parsing commit objects][pco] is simple and gives you access to all the data in the commit
  // - the // author (name, email, datetime), committer (same), tree, message, encoding and parent(s).
  // [pco]: http://libgit2.github.com/libgit2/#HEAD/group/commit

  printf("\n*Commit Parsing*\n");

  git_commit *commit;
  git_oid_fromstr(&oid, "f0877d0b841d75172ec404fc9370173dfffc20d1");

  error = git_commit_lookup(&commit, repo, &oid);

  const git_signature *author, *cmtter;
  const char *message;
  time_t ctime;
  unsigned int parents, p;

  // Each of the properties of the commit object are accessible via methods, including commonly
  // needed variations, such as `git_commit_time` which returns the author time and `_message`
  // which gives you the commit message.
  message  = git_commit_message(commit);
  author   = git_commit_author(commit);
  cmtter   = git_commit_committer(commit);
  ctime    = git_commit_time(commit);

  // The author and committer methods return [git_signature] structures, which give you name, email
  // and `when`, which is a `git_time` structure, giving you a timestamp and timezone offset.
  printf("Author: %s (%s)\n", author->name, author->email);

  // Commits can have zero or more parents. The first (root) commit will have no parents, most commits
  // will have one, which is the commit it was based on, and merge commits will have two or more.
  // Commits can technically have any number, though it's pretty rare to have more than two.
  parents  = git_commit_parentcount(commit);
  for (p = 0;p < parents;p++) {
    git_commit *parent;
    git_commit_parent(&parent, commit, p);
    git_oid_fmt(out, git_commit_id(parent));
    printf("Parent: %s\n", out);
    git_commit_free(parent);
  }

  // Don't forget to close the object to prevent memory leaks. You will have to do this for
  // all the objects you open and parse.
  git_commit_free(commit);

  // #### Writing Commits
  //
  // libgit2 provides a couple of methods to create commit objects easily as well. There are four
  // different create signatures, we'll just show one of them here.  You can read about the other
  // ones in the [commit API docs][cd].
  // [cd]: http://libgit2.github.com/libgit2/#HEAD/group/commit

  printf("\n*Commit Writing*\n");
  git_oid tree_id, parent_id, commit_id;
  git_tree *tree;
  git_commit *parent;

  // Creating signatures for an authoring identity and time is pretty simple - you will need to have
  // this to create a commit in order to specify who created it and when.  Default values for the name
  // and email should be found in the `user.name` and `user.email` configuration options.  See the `config`
  // section of this example file to see how to access config values.
  git_signature_new((git_signature **)&author, "Scott Chacon", "*****@*****.**",
      123456789, 60);
  git_signature_new((git_signature **)&cmtter, "Scott A Chacon", "*****@*****.**",
      987654321, 90);

  // Commit objects need a tree to point to and optionally one or more parents.  Here we're creating oid
  // objects to create the commit with, but you can also use
  git_oid_fromstr(&tree_id, "28873d96b4e8f4e33ea30f4c682fd325f7ba56ac");
  git_tree_lookup(&tree, repo, &tree_id);
  git_oid_fromstr(&parent_id, "f0877d0b841d75172ec404fc9370173dfffc20d1");
  git_commit_lookup(&parent, repo, &parent_id);

  // Here we actually create the commit object with a single call with all the values we need to create
  // the commit.  The SHA key is written to the `commit_id` variable here.
  git_commit_create_v(
    &commit_id, /* out id */
    repo,
    NULL, /* do not update the HEAD */
    author,
    cmtter,
    NULL, /* use default message encoding */
    "example commit",
    tree,
    1, parent);

  // Now we can take a look at the commit SHA we've generated.
  git_oid_fmt(out, &commit_id);
  printf("New Commit: %s\n", out);

  // #### Tag Parsing
  // You can parse and create tags with the [tag management API][tm], which functions very similarly
  // to the commit lookup, parsing and creation methods, since the objects themselves are very similar.
  // [tm]: http://libgit2.github.com/libgit2/#HEAD/group/tag
  printf("\n*Tag Parsing*\n");
  git_tag *tag;
  const char *tmessage, *tname;
  git_otype ttype;

  // We create an oid for the tag object if we know the SHA and look it up in the repository the same
  // way that we would a commit (or any other) object.
  git_oid_fromstr(&oid, "bc422d45275aca289c51d79830b45cecebff7c3a");

  error = git_tag_lookup(&tag, repo, &oid);

  // Now that we have the tag object, we can extract the information it generally contains: the target
  // (usually a commit object), the type of the target object (usually 'commit'), the name ('v1.0'),
  // the tagger (a git_signature - name, email, timestamp), and the tag message.
  git_tag_target((git_object **)&commit, tag);
  tname = git_tag_name(tag);    // "test"
  ttype = git_tag_type(tag);    // GIT_OBJ_COMMIT (otype enum)
  tmessage = git_tag_message(tag); // "tag message\n"
  printf("Tag Message: %s\n", tmessage);

  git_commit_free(commit);

  // #### Tree Parsing
  // [Tree parsing][tp] is a bit different than the other objects, in that we have a subtype which is the
  // tree entry.  This is not an actual object type in Git, but a useful structure for parsing and
  // traversing tree entries.
  //
  // [tp]: http://libgit2.github.com/libgit2/#HEAD/group/tree
  printf("\n*Tree Parsing*\n");

  const git_tree_entry *entry;
  git_object *objt;

  // Create the oid and lookup the tree object just like the other objects.
  git_oid_fromstr(&oid, "2a741c18ac5ff082a7caaec6e74db3075a1906b5");
  git_tree_lookup(&tree, repo, &oid);

  // Getting the count of entries in the tree so you can iterate over them if you want to.
  int cnt = git_tree_entrycount(tree); // 3
  printf("tree entries: %d\n", cnt);

  entry = git_tree_entry_byindex(tree, 0);
  printf("Entry name: %s\n", git_tree_entry_name(entry)); // "hello.c"

  // You can also access tree entries by name if you know the name of the entry you're looking for.
  entry = git_tree_entry_byname(tree, "hello.c");
  git_tree_entry_name(entry); // "hello.c"

  // Once you have the entry object, you can access the content or subtree (or commit, in the case
  // of submodules) that it points to.  You can also get the mode if you want.
  git_tree_entry_to_object(&objt, repo, entry); // blob

  // Remember to close the looked-up object once you are done using it
  git_object_free(objt);

  // #### Blob Parsing
  //
  // The last object type is the simplest and requires the least parsing help. Blobs are just file
  // contents and can contain anything, there is no structure to it. The main advantage to using the
  // [simple blob api][ba] is that when you're creating blobs you don't have to calculate the size
  // of the content.  There is also a helper for reading a file from disk and writing it to the db and
  // getting the oid back so you don't have to do all those steps yourself.
  //
  // [ba]: http://libgit2.github.com/libgit2/#HEAD/group/blob

  printf("\n*Blob Parsing*\n");
  git_blob *blob;

  git_oid_fromstr(&oid, "af7574ea73f7b166f869ef1a39be126d9a186ae0");
  git_blob_lookup(&blob, repo, &oid);

  // You can access a buffer with the raw contents of the blob directly.
  // Note that this buffer may not be contain ASCII data for certain blobs (e.g. binary files):
  // do not consider the buffer a NULL-terminated string, and use the `git_blob_rawsize` attribute to
  // find out its exact size in bytes
  printf("Blob Size: %ld\n", git_blob_rawsize(blob)); // 8
  git_blob_rawcontent(blob); // "content"

  // ### Revwalking
  //
  // The libgit2 [revision walking api][rw] provides methods to traverse the directed graph created
  // by the parent pointers of the commit objects.  Since all commits point back to the commit that
  // came directly before them, you can walk this parentage as a graph and find all the commits that
  // were ancestors of (reachable from) a given starting point.  This can allow you to create `git log`
  // type functionality.
  //
  // [rw]: http://libgit2.github.com/libgit2/#HEAD/group/revwalk

  printf("\n*Revwalking*\n");
  git_revwalk *walk;
  git_commit *wcommit;

  git_oid_fromstr(&oid, "f0877d0b841d75172ec404fc9370173dfffc20d1");

  // To use the revwalker, create a new walker, tell it how you want to sort the output and then push
  // one or more starting points onto the walker.  If you want to emulate the output of `git log` you
  // would push the SHA of the commit that HEAD points to into the walker and then start traversing them.
  // You can also 'hide' commits that you want to stop at or not see any of their ancestors.  So if you
  // want to emulate `git log branch1..branch2`, you would push the oid of `branch2` and hide the oid
  // of `branch1`.
  git_revwalk_new(&walk, repo);
  git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE);
  git_revwalk_push(walk, &oid);

  const git_signature *cauth;
  const char *cmsg;

  // Now that we have the starting point pushed onto the walker, we can start asking for ancestors. It
  // will return them in the sorting order we asked for as commit oids.
  // We can then lookup and parse the commited pointed at by the returned OID;
  // note that this operation is specially fast since the raw contents of the commit object will
  // be cached in memory
  while ((git_revwalk_next(&oid, walk)) == 0) {
    error = git_commit_lookup(&wcommit, repo, &oid);
    cmsg  = git_commit_message(wcommit);
    cauth = git_commit_author(wcommit);
    printf("%s (%s)\n", cmsg, cauth->email);
    git_commit_free(wcommit);
  }

  // Like the other objects, be sure to free the revwalker when you're done to prevent memory leaks.
  // Also, make sure that the repository being walked it not deallocated while the walk is in
  // progress, or it will result in undefined behavior
  git_revwalk_free(walk);

  // ### Index File Manipulation
  //
  // The [index file API][gi] allows you to read, traverse, update and write the Git index file
  // (sometimes thought of as the staging area).
  //
  // [gi]: http://libgit2.github.com/libgit2/#HEAD/group/index

  printf("\n*Index Walking*\n");

  git_index *index;
  unsigned int i, ecount;

  // You can either open the index from the standard location in an open repository, as we're doing
  // here, or you can open and manipulate any index file with `git_index_open_bare()`. The index
  // for the repository will be located and loaded from disk.
  git_repository_index(&index, repo);

  // For each entry in the index, you can get a bunch of information including the SHA (oid), path
  // and mode which map to the tree objects that are written out.  It also has filesystem properties
  // to help determine what to inspect for changes (ctime, mtime, dev, ino, uid, gid, file_size and flags)
  // All these properties are exported publicly in the `git_index_entry` struct
  ecount = git_index_entrycount(index);
  for (i = 0; i < ecount; ++i) {
    git_index_entry *e = git_index_get(index, i);

    printf("path: %s\n", e->path);
    printf("mtime: %d\n", (int)e->mtime.seconds);
    printf("fs: %d\n", (int)e->file_size);
  }

  git_index_free(index);

  // ### References
  //
  // The [reference API][ref] allows you to list, resolve, create and update references such as
  // branches, tags and remote references (everything in the .git/refs directory).
  //
  // [ref]: http://libgit2.github.com/libgit2/#HEAD/group/reference

  printf("\n*Reference Listing*\n");

  // Here we will implement something like `git for-each-ref` simply listing out all available
  // references and the object SHA they resolve to.
  git_strarray ref_list;
  git_reference_list(&ref_list, repo, GIT_REF_LISTALL);

  const char *refname;
  git_reference *ref;

  // Now that we have the list of reference names, we can lookup each ref one at a time and
  // resolve them to the SHA, then print both values out.
  for (i = 0; i < ref_list.count; ++i) {
    refname = ref_list.strings[i];
    git_reference_lookup(&ref, repo, refname);

    switch (git_reference_type(ref)) {
    case GIT_REF_OID:
      git_oid_fmt(out, git_reference_oid(ref));
      printf("%s [%s]\n", refname, out);
      break;

    case GIT_REF_SYMBOLIC:
      printf("%s => %s\n", refname, git_reference_target(ref));
      break;
    default:
      fprintf(stderr, "Unexpected reference type\n");
      exit(1);
    }
  }

  git_strarray_free(&ref_list);

  // ### Config Files
  //
  // The [config API][config] allows you to list and updatee config values in
  // any of the accessible config file locations (system, global, local).
  //
  // [config]: http://libgit2.github.com/libgit2/#HEAD/group/config

  printf("\n*Config Listing*\n");

  const char *email;
  int32_t j;

  git_config *cfg;

  // Open a config object so we can read global values from it.
  git_config_open_ondisk(&cfg, "~/.gitconfig");

  git_config_get_int32(cfg, "help.autocorrect", &j);
  printf("Autocorrect: %d\n", j);

  git_config_get_string(cfg, "user.email", &email);
  printf("Email: %s\n", email);

  // Finally, when you're done with the repository, you can free it as well.
  git_repository_free(repo);

  return 0;
}
Пример #24
0
/*
 * And the Lord said: Is this tree properly sorted?
 */
void test_object_tree_write__sorted_subtrees(void)
{
	git_treebuilder *builder;
	git_tree *tree;
	unsigned int i;
	int position_c = -1, position_cake = -1, position_config = -1;

	struct {
		unsigned int attr;
		const char *filename;
	} entries[] = {
		{ GIT_FILEMODE_BLOB, ".gitattributes" },
	  	{ GIT_FILEMODE_BLOB, ".gitignore" },
	  	{ GIT_FILEMODE_BLOB, ".htaccess" },
	  	{ GIT_FILEMODE_BLOB, "Capfile" },
	  	{ GIT_FILEMODE_BLOB, "Makefile"},
	  	{ GIT_FILEMODE_BLOB, "README"},
	  	{ GIT_FILEMODE_TREE, "app"},
	  	{ GIT_FILEMODE_TREE, "cake"},
	  	{ GIT_FILEMODE_TREE, "config"},
	  	{ GIT_FILEMODE_BLOB, "c"},
	  	{ GIT_FILEMODE_BLOB, "git_test.txt"},
	  	{ GIT_FILEMODE_BLOB, "htaccess.htaccess"},
	  	{ GIT_FILEMODE_BLOB, "index.php"},
	  	{ GIT_FILEMODE_TREE, "plugins"},
	  	{ GIT_FILEMODE_TREE, "schemas"},
	  	{ GIT_FILEMODE_TREE, "ssl-certs"},
	  	{ GIT_FILEMODE_TREE, "vendors"}
	};

	git_oid bid, tid, tree_oid;

	cl_git_pass(git_oid_fromstr(&bid, blob_oid));
	cl_git_pass(git_oid_fromstr(&tid, first_tree));

	cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL));

	for (i = 0; i < ARRAY_SIZE(entries); ++i) {
		git_oid *id = entries[i].attr == GIT_FILEMODE_TREE ?  &tid : &bid; 

		cl_git_pass(git_treebuilder_insert(NULL,
			builder, entries[i].filename, id, entries[i].attr));
	}

	cl_git_pass(git_treebuilder_write(&tree_oid, builder));

	cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid));
	for (i = 0; i < git_tree_entrycount(tree); i++) {
		const git_tree_entry *entry = git_tree_entry_byindex(tree, i);

		if (strcmp(entry->filename, "c") == 0)
			position_c = i;

		if (strcmp(entry->filename, "cake") == 0)
			position_cake = i;

		if (strcmp(entry->filename, "config") == 0)
			position_config = i;
	}

	git_tree_free(tree);

	cl_assert(position_c != -1);
	cl_assert(position_cake != -1);
	cl_assert(position_config != -1);

	cl_assert(position_c < position_cake);
	cl_assert(position_cake < position_config);

	git_treebuilder_free(builder);
}
Пример #25
0
void test_object_tree_write__removing_and_re_adding_in_treebuilder(void)
{
	git_treebuilder *builder;
	int i, aardvark_i, apple_i, apple_after_i, apple_extra_i, last_i;
	git_oid entry_oid, tree_oid;
	git_tree *tree;

	cl_git_pass(git_oid_fromstr(&entry_oid, blob_oid));

	cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL));

	cl_assert_equal_i(0, (int)git_treebuilder_entrycount(builder));

	for (i = 0; _entries[i].filename; ++i)
		cl_git_pass(git_treebuilder_insert(NULL,
			builder, _entries[i].filename, &entry_oid, _entries[i].attr));

	cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder));

	cl_git_pass(git_treebuilder_remove(builder, "apple"));
	cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder));

	cl_git_pass(git_treebuilder_remove(builder, "apple_after"));
	cl_assert_equal_i(4, (int)git_treebuilder_entrycount(builder));

	cl_git_pass(git_treebuilder_insert(
		NULL, builder, "before_last", &entry_oid, GIT_FILEMODE_BLOB));
	cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder));

	/* reinsert apple_after */
	cl_git_pass(git_treebuilder_insert(
		NULL, builder, "apple_after", &entry_oid, GIT_FILEMODE_BLOB));
	cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder));

	cl_git_pass(git_treebuilder_remove(builder, "last"));
	cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder));

	/* reinsert last */
	cl_git_pass(git_treebuilder_insert(
		NULL, builder, "last", &entry_oid, GIT_FILEMODE_BLOB));
	cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder));

	cl_git_pass(git_treebuilder_insert(
		NULL, builder, "apple_extra", &entry_oid, GIT_FILEMODE_BLOB));
	cl_assert_equal_i(7, (int)git_treebuilder_entrycount(builder));

	cl_git_pass(git_treebuilder_write(&tree_oid, builder));

	git_treebuilder_free(builder);

	cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid));

	cl_assert_equal_i(7, (int)git_tree_entrycount(tree));

	cl_assert(git_tree_entry_byname(tree, ".first") != NULL);
	cl_assert(git_tree_entry_byname(tree, "apple") == NULL);
	cl_assert(git_tree_entry_byname(tree, "apple_after") != NULL);
	cl_assert(git_tree_entry_byname(tree, "apple_extra") != NULL);
	cl_assert(git_tree_entry_byname(tree, "last") != NULL);

	aardvark_i = apple_i = apple_after_i = apple_extra_i = last_i = -1;

	for (i = 0; i < 7; ++i) {
		const git_tree_entry *entry = git_tree_entry_byindex(tree, i);

		if (!strcmp(entry->filename, "aardvark"))
			aardvark_i = i;
		else if (!strcmp(entry->filename, "apple"))
			apple_i = i;
		else if (!strcmp(entry->filename, "apple_after"))
			apple_after_i = i;
		else if (!strcmp(entry->filename, "apple_extra"))
			apple_extra_i = i;
		else if (!strcmp(entry->filename, "last"))
			last_i = i;
	}

	cl_assert_equal_i(-1, apple_i);
	cl_assert_equal_i(6, last_i);
	cl_assert(aardvark_i < apple_after_i);
	cl_assert(apple_after_i < apple_extra_i);

	git_tree_free(tree);
}
Пример #26
0
BEGIN_TEST(read0, "acces randomly the entries on a loaded tree")
	git_oid id;
	git_repository *repo;
	git_tree *tree;

	must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));

	git_oid_mkstr(&id, tree_oid);

	must_pass(git_tree_lookup(&tree, repo, &id));

	must_be_true(git_tree_entry_byname(tree, "README") != NULL);
	must_be_true(git_tree_entry_byname(tree, "NOTEXISTS") == NULL);
	must_be_true(git_tree_entry_byname(tree, "") == NULL);
	must_be_true(git_tree_entry_byindex(tree, 0) != NULL);
	must_be_true(git_tree_entry_byindex(tree, 2) != NULL);
	must_be_true(git_tree_entry_byindex(tree, 3) == NULL);
	must_be_true(git_tree_entry_byindex(tree, -1) == NULL);

	git_repository_free(repo);
END_TEST

BEGIN_TEST(read1, "read a tree from the repository")
	git_oid id;
	git_repository *repo;
	git_tree *tree;
	git_tree_entry *entry;
	git_object *obj;

	must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
Пример #27
0
int CRepositoryBrowser::ReadTreeRecursive(git_repository &repo, const git_tree * tree, CShadowFilesTree * treeroot)
{
	size_t count = git_tree_entrycount(tree);
	bool hasSubfolders = false;

	for (size_t i = 0; i < count; ++i)
	{
		const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
		if (entry == NULL)
			continue;

		const int mode = git_tree_entry_filemode(entry);

		CString base = CUnicodeUtils::GetUnicode(git_tree_entry_name(entry), CP_UTF8);

		const git_oid *oid = git_tree_entry_id(entry);
		CShadowFilesTree * pNextTree = &treeroot->m_ShadowTree[base];
		pNextTree->m_sName = base;
		pNextTree->m_pParent = treeroot;
		pNextTree->m_hash = CGitHash((char *)oid->id);

		if (mode == GIT_FILEMODE_COMMIT)
			pNextTree->m_bSubmodule = true;
		else if (mode & S_IFDIR)
		{
			hasSubfolders = true;
			pNextTree->m_bFolder = true;
			pNextTree->m_bLoaded = false;

			TVINSERTSTRUCT tvinsert = {0};
			tvinsert.hParent = treeroot->m_hTree;
			tvinsert.hInsertAfter = TVI_SORT;
			tvinsert.itemex.mask = TVIF_DI_SETITEM | TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE | TVIF_CHILDREN;
			tvinsert.itemex.pszText = base.GetBuffer(base.GetLength());
			tvinsert.itemex.cChildren = 1;
			tvinsert.itemex.lParam = (LPARAM)pNextTree;
			tvinsert.itemex.iImage = m_nIconFolder;
			tvinsert.itemex.iSelectedImage = m_nOpenIconFolder;
			pNextTree->m_hTree = m_RepoTree.InsertItem(&tvinsert);
			base.ReleaseBuffer();
		}
		else
		{
			if (mode == GIT_FILEMODE_BLOB_EXECUTABLE)
				pNextTree->m_bExecutable = true;
			if (mode == GIT_FILEMODE_LINK)
				pNextTree->m_bSymlink = true;
			CAutoBlob blob;
			git_blob_lookup(blob.GetPointer(), &repo, oid);
			if (!blob)
				continue;

			pNextTree->m_iSize = git_blob_rawsize(blob);
		}
	}

	if (!hasSubfolders)
	{
		TVITEM tvitem = { 0 };
		tvitem.hItem = treeroot->m_hTree;
		tvitem.mask = TVIF_CHILDREN;
		tvitem.cChildren = 0;
		m_RepoTree.SetItem(&tvitem);
	}

	return 0;
}
Пример #28
0
static int tree_iterator__push_frame(tree_iterator *ti)
{
	int error = 0;
	tree_iterator_frame *head = ti->head, *tf = NULL;
	size_t i, n_entries = 0;

	if (head->current >= head->n_entries || !head->entries[head->current]->tree)
		return GIT_ITEROVER;

	for (i = head->current; i < head->next; ++i)
		n_entries += git_tree_entrycount(head->entries[i]->tree);

	tf = git__calloc(sizeof(tree_iterator_frame) +
		n_entries * sizeof(tree_iterator_entry *), 1);
	GITERR_CHECK_ALLOC(tf);

	tf->n_entries = n_entries;

	tf->up     = head;
	head->down = tf;
	ti->head   = tf;

	for (i = head->current, n_entries = 0; i < head->next; ++i) {
		git_tree *tree = head->entries[i]->tree;
		size_t j, max_j = git_tree_entrycount(tree);

		for (j = 0; j < max_j; ++j) {
			tree_iterator_entry *entry = git_pool_malloc(&ti->pool, 1);
			GITERR_CHECK_ALLOC(entry);

			entry->parent = head->entries[i];
			entry->te     = git_tree_entry_byindex(tree, j);
			entry->tree   = NULL;

			tf->entries[n_entries++] = entry;
		}
	}

	/* if ignore_case, sort entries case insensitively */
	if (iterator__ignore_case(ti))
		git__tsort_r(
			(void **)tf->entries, tf->n_entries, tree_iterator__ci_cmp, tf);

	/* pick tf->current based on "start" (or start at zero) */
	if (head->startlen > 0) {
		git__bsearch_r((void **)tf->entries, tf->n_entries, head,
			tree_iterator__search_cmp, ti, &tf->current);

		while (tf->current &&
			   !tree_iterator__search_cmp(head, tf->entries[tf->current-1], ti))
			tf->current--;

		if ((tf->start = strchr(head->start, '/')) != NULL) {
			tf->start++;
			tf->startlen = strlen(tf->start);
		}
	}

	ti->path_has_filename = ti->entry_is_current = false;

	if ((error = tree_iterator__set_next(ti, tf)) < 0)
		return error;

	/* autoexpand as needed */
	if (!iterator__include_trees(ti) && tree_iterator__at_tree(ti))
		return tree_iterator__push_frame(ti);

	return 0;
}
Пример #29
0
BEGIN_TEST(read0, "acces randomly the entries on a loaded tree")
	git_oid id;
	git_repository *repo;
	git_tree *tree;

	must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));

	git_oid_fromstr(&id, tree_oid);

	must_pass(git_tree_lookup(&tree, repo, &id));

	must_be_true(git_tree_entry_byname(tree, "README") != NULL);
	must_be_true(git_tree_entry_byname(tree, "NOTEXISTS") == NULL);
	must_be_true(git_tree_entry_byname(tree, "") == NULL);
	must_be_true(git_tree_entry_byindex(tree, 0) != NULL);
	must_be_true(git_tree_entry_byindex(tree, 2) != NULL);
	must_be_true(git_tree_entry_byindex(tree, 3) == NULL);
	must_be_true(git_tree_entry_byindex(tree, (unsigned int)-1) == NULL);

	git_tree_close(tree);
	git_repository_free(repo);
END_TEST

BEGIN_TEST(read1, "read a tree from the repository")
	git_oid id;
	git_repository *repo;
	git_tree *tree;
	const git_tree_entry *entry;
	git_object *obj;