Example #1
0
void test_refs_branches_create__default_reflog_message(void)
{
	git_reflog *log;
	const git_reflog_entry *entry;
	git_signature *sig;
	git_config *cfg;

	cl_git_pass(git_repository_config(&cfg, repo));
	cl_git_pass(git_config_set_string(cfg, "user.name", "Foo Bar"));
	cl_git_pass(git_config_set_string(cfg, "user.email", "*****@*****.**"));
	git_config_free(cfg);

	cl_git_pass(git_signature_default(&sig, repo));

	retrieve_known_commit(&target, repo);
	cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, false, NULL, NULL));
	cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));

	entry = git_reflog_entry_byindex(log, 0);
	cl_assert_equal_s("Branch: created", git_reflog_entry_message(entry));
	cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email);

	git_reflog_free(log);
	git_signature_free(sig);
}
Example #2
0
static void action_create_tag(tag_state *state)
{
	git_repository *repo = state->repo;
	tag_options *opts = state->opts;
	git_signature *tagger;
	git_oid oid;
	git_object *target;

	check(!opts->tag_name, "Name required");
	check(!opts->message, "Message required");

	if (!opts->target) opts->target = "HEAD";

	check_lg2(git_revparse_single(&target, repo, opts->target),
			"Unable to resolve spec", opts->target);

	check_lg2(git_signature_default(&tagger, repo),
			"Unable to create signature", NULL);

	check_lg2(git_tag_create(&oid, repo, opts->tag_name,
				target, tagger, opts->message, opts->force), "Unable to create tag", NULL);

	git_object_free(target);
	git_signature_free(tagger);
}
Example #3
0
int git_reference_rename(
	git_reference **out,
	git_reference *ref,
	const char *new_name,
	int force,
	const git_signature *signature,
	const char *log_message)
{
	git_signature *who = (git_signature*)signature;
	int error;

	/* Should we return an error if there is no default? */
	if (!who &&
	    ((error = git_signature_default(&who, ref->db->repo)) < 0) &&
	    ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) {
		return error;
	}

	error = reference__rename(out, ref, new_name, force, who, log_message);

	if (!signature)
		git_signature_free(who);

	return error;
}
Example #4
0
PyObject *
Repository_default_signature__get__(Repository *self)
{
    git_signature *sig;
    int err;

    if ((err = git_signature_default(&sig, self->repo)) < 0)
        return Error_set(err);

    return build_signature(NULL, sig, "utf-8");
}
Example #5
0
int git_reference__log_signature(git_signature **out, git_repository *repo)
{
	int error;
	git_signature *who;

	if(((error = git_signature_default(&who, repo)) < 0) &&
	   ((error = git_signature_now(&who, "unknown", "unknown")) < 0))
		return error;

	*out = who;
	return 0;
}
Example #6
0
git_signature *rugged_signature_get(VALUE rb_sig, git_repository *repo)
{
	int error;
	VALUE rb_time, rb_unix_t, rb_offset, rb_name, rb_email, rb_time_offset;
	git_signature *sig;

	if (NIL_P(rb_sig)) {
		rugged_exception_check(
			git_signature_default(&sig, repo)
		);
		return sig;
	}

	Check_Type(rb_sig, T_HASH);

	rb_name = rb_hash_aref(rb_sig, CSTR2SYM("name"));
	rb_email = rb_hash_aref(rb_sig, CSTR2SYM("email"));
	rb_time = rb_hash_aref(rb_sig, CSTR2SYM("time"));
	rb_time_offset = rb_hash_aref(rb_sig, CSTR2SYM("time_offset"));

	Check_Type(rb_name, T_STRING);
	Check_Type(rb_email, T_STRING);


	if (NIL_P(rb_time)) {
		error = git_signature_now(&sig,
				StringValueCStr(rb_name),
				StringValueCStr(rb_email));
	} else {
		if (!rb_obj_is_kind_of(rb_time, rb_cTime))
			rb_raise(rb_eTypeError, "expected Time object");

		rb_unix_t = rb_funcall(rb_time, rb_intern("tv_sec"), 0);

		if (NIL_P(rb_time_offset)) {
			rb_offset = rb_funcall(rb_time, rb_intern("utc_offset"), 0);
		} else {
			Check_Type(rb_time_offset, T_FIXNUM);
			rb_offset = rb_time_offset;
		}

		error = git_signature_new(&sig,
				StringValueCStr(rb_name),
				StringValueCStr(rb_email),
				NUM2LONG(rb_unix_t),
				FIX2INT(rb_offset) / 60);
	}

	rugged_exception_check(error);

	return sig;
}
Example #7
0
void QGit::signature()
{
    git_repository *repo = nullptr;
    git_signature *me = nullptr;
    QString email;
    QString name;
    int res = 0;

    QGitError error;

    try {

        res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData());
        if (res)
        {
            throw QGitError("git_repository_open", res);
        }

        res = git_signature_default(&me, repo);
        if (res)
        {
            throw QGitError("git_signature_default", res);
        }

        name = QString::fromUtf8(me->name);
        email = QString::fromUtf8(me->email);

    } catch(const QGitError & ex) {
        error = ex;
    }

    emit signatureReply(name, email, error);

    if (me)
    {
        git_signature_free(me);
        me = nullptr;
    }

    if (repo)
    {
        git_repository_free(repo);
        repo = nullptr;
    }
}
Example #8
0
void test_refs_branches_create__default_reflog_message(void)
{
	git_reflog *log;
	git_buf buf = GIT_BUF_INIT;
	const git_reflog_entry *entry;
	git_annotated_commit *annotated;
	git_signature *sig;
	git_config *cfg;

	cl_git_pass(git_repository_config(&cfg, repo));
	cl_git_pass(git_config_set_string(cfg, "user.name", "Foo Bar"));
	cl_git_pass(git_config_set_string(cfg, "user.email", "*****@*****.**"));
	git_config_free(cfg);

	cl_git_pass(git_signature_default(&sig, repo));

	retrieve_known_commit(&target, repo);
	cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, false));
	cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));

	entry = git_reflog_entry_byindex(log, 0);
	cl_git_pass(git_buf_printf(&buf, "branch: Created from %s", git_oid_tostr_s(git_commit_id(target))));
	cl_assert_equal_s(git_buf_cstr(&buf), git_reflog_entry_message(entry));
	cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email);

	cl_git_pass(git_reference_remove(repo, "refs/heads/" NEW_BRANCH_NAME));
	git_reference_free(branch);
	git_reflog_free(log);
	git_buf_clear(&buf);

	cl_git_pass(git_annotated_commit_from_revspec(&annotated, repo, "e90810b8df3"));
	cl_git_pass(git_branch_create_from_annotated(&branch, repo, NEW_BRANCH_NAME, annotated, true));
	cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));

	entry = git_reflog_entry_byindex(log, 0);
	cl_git_pass(git_buf_printf(&buf, "branch: Created from e90810b8df3"));
	cl_assert_equal_s(git_buf_cstr(&buf), git_reflog_entry_message(entry));
	cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email);

	git_annotated_commit_free(annotated);
	git_buf_free(&buf);
	git_reflog_free(log);
	git_signature_free(sig);
}
Example #9
0
static int rebase_copy_note(
	git_rebase *rebase,
	const char *notes_ref,
	git_oid *from,
	git_oid *to,
	const git_signature *committer)
{
	git_note *note = NULL;
	git_oid note_id;
	git_signature *who = NULL;
	int error;

	if ((error = git_note_read(&note, rebase->repo, notes_ref, from)) < 0) {
		if (error == GIT_ENOTFOUND) {
			giterr_clear();
			error = 0;
		}

		goto done;
	}

	if (!committer) {
		if((error = git_signature_default(&who, rebase->repo)) < 0) {
			if (error != GIT_ENOTFOUND ||
				(error = git_signature_now(&who, "unknown", "unknown")) < 0)
				goto done;

			giterr_clear();
		}

		committer = who;
	}

	error = git_note_create(&note_id, rebase->repo, notes_ref,
		git_note_author(note), committer, to, git_note_message(note), 0);

done:
	git_note_free(note);
	git_signature_free(who);

	return error;
}
Example #10
0
bool QGit::gitRepositoryDefaultSignature(const QDir &path, QString &name, QString &email)
{
    git_repository *repo = nullptr;
    git_signature *me = nullptr;
    int result = 0;
    bool ret = false;

    result = git_repository_open(&repo, path.absolutePath().toUtf8().constData());
    if (result)
    {
        goto cleanup;
    }

    result = git_signature_default(&me, repo);
    if (result)
    {
        goto cleanup;
    }

    name = me->name;
    email = me->email;

    ret = true;

cleanup:
    if (me)
    {
        git_signature_free(me);
        me = nullptr;
    }

    if (repo)
    {
        git_repository_free(repo);
        repo = nullptr;
    }

    return ret;
}
Example #11
0
File: init.c Project: Arhzi/libgit2
void test_repo_init__init_with_initial_commit(void)
{
	git_index *index;

	cl_set_cleanup(&cleanup_repository, "committed");

	/* Initialize the repository */
	cl_git_pass(git_repository_init(&_repo, "committed", 0));

	/* Index will be automatically created when requested for a new repo */
	cl_git_pass(git_repository_index(&index, _repo));

	/* Create a file so we can commit it
	 *
	 * If you are writing code outside the test suite, you can create this
	 * file any way that you like, such as:
	 *      FILE *fp = fopen("committed/file.txt", "w");
	 *      fputs("some stuff\n", fp);
	 *      fclose(fp);
	 * We like to use the help functions because they do error detection
	 * in a way that's easily compatible with our test suite.
	 */
	cl_git_mkfile("committed/file.txt", "some stuff\n");

	/* Add file to the index */
	cl_git_pass(git_index_add_bypath(index, "file.txt"));
	cl_git_pass(git_index_write(index));

	/* Intentionally not using cl_repo_commit_from_index here so this code
	 * can be used as an example of how an initial commit is typically
	 * made to a repository...
	 */

	/* Make sure we're ready to use git_signature_default :-) */
	{
		git_config *cfg, *local;
		cl_git_pass(git_repository_config(&cfg, _repo));
		cl_git_pass(git_config_open_level(&local, cfg, GIT_CONFIG_LEVEL_LOCAL));
		cl_git_pass(git_config_set_string(local, "user.name", "Test User"));
		cl_git_pass(git_config_set_string(local, "user.email", "*****@*****.**"));
		git_config_free(local);
		git_config_free(cfg);
	}

	/* Create a commit with the new contents of the index */
	{
		git_signature *sig;
		git_oid tree_id, commit_id;
		git_tree *tree;

		cl_git_pass(git_signature_default(&sig, _repo));
		cl_git_pass(git_index_write_tree(&tree_id, index));
		cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id));

		cl_git_pass(git_commit_create_v(
			&commit_id, _repo, "HEAD", sig, sig,
			NULL, "First", tree, 0));

		git_tree_free(tree);
		git_signature_free(sig);
	}

	git_index_free(index);
}
Example #12
0
static int try_to_git_merge(git_repository *repo, git_reference *local, git_reference *remote, git_oid *base, const git_oid *local_id, const git_oid *remote_id)
{
	git_tree *local_tree, *remote_tree, *base_tree;
	git_commit *local_commit, *remote_commit, *base_commit;
	git_index *merged_index;
	git_merge_options merge_options;

	if (verbose) {
		char outlocal[41], outremote[41];
		outlocal[40] = outremote[40] = 0;
		git_oid_fmt(outlocal, local_id);
		git_oid_fmt(outremote, remote_id);
		fprintf(stderr, "trying to merge local SHA %s remote SHA %s\n", outlocal, outremote);
	}

	git_merge_init_options(&merge_options, GIT_MERGE_OPTIONS_VERSION);
#ifdef USE_LIBGIT23_API
	merge_options.tree_flags = GIT_MERGE_TREE_FIND_RENAMES;
#else
	merge_options.flags = GIT_MERGE_TREE_FIND_RENAMES;
#endif
	merge_options.file_favor = GIT_MERGE_FILE_FAVOR_UNION;
	merge_options.rename_threshold = 100;
	if (git_commit_lookup(&local_commit, repo, local_id))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: can't get commit (%s)"), giterr_last()->message);
	if (git_commit_tree(&local_tree, local_commit))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: failed local tree lookup (%s)"), giterr_last()->message);
	if (git_commit_lookup(&remote_commit, repo, remote_id))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: can't get commit (%s)"), giterr_last()->message);
	if (git_commit_tree(&remote_tree, remote_commit))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: failed remote tree lookup (%s)"), giterr_last()->message);
	if (git_commit_lookup(&base_commit, repo, base))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: can't get commit: (%s)"), giterr_last()->message);
	if (git_commit_tree(&base_tree, base_commit))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: failed base tree lookup: (%s)"), giterr_last()->message);
	if (git_merge_trees(&merged_index, repo, base_tree, local_tree, remote_tree, &merge_options))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge failed (%s)"), giterr_last()->message);
	if (git_index_has_conflicts(merged_index)) {
		int error;
		const git_index_entry *ancestor = NULL,
				*ours = NULL,
				*theirs = NULL;
		git_index_conflict_iterator *iter = NULL;
		error = git_index_conflict_iterator_new(&iter, merged_index);
		while (git_index_conflict_next(&ancestor, &ours, &theirs, iter)
		       != GIT_ITEROVER) {
			/* Mark this conflict as resolved */
			fprintf(stderr, "conflict in %s / %s / %s -- ",
				ours ? ours->path : "-",
				theirs ? theirs->path : "-",
				ancestor ? ancestor->path : "-");
			if ((!ours && theirs && ancestor) ||
			    (ours && !theirs && ancestor)) {
				// the file was removed on one side or the other - just remove it
				fprintf(stderr, "looks like a delete on one side; removing the file from the index\n");
				error = git_index_remove(merged_index, ours ? ours->path : theirs->path, GIT_INDEX_STAGE_ANY);
			} else {
				error = git_index_conflict_remove(merged_index, ours ? ours->path : theirs ? theirs->path : ancestor->path);
			}
			if (error) {
				fprintf(stderr, "error at conflict resplution (%s)", giterr_last()->message);
			}
		}
		git_index_conflict_cleanup(merged_index);
		git_index_conflict_iterator_free(iter);
		report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge conflict - manual intervention needed"));
	}
	git_oid merge_oid, commit_oid;
	git_tree *merged_tree;
	git_signature *author;
	git_commit *commit;

	if (git_index_write_tree_to(&merge_oid, merged_index, repo))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: writing the tree failed (%s)"), giterr_last()->message);
	if (git_tree_lookup(&merged_tree, repo, &merge_oid))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: tree lookup failed (%s)"), giterr_last()->message);
	if (git_signature_default(&author, repo) < 0)
		return report_error(translate("gettextFromC", "Failed to get author: (%s)"), giterr_last()->message);
	if (git_commit_create_v(&commit_oid, repo, NULL, author, author, NULL, "automatic merge", merged_tree, 2, local_commit, remote_commit))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: git commit create failed (%s)"), giterr_last()->message);
	if (git_commit_lookup(&commit, repo, &commit_oid))
		return report_error(translate("gettextFromC", "Error: could not lookup the merge commit I just created (%s)"), giterr_last()->message);
	if (git_branch_is_head(local) && !git_repository_is_bare(repo)) {
		git_object *parent;
		git_reference_peel(&parent, local, GIT_OBJ_COMMIT);
		if (update_git_checkout(repo, parent, merged_tree)) {
			report_error("Warning: checked out branch is inconsistent with git data");
		}
	}
	if (git_reference_set_target(&local, local, &commit_oid, "Subsurface merge event"))
		return report_error("Error: failed to update branch (%s)", giterr_last()->message);
	set_git_id(&commit_oid);
	git_signature_free(author);

	return 0;
}
Example #13
0
static int try_to_git_merge(git_repository *repo, git_reference **local_p, git_reference *remote, git_oid *base, const git_oid *local_id, const git_oid *remote_id)
{
	UNUSED(remote);
	git_tree *local_tree, *remote_tree, *base_tree;
	git_commit *local_commit, *remote_commit, *base_commit;
	git_index *merged_index;
	git_merge_options merge_options;

	if (verbose) {
		char outlocal[41], outremote[41];
		outlocal[40] = outremote[40] = 0;
		git_oid_fmt(outlocal, local_id);
		git_oid_fmt(outremote, remote_id);
		fprintf(stderr, "trying to merge local SHA %s remote SHA %s\n", outlocal, outremote);
	}

	git_merge_init_options(&merge_options, GIT_MERGE_OPTIONS_VERSION);
#if !LIBGIT2_VER_MAJOR && LIBGIT2_VER_MINOR > 23
	merge_options.flags = GIT_MERGE_FIND_RENAMES;
#else
	merge_options.tree_flags = GIT_MERGE_TREE_FIND_RENAMES;
#endif
	merge_options.file_favor = GIT_MERGE_FILE_FAVOR_UNION;
	merge_options.rename_threshold = 100;
	if (git_commit_lookup(&local_commit, repo, local_id)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: can't get commit (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_tree(&local_tree, local_commit)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: failed local tree lookup (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_lookup(&remote_commit, repo, remote_id)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: can't get commit (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_tree(&remote_tree, remote_commit)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: failed local tree lookup (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_lookup(&base_commit, repo, base)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: can't get commit (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_tree(&base_tree, base_commit)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: failed base tree lookup (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_merge_trees(&merged_index, repo, base_tree, local_tree, remote_tree, &merge_options)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: merge failed (%s)", giterr_last()->message);
		// this is the one where I want to report more detail to the user - can't quite explain why
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge failed (%s)"), giterr_last()->message);
	}
	if (git_index_has_conflicts(merged_index)) {
		int error;
		const git_index_entry *ancestor = NULL,
				*ours = NULL,
				*theirs = NULL;
		git_index_conflict_iterator *iter = NULL;
		error = git_index_conflict_iterator_new(&iter, merged_index);
		while (git_index_conflict_next(&ancestor, &ours, &theirs, iter)
		       != GIT_ITEROVER) {
			/* Mark this conflict as resolved */
			fprintf(stderr, "conflict in %s / %s / %s -- ",
				ours ? ours->path : "-",
				theirs ? theirs->path : "-",
				ancestor ? ancestor->path : "-");
			if ((!ours && theirs && ancestor) ||
			    (ours && !theirs && ancestor)) {
				// the file was removed on one side or the other - just remove it
				fprintf(stderr, "looks like a delete on one side; removing the file from the index\n");
				error = git_index_remove(merged_index, ours ? ours->path : theirs->path, GIT_INDEX_STAGE_ANY);
			} else if (ancestor) {
				error = git_index_conflict_remove(merged_index, ours ? ours->path : theirs ? theirs->path : ancestor->path);
			}
			if (error) {
				fprintf(stderr, "error at conflict resplution (%s)", giterr_last()->message);
			}
		}
		git_index_conflict_cleanup(merged_index);
		git_index_conflict_iterator_free(iter);
		report_error(translate("gettextFromC", "Remote storage and local data diverged. Cannot combine local and remote changes"));
	}
	git_oid merge_oid, commit_oid;
	git_tree *merged_tree;
	git_signature *author;
	git_commit *commit;

	if (git_index_write_tree_to(&merge_oid, merged_index, repo))
		goto write_error;
	if (git_tree_lookup(&merged_tree, repo, &merge_oid))
		goto write_error;
	if (git_signature_default(&author, repo) < 0)
		if (git_signature_now(&author, "Subsurface", "noemail@given") < 0)
			goto write_error;
	if (git_commit_create_v(&commit_oid, repo, NULL, author, author, NULL, "automatic merge", merged_tree, 2, local_commit, remote_commit))
		goto write_error;
	if (git_commit_lookup(&commit, repo, &commit_oid))
		goto write_error;
	if (git_branch_is_head(*local_p) && !git_repository_is_bare(repo)) {
		git_object *parent;
		git_reference_peel(&parent, *local_p, GIT_OBJ_COMMIT);
		if (update_git_checkout(repo, parent, merged_tree)) {
			goto write_error;
		}
	}
	if (git_reference_set_target(local_p, *local_p, &commit_oid, "Subsurface merge event"))
		goto write_error;
	set_git_id(&commit_oid);
	git_signature_free(author);
	if (verbose)
		fprintf(stderr, "Successfully merged repositories");
	return 0;

diverged_error:
	return report_error(translate("gettextFromC", "Remote storage and local data diverged"));

write_error:
	return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: writing the data failed (%s)"), giterr_last()->message);
}
Example #14
0
void QGit::stashSave(QString name)
{
    git_repository *repo = nullptr;
    git_reference *head = nullptr;
    //git_commit *commit = nullptr;
    git_signature *me = nullptr;
    //git_index *index = nullptr;
    git_oid *oid = nullptr;

    QStringList stashes;
    int res = 0;

    QGitError error;

    try {

        res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData());
        if (res)
        {
            throw QGitError("git_repository_open", res);
        }

        res = git_signature_default(&me, repo);
        if (res)
        {
            throw QGitError("git_signature_default", res);
        }

        res = git_repository_head(&head, repo);
        if (res)
        {
            throw QGitError("git_repository_head", res);
        }

        // TODO: Check if we have memory leak here!
        oid = const_cast<git_oid *>(git_reference_target(head));
        if (!oid)
        {
            throw QGitError("git_reference_target returned NULL", 0);
        }

        res = git_stash_save(oid, repo, me, name.toUtf8().constData(), 0);
        if (res)
        {
            throw QGitError("git_stash_save", res);
        }

    } catch(const QGitError &ex) {
        error = ex;
    }

    emit stashSaveReply(error);

    if (oid)
    {
        // TODO: Check if we need to free memory here!
        //git_oid_shorten_free();
        oid = nullptr;
    }

    if (head)
    {
        git_reference_delete(head);
        head = nullptr;
    }

    if (me)
    {
        git_signature_free(me);
        me = nullptr;
    }

    if (repo)
    {
        git_repository_free(repo);
        repo = nullptr;
    }
}
Example #15
0
void QGit::commit(QString message)
{
    git_repository *repo = nullptr;
    git_signature *me = nullptr;
    git_commit *parent = nullptr;
    git_index *index = nullptr;
    git_tree *tree = nullptr;
    git_oid new_commit_id = { {0} };
    git_oid parent_id = { {0} };
    git_oid tree_id = { {0} };
    git_object *git_obj = nullptr;
    git_diff *diff = nullptr;
    size_t _count = 0;
    int unborn = 0;
    int res = 0;

    QGitError error;

    try {

        res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData());
        if (res)
        {
            throw QGitError("git_repository_open", res);
        }

        /// Check if somthing is staged
        res = git_revparse_single(&git_obj, repo, "HEAD^{tree}");
        if (res)
        {
            throw QGitError("git_revparse_single(staged)", res);
        }

        res = git_tree_lookup(&tree, repo, git_object_id(git_obj));
        if (res)
        {
            throw QGitError("git_tree_lookup(staged)", res);
        }

        res = git_diff_tree_to_index(&diff, repo, tree, nullptr, nullptr);
        if (res)
        {
            throw QGitError("git_diff_tree_to_index(staged)", res);
        }

        _count = git_diff_num_deltas(diff);

        if (_count == 0)
        {
            throw QGitError("Nothing staged.", res);
        }

        if (tree)
        {
            git_tree_free(tree);
            tree = nullptr;
        }
        /// Check end

        res = git_signature_default(&me, repo);
        if (res)
        {
            throw QGitError("git_signature_default", res);
        }

        res = git_repository_index(&index, repo);
        if (res)
        {
            throw QGitError("git_repository_index", res);
        }

        res = git_index_write_tree(&tree_id, index);
        if (res)
        {
            throw QGitError("git_index_write_tree", res);
        }

        res = git_tree_lookup(&tree, repo, &tree_id);
        if (res)
        {
            throw QGitError("git_tree_lookup", res);
        }

        unborn = git_repository_head_unborn(repo);
        if (unborn)
        {
            res = git_commit_create_v(
              &new_commit_id,
              repo,
              "HEAD",                        /* name of ref to update */
              me,                            /* author */
              me,                            /* committer */
              nullptr,                       /* nullptr = UTF-8 message encoding */
              message.toUtf8().constData(),  /* message */
              tree,                          /* root tree */
              0);                            /* parent count */
            if (res)
            {
                throw QGitError("git_commit_create_v", res);
            }
        }
        else
        {
            res = git_reference_name_to_id(&parent_id, repo, "HEAD");
            if (res)
            {
                throw QGitError("git_reference_name_to_id", res);
            }

            res = git_commit_lookup(&parent, repo, &parent_id);
            if (res)
            {
                throw QGitError("git_commit_lookup", res);
            }

            res = git_commit_create_v(
              &new_commit_id,
              repo,
              "HEAD",                        /* name of ref to update */
              me,                            /* author */
              me,                            /* committer */
              nullptr,                       /* nullptr = UTF-8 message encoding */
              message.toUtf8().constData(),  /* message */
              tree,                          /* root tree */
              1,                             /* parent count */
              parent);                       /* parent */
            if (res)
            {
                throw QGitError("git_commit_create_v", res);
            }
        }

    } catch(const QGitError &ex) {
        error = ex;
    }

    emit commitReply(QString::fromUtf8(reinterpret_cast<const char *>(new_commit_id.id)), error);

    if (parent)
    {
        git_commit_free(parent);
        parent = nullptr;
    }


    if (index)
    {
        git_index_free(index);
        index = nullptr;
    }

    if (tree)
    {
        git_tree_free(tree);
        tree = nullptr;
    }

    if (me)
    {
        git_signature_free(me);
        me = nullptr;
    }

    if (diff)
    {
        git_diff_free(diff);
        diff = nullptr;
    }

    if (git_obj)
    {
        git_object_free(git_obj);
        git_obj = nullptr;
    }

    if (repo)
    {
        git_repository_free(repo);
        repo = nullptr;
    }
}