Пример #1
0
static int create_and_configure_origin(
		git_remote **out,
		git_repository *repo,
		const char *url,
		const git_clone_options *options)
{
	int error;
	git_remote *origin = NULL;
	const char *name;

	name = options->remote_name ? options->remote_name : "origin";
	if ((error = git_remote_create(&origin, repo, name, url)) < 0)
		goto on_error;

	if (options->ignore_cert_errors)
		git_remote_check_cert(origin, 0);

	if ((error = git_remote_set_callbacks(origin, &options->remote_callbacks)) < 0)
		goto on_error;

	if ((error = git_remote_save(origin)) < 0)
		goto on_error;

	*out = origin;
	return 0;

on_error:
	git_remote_free(origin);
	return error;
}
Пример #2
0
/**
 * Fetch new data and update tips
 *
 * @param repo S4 class git_repository
 * @param name The name of the remote to fetch from
 * @param credentials The credentials for remote repository access.
 * @param msg The one line long message to be appended to the reflog
 * @return R_NilValue
 */
SEXP git2r_remote_fetch(
    SEXP repo,
    SEXP name,
    SEXP credentials,
    SEXP msg)
{
    int err;
    SEXP result = R_NilValue;
    const git_transfer_progress *stats;
    git_remote *remote = NULL;
    git_repository *repository = NULL;
    git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

    if (git2r_arg_check_string(name))
        git2r_error(git2r_err_string_arg, __func__, "name");
    if (git2r_arg_check_credentials(credentials))
        git2r_error(git2r_err_credentials_arg, __func__, "credentials");
    if (git2r_arg_check_string(msg))
        git2r_error(git2r_err_string_arg, __func__, "msg");

    repository = git2r_repository_open(repo);
    if (!repository)
        git2r_error(git2r_err_invalid_repository, __func__, NULL);

    err = git_remote_lookup(&remote, repository, CHAR(STRING_ELT(name, 0)));
    if (GIT_OK != err)
        goto cleanup;

    callbacks.credentials = &git2r_cred_acquire_cb;
    callbacks.payload = credentials;
    err = git_remote_set_callbacks(remote, &callbacks);
    if (GIT_OK != err)
        goto cleanup;

    err = git_remote_fetch(remote, NULL,  CHAR(STRING_ELT(msg, 0)));
    if (GIT_OK != err)
        goto cleanup;

    stats = git_remote_stats(remote);
    PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_transfer_progress")));
    git2r_transfer_progress_init(stats, result);

cleanup:
    if (remote) {
        if (git_remote_connected(remote))
            git_remote_disconnect(remote);
        git_remote_free(remote);
    }

    if (repository)
        git_repository_free(repository);

    if (R_NilValue != result)
        UNPROTECT(1);

    if (GIT_OK != err)
        git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message);

    return result;
}
Пример #3
0
void test_network_fetchlocal__partial(void)
{
	git_repository *repo = cl_git_sandbox_init("partial-testrepo");
	git_remote *origin;
	int callcount = 0;
	git_strarray refnames = {0};
	const char *url;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

	callbacks.transfer_progress = transfer_cb;
	callbacks.payload = &callcount;

	cl_set_cleanup(&cleanup_sandbox, NULL);
	cl_git_pass(git_reference_list(&refnames, repo));
	cl_assert_equal_i(1, (int)refnames.count);

	url = cl_git_fixture_url("testrepo.git");
	cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
	git_remote_set_callbacks(origin, &callbacks);
	cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH));
	cl_git_pass(git_remote_download(origin));
	cl_git_pass(git_remote_update_tips(origin, NULL, NULL));

	git_strarray_free(&refnames);

	cl_git_pass(git_reference_list(&refnames, repo));
	cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */
	cl_assert(callcount > 0);

	git_strarray_free(&refnames);
	git_remote_free(origin);
}
Пример #4
0
void test_online_clone__clone_mirror(void)
{
	git_buf path = GIT_BUF_INIT;
	git_remote *remote;
	git_reference *head;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

	bool fetch_progress_cb_was_called = false;

	cl_git_pass(git_repository_init(&g_repo, "./foo.git", true));
	cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL));

	callbacks.transfer_progress = &fetch_progress;
	callbacks.payload = &fetch_progress_cb_was_called;
	git_remote_set_callbacks(remote, &callbacks);

	git_remote_clear_refspecs(remote);
	cl_git_pass(git_remote_add_fetch(remote, "+refs/*:refs/*"));

	cl_git_pass(git_clone_into(g_repo, remote, NULL, NULL, NULL));

	cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
	cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
	cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));

	cl_assert_equal_i(true, fetch_progress_cb_was_called);

	git_remote_free(remote);
	git_reference_free(head);
	git_buf_free(&path);
	git_repository_free(g_repo);
	g_repo = NULL;

	cl_fixture_cleanup("./foo.git");
}
Пример #5
0
static int use_remote(git_repository *repo, char *name)
{
	git_remote *remote = NULL;
	int error;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

	// Find the remote by name
	error = git_remote_load(&remote, repo, name);
	if (error < 0) {
		error = git_remote_create_inmemory(&remote, repo, NULL, name);
		if (error < 0)
			goto cleanup;
	}

	callbacks.credentials = cred_acquire_cb;
	git_remote_set_callbacks(remote, &callbacks);

	error = git_remote_connect(remote, GIT_DIRECTION_FETCH);
	if (error < 0)
		goto cleanup;

	error = git_remote_ls(remote, &show_ref__cb, NULL);

cleanup:
	git_remote_free(remote);
	return error;
}
Пример #6
0
static int remote_mirror_cb(git_remote **out, git_repository *repo,
                            const char *name, const char *url, void *payload)
{
    int error;
    git_remote *remote;
    git_remote_callbacks *callbacks = (git_remote_callbacks *) payload;


    if ((error = git_remote_create(&remote, repo, name, url)) < 0)
        return error;

    if ((error = git_remote_set_callbacks(remote, callbacks)) < 0) {
        git_remote_free(remote);
        return error;
    }

    git_remote_clear_refspecs(remote);

    if ((error = git_remote_add_fetch(remote, "+refs/*:refs/*")) < 0) {
        git_remote_free(remote);
        return error;
    }

    *out = remote;
    return 0;
}
Пример #7
0
void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void)
{
	git_repository *_repository;
	bool invoked = false;
	git_remote *remote;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
	git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
	opts.bare = true;

	cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git",
				"./fetch/lg2", &opts));
	git_repository_free(_repository);

	cl_git_pass(git_repository_open(&_repository, "./fetch/lg2"));

	cl_git_pass(git_remote_load(&remote, _repository, "origin"));
	cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));

	cl_assert_equal_i(false, invoked);

	callbacks.transfer_progress = &transferProgressCallback;
	callbacks.payload = &invoked;
	git_remote_set_callbacks(remote, &callbacks);
	cl_git_pass(git_remote_download(remote));

	cl_assert_equal_i(false, invoked);

	cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
	git_remote_disconnect(remote);

	git_remote_free(remote);
	git_repository_free(_repository);
}
Пример #8
0
/*
 *  call-seq:
 *    remote.fetch(refspecs = nil, options = {}) -> hash
 *
 *  Downloads new data from the remote for the given +refspecs+ and updates tips.
 *
 *  You can optionally pass in a single or multiple alternative +refspecs+ to use instead of the fetch
 *  refspecs already configured for +remote+.
 *
 *  Returns a hash containing statistics for the fetch operation.
 *
 *  The following options can be passed in the +options+ Hash:
 *
 *  :credentials ::
 *    The credentials to use for the fetch operation. Can be either an instance of one
 *    of the Rugged::Credentials types, or a proc returning one of the former.
 *    The proc will be called with the +url+, the +username+ from the url (if applicable) and
 *    a list of applicable credential types.
 *
 *  :progress ::
 *    A callback that will be executed with the textual progress received from the remote.
 *    This is the text send over the progress side-band (ie. the "counting objects" output).
 *
 *  :transfer_progress ::
 *    A callback that will be executed to report clone progress information. It will be passed
 *    the amount of +total_objects+, +indexed_objects+, +received_objects+, +local_objects+,
 *    +total_deltas+, +indexed_deltas+ and +received_bytes+.
 *
 *  :update_tips ::
 *    A callback that will be executed each time a reference is updated locally. It will be
 *    passed the +refname+, +old_oid+ and +new_oid+.
 *
 *  :message ::
 *    The message to insert into the reflogs. Defaults to "fetch".
 *
 *  Example:
 *
 *    remote = Rugged::Remote.lookup(@repo, 'origin')
 *    remote.fetch({
 *      transfer_progress: lambda { |total_objects, indexed_objects, received_objects, local_objects, total_deltas, indexed_deltas, received_bytes|
 *        # ...
 *      }
 *    })
 */
static VALUE rb_git_remote_fetch(int argc, VALUE *argv, VALUE self)
{
	git_remote *remote;
	git_repository *repo;
	git_strarray refspecs;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
	struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 };

	char *log_message = NULL;
	int error;

	VALUE rb_options, rb_refspecs, rb_result = Qnil, rb_repo = rugged_owner(self);

	rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options);

	rugged_rb_ary_to_strarray(rb_refspecs, &refspecs);

	Data_Get_Struct(self, git_remote, remote);
	rugged_check_repo(rb_repo);
	Data_Get_Struct(rb_repo, git_repository, repo);

	rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);

	if (!NIL_P(rb_options)) {
		VALUE rb_val = rb_hash_aref(rb_options, CSTR2SYM("message"));
		if (!NIL_P(rb_val))
			log_message = StringValueCStr(rb_val);
	}

	if ((error = git_remote_set_callbacks(remote, &callbacks)))
		goto cleanup;

	if ((error = git_remote_fetch(remote, &refspecs, log_message)) == GIT_OK) {
		const git_transfer_progress *stats = git_remote_stats(remote);

		rb_result = rb_hash_new();
		rb_hash_aset(rb_result, CSTR2SYM("total_objects"),    UINT2NUM(stats->total_objects));
		rb_hash_aset(rb_result, CSTR2SYM("indexed_objects"),  UINT2NUM(stats->indexed_objects));
		rb_hash_aset(rb_result, CSTR2SYM("received_objects"), UINT2NUM(stats->received_objects));
		rb_hash_aset(rb_result, CSTR2SYM("local_objects"),    UINT2NUM(stats->local_objects));
		rb_hash_aset(rb_result, CSTR2SYM("total_deltas"),     UINT2NUM(stats->total_deltas));
		rb_hash_aset(rb_result, CSTR2SYM("indexed_deltas"),   UINT2NUM(stats->indexed_deltas));
		rb_hash_aset(rb_result, CSTR2SYM("received_bytes"),   INT2FIX(stats->received_bytes));
	}

	cleanup:

	xfree(refspecs.strings);

	if (payload.exception)
		rb_jump_tag(payload.exception);

	rugged_exception_check(error);

	return rb_result;
}
Пример #9
0
static int default_remote_create(
		git_remote **out,
		git_repository *repo,
		const char *name,
		const char *url,
		void *payload)
{
	int error;
	git_remote_callbacks *callbacks = payload;

	if ((error = git_remote_create(out, repo, name, url)) < 0)
		return error;

	return git_remote_set_callbacks(*out, callbacks);
}
Пример #10
0
static int create_and_configure_origin(
		git_remote **out,
		git_repository *repo,
		const char *url,
		const git_clone_options *options)
{
	int error;
	git_remote *origin = NULL;

	if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0)
		goto on_error;

	git_remote_set_cred_acquire_cb(origin, options->cred_acquire_cb,
			options->cred_acquire_payload);
	git_remote_set_autotag(origin, options->remote_autotag);
	/*
	 * Don't write FETCH_HEAD, we'll check out the remote tracking
	 * branch ourselves based on the server's default.
	 */
	git_remote_set_update_fetchhead(origin, 0);

	if (options->remote_callbacks &&
	    (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0)
		goto on_error;

	if (options->fetch_spec &&
	    (error = git_remote_set_fetchspec(origin, options->fetch_spec)) < 0)
		goto on_error;

	if (options->push_spec &&
	    (error = git_remote_set_pushspec(origin, options->push_spec)) < 0)
		goto on_error;

	if (options->pushurl &&
	    (error = git_remote_set_pushurl(origin, options->pushurl)) < 0)
		goto on_error;

	if ((error = git_remote_save(origin)) < 0)
		goto on_error;

	*out = origin;
	return 0;

on_error:
	git_remote_free(origin);
	return error;
}
Пример #11
0
void test_online_fetch__can_cancel(void)
{
	git_remote *remote;
	size_t bytes_received = 0;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

	cl_git_pass(git_remote_create(&remote, _repo, "test",
				"http://github.com/libgit2/TestGitRepository.git"));

	callbacks.transfer_progress = cancel_at_half;
	callbacks.payload = &bytes_received;
	git_remote_set_callbacks(remote, &callbacks);

	cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
	cl_git_fail_with(git_remote_download(remote), -4321);
	git_remote_disconnect(remote);
	git_remote_free(remote);
}
Пример #12
0
int NotesModel::push() {
    git_push *push;
    git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
    git_repository *repo = NULL;
    git_remote *remote = NULL;


    if (!QSettings().value("gitRemoteUrl").isValid())
        return false;

    if (QSettings().value("gitRemoteUrl") == "")
        return false;

    try {
        //Open Repo
        e(git_repository_open(&repo, notesFolder().absolutePath().toUtf8().constData()));
        e(git_remote_load(&remote, repo, "upstream"));
        callbacks.credentials = cred_acquire_cb;
        e(git_remote_set_callbacks(remote, &callbacks));
        e(git_remote_connect(remote, GIT_DIRECTION_PUSH));
        int connected = git_remote_connected(remote);
        if (connected) {
            e(git_push_new(&push, remote));

            e(git_push_add_refspec(push, "refs/heads/master:refs/heads/master"));
            e(git_push_finish(push));
            e(git_push_unpack_ok(push));
            e(git_push_status_foreach(push, &status_cb, NULL) < 0);

            git_push_free(push);
        }
    }
    catch (int error) {
        const git_error *err = giterr_last();
        if (err != NULL)
            qDebug() << QString::number(err->klass) + "\t" + QString(err->message);
        emit this->error(QString(err->message));
        giterr_clear();
        git_remote_free(remote);
        git_repository_free(repo);
    }
    return true;

}
Пример #13
0
/*
 *  call-seq:
 *    remote.ls(options = {}) -> an_enumerator
 *    remote.ls(options = {}) { |remote_head_hash| block }
 *
 *  List references available in a connected +remote+ repository along
 *  with the associated commit IDs.
 *
 *  Call the given block once for each remote head in the +remote+ as a
 *  +Hash+.
 *  If no block is given an Enumerator is returned.
 *
 *    r.ls.to_a #=> [{:local?=>false, :oid=>"b3ee97a91b02e91c35394950bda6ea622044baad", :loid=> nil, :name=>"refs/heads/development"}]
 *
 *  remote head hash includes:
 *  [:oid] oid of the remote head
 *  [:name] name of the remote head
 *
 *  The following options can be passed in the +options+ Hash:
 *
 *  :credentials ::
 *    The credentials to use for the ls operation. Can be either an instance of one
 *    of the Rugged::Credentials types, or a proc returning one of the former.
 *    The proc will be called with the +url+, the +username+ from the url (if applicable) and
 *    a list of applicable credential types.
 */
static VALUE rb_git_remote_ls(int argc, VALUE *argv, VALUE self)
{
	git_remote *remote;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
	const git_remote_head **heads;

	struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, 0 };

	VALUE rb_options;

	int error;
	size_t heads_len, i;

	Data_Get_Struct(self, git_remote, remote);

	rb_scan_args(argc, argv, ":", &rb_options);

	if (!rb_block_given_p())
		return rb_funcall(self, rb_intern("to_enum"), 2, CSTR2SYM("ls"), rb_options);

	if (!NIL_P(rb_options))
		rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);

	if ((error = git_remote_set_callbacks(remote, &callbacks)) ||
	    (error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) ||
	    (error = git_remote_ls(&heads, &heads_len, remote)))
		goto cleanup;

	for (i = 0; i < heads_len && !payload.exception; i++)
		rb_protect(rb_yield, rugged_rhead_new(heads[i]), &payload.exception);

	cleanup:

	git_remote_disconnect(remote);

	if (payload.exception)
		rb_jump_tag(payload.exception);

	rugged_exception_check(error);

	return Qnil;
}
Пример #14
0
static int custom_remote_ssh_with_paths(
    git_remote **out,
    git_repository *repo,
    const char *name,
    const char *url,
    void *payload)
{
    int error;
    git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

    if ((error = git_remote_create(out, repo, name, url)) < 0)
        return error;

    if ((error = git_remote_set_transport(*out, git_transport_ssh_with_paths, payload)) < 0)
        return error;

    callbacks.credentials = cred_cb;
    git_remote_set_callbacks(*out, &callbacks);

    return 0;
}
Пример #15
0
/*
 *  call-seq:
 *    remote.push(refspecs = nil, options = {}) -> hash
 *
 *  Pushes the given +refspecs+ to the given +remote+. Returns a hash that contains
 *  key-value pairs that reflect pushed refs and error messages, if applicable.
 *
 *  You can optionally pass in an alternative list of +refspecs+ to use instead of the push
 *  refspecs already configured for +remote+.
 *
 *  The following options can be passed in the +options+ Hash:
 *
 *  :credentials ::
 *    The credentials to use for the push operation. Can be either an instance of one
 *    of the Rugged::Credentials types, or a proc returning one of the former.
 *    The proc will be called with the +url+, the +username+ from the url (if applicable) and
 *    a list of applicable credential types.
 *
 *  :update_tips ::
 *    A callback that will be executed each time a reference is updated remotely. It will be
 *    passed the +refname+, +old_oid+ and +new_oid+.
 *
 *  Example:
 *
 *    remote = Rugged::Remote.lookup(@repo, 'origin')
 *    remote.push(["refs/heads/master", ":refs/heads/to_be_deleted"])
 */
static VALUE rb_git_remote_push(int argc, VALUE *argv, VALUE self)
{
	VALUE rb_refspecs, rb_options;
	VALUE rb_repo = rugged_owner(self);

	git_repository *repo;
	git_remote *remote;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
	git_strarray refspecs;
	git_push_options opts = GIT_PUSH_OPTIONS_INIT;

	int error = 0;

	struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, rb_hash_new(), 0 };

	rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options);

	rugged_rb_ary_to_strarray(rb_refspecs, &refspecs);

	rugged_check_repo(rb_repo);
	Data_Get_Struct(rb_repo, git_repository, repo);
	Data_Get_Struct(self, git_remote, remote);

	rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);

	if ((error = git_remote_set_callbacks(remote, &callbacks)))
	    goto cleanup;

	error = git_remote_push(remote, &refspecs, &opts);

cleanup:
	xfree(refspecs.strings);

	if (payload.exception)
		rb_jump_tag(payload.exception);

	rugged_exception_check(error);

	return payload.result;
}
Пример #16
0
static int clone_into(git_repository *repo, git_remote *_remote, const git_checkout_options *co_opts, const char *branch, const git_signature *signature)
{
	int error;
	git_buf reflog_message = GIT_BUF_INIT;
	git_remote *remote;
	const git_remote_callbacks *callbacks;

	assert(repo && _remote);

	if (!git_repository_is_empty(repo)) {
		giterr_set(GITERR_INVALID, "the repository is not empty");
		return -1;
	}

	if ((error = git_remote_dup(&remote, _remote)) < 0)
		return error;

	callbacks = git_remote_get_callbacks(_remote);
	if (!giterr__check_version(callbacks, 1, "git_remote_callbacks") &&
	    (error = git_remote_set_callbacks(remote, callbacks)) < 0)
		goto cleanup;

	if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0)
		goto cleanup;

	git_remote_set_update_fetchhead(remote, 0);
	git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));

	if ((error = git_remote_fetch(remote, signature, git_buf_cstr(&reflog_message))) != 0)
		goto cleanup;

	error = checkout_branch(repo, remote, co_opts, branch, signature, git_buf_cstr(&reflog_message));

cleanup:
	git_remote_free(remote);
	git_buf_free(&reflog_message);

	return error;
}
Пример #17
0
/*
 *  call-seq:
 *    remote.check_connection(direction, options = {}) -> boolean
 *
 *  Try to connect to the +remote+. Useful to simulate
 *  <tt>git fetch --dry-run</tt> and <tt>git push --dry-run</tt>.
 *
 *  Returns +true+ if connection is successful, +false+ otherwise.
 *
 *  +direction+ must be either +:fetch+ or +:push+.
 *
 *  The following options can be passed in the +options+ Hash:
 *
 *  +credentials+ ::
 *    The credentials to use for the connection. Can be either an instance of
 *    one of the Rugged::Credentials types, or a proc returning one of the
 *    former.
 *    The proc will be called with the +url+, the +username+ from the url (if
 *    applicable) and a list of applicable credential types.
 *
 *  Example:
 *
 *    remote = repo.remotes["origin"]
 *    success = remote.check_connection(:fetch)
 *    raise Error("Unable to pull without credentials") unless success
 */
static VALUE rb_git_remote_check_connection(int argc, VALUE *argv, VALUE self)
{
	git_remote *remote;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
	struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 };
	VALUE rb_direction, rb_options;
	ID id_direction;
	int error, direction;

	Data_Get_Struct(self, git_remote, remote);
	rb_scan_args(argc, argv, "01:", &rb_direction, &rb_options);

	Check_Type(rb_direction, T_SYMBOL);
	id_direction = SYM2ID(rb_direction);
	if (id_direction == rb_intern("fetch"))
		direction = GIT_DIRECTION_FETCH;
	else if (id_direction == rb_intern("push"))
		direction = GIT_DIRECTION_PUSH;
	else
		rb_raise(rb_eTypeError, "Invalid direction. Expected :fetch or :push");

	rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);

	if ((error = git_remote_set_callbacks(remote, &callbacks)) < 0)
		goto cleanup;

	if (git_remote_connect(remote, direction))
		return Qfalse;
	else {
		git_remote_disconnect(remote);
		return Qtrue;
	}

cleanup:
	if (payload.exception)
		rb_jump_tag(payload.exception);
	rugged_exception_check(error);
	return Qfalse;
}
Пример #18
0
void test_online_clone__clone_into(void)
{
	git_buf path = GIT_BUF_INIT;
	git_remote *remote;
	git_reference *head;
	git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

	bool checkout_progress_cb_was_called = false,
		  fetch_progress_cb_was_called = false;

	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
	checkout_opts.progress_cb = &checkout_progress;
	checkout_opts.progress_payload = &checkout_progress_cb_was_called;

	cl_git_pass(git_repository_init(&g_repo, "./foo", false));
	cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL));

	callbacks.transfer_progress = &fetch_progress;
	callbacks.payload = &fetch_progress_cb_was_called;
	git_remote_set_callbacks(remote, &callbacks);

	cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL, NULL));

	cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
	cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));

	cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
	cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
	cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));

	cl_assert_equal_i(true, checkout_progress_cb_was_called);
	cl_assert_equal_i(true, fetch_progress_cb_was_called);

	git_remote_free(remote);
	git_reference_free(head);
	git_buf_free(&path);
}
Пример #19
0
static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n)
{
	git_remote *remote;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
	size_t bytes_received = 0;

	callbacks.transfer_progress = progress;
	callbacks.update_tips = update_tips;
	callbacks.payload = &bytes_received;
	counter = 0;

	cl_git_pass(git_remote_create(&remote, _repo, "test", url));
	git_remote_set_callbacks(remote, &callbacks);
	git_remote_set_autotag(remote, flag);
	cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
	cl_git_pass(git_remote_download(remote));
	cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
	git_remote_disconnect(remote);
	cl_assert_equal_i(counter, n);
	cl_assert(bytes_received > 0);

	git_remote_free(remote);
}
Пример #20
0
/*
 *  call-seq:
 *    remote.push(refspecs = nil, options = {}) -> hash
 *
 *  Pushes the given +refspecs+ to the given +remote+. Returns a hash that contains
 *  key-value pairs that reflect pushed refs and error messages, if applicable.
 *
 *  The following options can be passed in the +options+ Hash:
 *
 *  :credentials ::
 *    The credentials to use for the push operation. Can be either an instance of one
 *    of the Rugged::Credentials types, or a proc returning one of the former.
 *    The proc will be called with the +url+, the +username+ from the url (if applicable) and
 *    a list of applicable credential types.
 *
 *  :message ::
 *    A single line log message to be appended to the reflog of each local remote-tracking
 *    branch that gets updated. Defaults to: "fetch".
 *
 *  :signature ::
 *    The signature to be used for populating the reflog entries.
 *
 *  Example:
 *
 *    remote = Rugged::Remote.lookup(@repo, 'origin')
 *    remote.push(["refs/heads/master", ":refs/heads/to_be_deleted"])
 */
static VALUE rb_git_remote_push(int argc, VALUE *argv, VALUE self)
{
	VALUE rb_refspecs, rb_options, rb_val;
	VALUE rb_repo = rugged_owner(self);
	VALUE rb_exception = Qnil, rb_result = rb_hash_new();

	git_repository *repo;
	git_remote *remote, *tmp_remote = NULL;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
	git_push *push = NULL;
	git_signature *signature = NULL;

	int error = 0, i = 0;
	char *log_message = NULL;

	struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, 0 };

	rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options);

	if (!NIL_P(rb_refspecs)) {
		Check_Type(rb_refspecs, T_ARRAY);
		for (i = 0; i < RARRAY_LEN(rb_refspecs); ++i) {
			VALUE rb_refspec = rb_ary_entry(rb_refspecs, i);
			Check_Type(rb_refspec, T_STRING);
		}
	}

	rugged_check_repo(rb_repo);
	Data_Get_Struct(rb_repo, git_repository, repo);
	Data_Get_Struct(self, git_remote, remote);

	if (!NIL_P(rb_options)) {
		rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);

		rb_val = rb_hash_aref(rb_options, CSTR2SYM("message"));
		if (!NIL_P(rb_val))
			log_message = StringValueCStr(rb_val);

		rb_val = rb_hash_aref(rb_options, CSTR2SYM("signature"));
		if (!NIL_P(rb_val))
			signature = rugged_signature_get(rb_val, repo);
	}

	// Create a temporary remote that we use for pushing
	if ((error = git_remote_dup(&tmp_remote, remote)) ||
	    (error = git_remote_set_callbacks(tmp_remote, &callbacks)))
	    goto cleanup;

	if (!NIL_P(rb_refspecs)) {
		git_remote_clear_refspecs(tmp_remote);

		for (i = 0; !error && i < RARRAY_LEN(rb_refspecs); ++i) {
			VALUE rb_refspec = rb_ary_entry(rb_refspecs, i);

			if ((error = git_remote_add_push(tmp_remote, StringValueCStr(rb_refspec))))
				goto cleanup;
		}
	}

	if ((error = git_push_new(&push, tmp_remote)))
		goto cleanup;

	// TODO: Get rid of this once git_remote_push lands in libgit2.
	{
		git_strarray push_refspecs;
		size_t i;

		if ((error = git_remote_get_push_refspecs(&push_refspecs, tmp_remote)))
			goto cleanup;

		if (push_refspecs.count == 0) {
			rb_exception = rb_exc_new2(rb_eRuggedError, "no pushspecs are configured for the given remote");
			goto cleanup;
		}

		for (i = 0; !error && i < push_refspecs.count; ++i) {
			error = git_push_add_refspec(push, push_refspecs.strings[i]);
		}

		git_strarray_free(&push_refspecs);
		if (error) goto cleanup;
	}

	if ((error = git_push_finish(push)))
		goto cleanup;

	if (!git_push_unpack_ok(push)) {
		rb_exception = rb_exc_new2(rb_eRuggedError, "the remote side did not unpack successfully");
		goto cleanup;
	}

	if ((error = git_push_status_foreach(push, &push_status_cb, (void *)rb_result)) ||
	    (error = git_push_update_tips(push, signature, log_message)))
	    goto cleanup;

cleanup:
	git_push_free(push);
	git_remote_free(tmp_remote);
	git_signature_free(signature);

	if (!NIL_P(rb_exception))
		rb_exc_raise(rb_exception);

	rugged_exception_check(error);

	return rb_result;
}
Пример #21
0
/*
 *  call-seq:
 *    remote.fetch(refspecs = nil, options = {}) -> hash
 *
 *  Downloads new data from the remote for the given +refspecs+ and updates tips.
 *
 *  You can optionally pass in an alternative list of +refspecs+ to use instead of the fetch
 *  refspecs already configured for +remote+.
 *
 *  Returns a hash containing statistics for the fetch operation.
 *
 *  The following options can be passed in the +options+ Hash:
 *
 *  :credentials ::
 *    The credentials to use for the fetch operation. Can be either an instance of one
 *    of the Rugged::Credentials types, or a proc returning one of the former.
 *    The proc will be called with the +url+, the +username+ from the url (if applicable) and
 *    a list of applicable credential types.
 *
 *  :progress ::
 *    A callback that will be executed with the textual progress received from the remote.
 *    This is the text send over the progress side-band (ie. the "counting objects" output).
 *
 *  :transfer_progress ::
 *    A callback that will be executed to report clone progress information. It will be passed
 *    the amount of +total_objects+, +indexed_objects+, +received_objects+, +local_objects+,
 *    +total_deltas+, +indexed_deltas+ and +received_bytes+.
 *
 *  :update_tips ::
 *    A callback that will be executed each time a reference is updated locally. It will be
 *    passed the +refname+, +old_oid+ and +new_oid+.
 *
 *  :message ::
 *    The message to insert into the reflogs. Defaults to "fetch".
 *
 *  :signature ::
 *    The signature to be used for updating the reflogs.
 *
 *  Example:
 *
 *    remote = Rugged::Remote.lookup(@repo, 'origin')
 *    remote.fetch({
 *      transfer_progress: lambda { |total_objects, indexed_objects, received_objects, local_objects, total_deltas, indexed_deltas, received_bytes|
 *        # ...
 *      }
 *    })
 */
static VALUE rb_git_remote_fetch(int argc, VALUE *argv, VALUE self)
{
	git_remote *remote, *tmp_remote = NULL;
	git_repository *repo;
	git_signature *signature = NULL;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
	struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, 0 };

	char *log_message = NULL;
	int error, i;

	VALUE rb_options, rb_refspecs, rb_result = Qnil, rb_repo = rugged_owner(self);

	rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options);

	if (!NIL_P(rb_refspecs)) {
		Check_Type(rb_refspecs, T_ARRAY);
		for (i = 0; i < RARRAY_LEN(rb_refspecs); ++i) {
			VALUE rb_refspec = rb_ary_entry(rb_refspecs, i);
			Check_Type(rb_refspec, T_STRING);
		}
	}

	Data_Get_Struct(self, git_remote, remote);
	rugged_check_repo(rb_repo);
	Data_Get_Struct(rb_repo, git_repository, repo);

	if (!NIL_P(rb_options)) {
		VALUE rb_val = rb_hash_aref(rb_options, CSTR2SYM("signature"));
		if (!NIL_P(rb_val))
			signature = rugged_signature_get(rb_val, repo);

		rb_val = rb_hash_aref(rb_options, CSTR2SYM("message"));
		if (!NIL_P(rb_val))
			log_message = StringValueCStr(rb_val);

		rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
	}

	if ((error = git_remote_dup(&tmp_remote, remote)) ||
		(error = git_remote_set_callbacks(tmp_remote, &callbacks)))
		goto cleanup;

	if (!NIL_P(rb_refspecs)) {
		git_remote_clear_refspecs(tmp_remote);
		for (i = 0; !error && i < RARRAY_LEN(rb_refspecs); ++i) {
			VALUE rb_refspec = rb_ary_entry(rb_refspecs, i);

			if ((error = git_remote_add_fetch(tmp_remote, StringValueCStr(rb_refspec))))
				goto cleanup;
		}
	}

	if ((error = git_remote_fetch(tmp_remote, signature, log_message)) == GIT_OK) {
		const git_transfer_progress *stats = git_remote_stats(tmp_remote);

		rb_result = rb_hash_new();
		rb_hash_aset(rb_result, CSTR2SYM("total_objects"),    UINT2NUM(stats->total_objects));
		rb_hash_aset(rb_result, CSTR2SYM("indexed_objects"),  UINT2NUM(stats->indexed_objects));
		rb_hash_aset(rb_result, CSTR2SYM("received_objects"), UINT2NUM(stats->received_objects));
		rb_hash_aset(rb_result, CSTR2SYM("local_objects"),    UINT2NUM(stats->local_objects));
		rb_hash_aset(rb_result, CSTR2SYM("total_deltas"),     UINT2NUM(stats->total_deltas));
		rb_hash_aset(rb_result, CSTR2SYM("indexed_deltas"),   UINT2NUM(stats->indexed_deltas));
		rb_hash_aset(rb_result, CSTR2SYM("received_bytes"),   INT2FIX(stats->received_bytes));
	}

	cleanup:

	git_signature_free(signature);
	git_remote_free(tmp_remote);

	if (payload.exception)
		rb_jump_tag(payload.exception);

	rugged_exception_check(error);

	return rb_result;
}
Пример #22
0
void test_network_fetchlocal__prune(void)
{
	git_repository *repo;
	git_remote *origin;
	int callcount = 0;
	git_strarray refnames = {0};
	git_reference *ref;
	git_repository *remote_repo = cl_git_sandbox_init("testrepo.git");
	const char *url = cl_git_path_url(git_repository_path(remote_repo));
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

	callbacks.transfer_progress = transfer_cb;
	callbacks.payload = &callcount;

	cl_set_cleanup(&cleanup_local_repo, "foo");
	cl_git_pass(git_repository_init(&repo, "foo", true));

	cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
	git_remote_set_callbacks(origin, &callbacks);
	cl_git_pass(git_remote_fetch(origin, NULL, NULL, NULL));

	cl_git_pass(git_reference_list(&refnames, repo));
	cl_assert_equal_i(19, (int)refnames.count);
	cl_assert(callcount > 0);
	git_strarray_free(&refnames);
	git_remote_free(origin);

	cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/br2"));
	cl_git_pass(git_reference_delete(ref));
	git_reference_free(ref);

	cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
	git_remote_set_callbacks(origin, &callbacks);
	cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH));
	cl_git_pass(git_remote_download(origin, NULL));
	cl_git_pass(git_remote_prune(origin));
	cl_git_pass(git_remote_update_tips(origin, NULL, NULL));

	cl_git_pass(git_reference_list(&refnames, repo));
	cl_assert_equal_i(18, (int)refnames.count);
	git_strarray_free(&refnames);
	git_remote_free(origin);

	cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/packed"));
	cl_git_pass(git_reference_delete(ref));
	git_reference_free(ref);

	cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
	git_remote_set_callbacks(origin, &callbacks);
	cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH));
	cl_git_pass(git_remote_download(origin, NULL));
	cl_git_pass(git_remote_prune(origin));
	cl_git_pass(git_remote_update_tips(origin, NULL, NULL));

	cl_git_pass(git_reference_list(&refnames, repo));
	cl_assert_equal_i(17, (int)refnames.count);
	git_strarray_free(&refnames);
	git_remote_free(origin);

	git_repository_free(repo);
}
Пример #23
0
Файл: fetch.c Проект: bxio/.atom
int fetch(git_repository *repo, int argc, char **argv)
{
	git_remote *remote = NULL;
	const git_transfer_progress *stats;
	struct dl_data data;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
#ifndef _WIN32
	pthread_t worker;
#endif

	argc = argc;
	// Figure out whether it's a named remote or a URL
	printf("Fetching %s for repo %p\n", argv[1], repo);
	if (git_remote_load(&remote, repo, argv[1]) < 0) {
		if (git_remote_create_inmemory(&remote, repo, NULL, argv[1]) < 0)
			return -1;
	}

	// Set up the callbacks (only update_tips for now)
	callbacks.update_tips = &update_cb;
	callbacks.progress = &progress_cb;
	git_remote_set_callbacks(remote, &callbacks);

	// Set up the information for the background worker thread
	data.remote = remote;
	data.ret = 0;
	data.finished = 0;

	stats = git_remote_stats(remote);

#ifdef _WIN32
	download(&data);
#else
	pthread_create(&worker, NULL, download, &data);

	// Loop while the worker thread is still running. Here we show processed
	// and total objects in the pack and the amount of received
	// data. Most frontends will probably want to show a percentage and
	// the download rate.
	do {
		usleep(10000);

		if (stats->total_objects > 0)
			printf("Received %d/%d objects (%d) in %" PRIuZ " bytes\r",
			       stats->received_objects, stats->total_objects,
				   stats->indexed_objects, stats->received_bytes);
	} while (!data.finished);

	if (data.ret < 0)
		goto on_error;

	pthread_join(worker, NULL);
#endif

	printf("\rReceived %d/%d objects in %zu bytes\n",
			stats->indexed_objects, stats->total_objects, stats->received_bytes);

	// Disconnect the underlying connection to prevent from idling.
	git_remote_disconnect(remote);

	// Update the references in the remote's namespace to point to the
	// right commits. This may be needed even if there was no packfile
	// to download, which can happen e.g. when the branches have been
	// changed but all the neede objects are available locally.
	if (git_remote_update_tips(remote) < 0)
		return -1;

	git_remote_free(remote);

	return 0;

 on_error:
	git_remote_free(remote);
	return -1;
}
Пример #24
0
/** Entry point for this command */
int fetch(git_repository *repo, int argc, char **argv)
{
	git_remote *remote = NULL;
	const git_transfer_progress *stats;
	struct dl_data data;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
#ifndef _WIN32
	pthread_t worker;
#endif

	if (argc < 2) {
		fprintf(stderr, "usage: %s fetch <repo>\n", argv[-1]);
		return EXIT_FAILURE;
	}

	// Figure out whether it's a named remote or a URL
	printf("Fetching %s for repo %p\n", argv[1], repo);
	if (git_remote_lookup(&remote, repo, argv[1]) < 0) {
		if (git_remote_create_anonymous(&remote, repo, argv[1], NULL) < 0)
			return -1;
	}

	// Set up the callbacks (only update_tips for now)
	callbacks.update_tips = &update_cb;
	callbacks.sideband_progress = &progress_cb;
	callbacks.credentials = cred_acquire_cb;
	git_remote_set_callbacks(remote, &callbacks);

	// Set up the information for the background worker thread
	data.remote = remote;
	data.ret = 0;
	data.finished = 0;

	stats = git_remote_stats(remote);

#ifdef _WIN32
	download(&data);
#else
	pthread_create(&worker, NULL, download, &data);

	// Loop while the worker thread is still running. Here we show processed
	// and total objects in the pack and the amount of received
	// data. Most frontends will probably want to show a percentage and
	// the download rate.
	do {
		usleep(10000);

		if (stats->received_objects == stats->total_objects) {
			printf("Resolving deltas %d/%d\r",
			       stats->indexed_deltas, stats->total_deltas);
		} else if (stats->total_objects > 0) {
			printf("Received %d/%d objects (%d) in %" PRIuZ " bytes\r",
			       stats->received_objects, stats->total_objects,
				   stats->indexed_objects, stats->received_bytes);
		}
	} while (!data.finished);

	if (data.ret < 0)
		goto on_error;

	pthread_join(worker, NULL);
#endif

	/**
	 * If there are local objects (we got a thin pack), then tell
	 * the user how many objects we saved from having to cross the
	 * network.
	 */
	if (stats->local_objects > 0) {
		printf("\rReceived %d/%d objects in %zu bytes (used %d local objects)\n",
		       stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects);
	} else{
		printf("\rReceived %d/%d objects in %zu bytes\n",
			stats->indexed_objects, stats->total_objects, stats->received_bytes);
	}

	// Disconnect the underlying connection to prevent from idling.
	git_remote_disconnect(remote);

	// Update the references in the remote's namespace to point to the
	// right commits. This may be needed even if there was no packfile
	// to download, which can happen e.g. when the branches have been
	// changed but all the needed objects are available locally.
	if (git_remote_update_tips(remote, NULL) < 0)
		return -1;

	git_remote_free(remote);

	return 0;

 on_error:
	git_remote_free(remote);
	return -1;
}
Пример #25
0
/** Entry point for this command */
int fetch(git_repository *repo, int argc, char **argv)
{
	int err = GIT_OK;
	int rc = EXIT_FAILURE;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

	const git_transfer_progress *stats;
	git_remote *remote = NULL;

	if (argc < 2) {
		fprintf(stderr, "usage: %s fetch <repo>\n", argv[-1]);
		return EXIT_FAILURE;
	}

	// Figure out whether it's a named remote or a URL
	printf("Fetching %s for repo at %s\n", argv[1], git_repository_path(repo));
	if (git_remote_lookup(&remote, repo, argv[1]) < 0) {
		if ((err = git_remote_create_anonymous(&remote, repo, argv[1], NULL)) < 0)
			goto out;
	}

	// Set up the callbacks (only update_tips for now)
	callbacks.update_tips = &update_cb;
	callbacks.sideband_progress = &progress_cb;
	callbacks.credentials = cred_acquire_cb;
	callbacks.certificate_check = certificate_check;
	git_remote_set_callbacks(remote, &callbacks);

	stats = git_remote_stats(remote);

	if ((err = git_remote_connect(remote, GIT_DIRECTION_FETCH) < 0))
		goto out;

	// Download the packfile and index it. This function updates the
	// amount of received data and the indexer stats which lets you
	// inform the user about progress.
	if ((err = git_remote_download(remote, NULL) < 0))
		goto out;

	/**
	 * If there are local objects (we got a thin pack), then tell
	 * the user how many objects we saved from having to cross the
	 * network.
	 */
	if (stats->local_objects > 0) {
		printf("\rReceived %d/%d objects in %zu bytes (used %d local objects)\n",
		       stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects);
	} else{
		printf("\rReceived %d/%d objects in %zu bytes\n",
			stats->indexed_objects, stats->total_objects, stats->received_bytes);
	}

	// Disconnect the underlying connection to prevent from idling.
	git_remote_disconnect(remote);

	// Update the references in the remote's namespace to point to the
	// right commits. This may be needed even if there was no packfile
	// to download, which can happen e.g. when the branches have been
	// changed but all the needed objects are available locally.
	if ((err = git_remote_update_tips(remote, NULL, NULL)) < 0)
		goto out;

	rc = EXIT_SUCCESS;
out:
	if (err != GIT_OK)
		libgit_error();
	if (remote) git_remote_free(remote);
	return rc;
}
Пример #26
0
int NotesModel::pull() {

    git_repository *repo = NULL;
    git_remote *remote = NULL;
    git_merge_head *merge_head = NULL;

    if (!QSettings().value("gitRemoteUrl").isValid()) {
        qDebug() << "gitRemoteUrl setting invalid";
        return false; }

    if (QSettings().value("gitRemoteUrl") == "")
        return false;

    try {
        //Open Repo
        e(git_repository_open(&repo, notesFolder().absolutePath().toUtf8().constData()));

        //List repository and add one from Settings if none exists or doesn t have same URI than settings
        git_strarray   remotes = {0};
        git_remote_list(&remotes, repo);
        if (remotes.count >= 1) {
            for (size_t i = 0; i < remotes.count; i++) {
                e(git_remote_load(&remote, repo, remotes.strings[i]));
                qDebug() << git_remote_url(remote);
                if (QSettings().value("gitRemoteUrl").isValid() && git_remote_url(remote)) {
                    if (strcmp(git_remote_url(remote),QSettings().value("gitRemoteUrl").toString().toUtf8().constData()) != 0) {
                        e(git_remote_delete(remote));
                        e(git_remote_create(&remote, repo, "upstream",
                                            QSettings().value("gitRemoteUrl").toString().toUtf8().constData()));
                        e(git_remote_save(remote));
                    }

                }
            }
        } else if (remotes.count == 0) {
            e(git_remote_create(&remote, repo, "upstream",
                                QSettings().value("gitRemoteUrl").toString().toUtf8().constData()));
            e(git_remote_save(remote));
        }

        e(git_remote_load(&remote, repo, "upstream"));

        git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
        callbacks.credentials = cred_acquire_cb;
        e(git_remote_set_callbacks(remote, &callbacks));

        e(git_remote_connect(remote, GIT_DIRECTION_FETCH));
        int connected = git_remote_connected(remote);
        if (connected)
            e(git_remote_fetch(remote, NULL, NULL));


        git_checkout_options checkout_opt = GIT_CHECKOUT_OPTIONS_INIT;
        checkout_opt.checkout_strategy = GIT_CHECKOUT_FORCE;
        checkout_opt.file_mode = 0644;
        git_merge_options merge_opt = GIT_MERGE_OPTIONS_INIT;
        merge_opt.file_favor = GIT_MERGE_FILE_FAVOR_UNION;

        const git_remote_head **head = NULL;
        size_t size = 0;
        e(git_remote_ls(&head, &size, remote));
        if (size <= 0)
            e(-1);

        git_oid oid = head[0]->oid;

        e(git_merge_head_from_fetchhead(&merge_head, repo, "master", git_remote_url(remote), &oid));
        e(git_merge(repo, (const git_merge_head **)(&merge_head), 1, &merge_opt, &checkout_opt));

        //TRY TO COMMIT
        /* Create signature */
        git_signature *me = NULL;
        e(git_signature_now(&me, "sparkleNotes", "*****@*****.**"));

        //Tree Lookup
        git_object *tree_obj;
        e(git_revparse_single(&tree_obj, repo, "HEAD^{tree}"));

        // Get parent commit
        git_oid parentCommitId;
        git_commit *parent;
        git_oid remoteParentCommitId;
        git_commit *remoteParent;
        e(git_reference_name_to_id( &parentCommitId, repo, "ORIG_HEAD" ));
        e(git_commit_lookup( &parent, repo, &parentCommitId ));
        e(git_reference_name_to_id( &remoteParentCommitId, repo, "MERGE_HEAD" ));
        e(git_commit_lookup( &remoteParent, repo, &remoteParentCommitId ));

        if (remoteParent == parent) {
            //Same commit ... nothing to merge
            e(git_repository_state_cleanup(repo));
            git_merge_head_free(merge_head);
            git_remote_free(remote);
            git_repository_free(repo);
            return false;
        }
        const git_commit *parents [2] = { parent, remoteParent };

        git_oid new_commit_id;
        e(git_commit_create(
              &new_commit_id,
              repo,
              "HEAD",                           /* name of ref to update */
              me,                               /* author */
              me,                               /* committer */
              "UTF-8",                          /* message encoding */
              "Merge remote upstream/master",   /* message */
              (git_tree *) tree_obj,            /* root tree */
              2,                                /* parent count */
              parents));                        /* parents */


        git_merge_head_free(merge_head);
        git_remote_free(remote);

        e(git_repository_state_cleanup(repo));

        git_repository_free(repo);

    }

    catch (int error) {
        const git_error *err = giterr_last();
        if (err != NULL)
            qDebug() << QString::number(err->klass) + "\t" + QString(err->message);
        emit this->error(QString(err->message));
        giterr_clear();
        git_merge_head_free(merge_head);
        git_remote_free(remote);
        git_repository_free(repo);
    }
    return true;
}
Пример #27
0
void Gitarre::onPushAction ()
{
	Repository *repo = Repos[RepoView->currentIndex().row()];
	 // TODO: Add remote selection

	git_remote *remote = repo->GetRemote(0);
	struct git_remote_callbacks cb = { 1,
										Gitarre::sRProgressCb,
										Gitarre::sRCompletionCb,
										Gitarre::sRCredentialsCb,
										Gitarre::sRTransferProgressCb,
										Gitarre::sRUpdateTipsCb,
										(void *)this
	};
	git_remote_set_callbacks (remote, &cb);

	// fix git protocol address
	const char *url = git_remote_url (remote);
	if (!strncmp (url, "git@", 4))
	{
		int len = strlen (url) - 4;
		char *_url = (char *) malloc (len + 9);
		strcpy (_url, "https://");
		strncpy (_url + 8, url + 4, len);
		_url [len + 8] = 0;
		char *sc = strrchr (_url, ':');
		if (sc)
			*sc = '/';
		git_remote_set_url (remote, _url);
	}

	StatusLabel->show();
	StatusLabel->setText ("Connecting to remote...");
	StatusProgress->show();
	StatusProgress->setRange (0,0);
	git_remote_connect (remote, GIT_DIRECTION_PUSH);
	if (git_remote_connected (remote))
	{
		git_push *push;
		git_push_new (&push, remote);
		git_push_add_refspec (push, "refs/heads/master:refs/heads/master");

		git_push_set_callbacks (push,
								Gitarre::sPPackbuilderProgressCb,
								(void *)this,
								Gitarre::sPTransferProgressCb,
								(void *)this);
		git_push_finish (push);
		if (git_push_unpack_ok (push))
		{
			git_push_status_foreach (push, Gitarre::sPStatusForeachCb, (void *)this);
			git_push_update_tips (push);
		}
		git_push_free (push);
		git_remote_disconnect (remote);
		git_remote_free (remote);
	}
	else
	{
		const git_error *error = giterr_last ();
		if (error->message)
			QMessageBox::warning(this, "Connect to remote", QString ("Failed to connect to ") + git_remote_url (remote) + " :\n" + error->message);
		else
			QMessageBox::warning(this, "Connect to remote", QString ("Failed to connect to ") + git_remote_url (remote));
	}
	StatusLabel->hide();
	StatusProgress->hide();
}