コード例 #1
0
ファイル: branch.c プロジェクト: ralpheav/PM_GIT
int git_branch_tracking(
		git_reference **tracking_out,
		git_reference *branch)
{
	const char *remote_name, *merge_name;
	git_buf buf = GIT_BUF_INIT;
	int error = -1;
	git_remote *remote = NULL;
	const git_refspec *refspec;

	assert(tracking_out && branch);

	if (!git_reference_is_branch(branch))
		return not_a_local_branch(branch);

	if ((error = retrieve_tracking_configuration(&remote_name, branch, "branch.%s.remote")) < 0)
		goto cleanup;

	if ((error = retrieve_tracking_configuration(&merge_name, branch, "branch.%s.merge")) < 0)
		goto cleanup;

	if (strcmp(".", remote_name) != 0) {
		if ((error = git_remote_load(&remote, git_reference_owner(branch), remote_name)) < 0)
			goto cleanup;

		refspec = git_remote_fetchspec(remote);
		if (refspec == NULL
			|| refspec->src == NULL
			|| refspec->dst == NULL) {
				error = GIT_ENOTFOUND;
				goto cleanup;
		}

		if (git_refspec_transform_r(&buf, refspec, merge_name) < 0)
			goto cleanup;
	} else
		if (git_buf_sets(&buf, merge_name) < 0)
			goto cleanup;

	error = git_reference_lookup(
		tracking_out,
		git_reference_owner(branch),
		git_buf_cstr(&buf));

cleanup:
	git_remote_free(remote);
	git_buf_free(&buf);
	return error;
}
コード例 #2
0
ファイル: rugged_reference.c プロジェクト: Angolier/sonic-pi
/*
 *  call-seq:
 *    reference.log -> [reflog_entry, ...]
 *
 *  Return an array with the log of all modifications to this reference
 *
 *  Each +reflog_entry+ is a hash with the following keys:
 *
 *  - +:id_old+: previous OID before the change
 *  - +:id_new+: OID after the change
 *  - +:committer+: author of the change
 *  - +:message+: message for the change
 *
 *  Example:
 *
 *    reference.log #=> [
 *    # {
 *    #  :id_old => nil,
 *    #  :id_new => '9d09060c850defbc7711d08b57def0d14e742f4e',
 *    #  :committer => {:name => 'Vicent Marti', :email => {'*****@*****.**'}},
 *    #  :message => 'created reference'
 *    # }, ... ]
 */
static VALUE rb_git_reflog(VALUE self)
{
	git_reflog *reflog;
	git_reference *ref;
	int error;
	VALUE rb_log;
	size_t i, ref_count;

	Data_Get_Struct(self, git_reference, ref);

	error = git_reflog_read(&reflog, git_reference_owner(ref), git_reference_name(ref));
	rugged_exception_check(error);

	ref_count = git_reflog_entrycount(reflog);
	rb_log = rb_ary_new2(ref_count);

	for (i = 0; i < ref_count; ++i) {
		const git_reflog_entry *entry =
			git_reflog_entry_byindex(reflog, ref_count - i - 1);

		rb_ary_push(rb_log, reflog_entry_new(entry));
	}

	git_reflog_free(reflog);
	return rb_log;
}
コード例 #3
0
/**
 * ggit_ref_get_log:
 * @ref: a #GgitRef.
 * @error: a #GError for error reporting, or %NULL.
 *
 * Gets the #GgitReflog for @ref. The reflog will be created if it doesn't exist
 * yet.
 *
 * Returns: (transfer full): the reflog.
 */
GgitReflog *
ggit_ref_get_log (GgitRef  *ref,
                  GError  **error)
{
	git_reflog *reflog;
	git_reference *nref;
	gint ret;

	g_return_val_if_fail (GGIT_IS_REF (ref), NULL);
	g_return_val_if_fail (error == NULL || *error == NULL, NULL);

	nref = _ggit_native_get (ref);

	ret = git_reflog_read (&reflog,
	                       git_reference_owner (nref),
	                       git_reference_name (nref));

	if (ret != GIT_OK)
	{
		_ggit_error_set (error, ret);
		return NULL;
	}

	return _ggit_reflog_wrap (ref, reflog);
}
コード例 #4
0
ファイル: reference.c プロジェクト: ridgek/pygit2
int
Reference_oid__set__(Reference *self, PyObject *py_hex)
{
    git_oid oid;
    int err;
    git_reference *new_ref;

    CHECK_REFERENCE_INT(self);

    /* Get the oid */
    err = py_str_to_git_oid_expand(git_reference_owner(self->reference),
                                   py_hex, &oid);
    if (err < 0) {
        Error_set(err);
        return -1;
    }

    /* Set the oid */
    err = git_reference_set_target(&new_ref, self->reference, &oid);
    if (err < 0) {
        Error_set(err);
        return -1;
    }

    git_reference_free(self->reference);
    self->reference = new_ref;
    return 0;
}
コード例 #5
0
ファイル: branch.c プロジェクト: ralpheav/PM_GIT
int git_branch_is_head(
		git_reference *branch)
{
	git_reference *head;
	bool is_same = false;
	int error;

	assert(branch);

	if (!git_reference_is_branch(branch))
		return false;

	error = git_repository_head(&head, git_reference_owner(branch));

	if (error == GIT_EORPHANEDHEAD)
		return false;

	if (error < 0)
		return -1;

	is_same = strcmp(
		git_reference_name(branch),
		git_reference_name(head)) == 0;

	git_reference_free(head);

	return is_same;
}
コード例 #6
0
ファイル: refs.c プロジェクト: DavidMolinari/sonic-pi
static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force,
				 const git_signature *signature, const char *message)
{
	git_refname_t normalized;
	bool should_head_be_updated = false;
	int error = 0;

	assert(ref && new_name && signature);

	if ((error = reference_normalize_for_repo(
			normalized, git_reference_owner(ref), new_name)) < 0)
		return error;


	/* Check if we have to update HEAD. */
	if ((error = git_branch_is_head(ref)) < 0)
		return error;

	should_head_be_updated = (error > 0);

	if ((error = git_refdb_rename(out, ref->db, ref->name, normalized, force, signature, message)) < 0)
		return error;

	/* Update HEAD it was pointing to the reference being renamed */
	if (should_head_be_updated &&
		(error = git_repository_set_head(ref->db->repo, normalized)) < 0) {
		giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference");
		return error;
	}

	return 0;
}
コード例 #7
0
ファイル: ggit-reflog.c プロジェクト: GNOME/libgit2-glib
/**
 * ggit_reflog_rename:
 * @reflog: a #GgitReflog.
 * @new_name: the new name of the reference.
 * @error: a #GError for error reporting, or %NULL.
 *
 * Renames the reflog for to @new_name, on error @error is set.
 */
gboolean
ggit_reflog_rename (GgitReflog  *reflog,
                    const gchar *new_name,
                    GError      **error)
{
	git_reference *nref;
	gint ret;

	g_return_val_if_fail (reflog != NULL, FALSE);
	g_return_val_if_fail (new_name != NULL && *new_name != '\0', FALSE);
	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	nref = _ggit_native_get (reflog->ref);

	ret = git_reflog_rename (git_reference_owner (nref),
	                         git_reference_name (nref),
	                         new_name);

	if (ret != GIT_OK)
	{
		_ggit_error_set (error, ret);
		return FALSE;
	}

	return TRUE;
}
コード例 #8
0
ファイル: branch.c プロジェクト: Angeldude/sonic-pi
int git_branch_is_head(
		const git_reference *branch)
{
	git_reference *head;
	bool is_same = false;
	int error;

	assert(branch);

	if (!git_reference_is_branch(branch))
		return false;

	error = git_repository_head(&head, git_reference_owner(branch));

	if (error == GIT_EUNBORNBRANCH || error == GIT_ENOTFOUND)
		return false;

	if (error < 0)
		return -1;

	is_same = strcmp(
		git_reference_name(branch),
		git_reference_name(head)) == 0;

	git_reference_free(head);

	return is_same;
}
コード例 #9
0
/**
 * ggit_ref_get_owner:
 * @ref: a #GgitRef.
 *
 * Gets the repository where @ref resides.
 *
 * Returns: (transfer full): the repository where a reference resides.
 */
GgitRepository *
ggit_ref_get_owner (GgitRef *ref)
{
	g_return_val_if_fail (ref != NULL, NULL);

	return _ggit_repository_wrap (git_reference_owner (_ggit_native_get (ref)),
	                              FALSE);
}
コード例 #10
0
ファイル: refs.c プロジェクト: DavidMolinari/sonic-pi
int git_reference_peel(
	git_object **peeled,
	git_reference *ref,
	git_otype target_type)
{
	git_reference *resolved = NULL;
	git_object *target = NULL;
	int error;

	assert(ref);

	if (ref->type == GIT_REF_OID) {
		resolved = ref;
	} else {
		if ((error = git_reference_resolve(&resolved, ref)) < 0)
			return peel_error(error, ref, "Cannot resolve reference");
	}

	if (!git_oid_iszero(&resolved->peel)) {
		error = git_object_lookup(&target,
			git_reference_owner(ref), &resolved->peel, GIT_OBJ_ANY);
	} else {
		error = git_object_lookup(&target,
			git_reference_owner(ref), &resolved->target.oid, GIT_OBJ_ANY);
	}

	if (error < 0) {
		peel_error(error, ref, "Cannot retrieve reference target");
		goto cleanup;
	}

	if (target_type == GIT_OBJ_ANY && git_object_type(target) != GIT_OBJ_TAG)
		error = git_object_dup(peeled, target);
	else
		error = git_object_peel(peeled, target, target_type);

cleanup:
	git_object_free(target);

	if (resolved != ref)
		git_reference_free(resolved);

	return error;
}
コード例 #11
0
ファイル: branch.c プロジェクト: Angeldude/sonic-pi
int git_branch_upstream(
	git_reference **tracking_out,
	const git_reference *branch)
{
	int error;
	git_buf tracking_name = GIT_BUF_INIT;

	if ((error = git_branch_upstream_name(&tracking_name,
		git_reference_owner(branch), git_reference_name(branch))) < 0)
			return error;

	error = git_reference_lookup(
		tracking_out,
		git_reference_owner(branch),
		git_buf_cstr(&tracking_name));

	git_buf_free(&tracking_name);
	return error;
}
コード例 #12
0
ファイル: rugged_reference.c プロジェクト: Angolier/sonic-pi
/*
 *  call-seq:
 *    reference.log? -> true or false
 *
 *  Return +true+ if the reference has a reflog, +false+ otherwise.
 */
static VALUE rb_git_has_reflog(VALUE self)
{
	git_reference *ref;
	git_repository *repo;

	Data_Get_Struct(self, git_reference, ref);
	repo = git_reference_owner(ref);

	return git_reference_has_log(repo, git_reference_name(ref)) ? Qtrue : Qfalse;
}
コード例 #13
0
/**
 * ggit_ref_has_log:
 * @ref: a #GgitRef.
 *
 * Get whether @ref has an existing log.
 *
 * Returns: %TRUE if @ref has a log, %FALSE otherwise.
 *
 **/
gboolean
ggit_ref_has_log (GgitRef *ref)
{
	git_reference *nref;

	g_return_val_if_fail (GGIT_IS_REF (ref), FALSE);

	nref = _ggit_native_get (ref);

	return git_reference_has_log (git_reference_owner (nref),
	                              git_reference_name (nref)) == 1;
}
コード例 #14
0
ファイル: revparse.c プロジェクト: ANNAVARAMVENKATESH/libgit2
static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t identifier)
{
	git_reflog *reflog;
	int error = -1;
	size_t numentries;
	const git_reflog_entry *entry;
	bool search_by_pos = (identifier <= 100000000);

	if (git_reflog_read(&reflog, git_reference_owner(ref), git_reference_name(ref)) < 0)
		return -1;

	numentries = git_reflog_entrycount(reflog);

	if (search_by_pos) {
		if (numentries < identifier + 1) {
			giterr_set(
				GITERR_REFERENCE,
				"Reflog for '%s' has only %"PRIuZ" entries, asked for %"PRIuZ,
				git_reference_name(ref), numentries, identifier);

			error = GIT_ENOTFOUND;
			goto cleanup;
		}

		entry = git_reflog_entry_byindex(reflog, identifier);
		git_oid_cpy(oid, git_reflog_entry_id_new(entry));
		error = 0;
		goto cleanup;

	} else {
		size_t i;
		git_time commit_time;

		for (i = 0; i < numentries; i++) {
			entry = git_reflog_entry_byindex(reflog, i);
			commit_time = git_reflog_entry_committer(entry)->when;

			if (commit_time.time > (git_time_t)identifier)
				continue;

			git_oid_cpy(oid, git_reflog_entry_id_new(entry));
			error = 0;
			goto cleanup;
		}

		error = GIT_ENOTFOUND;
	}

cleanup:
	git_reflog_free(reflog);
	return error;
}
コード例 #15
0
ファイル: rugged_reference.c プロジェクト: Angolier/sonic-pi
/*
 *  call-seq:
 *    reference.target_id -> id
 *    reference.target_id -> ref_name
 *
 *  Return the target of +reference+.
 *
 *  If +reference+ is a symbolic reference, it returns the target
 *  reference object.
 *
 *  If +reference+ is a direct reference, it returns the target object.
 *
 *    ref1.type #=> :symbolic
 *    ref1.target #=> #<Rugged::Reference ...>
 *
 *    ref2.type #=> :direct
 *    ref2.target #=> #<Rugged::Commit ...>
 */
static VALUE rb_git_ref_target(VALUE self)
{
	git_reference *ref;

	Data_Get_Struct(self, git_reference, ref);

	if (git_reference_type(ref) == GIT_REF_OID) {
		git_object *target;

		rugged_exception_check(
			git_object_lookup(&target, git_reference_owner(ref), git_reference_target(ref), GIT_OBJ_ANY)
		);
		return rugged_object_new(rugged_owner(self), target);
	} else {
		git_reference *target;

		rugged_exception_check(
			git_reference_lookup(&target, git_reference_owner(ref), git_reference_symbolic_target(ref))
		);

		return rugged_ref_new(rb_cRuggedReference, rugged_owner(self), target);
	}
}
コード例 #16
0
ファイル: branch.c プロジェクト: Angeldude/sonic-pi
int git_branch_move(
	git_reference **out,
	git_reference *branch,
	const char *new_branch_name,
	int force)
{
	git_buf new_reference_name = GIT_BUF_INIT,
	        old_config_section = GIT_BUF_INIT,
	        new_config_section = GIT_BUF_INIT,
	        log_message = GIT_BUF_INIT;
	int error;

	assert(branch && new_branch_name);

	if (!git_reference_is_branch(branch))
		return not_a_local_branch(git_reference_name(branch));

	if ((error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0)
		goto done;

	if ((error = git_buf_printf(&log_message, "branch: renamed %s to %s",
				    git_reference_name(branch), git_buf_cstr(&new_reference_name))) < 0)
			goto done;

	/* first update ref then config so failure won't trash config */

	error = git_reference_rename(
		out, branch, git_buf_cstr(&new_reference_name), force,
		git_buf_cstr(&log_message));
	if (error < 0)
		goto done;

	git_buf_join(&old_config_section, '.', "branch",
		git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR));
	git_buf_join(&new_config_section, '.', "branch", new_branch_name);

	error = git_config_rename_section(
		git_reference_owner(branch),
		git_buf_cstr(&old_config_section),
		git_buf_cstr(&new_config_section));

done:
	git_buf_free(&new_reference_name);
	git_buf_free(&old_config_section);
	git_buf_free(&new_config_section);
	git_buf_free(&log_message);

	return error;
}
コード例 #17
0
ファイル: refs.c プロジェクト: ANNAVARAMVENKATESH/libgit2
int git_reference_rename(
	git_reference **out,
	git_reference *ref,
	const char *new_name,
	int force)
{
	unsigned int normalization_flags;
	char normalized[GIT_REFNAME_MAX];
	bool should_head_be_updated = false;
	int error = 0;
	int reference_has_log;

	normalization_flags = ref->type == GIT_REF_SYMBOLIC ?
		GIT_REF_FORMAT_ALLOW_ONELEVEL : GIT_REF_FORMAT_NORMAL;

	if ((error = git_reference_normalize_name(
			normalized, sizeof(normalized), new_name, normalization_flags)) < 0)
		return error;

	/* Check if we have to update HEAD. */
	if ((error = git_branch_is_head(ref)) < 0)
		return error;

	should_head_be_updated = (error > 0);

	if ((error = git_refdb_rename(out, ref->db, ref->name, new_name, force)) < 0)
		return error;

	/* Update HEAD it was poiting to the reference being renamed. */
	if (should_head_be_updated &&
		(error = git_repository_set_head(ref->db->repo, new_name)) < 0) {
		giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference");
		return error;
	}

	/* Rename the reflog file, if it exists. */
	reference_has_log = git_reference_has_log(ref);
	if (reference_has_log < 0)
		return reference_has_log;

	if (reference_has_log && (error = git_reflog_rename(git_reference_owner(ref), git_reference_name(ref), new_name)) < 0)
		return error;

	return 0;
}
コード例 #18
0
ファイル: branch.c プロジェクト: ralpheav/PM_GIT
static int retrieve_tracking_configuration(
	const char **out, git_reference *branch, const char *format)
{
	git_config *config;
	git_buf buf = GIT_BUF_INIT;
	int error;

	if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0)
		return -1;

	if (git_buf_printf(&buf, format,
		git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
			return -1;

	error = git_config_get_string(out, config, git_buf_cstr(&buf));
	git_buf_free(&buf);
	return error;
}
コード例 #19
0
ファイル: ref_helpers.c プロジェクト: 0CV0/libgit2
int reference_is_packed(git_reference *ref)
{
	git_buf ref_path = GIT_BUF_INIT;
	int packed;

	assert(ref);

	if (git_buf_joinpath(&ref_path,
		git_repository_path(git_reference_owner(ref)),
		git_reference_name(ref)) < 0)
		return -1;

	packed = !git_path_isfile(ref_path.ptr);

	git_buf_free(&ref_path);

	return packed;
}
コード例 #20
0
ファイル: branch.c プロジェクト: ralpheav/PM_GIT
int git_branch_move(
	git_reference *branch,
	const char *new_branch_name,
	int force)
{
	git_buf new_reference_name = GIT_BUF_INIT,
		old_config_section = GIT_BUF_INIT,
		new_config_section = GIT_BUF_INIT;
	int error;

	assert(branch && new_branch_name);

	if (!git_reference_is_branch(branch))
		return not_a_local_branch(branch);

	if ((error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0)
		goto cleanup;

	if (git_buf_printf(
		&old_config_section,
		"branch.%s",
		git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
			goto cleanup;

	if ((error = git_reference_rename(branch, git_buf_cstr(&new_reference_name), force)) < 0)
		goto cleanup;

	if (git_buf_printf(&new_config_section, "branch.%s", new_branch_name) < 0)
		goto cleanup;

	if ((error = git_config_rename_section(
		git_reference_owner(branch), 
		git_buf_cstr(&old_config_section),
		git_buf_cstr(&new_config_section))) < 0)
			goto cleanup;

cleanup:
	git_buf_free(&new_reference_name);
	git_buf_free(&old_config_section);
	git_buf_free(&new_config_section);

	return error;
}
コード例 #21
0
/**
 * ggit_ref_delete_log:
 * @ref: a #GgitRef.
 * @error: a #GError for error reporting, or %NULL.
 *
 * Deletes the log for @ref, on error @error is set.
 */
void
ggit_ref_delete_log (GgitRef  *ref,
                     GError  **error)
{
	git_reference *nref;
	gint ret;

	g_return_if_fail (GGIT_IS_REF (ref));
	g_return_if_fail (error == NULL || *error == NULL);

	nref = _ggit_native_get (ref);

	ret = git_reflog_delete (git_reference_owner (nref),
	                         git_reference_name (nref));

	if (ret != GIT_OK)
	{
		_ggit_error_set (error, ret);
	}
}
int git_branch_delete(git_reference *branch)
{
	int is_head;
	git_buf config_section = GIT_BUF_INIT;
	int error = -1;

	assert(branch);

	if (!git_reference_is_branch(branch) &&
		!git_reference_is_remote(branch)) {
		giterr_set(GITERR_INVALID, "Reference '%s' is not a valid branch.", git_reference_name(branch));
		return -1;
	}

	if ((is_head = git_branch_is_head(branch)) < 0)
		return is_head;

	if (is_head) {
		giterr_set(GITERR_REFERENCE,
				"Cannot delete branch '%s' as it is the current HEAD of the repository.", git_reference_name(branch));
		return -1;
	}

	if (git_buf_printf(&config_section, "branch.%s", git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
		goto on_error;

	if (git_config_rename_section(
		git_reference_owner(branch), 
		git_buf_cstr(&config_section),
		NULL) < 0)
			goto on_error;

	if (git_reference_delete(branch) < 0)
		goto on_error;

	error = 0;

on_error:
	git_buf_free(&config_section);
	return error;
}
コード例 #23
0
ファイル: reference.c プロジェクト: KINFOO/pygit2
PyObject *
Reference_log(Reference *self)
{
    int err;
    RefLogIter *iter;
    git_repository *repo;

    CHECK_REFERENCE(self);

    repo = git_reference_owner(self->reference);
    iter = PyObject_New(RefLogIter, &RefLogIterType);
    if (iter != NULL) {
        err = git_reflog_read(&iter->reflog, repo, git_reference_name(self->reference));
        if (err < 0)
            return Error_set(err);

        iter->size = git_reflog_entrycount(iter->reflog);
        iter->i = 0;
    }
    return (PyObject*)iter;
}
コード例 #24
0
ファイル: refs.c プロジェクト: Nemchinovrp/sonic-pi
static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force,
				 const git_signature *signature, const char *message)
{
	git_repository *repo;
	git_refname_t normalized;
	bool should_head_be_updated = false;
	int error = 0;

	assert(ref && new_name && signature);

	repo = git_reference_owner(ref);

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

	/* Check if we have to update HEAD. */
	if ((error = git_branch_is_head(ref)) < 0)
		return error;

	should_head_be_updated = (error > 0);

	if ((error = git_refdb_rename(out, ref->db, ref->name, normalized, force, signature, message)) < 0)
		return error;

	/* Update HEAD if it was pointing to the reference being renamed */
	if (should_head_be_updated) {
		error = git_repository_set_head(ref->db->repo, normalized);
	} else {
		rename_cb_data payload;
		payload.old_name = ref->name;
		memcpy(&payload.new_name, &normalized, sizeof(normalized));

		error = git_repository_foreach_head(repo, update_wt_heads, &payload);
	}

	return error;
}
コード例 #25
0
/**
 * ggit_ref_lookup:
 * @ref: a #GgitRef.
 * @error: a #GError for error reporting, or %NULL.
 *
 * Convenient method to resolve a reference to an object.
 *
 * Returns: (transfer full): a #GgitObject.
 *
 **/
GgitObject *
ggit_ref_lookup (GgitRef  *ref,
                 GError  **error)
{
	git_object *obj;
	git_reference *r;
	gint ret;
	GgitRef *lref;

	g_return_val_if_fail (GGIT_IS_REF (ref), NULL);
	g_return_val_if_fail (error == NULL || *error == NULL, NULL);

	lref = ggit_ref_resolve (ref, error);

	if (lref == NULL)
	{
		return NULL;
	}

	r = _ggit_native_get (lref);

	ret = git_object_lookup (&obj,
	                         git_reference_owner (r),
	                         git_reference_target (r),
	                         GIT_OBJ_ANY);

	g_object_unref (lref);

	if (ret != GIT_OK)
	{
		_ggit_error_set (error, ret);
		return NULL;
	}

	return ggit_utils_create_real_object (obj, TRUE);
}
コード例 #26
0
ファイル: branch.c プロジェクト: Angeldude/sonic-pi
int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
{
	git_buf key = GIT_BUF_INIT, value = GIT_BUF_INIT;
	git_reference *upstream;
	git_repository *repo;
	git_remote *remote = NULL;
	git_config *config;
	const char *name, *shortname;
	int local, error;
	const git_refspec *fetchspec;

	name = git_reference_name(branch);
	if (!git_reference__is_branch(name))
		return not_a_local_branch(name);

	if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0)
		return -1;

	shortname = name + strlen(GIT_REFS_HEADS_DIR);

	if (upstream_name == NULL)
		return unset_upstream(config, shortname);

	repo = git_reference_owner(branch);

	/* First we need to figure out whether it's a branch or remote-tracking */
	if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_LOCAL) == 0)
		local = 1;
	else if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_REMOTE) == 0)
		local = 0;
	else {
		giterr_set(GITERR_REFERENCE,
			"Cannot set upstream for branch '%s'", shortname);
		return GIT_ENOTFOUND;
	}

	/*
	 * If it's local, the remote is "." and the branch name is
	 * simply the refname. Otherwise we need to figure out what
	 * the remote-tracking branch's name on the remote is and use
	 * that.
	 */
	if (local)
		error = git_buf_puts(&value, ".");
	else
		error = git_branch_remote_name(&value, repo, git_reference_name(upstream));

	if (error < 0)
		goto on_error;

	if (git_buf_printf(&key, "branch.%s.remote", shortname) < 0)
		goto on_error;

	if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0)
		goto on_error;

	if (local) {
		git_buf_clear(&value);
		if (git_buf_puts(&value, git_reference_name(upstream)) < 0)
			goto on_error;
	} else {
		/* Get the remoe-tracking branch's refname in its repo */
		if (git_remote_lookup(&remote, repo, git_buf_cstr(&value)) < 0)
			goto on_error;

		fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
		git_buf_clear(&value);
		if (!fetchspec || git_refspec_rtransform(&value, fetchspec, git_reference_name(upstream)) < 0)
			goto on_error;

		git_remote_free(remote);
		remote = NULL;
	}

	git_buf_clear(&key);
	if (git_buf_printf(&key, "branch.%s.merge", shortname) < 0)
		goto on_error;

	if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0)
		goto on_error;

	git_reference_free(upstream);
	git_buf_free(&key);
	git_buf_free(&value);

	return 0;

on_error:
	git_reference_free(upstream);
	git_buf_free(&key);
	git_buf_free(&value);
	git_remote_free(remote);

	return -1;
}
コード例 #27
0
ファイル: qgitref.cpp プロジェクト: KDE/libqgit2
Repository Reference::owner() const
{
    return Repository(git_reference_owner(d.data()));
}