Esempio n. 1
0
int git_commit_create(
		git_oid *oid,
		git_repository *repo,
		const char *update_ref,
		const git_signature *author,
		const git_signature *committer,
		const char *message_encoding,
		const char *message,
		const git_tree *tree,
		int parent_count,
		const git_commit *parents[])
{
	git_buf commit = GIT_BUF_INIT;
	int i;
	git_odb *odb;

	assert(git_object_owner((const git_object *)tree) == repo);

	git_oid__writebuf(&commit, "tree ", git_object_id((const git_object *)tree));

	for (i = 0; i < parent_count; ++i) {
		assert(git_object_owner((const git_object *)parents[i]) == repo);
		git_oid__writebuf(&commit, "parent ", git_object_id((const git_object *)parents[i]));
	}

	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(oid, odb, commit.ptr, commit.size, GIT_OBJ_COMMIT) < 0)
		goto on_error;

	git_buf_free(&commit);

	if (update_ref != NULL)
		return git_reference__update(repo, oid, update_ref);

	return 0;

on_error:
	git_buf_free(&commit);
	giterr_set(GITERR_OBJECT, "Failed to create commit.");
	return -1;
}
Esempio n. 2
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;
}
Esempio n. 3
0
static int handle_colon_syntax(
	git_object **out,
	git_object *obj,
	const char *path)
{
	git_object *tree;
	int error = -1;
	git_tree_entry *entry = NULL;

	if ((error = git_object_peel(&tree, obj, GIT_OBJ_TREE)) < 0)
		return error == GIT_ENOTFOUND ? GIT_EINVALIDSPEC : error;

	if (*path == '\0') {
		*out = tree;
		return 0;
	}

	/*
	 * TODO: Handle the relative path syntax
	 * (:./relative/path and :../relative/path)
	 */
	if ((error = git_tree_entry_bypath(&entry, (git_tree *)tree, path)) < 0)
		goto cleanup;

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

cleanup:
	git_tree_entry_free(entry);
	git_object_free(tree);

	return error;
}
int git_branch_create(
	git_reference **ref_out,
	git_repository *repository,
	const char *branch_name,
	const git_commit *commit,
	int force)
{
	git_reference *branch = NULL;
	git_buf canonical_branch_name = GIT_BUF_INIT;
	int error = -1;

	assert(branch_name && commit && ref_out);
	assert(git_object_owner((const git_object *)commit) == repository);

	if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
		goto cleanup;

	error = git_reference_create(&branch, repository,
		git_buf_cstr(&canonical_branch_name), git_commit_id(commit), force);

	if (!error)
		*ref_out = branch;

cleanup:
	git_buf_free(&canonical_branch_name);
	return error;
}
Esempio n. 5
0
int git_branch_create(
		git_reference **ref_out,
		git_repository *repository,
		const char *branch_name,
		const git_object *target,
		int force)
{
	git_object *commit = NULL;
	git_reference *branch = NULL;
	git_buf canonical_branch_name = GIT_BUF_INIT;
	int error = -1;

	assert(branch_name && target && ref_out);
	assert(git_object_owner(target) == repository);

	if (git_object_peel(&commit, (git_object *)target, GIT_OBJ_COMMIT) < 0)
		return create_error_invalid("The given target does not resolve to a commit");

	if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
		goto cleanup;

	error = git_reference_create_oid(&branch, repository,
		git_buf_cstr(&canonical_branch_name), git_object_id(commit), force);

	if (!error)
		*ref_out = branch;

cleanup:
	git_object_free(commit);
	git_buf_free(&canonical_branch_name);
	return error;
}
Esempio n. 6
0
int git_branch_create(
		git_oid *oid_out,
		git_repository *repo,
		const char *branch_name,
		const git_object *target,
		int force)
{
	git_otype target_type = GIT_OBJ_BAD;
	git_object *commit = NULL;
	git_reference *branch = NULL;
	git_buf canonical_branch_name = GIT_BUF_INIT;
	int error = -1;

	assert(repo && branch_name && target && oid_out);

	if (git_object_owner(target) != repo)
		return create_error_invalid("The given target does not belong to this repository");

	target_type = git_object_type(target);

	switch (target_type)
	{
	case GIT_OBJ_TAG:
		if (git_tag_peel(&commit, (git_tag *)target) < 0)
			goto cleanup;

		if (git_object_type(commit) != GIT_OBJ_COMMIT) {
			create_error_invalid("The given target does not resolve to a commit");
			goto cleanup;
		}
		break;

	case GIT_OBJ_COMMIT:
		commit = (git_object *)target;
		break;

	default:
		return create_error_invalid("Only git_tag and git_commit objects are valid targets.");
	}

	if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
		goto cleanup;

	if (git_reference_create_oid(&branch, repo, git_buf_cstr(&canonical_branch_name), git_object_id(commit), force) < 0)
		goto cleanup;

	git_oid_cpy(oid_out, git_reference_oid(branch));
	error = 0;

cleanup:
	if (target_type == GIT_OBJ_TAG)
		git_object_free(commit);

	git_reference_free(branch);
	git_buf_free(&canonical_branch_name);
	return error;
}
Esempio n. 7
0
static VALUE rb_git_tag_target_SET(VALUE self, VALUE val)
{
	git_tag *tag;
	git_object *target;
	Data_Get_Struct(self, git_tag, tag);

	target = rugged_object_rb2c(git_object_owner((git_object *)tag), val, GIT_OBJ_ANY);
	git_tag_set_target(tag, target);
	return Qnil;
}
Esempio n. 8
0
static VALUE rb_git_commit_tree_SET(VALUE self, VALUE val)
{
    git_commit *commit;
    git_tree *tree;
    Data_Get_Struct(self, git_commit, commit);

    tree = (git_tree *)rugged_object_rb2c(git_object_owner((git_object *)commit), val, GIT_OBJ_TREE);
    git_commit_set_tree(commit, tree);
    return Qnil;
}
Esempio n. 9
0
static VALUE rb_git_commit_tree_SET(VALUE self, VALUE val)
{
	git_commit *commit;
	git_tree *tree;
	RUGGED_OBJ_UNWRAP(self, git_commit, commit);

	tree = (git_tree *)rugged_object_get(git_object_owner((git_object *)commit), val, GIT_OBJ_TREE);
	git_commit_set_tree(commit, tree);
	return Qnil;
}
Esempio n. 10
0
static VALUE rb_git_tag_target_SET(VALUE self, VALUE val)
{
	git_tag *tag;
	git_object *target;
	RUGGED_OBJ_UNWRAP(self, git_tag, tag);

	target = rugged_object_get(git_object_owner((git_object *)tag), val, GIT_OBJ_ANY);
	git_tag_set_target(tag, target);
	return Qnil;
}
Esempio n. 11
0
/**
 * ggit_object_get_owner:
 * @object: a #GgitObject.
 *
 * Gets the #GgitRepository that owns @object.
 *
 * Returns: (transfer full): the #GgitRepository that owns this object.
 * The returned value must be free'd calling g_object_unref().
 */
GgitRepository *
ggit_object_get_owner (GgitObject *object)
{
	git_repository *repository;

	g_return_val_if_fail (GGIT_IS_OBJECT (object), NULL);

	repository = git_object_owner (object->priv->obj);

	return _ggit_repository_new (repository);
}
Esempio n. 12
0
static int create_branch(
	git_reference **ref_out,
	git_repository *repository,
	const char *branch_name,
	const git_commit *commit,
	const char *from,
	int force)
{
	int is_unmovable_head = 0;
	git_reference *branch = NULL;
	git_buf canonical_branch_name = GIT_BUF_INIT,
			  log_message = GIT_BUF_INIT;
	int error = -1;
	int bare = git_repository_is_bare(repository);

	assert(branch_name && commit && ref_out);
	assert(git_object_owner((const git_object *)commit) == repository);

	if (force && !bare && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) {
		error = git_branch_is_head(branch);
		git_reference_free(branch);
		branch = NULL;

		if (error < 0)
			goto cleanup;

		is_unmovable_head = error;
	}

	if (is_unmovable_head && force) {
		giterr_set(GITERR_REFERENCE, "Cannot force update branch '%s' as it is "
			"the current HEAD of the repository.", branch_name);
		error = -1;
		goto cleanup;
	}

	if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
		goto cleanup;

	if (git_buf_printf(&log_message, "branch: Created from %s", from) < 0)
		goto cleanup;

	error = git_reference_create(&branch, repository,
		git_buf_cstr(&canonical_branch_name), git_commit_id(commit), force,
		git_buf_cstr(&log_message));

	if (!error)
		*ref_out = branch;

cleanup:
	git_buf_free(&canonical_branch_name);
	git_buf_free(&log_message);
	return error;
}
static int blob_content_to_file(
	git_blob *blob,
	const char *path,
	mode_t entry_filemode,
	git_checkout_opts *opts)
{
	int error = -1, nb_filters = 0;
	mode_t file_mode = opts->file_mode;
	bool dont_free_filtered = false;
	git_buf unfiltered = GIT_BUF_INIT, filtered = GIT_BUF_INIT;
	git_vector filters = GIT_VECTOR_INIT;

	if (opts->disable_filters ||
		(nb_filters = git_filters_load(
			&filters,
			git_object_owner((git_object *)blob),
			path,
			GIT_FILTER_TO_WORKTREE)) == 0) {

		/* Create a fake git_buf from the blob raw data... */
		filtered.ptr = blob->odb_object->raw.data;
		filtered.size = blob->odb_object->raw.len;

		/* ... and make sure it doesn't get unexpectedly freed */
		dont_free_filtered = true;
	}

	if (nb_filters < 0)
		return nb_filters;

	if (nb_filters > 0)	 {
		if ((error = git_blob__getbuf(&unfiltered, blob)) < 0)
			goto cleanup;

		if ((error = git_filters_apply(&filtered, &unfiltered, &filters)) < 0)
			goto cleanup;
	}

	/* Allow overriding of file mode */
	if (!file_mode)
		file_mode = entry_filemode;

	error = buffer_to_file(&filtered, path, opts->dir_mode, opts->file_open_flags, file_mode);

cleanup:
	git_filters_free(&filters);
	git_buf_free(&unfiltered);
	if (!dont_free_filtered)
		git_buf_free(&filtered);

	return error;
}
Esempio n. 14
0
void reset_index_to_treeish(git_object *treeish)
{
	git_object *tree;
	git_index *index;
	git_repository *repo = git_object_owner(treeish);

	cl_git_pass(git_object_peel(&tree, treeish, GIT_OBJ_TREE));

	cl_git_pass(git_repository_index(&index, repo));
	cl_git_pass(git_index_read_tree(index, (git_tree *)tree));
	cl_git_pass(git_index_write(index));

	git_object_free(tree);
	git_index_free(index);
}
Esempio n. 15
0
static int git_tag_create__internal(
    git_oid *oid,
    git_repository *repo,
    const char *tag_name,
    const git_object *target,
    const git_signature *tagger,
    const char *message,
    int allow_ref_overwrite,
    int create_tag_annotation)
{
    git_reference *new_ref = NULL;
    git_buf ref_name = GIT_BUF_INIT;

    int error;

    assert(repo && tag_name && target);
    assert(!create_tag_annotation || (tagger && message));

    if (git_object_owner(target) != repo) {
        giterr_set(GITERR_INVALID, "The given target does not belong to this repository");
        return -1;
    }

    error = retrieve_tag_reference_oid(oid, &ref_name, repo, tag_name);
    if (error < 0 && error != GIT_ENOTFOUND)
        goto cleanup;

    /** Ensure the tag name doesn't conflict with an already existing
     *	reference unless overwriting has explicitly been requested **/
    if (error == 0 && !allow_ref_overwrite) {
        git_buf_free(&ref_name);
        giterr_set(GITERR_TAG, "Tag already exists");
        return GIT_EEXISTS;
    }

    if (create_tag_annotation) {
        if (write_tag_annotation(oid, repo, tag_name, target, tagger, message) < 0)
            return -1;
    } else
        git_oid_cpy(oid, git_object_id(target));

    error = git_reference_create(&new_ref, repo, ref_name.ptr, oid, allow_ref_overwrite, NULL);

cleanup:
    git_reference_free(new_ref);
    git_buf_free(&ref_name);
    return error;
}
Esempio n. 16
0
static int handle_caret_curly_syntax(git_object **out, git_object *obj, const char *curly_braces_content)
{
	git_otype expected_type;

	if (*curly_braces_content == '\0')
		return dereference_to_non_tag(out, obj);

	if (*curly_braces_content == '/')
		return handle_grep_syntax(out, git_object_owner(obj), git_object_id(obj), curly_braces_content + 1);

	expected_type = parse_obj_type(curly_braces_content);

	if (expected_type == GIT_OBJ_BAD)
		return GIT_EINVALIDSPEC;

	return git_object_peel(out, obj, expected_type);
}
Esempio n. 17
0
int git_object_short_id(git_buf *out, const git_object *obj)
{
	git_repository *repo;
	int len = GIT_ABBREV_DEFAULT, error;
	git_oid id = {{0}};
	git_odb *odb;

	assert(out && obj);

	git_buf_sanitize(out);
	repo = git_object_owner(obj);

	if ((error = git_repository__cvar(&len, repo, GIT_CVAR_ABBREV)) < 0)
		return error;

	if ((error = git_repository_odb(&odb, repo)) < 0)
		return error;

	while (len < GIT_OID_HEXSZ) {
		/* set up short oid */
		memcpy(&id.id, &obj->cached.oid.id, (len + 1) / 2);
		if (len & 1)
			id.id[len / 2] &= 0xf0;

		error = git_odb_exists_prefix(NULL, odb, &id, len);
		if (error != GIT_EAMBIGUOUS)
			break;

		giterr_clear();
		len++;
	}

	if (!error && !(error = git_buf_grow(out, len + 1))) {
		git_oid_tostr(out->ptr, len + 1, &id);
		out->size = len;
	}

	git_odb_free(odb);

	return error;
}
Esempio n. 18
0
int git_reset(
	git_repository *repo,
	const git_object *target,
	git_reset_type reset_type)
{
	git_otype target_type = GIT_OBJ_BAD;
	git_object *commit = NULL;
	git_index *index = NULL;
	git_tree *tree = NULL;
	int error = -1;

	assert(repo && target);
	assert(reset_type == GIT_RESET_SOFT || reset_type == GIT_RESET_MIXED);

	if (git_object_owner(target) != repo)
		return reset_error_invalid("The given target does not belong to this repository.");

	if (reset_type == GIT_RESET_MIXED && git_repository_is_bare(repo))
		return reset_error_invalid("Mixed reset is not allowed in a bare repository.");

	target_type = git_object_type(target);

	switch (target_type)
	{
	case GIT_OBJ_TAG:
		if (git_tag_peel(&commit, (git_tag *)target) < 0)
			goto cleanup;

		if (git_object_type(commit) != GIT_OBJ_COMMIT) {
			reset_error_invalid("The given target does not resolve to a commit.");
			goto cleanup;
		}
		break;

	case GIT_OBJ_COMMIT:
		commit = (git_object *)target;
		break;

	default:
		return reset_error_invalid("Only git_tag and git_commit objects are valid targets.");
	}

	//TODO: Check for unmerged entries

	if (git_reference__update(repo, git_object_id(commit), GIT_HEAD_FILE) < 0)
		goto cleanup;

	if (reset_type == GIT_RESET_SOFT) {
		error = 0;
		goto cleanup;
	}

	if (git_commit_tree(&tree, (git_commit *)commit) < 0) {
		giterr_set(GITERR_OBJECT, "%s - Failed to retrieve the commit tree.", ERROR_MSG);
		goto cleanup;
	}

	if (git_repository_index(&index, repo) < 0) {
		giterr_set(GITERR_OBJECT, "%s - Failed to retrieve the index.", ERROR_MSG);
		goto cleanup;
	}

	if (git_index_read_tree(index, tree) < 0) {
		giterr_set(GITERR_INDEX, "%s - Failed to update the index.", ERROR_MSG);
		goto cleanup;
	}

	if (git_index_write(index) < 0) {
		giterr_set(GITERR_INDEX, "%s - Failed to write the index.", ERROR_MSG);
		goto cleanup;
	}

	error = 0;

cleanup:
	if (target_type == GIT_OBJ_TAG)
		git_object_free(commit);

	git_index_free(index);
	git_tree_free(tree);

	return error;
}
Esempio n. 19
0
int git_reset_default(
	git_repository *repo,
	const git_object *target,
	const git_strarray* pathspecs)
{
	git_object *commit = NULL;
	git_tree *tree = NULL;
	git_diff *diff = NULL;
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
	size_t i, max_i;
	git_index_entry entry;
	int error;
	git_index *index = NULL;

	assert(pathspecs != NULL && pathspecs->count > 0);

	memset(&entry, 0, sizeof(git_index_entry));

	if ((error = git_repository_index(&index, repo)) < 0)
		goto cleanup;

	if (target) {
		if (git_object_owner(target) != repo) {
			giterr_set(GITERR_OBJECT,
				"%s_default - The given target does not belong to this repository.", ERROR_MSG);
			return -1;
		}

		if ((error = git_object_peel(&commit, target, GIT_OBJECT_COMMIT)) < 0 ||
			(error = git_commit_tree(&tree, (git_commit *)commit)) < 0)
			goto cleanup;
	}

	opts.pathspec = *pathspecs;
	opts.flags = GIT_DIFF_REVERSE;

	if ((error = git_diff_tree_to_index(
		&diff, repo, tree, index, &opts)) < 0)
			goto cleanup;

	for (i = 0, max_i = git_diff_num_deltas(diff); i < max_i; ++i) {
		const git_diff_delta *delta = git_diff_get_delta(diff, i);

		assert(delta->status == GIT_DELTA_ADDED ||
			delta->status == GIT_DELTA_MODIFIED ||
			delta->status == GIT_DELTA_CONFLICTED ||
			delta->status == GIT_DELTA_DELETED);

		error = git_index_conflict_remove(index, delta->old_file.path);
		if (error < 0) {
			if (delta->status == GIT_DELTA_ADDED && error == GIT_ENOTFOUND)
				giterr_clear();
			else
				goto cleanup;
		}

		if (delta->status == GIT_DELTA_DELETED) {
			if ((error = git_index_remove(index, delta->old_file.path, 0)) < 0)
				goto cleanup;
		} else {
			entry.mode = delta->new_file.mode;
			git_oid_cpy(&entry.id, &delta->new_file.id);
			entry.path = (char *)delta->new_file.path;

			if ((error = git_index_add(index, &entry)) < 0)
				goto cleanup;
		}
	}

	error = git_index_write(index);

cleanup:
	git_object_free(commit);
	git_tree_free(tree);
	git_index_free(index);
	git_diff_free(diff);

	return error;
}
Esempio n. 20
0
static int reset(
	git_repository *repo,
	const git_object *target,
	const char *to,
	git_reset_t reset_type,
	const git_checkout_options *checkout_opts)
{
	git_object *commit = NULL;
	git_index *index = NULL;
	git_tree *tree = NULL;
	int error = 0;
	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
	git_buf log_message = GIT_BUF_INIT;

	assert(repo && target);

	if (checkout_opts)
		opts = *checkout_opts;

	if (git_object_owner(target) != repo) {
		giterr_set(GITERR_OBJECT,
			"%s - The given target does not belong to this repository.", ERROR_MSG);
		return -1;
	}

	if (reset_type != GIT_RESET_SOFT &&
		(error = git_repository__ensure_not_bare(repo,
			reset_type == GIT_RESET_MIXED ? "reset mixed" : "reset hard")) < 0)
		return error;

	if ((error = git_object_peel(&commit, target, GIT_OBJECT_COMMIT)) < 0 ||
		(error = git_repository_index(&index, repo)) < 0 ||
		(error = git_commit_tree(&tree, (git_commit *)commit)) < 0)
		goto cleanup;

	if (reset_type == GIT_RESET_SOFT &&
		(git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE ||
		 git_index_has_conflicts(index)))
	{
		giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge", ERROR_MSG);
		error = GIT_EUNMERGED;
		goto cleanup;
	}

	if ((error = git_buf_printf(&log_message, "reset: moving to %s", to)) < 0)
		return error;

	if (reset_type == GIT_RESET_HARD) {
		/* overwrite working directory with the new tree */
		opts.checkout_strategy = GIT_CHECKOUT_FORCE;

		if ((error = git_checkout_tree(repo, (git_object *)tree, &opts)) < 0)
			goto cleanup;
	}

	/* move HEAD to the new target */
	if ((error = git_reference__update_terminal(repo, GIT_HEAD_FILE,
		git_object_id(commit), NULL, git_buf_cstr(&log_message))) < 0)
		goto cleanup;

	if (reset_type > GIT_RESET_SOFT) {
		/* reset index to the target content */

		if ((error = git_index_read_tree(index, tree)) < 0 ||
			(error = git_index_write(index)) < 0)
			goto cleanup;

		if ((error = git_repository_state_cleanup(repo)) < 0) {
			giterr_set(GITERR_INDEX, "%s - failed to clean up merge data", ERROR_MSG);
			goto cleanup;
		}
	}

cleanup:
	git_object_free(commit);
	git_index_free(index);
	git_tree_free(tree);
	git_buf_dispose(&log_message);

	return error;
}
Esempio n. 21
0
int git_reset(
	git_repository *repo,
	git_object *target,
	git_reset_t reset_type)
{
	git_object *commit = NULL;
	git_index *index = NULL;
	git_tree *tree = NULL;
	int error = 0;
	git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;

	assert(repo && target);

	if (git_object_owner(target) != repo) {
		giterr_set(GITERR_OBJECT,
			"%s - The given target does not belong to this repository.", ERROR_MSG);
		return -1;
	}

	if (reset_type != GIT_RESET_SOFT &&
		(error = git_repository__ensure_not_bare(repo,
			reset_type == GIT_RESET_MIXED ? "reset mixed" : "reset hard")) < 0)
		return error;

	if ((error = git_object_peel(&commit, target, GIT_OBJ_COMMIT)) < 0 ||
		(error = git_repository_index(&index, repo)) < 0 ||
		(error = git_commit_tree(&tree, (git_commit *)commit)) < 0)
		goto cleanup;

	if (reset_type == GIT_RESET_SOFT &&
		(git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE ||
		 git_index_has_conflicts(index)))
	{
		giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge.", ERROR_MSG);
		error = GIT_EUNMERGED;
		goto cleanup;
	}

	/* move HEAD to the new target */
	if ((error = update_head(repo, commit)) < 0)
		goto cleanup;

	if (reset_type == GIT_RESET_HARD) {
		/* overwrite working directory with HEAD */
		opts.checkout_strategy = GIT_CHECKOUT_FORCE;

		if ((error = git_checkout_tree(repo, (git_object *)tree, &opts)) < 0)
			goto cleanup;
	}

	if (reset_type > GIT_RESET_SOFT) {
		/* reset index to the target content */

		if ((error = git_index_read_tree(index, tree)) < 0 ||
			(error = git_index_write(index)) < 0)
			goto cleanup;

		if ((error = git_repository_merge_cleanup(repo)) < 0) {
			giterr_set(GITERR_INDEX, "%s - failed to clean up merge data", ERROR_MSG);
			goto cleanup;
		}
	}

cleanup:
	git_object_free(commit);
	git_index_free(index);
	git_tree_free(tree);

	return error;
}
Esempio n. 22
0
int git_commit_create(
		git_oid *oid,
		git_repository *repo,
		const char *update_ref,
		const git_signature *author,
		const git_signature *committer,
		const char *message_encoding,
		const char *message,
		const git_tree *tree,
		int parent_count,
		const git_commit *parents[])
{
	git_buf commit = GIT_BUF_INIT;
	int error, i;

	if (git_object_owner((const git_object *)tree) != repo)
		return git__throw(GIT_EINVALIDARGS, "The given tree does not belong to this repository");

	git_oid__writebuf(&commit, "tree ", git_object_id((const git_object *)tree));

	for (i = 0; i < parent_count; ++i) {
		if (git_object_owner((const git_object *)parents[i]) != repo) {
			error = git__throw(GIT_EINVALIDARGS, "The given parent does not belong to this repository");
			goto cleanup;
		}

		git_oid__writebuf(&commit, "parent ", git_object_id((const git_object *)parents[i]));
	}

	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');
	git_buf_puts(&commit, message);

	if (git_buf_oom(&commit)) {
		error = git__throw(GIT_ENOMEM, "Not enough memory to build the commit data");
		goto cleanup;
	}

	error = git_odb_write(oid, git_repository_database(repo), commit.ptr, commit.size, GIT_OBJ_COMMIT);
	git_buf_free(&commit);

	if (error == GIT_SUCCESS && update_ref != NULL) {
		git_reference *head;

		error = git_reference_lookup(&head, repo, update_ref);
		if (error < GIT_SUCCESS)
			return git__rethrow(error, "Failed to create commit");

		error = git_reference_resolve(&head, head);
		if (error < GIT_SUCCESS) {
			if (error != GIT_ENOTFOUND)
				return git__rethrow(error, "Failed to create commit");
		/*
		 * The target of the reference was not found. This can happen
		 * just after a repository has been initialized (the master
		 * branch doesn't exist yet, as it doesn't have anything to
		 * point to) or after an orphan checkout, so if the target
		 * branch doesn't exist yet, create it and return.
		 */
			return git_reference_create_oid(&head, repo, git_reference_target(head), oid, 1);
		}

		error = git_reference_set_oid(head, oid);
	}

	if (error < GIT_SUCCESS)
		return git__rethrow(error, "Failed to create commit");

	return GIT_SUCCESS;

cleanup:
	git_buf_free(&commit);
	return error;
}