Beispiel #1
0
int git_object_lookup_bypath(
		git_object **out,
		const git_object *treeish,
		const char *path,
		git_otype type)
{
	int error = -1;
	git_tree *tree = NULL;
	git_tree_entry *entry = NULL;

	assert(out && treeish && path);

	if ((error = git_object_peel((git_object**)&tree, treeish, GIT_OBJ_TREE)) < 0 ||
		 (error = git_tree_entry_bypath(&entry, tree, path)) < 0)
	{
		goto cleanup;
	}

	if (type != GIT_OBJ_ANY && git_tree_entry_type(entry) != type)
	{
		giterr_set(GITERR_OBJECT,
				"object at path '%s' is not of the asked-for type %d",
				path, type);
		error = GIT_EINVALIDSPEC;
		goto cleanup;
	}

	error = git_tree_entry_to_object(out, git_object_owner(treeish), entry);

cleanup:
	git_tree_entry_free(entry);
	git_tree_free(tree);
	return error;
}
Beispiel #2
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;
}
Beispiel #3
0
static int read_file_git(const char *repo_path, const char *name, void **out, size_t *outlen) {
    int ret, retcode = -1;

    git_repository *repo;
    ret = git_repository_open_bare(&repo, repo_path);
    if(check_lg2(ret, "opening repo"))
        goto out;

    git_object *master;
    ret = git_revparse_single(&master, repo, "master");
    if(check_lg2(ret, "getting master branch"))
        goto out_repo;

    if(git_object_type(master) != GIT_OBJ_COMMIT) {
        debug("master is not a commit");
        goto out_master;
    }

    git_tree *tree;
    ret = git_commit_tree(&tree, (git_commit*)master);
    if(check_lg2(ret, "getting tree from commit"))
        goto out_master;

    const git_tree_entry *entry = git_tree_entry_byname(tree, name);
    if(!entry) {
        debug("entry %s not found", name);
        goto out_tree;
    }

    if(git_tree_entry_type(entry) != GIT_OBJ_BLOB) {
        debug("entry is not a blob");
        goto out_tree;
    }

    git_object *file;
    ret = git_tree_entry_to_object(&file, repo, entry);
    if(check_lg2(ret, "getting file from tree entry"))
        goto out_tree;

    const void *data = git_blob_rawcontent((git_blob*)file);
    *outlen = git_blob_rawsize((git_blob*)file);

    *out = malloc(*outlen);
    memcpy(*out, data, *outlen);

    retcode = 0;

    git_object_free(file);
out_tree:
    git_tree_free(tree);
out_master:
    git_object_free(master);
out_repo:
    git_repository_free(repo);
out:
    return retcode;
}
Beispiel #4
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);
}
Beispiel #5
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);
}
Beispiel #6
0
static int rugged__treecount_cb(const char *root, const git_tree_entry *entry, void *data)
{
	struct rugged_treecount_cb_payload *payload = data;

	if (payload->limit >= 0 && payload->count >= payload->limit) {
		return -1;
	} else if(git_tree_entry_type(entry) == GIT_OBJ_TREE) {
		return 0;
	} else {
		++(payload->count);
		return 1;
	}
}
Beispiel #7
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));
	}
}
Beispiel #8
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;
}
Beispiel #9
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;
}
int CRepositoryBrowser::ReadTree(CShadowFilesTree * treeroot, const CString& root)
{
	CWaitCursor wait;
	CAutoRepository repository(g_Git.GetGitRepository());
	if (!repository)
	{
		MessageBox(CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_ICONERROR);
		return -1;
	}

	if (m_sRevision == _T("HEAD"))
	{
		int ret = git_repository_head_unborn(repository);
		if (ret == 1)	// is orphan
			return ret;
		else if (ret != 0)
		{
			MessageBox(g_Git.GetLibGit2LastErr(_T("Could not check HEAD.")), _T("TortoiseGit"), MB_ICONERROR);
			return ret;
		}
	}

	CGitHash hash;
	if (CGit::GetHash(repository, hash, m_sRevision))
	{
		MessageBox(CGit::GetLibGit2LastErr(_T("Could not get hash of ") + m_sRevision + _T(".")), _T("TortoiseGit"), MB_ICONERROR);
		return -1;
	}

	CAutoCommit commit;
	if (git_commit_lookup(commit.GetPointer(), repository, (git_oid *)hash.m_hash))
	{
		MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup commit.")), _T("TortoiseGit"), MB_ICONERROR);
		return -1;
	}

	CAutoTree tree;
	if (git_commit_tree(tree.GetPointer(), commit))
	{
		MessageBox(CGit::GetLibGit2LastErr(_T("Could not get tree of commit.")), _T("TortoiseGit"), MB_ICONERROR);
		return -1;
	}

	if (!root.IsEmpty())
	{
		CAutoTreeEntry treeEntry;
		if (git_tree_entry_bypath(treeEntry.GetPointer(), tree, CUnicodeUtils::GetUTF8(root)))
		{
			MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup path.")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}
		if (git_tree_entry_type(treeEntry) != GIT_OBJ_TREE)
		{
			MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup path.")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}

		CAutoObject object;
		if (git_tree_entry_to_object(object.GetPointer(), repository, treeEntry))
		{
			MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup path.")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}

		tree = (git_tree*)object.Detach();
	}

	treeroot->m_hash = CGitHash((char *)git_tree_id(tree)->id);
	ReadTreeRecursive(*repository, tree, treeroot);

	// try to resolve hash to a branch name
	if (m_sRevision == hash.ToString())
	{
		MAP_HASH_NAME map;
		if (CGit::GetMapHashToFriendName(repository, map))
			MessageBox(g_Git.GetLibGit2LastErr(_T("Could not get all refs.")), _T("TortoiseGit"), MB_ICONERROR);
		if (!map[hash].empty())
			m_sRevision = map[hash].at(0);
	}
	this->GetDlgItem(IDC_BUTTON_REVISION)->SetWindowText(m_sRevision);

	return 0;
}
Beispiel #11
0
PyObject *
TreeEntry_type__get__(TreeEntry *self)
{
    return to_path(git_object_type2string(git_tree_entry_type(self->entry)));
}
Beispiel #12
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;
}
Beispiel #13
0
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;
}