Esempio n. 1
0
static int validate_tree_and_parents(git_array_oid_t *parents, git_repository *repo, const git_oid *tree,
				     git_commit_parent_callback parent_cb, void *parent_payload,
				     const git_oid *current_id, bool validate)
{
	size_t i;
	int error;
	git_oid *parent_cpy;
	const git_oid *parent;

	if (validate && !git_object__is_valid(repo, tree, GIT_OBJECT_TREE))
		return -1;

	i = 0;
	while ((parent = parent_cb(i, parent_payload)) != NULL) {
		if (validate && !git_object__is_valid(repo, parent, GIT_OBJECT_COMMIT)) {
			error = -1;
			goto on_error;
		}

		parent_cpy = git_array_alloc(*parents);
		GITERR_CHECK_ALLOC(parent_cpy);

		git_oid_cpy(parent_cpy, parent);
		i++;
	}

	if (current_id && (parents->size == 0 || git_oid_cmp(current_id, git_array_get(*parents, 0)))) {
		giterr_set(GITERR_OBJECT, "failed to create commit: current tip is not the first parent");
		error = GIT_EMODIFIED;
		goto on_error;
	}

	return 0;

on_error:
	git_array_clear(*parents);
	return error;
}
Esempio n. 2
0
static int git_commit__create_internal(
    git_oid *id,
    git_repository *repo,
    const char *update_ref,
    const git_signature *author,
    const git_signature *committer,
    const char *message_encoding,
    const char *message,
    const git_oid *tree,
    git_commit_parent_callback parent_cb,
    void *parent_payload,
    bool validate)
{
    git_reference *ref = NULL;
    int error = 0, matched_parent = 0;
    const git_oid *current_id = NULL;
    git_buf commit = GIT_BUF_INIT;
    size_t i = 0;
    git_odb *odb;
    const git_oid *parent;

    assert(id && repo && tree && parent_cb);

    if (validate && !git_object__is_valid(repo, tree, GIT_OBJ_TREE))
        return -1;

    if (update_ref) {
        error = git_reference_lookup_resolved(&ref, repo, update_ref, 10);
        if (error < 0 && error != GIT_ENOTFOUND)
            return error;
    }
    giterr_clear();

    if (ref)
        current_id = git_reference_target(ref);

    git_oid__writebuf(&commit, "tree ", tree);

    while ((parent = parent_cb(i, parent_payload)) != NULL) {
        if (validate && !git_object__is_valid(repo, parent, GIT_OBJ_COMMIT)) {
            error = -1;
            goto on_error;
        }

        git_oid__writebuf(&commit, "parent ", parent);
        if (i == 0 && current_id && git_oid_equal(current_id, parent))
            matched_parent = 1;
        i++;
    }

    if (ref && !matched_parent) {
        git_reference_free(ref);
        git_buf_free(&commit);
        giterr_set(GITERR_OBJECT, "failed to create commit: current tip is not the first parent");
        return GIT_EMODIFIED;
    }

    git_signature__writebuf(&commit, "author ", author);
    git_signature__writebuf(&commit, "committer ", committer);

    if (message_encoding != NULL)
        git_buf_printf(&commit, "encoding %s\n", message_encoding);

    git_buf_putc(&commit, '\n');

    if (git_buf_puts(&commit, message) < 0)
        goto on_error;

    if (git_repository_odb__weakptr(&odb, repo) < 0)
        goto on_error;

    if (git_odb_write(id, odb, commit.ptr, commit.size, GIT_OBJ_COMMIT) < 0)
        goto on_error;

    git_buf_free(&commit);

    if (update_ref != NULL) {
        error = git_reference__update_for_commit(
                    repo, ref, update_ref, id, "commit");
        git_reference_free(ref);
        return error;
    }

    return 0;

on_error:
    git_buf_free(&commit);
    return -1;
}
Esempio n. 3
0
static int reference__create(
	git_reference **ref_out,
	git_repository *repo,
	const char *name,
	const git_oid *oid,
	const char *symbolic,
	int force,
	const git_signature *signature,
	const char *log_message,
	const git_oid *old_id,
	const char *old_target)
{
	git_refname_t normalized;
	git_refdb *refdb;
	git_reference *ref = NULL;
	int error = 0;

	assert(repo && name);
	assert(symbolic || signature);

	if (ref_out)
		*ref_out = NULL;

	error = reference_normalize_for_repo(normalized, repo, name, true);
	if (error < 0)
		return error;

	error = git_repository_refdb__weakptr(&refdb, repo);
	if (error < 0)
		return error;

	if (oid != NULL) {
		assert(symbolic == NULL);

		if (!git_object__is_valid(repo, oid, GIT_OBJ_ANY)) {
			giterr_set(GITERR_REFERENCE,
				"target OID for the reference doesn't exist on the repository");
			return -1;
		}

		ref = git_reference__alloc(normalized, oid, NULL);
	} else {
		git_refname_t normalized_target;

		error = reference_normalize_for_repo(normalized_target, repo,
			symbolic, git_reference__enable_symbolic_ref_target_validation);

		if (error < 0)
			return error;

		ref = git_reference__alloc_symbolic(normalized, normalized_target);
	}

	GITERR_CHECK_ALLOC(ref);

	if ((error = git_refdb_write(refdb, ref, force, signature, log_message, old_id, old_target)) < 0) {
		git_reference_free(ref);
		return error;
	}

	if (ref_out == NULL)
		git_reference_free(ref);
	else
		*ref_out = ref;

	return 0;
}