Exemplo n.º 1
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;
}
Exemplo n.º 2
0
void test_object_tree_read__two(void)
{
	/* read a tree from the repository */
	git_oid id;
	git_tree *tree;
	const git_tree_entry *entry;
	git_object *obj;

	git_oid_fromstr(&id, tree_oid);

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

	cl_assert(git_tree_entrycount(tree) == 3);

	/* GH-86: git_object_lookup() should also check the type if the object comes from the cache */
	cl_assert(git_object_lookup(&obj, g_repo, &id, GIT_OBJECT_TREE) == 0);
	cl_assert(obj != NULL);
	git_object_free(obj);
	obj = NULL;
	cl_git_fail(git_object_lookup(&obj, g_repo, &id, GIT_OBJECT_BLOB));
	cl_assert(obj == NULL);

	entry = git_tree_entry_byname(tree, "README");
	cl_assert(entry != NULL);

	cl_assert_equal_s(git_tree_entry_name(entry), "README");

	cl_git_pass(git_tree_entry_to_object(&obj, g_repo, entry));
	cl_assert(obj != NULL);

	git_object_free(obj);
	git_tree_free(tree);
}
Exemplo n.º 3
0
static VALUE rb_git_treeentry_fromC(const git_tree_entry *entry)
{
	VALUE rb_entry;
	VALUE type;

	if (!entry)
		return Qnil;

	rb_entry = rb_hash_new();

	rb_hash_aset(rb_entry, CSTR2SYM("name"), rugged_str_new2(git_tree_entry_name(entry), NULL));
	rb_hash_aset(rb_entry, CSTR2SYM("oid"), rugged_create_oid(git_tree_entry_id(entry)));

	rb_hash_aset(rb_entry, CSTR2SYM("filemode"), INT2FIX(git_tree_entry_filemode(entry)));

	switch(git_tree_entry_type(entry)) {
		case GIT_OBJ_TREE:
			type = CSTR2SYM("tree");
			break;

		case GIT_OBJ_BLOB:
			type = CSTR2SYM("blob");
			break;

		default:
			type = Qnil;
			break;
	}
	rb_hash_aset(rb_entry, CSTR2SYM("type"), type);

	return rb_entry;
}
Exemplo n.º 4
0
static int walk_tree_file(const char *root, const git_tree_entry *entry, git_repository *repo)
{
	struct dive *dive = active_dive;
	dive_trip_t *trip = active_trip;
	const char *name = git_tree_entry_name(entry);

	switch (*name) {
	/* Picture file? They are saved as time offsets in the dive */
	case '-': case '+':
		if (dive)
			return parse_picture_entry(repo, entry, name);
		break;
	case 'D':
		if (dive && !strncmp(name, "Divecomputer", 12))
			return parse_divecomputer_entry(repo, entry, name+12);
		if (dive && !strncmp(name, "Dive", 4))
			return parse_dive_entry(repo, entry, name+4);
		break;
	case '0':
		if (trip && !strcmp(name, "00-Trip"))
			return parse_trip_entry(repo, entry);
		if (!strcmp(name, "00-Subsurface"))
			return parse_settings_entry(repo, entry);
		break;
	}
	report_error("Unknown file %s%s (%p %p)", root, name, dive, trip);
	return GIT_WALK_SKIP;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
static VALUE rb_git_tree_entry_name_GET(VALUE self)
{
	rugged_tree_entry *tree_entry;
	Data_Get_Struct(self, rugged_tree_entry, tree_entry);

	return rugged_str_new2(git_tree_entry_name(tree_entry->entry), NULL);
}
Exemplo n.º 7
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);
		
	}
}
Exemplo n.º 8
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);
}
Exemplo n.º 9
0
PyObject *
TreeEntry_repr(TreeEntry *self)
{
    char str[GIT_OID_HEXSZ + 1] = { 0 };
    const char *typename;

    typename = git_object_type2string(git_tree_entry_type(self->entry));
    git_oid_fmt(str, git_tree_entry_id(self->entry));
    return PyString_FromFormat("pygit2.TreeEntry('%s', %s, %s)", git_tree_entry_name(self->entry), typename, str);
}
Exemplo n.º 10
0
Arquivo: merge.c Projeto: mikeando/agb
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;
}
Exemplo n.º 11
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;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
static void assert_tree_from_path(
	git_tree *root,
	const char *path,
	const char *expected_entry_name)
{
	git_tree_entry *entry;

	cl_git_pass(git_tree_entry_bypath(&entry, root, path));
	cl_assert_equal_s(git_tree_entry_name(entry), expected_entry_name);
	git_tree_entry_free(entry);
}
Exemplo n.º 14
0
static int TreewalkCB_FindFileRecentCommit(const char *root, const git_tree_entry *entry, void *payload)
{
	TreewalkStruct *treewalkstruct = (TreewalkStruct *)payload;
	char folder[MAX_PATH] = {0};
	strcpy_s(folder, root);
	strcat_s(folder, git_tree_entry_name(entry));
	strcat_s(folder, "/");
	if (strstr(treewalkstruct->folder, folder))
		return 0;

	if (!strcmp(treewalkstruct->folder, root))
	{
		if (!strcmp(git_tree_entry_name(entry), treewalkstruct->name))
		{
			git_oid_cpy(&treewalkstruct->oid, git_tree_entry_id(entry));
			return GIT_EUSER;
		}

		return 1;
	}

	return 1;
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
0
static int walk_tree_file(const char *root, const git_tree_entry *entry, git_repository *repo)
{
	struct dive *dive = active_dive;
	dive_trip_t *trip = active_trip;
	const char *name = git_tree_entry_name(entry);

	if (dive && !strncmp(name, "Divecomputer", 12))
		return parse_divecomputer_entry(repo, entry, name+12);
	if (dive && !strncmp(name, "Dive", 4))
		return parse_dive_entry(repo, entry, name+4);
	if (trip && !strcmp(name, "00-Trip"))
		return parse_trip_entry(repo, entry);
	if (!strcmp(name, "00-Subsurface"))
		return parse_settings_entry(repo, entry);
	report_error("Unknown file %s%s (%p %p)", root, name, dive, trip);
	return GIT_WALK_SKIP;
}
Exemplo n.º 17
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;
}
Exemplo n.º 18
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));
	}
}
Exemplo n.º 19
0
static int
checksum_tree_callback (const char *root,
                        const git_tree_entry *entry,
                        void *data)
{
  int iter_r = 1;
  int tmp_r;
  struct TreeWalkData *twdata = data;
  git_otype otype = git_tree_entry_type (entry);

  switch (otype)
    {
    case GIT_OBJ_TREE:
    case GIT_OBJ_BLOB:
      if (!checksum_object_id (twdata, git_tree_entry_id (entry),
                               twdata->error))
        {
          twdata->caught_error = TRUE;
          return -1;
        }
      break;
    case GIT_OBJ_COMMIT:
      {
        git_submodule *submod = NULL;
        tmp_r = git_submodule_lookup (&submod, twdata->repo, git_tree_entry_name (entry));
        if (!handle_libgit_ret (tmp_r, twdata->error))
          goto out;

        tmp_r = checksum_submodule (twdata, submod);
        if (tmp_r != 0)
          goto out;

        git_submodule_free (submod);
      }
      break;
    default:
      g_assert_not_reached ();
    }

  iter_r = 0;
 out:
  if (iter_r > 0)
    twdata->caught_error = TRUE;
  return iter_r;
}
Exemplo n.º 20
0
/*
 * When hitting a directory node, we have a couple of cases:
 *
 *  - It's just a date entry - all numeric (either year or month):
 *
 *       [yyyy|mm]
 *
 *    We don't do anything with these, we just traverse into them.
 *    The numeric data will show up as part of the full path when
 *    we hit more interesting entries.
 *
 *  - It's a trip directory. The name will be of the form
 *
 *       nn-alphabetic[~hex]
 *
 *    where 'nn' is the day of the month (year and month will be
 *    encoded in the path leading up to this).
 *
 *  - It's a dive directory. The name will be of the form
 *
 *       [[yyyy-]mm-]nn-ddd-hh=mm=ss[~hex]
 *
 *    (older versions had this as [[yyyy-]mm-]nn-ddd-hh:mm:ss[~hex]
 *     but that faile on Windows)
 *
 *    which describes the date and time of a dive (yyyy and mm
 *    are optional, and may be encoded in the path leading up to
 *    the dive).
 *
 *  - It is a per-dive picture directory ("Pictures")
 *
 *  - It's some random non-dive-data directory.
 *
 *    If it doesn't match the above patterns, we'll ignore them
 *    for dive loading purposes, and not even recurse into them.
 */
static int walk_tree_directory(const char *root, const git_tree_entry *entry)
{
	const char *name = git_tree_entry_name(entry);
	int digits = 0, len;
	char c;

	if (!strcmp(name, "Pictures"))
		return picture_directory(root, name);

	if (!strcmp(name, "01-Divesites"))
		return GIT_WALK_OK;

	while (isdigit(c = name[digits]))
		digits++;

	/* Doesn't start with two or four digits? Skip */
	if (digits != 4 && digits != 2)
		return GIT_WALK_SKIP;

	/* Only digits? Do nothing, but recurse into it */
	if (!c)
		return GIT_WALK_OK;

	/* All valid cases need to have a slash following */
	if (c != '-')
		return GIT_WALK_SKIP;

	/* Do a quick check for a common dive case */
	len = nonunique_length(name);

	/*
	 * We know the len is at least 3, because we had at least
	 * two digits and a dash
	 */
	if (name[len-3] == ':' || name[len-3] == '=')
		return dive_directory(root, name, len-8);

	if (digits != 2)
		return GIT_WALK_SKIP;

	return dive_trip_directory(root, name);
}
Exemplo n.º 21
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;
}
Exemplo n.º 22
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;
}
Exemplo n.º 23
0
PyObject *
TreeEntry__name__get__(TreeEntry *self)
{
    return PyBytes_FromString(git_tree_entry_name(self->entry));
}
Exemplo n.º 24
0
static int treebuilder_filter_prefixed(
	const git_tree_entry *entry, void *payload)
{
	return !git__prefixcmp(git_tree_entry_name(entry), payload);
}
Exemplo n.º 25
0
void test_object_tree_write__cruel_paths(void)
{
	static const char *the_paths[] = {
		"C:\\",
		" : * ? \" \n < > |",
		"a\\b",
		"\\\\b\a",
		":\\",
		"COM1",
		"foo.aux",
		REP1024("1234"), /* 4096 char string */
		REP1024("12345678"), /* 8192 char string */
		"\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD", /* Ūnĭcōde̽ */
		NULL
	};
	git_treebuilder *builder;
	git_tree *tree;
	git_oid id, bid, subid;
	const char **scan;
	int count = 0, i, j;
	git_tree_entry *te;

	git_oid_fromstr(&bid, blob_oid);

	/* create tree */
	cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL));
	for (scan = the_paths; *scan; ++scan) {
		cl_git_pass(git_treebuilder_insert(
			NULL, builder, *scan, &bid, GIT_FILEMODE_BLOB));
		count++;
	}
	cl_git_pass(git_treebuilder_write(&id, builder));
	git_treebuilder_free(builder);

	/* check data is correct */
	cl_git_pass(git_tree_lookup(&tree, g_repo, &id));

	cl_assert_equal_i(count, git_tree_entrycount(tree));

	for (scan = the_paths; *scan; ++scan) {
		const git_tree_entry *cte = git_tree_entry_byname(tree, *scan);
		cl_assert(cte != NULL);
		cl_assert_equal_s(*scan, git_tree_entry_name(cte));
	}
	for (scan = the_paths; *scan; ++scan) {
		cl_git_pass(git_tree_entry_bypath(&te, tree, *scan));
		cl_assert_equal_s(*scan, git_tree_entry_name(te));
		git_tree_entry_free(te);
	}

	git_tree_free(tree);

	/* let's try longer paths */
	cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL));
	for (scan = the_paths; *scan; ++scan) {
		cl_git_pass(git_treebuilder_insert(
			NULL, builder, *scan, &id, GIT_FILEMODE_TREE));
	}
	cl_git_pass(git_treebuilder_write(&subid, builder));
	git_treebuilder_free(builder);

	/* check data is correct */
	cl_git_pass(git_tree_lookup(&tree, g_repo, &subid));

	cl_assert_equal_i(count, git_tree_entrycount(tree));

	for (i = 0; i < count; ++i) {
		for (j = 0; j < count; ++j) {
			git_buf b = GIT_BUF_INIT;
			cl_git_pass(git_buf_joinpath(&b, the_paths[i], the_paths[j]));
			cl_git_pass(git_tree_entry_bypath(&te, tree, b.ptr));
			cl_assert_equal_s(the_paths[j], git_tree_entry_name(te));
			git_tree_entry_free(te);
			git_buf_free(&b);
		}
	}

	git_tree_free(tree);
}
Exemplo n.º 26
0
PyObject *
TreeEntry_name__get__(TreeEntry *self)
{
    return to_path(git_tree_entry_name(self->entry));
}
Exemplo n.º 27
0
	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_entrycount(tree) == 3);

	/* GH-86: git_object_lookup() should also check the type if the object comes from the cache */
	must_be_true(git_object_lookup(&obj, repo, &id, GIT_OBJ_TREE) == 0);
	must_be_true(git_object_lookup(&obj, repo, &id, GIT_OBJ_BLOB) == GIT_EINVALIDTYPE);

	entry = git_tree_entry_byname(tree, "README");
	must_be_true(entry != NULL);

	must_be_true(strcmp(git_tree_entry_name(entry), "README") == 0);

	must_pass(git_tree_entry_2object(&obj, repo, entry));

	git_repository_free(repo);
END_TEST

BEGIN_SUITE(tree)
	ADD_TEST(read0);
	ADD_TEST(read1);
//	ADD_TEST(write0); /* TODO THREADSAFE */
//	ADD_TEST(write1);
END_SUITE

Exemplo n.º 28
0
Arquivo: git.c Projeto: ileitch/meanie
static int mne_git_tree_entry_cb(const char *root, git_tree_entry *entry, void *arg) {
  mne_git_walk_ctx *ctx = (mne_git_walk_ctx*)arg;
  git_otype type = git_tree_entry_type(entry);
  
  if (likely(type == GIT_OBJ_BLOB)) {
    const git_oid *blob_oid = git_tree_entry_id(entry);
    char *sha1 = malloc(sizeof(char) * GIT_OID_HEXSZ + 1);
    assert(sha1 != NULL);
    git_oid_tostr(sha1, GIT_OID_HEXSZ + 1, blob_oid);

    git_odb_object *blob_odb_object;
    git_odb_read(&blob_odb_object, odb, blob_oid);

    gpointer blob = g_hash_table_lookup(blobs, (gpointer)sha1);

    char **sha1_refs;

    if (blob == NULL) {
      ctx->distinct_blobs++;
      char *tmp_data = (char*)git_odb_object_data(blob_odb_object);
      int data_len = strlen(tmp_data);
      char *data = malloc(sizeof(char) * (data_len + 1));
      memcpy(data, tmp_data, data_len);
      data[data_len] = 0;

      assert((strlen(root) + strlen(git_tree_entry_name(entry))) < MNE_MAX_PATH_LENGTH);
      char *path = malloc(sizeof(char) * MNE_MAX_PATH_LENGTH);
      assert(path != NULL);
      strcpy(path, root);
      strcat(path, git_tree_entry_name(entry));

      /* TOOD: Check that the blob <-> path mapping is 1-1. */
      g_hash_table_insert(paths, (gpointer)sha1, (gpointer)path);
      g_hash_table_insert(blobs, (gpointer)sha1, (gpointer)data);

      ctx->bytes += (unsigned long)(sizeof(char) * strlen(data));

      sha1_refs = malloc(sizeof(char*) * total_refs);
      assert(sha1_refs != NULL);

      int i;
      for (i = 0; i < total_refs; i++)
        sha1_refs[i] = NULL;

      g_hash_table_insert(refs, (gpointer)sha1, (gpointer)sha1_refs);
    } else {
      sha1_refs = g_hash_table_lookup(refs, (gpointer)sha1);
      free(sha1);
    }

    git_odb_object_free(blob_odb_object);

    int i;
    for (i = 0; i < total_refs; i++) {
      if (sha1_refs[i] != NULL)
        continue;

      sha1_refs[i] = ctx->ref_name;
      break;
    }
  }

  return GIT_OK;
}
Exemplo n.º 29
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;
}