Beispiel #1
0
int
Repository_head__set__(Repository *self, PyObject *py_val)
{
    int err;
    if (PyObject_TypeCheck(py_val, &OidType)) {
        git_oid oid;
        py_oid_to_git_oid(py_val, &oid);
        err = git_repository_set_head_detached(self->repo, &oid, NULL, NULL);
        if (err < 0) {
            Error_set(err);
            return -1;
        }
    } else {
        const char *refname;
        PyObject *trefname;

        refname = py_str_borrow_c_str(&trefname, py_val, NULL);
        if (refname == NULL)
            return -1;

        err = git_repository_set_head(self->repo, refname, NULL, NULL);
        Py_DECREF(trefname);
        if (err < 0) {
            Error_set_str(err, refname);
            return -1;
        }
    }

    return 0;
}
Beispiel #2
0
void test_repo_head__setting_head_updates_reflog(void)
{
	git_object *tag;
	git_signature *sig;
	git_annotated_commit *annotated;

	cl_git_pass(git_signature_now(&sig, "me", "*****@*****.**"));

	cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked"));
	cl_git_pass(git_repository_set_head(repo, "refs/heads/unborn"));
	cl_git_pass(git_revparse_single(&tag, repo, "tags/test"));
	cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag)));
	cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked"));

	test_reflog(repo, 2, NULL, "refs/heads/haacked", "*****@*****.**", "checkout: moving from master to haacked");
	test_reflog(repo, 1, NULL, "tags/test^{commit}", "*****@*****.**", "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d");
	test_reflog(repo, 0, "tags/test^{commit}", "refs/heads/haacked", "*****@*****.**", "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked");

	cl_git_pass(git_annotated_commit_from_revspec(&annotated, repo, "haacked~0"));
	cl_git_pass(git_repository_set_head_detached_from_annotated(repo, annotated));

	test_reflog(repo, 0, NULL, "refs/heads/haacked", "*****@*****.**", "checkout: moving from haacked to haacked~0");

	git_annotated_commit_free(annotated);
	git_object_free(tag);
	git_signature_free(sig);
}
Beispiel #3
0
void test_refs_reflog_messages__detaching_writes_reflog(void)
{
	git_signature *sig;
	git_oid id;
	const char *msg;

	cl_git_pass(git_signature_now(&sig, "me", "*****@*****.**"));

	msg = "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d";
	git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d");
	cl_git_pass(git_repository_set_head_detached(g_repo, &id));
	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0,
		"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
		"e90810b8df3e80c413d903f631643c716887138d",
		NULL, msg);

	msg = "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked";
	cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked"));
	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0,
		"e90810b8df3e80c413d903f631643c716887138d",
		"258f0e2a959a364e40ed6603d5d44fbb24765b10",
		NULL, msg);

	git_signature_free(sig);
}
Beispiel #4
0
void test_repo_head__orphan_branch_does_not_count(void)
{
    git_signature *sig;
    git_oid id;
    const char *msg;

    cl_git_pass(git_signature_now(&sig, "me", "*****@*****.**"));

    /* Have something known */
    msg = "message1";
    git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d");
    cl_git_pass(git_repository_set_head_detached(repo, &id, sig, msg));
    assert_head_reflog(repo, 0, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
                       "e90810b8df3e80c413d903f631643c716887138d", msg);

    /* Switching to an orphan branch does not write tot he reflog */
    cl_git_pass(git_repository_set_head(repo, "refs/heads/orphan", sig, "ignored message"));
    assert_head_reflog(repo, 0, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
                       "e90810b8df3e80c413d903f631643c716887138d", msg);

    /* And coming back, we set the source to zero */
    msg = "message2";
    cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", sig, msg));
    assert_head_reflog(repo, 0, "0000000000000000000000000000000000000000",
                       "258f0e2a959a364e40ed6603d5d44fbb24765b10", msg);

    git_signature_free(sig);
}
Beispiel #5
0
void test_refs_reflog_messages__orphan_branch_does_not_count(void)
{
	git_oid id;
	const char *msg;

	/* Have something known */
	msg = "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d";
	git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d");
	cl_git_pass(git_repository_set_head_detached(g_repo, &id));
	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0,
		"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
		"e90810b8df3e80c413d903f631643c716887138d",
		NULL, msg);

	/* Switching to an orphan branch does not write to the reflog */
	cl_git_pass(git_repository_set_head(g_repo, "refs/heads/orphan"));
	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0,
		"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
		"e90810b8df3e80c413d903f631643c716887138d",
		NULL, msg);

	/* And coming back, we set the source to zero */
	msg = "checkout: moving from orphan to haacked";
	cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked"));
	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0,
		"0000000000000000000000000000000000000000",
		"258f0e2a959a364e40ed6603d5d44fbb24765b10",
		NULL, msg);
}
Beispiel #6
0
void test_repo_head__set_head_detached_Return_ENOTFOUND_when_the_object_doesnt_exist(void)
{
	git_oid oid;

	cl_git_pass(git_oid_fromstr(&oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));

	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head_detached(repo, &oid));
}
Beispiel #7
0
void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish(void)
{
	git_object *blob;

	cl_git_pass(git_revparse_single(&blob, repo, "point_to_blob"));

	cl_git_fail(git_repository_set_head_detached(repo, git_object_id(blob)));

	git_object_free(blob);
}
Beispiel #8
0
void test_repo_head__set_head_detached_Detaches_HEAD_and_make_it_point_to_the_peeled_commit(void)
{
	git_object *tag;

	cl_git_pass(git_revparse_single(&tag, repo, "tags/test"));
	cl_assert_equal_i(GIT_OBJECT_TAG, git_object_type(tag));

	cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag)));

	assert_head_is_correctly_detached();

	git_object_free(tag);
}
Beispiel #9
0
void test_refs_reflog_messages__setting_head_updates_reflog(void)
{
	git_object *tag;
	git_signature *sig;
	git_annotated_commit *annotated;

	cl_git_pass(git_signature_now(&sig, "me", "*****@*****.**"));

	cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked")); /* 4 */
	cl_git_pass(git_repository_set_head(g_repo, "refs/heads/unborn"));
	cl_git_pass(git_revparse_single(&tag, g_repo, "tags/test"));
	cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(tag))); /* 3 */
	cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked"));        /* 2 */
	cl_git_pass(git_repository_set_head(g_repo, "refs/tags/test"));            /* 1 */
	cl_git_pass(git_repository_set_head(g_repo, "refs/remotes/test/master"));  /* 0 */

	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 4,
		NULL, "refs/heads/haacked",
		"*****@*****.**",
		"checkout: moving from master to haacked");
	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 3,
		NULL, "tags/test^{commit}",
		"*****@*****.**",
		"checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d");
	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 2,
		"tags/test^{commit}", "refs/heads/haacked",
		"*****@*****.**",
		"checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked");
	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 1,
		"refs/heads/haacked", "tags/test^{commit}",
		"*****@*****.**",
		"checkout: moving from haacked to test");
	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0,
		"tags/test^{commit}", "refs/remotes/test/master",
		"*****@*****.**",
		"checkout: moving from e90810b8df3e80c413d903f631643c716887138d to test/master");

	cl_git_pass(git_annotated_commit_from_revspec(&annotated, g_repo, "haacked~0"));
	cl_git_pass(git_repository_set_head_detached_from_annotated(g_repo, annotated));

	cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0,
		NULL, "refs/heads/haacked",
		"*****@*****.**",
		"checkout: moving from be3563ae3f795b2b4353bcce3a527ad0a4f7f644 to haacked~0");

	git_annotated_commit_free(annotated);
	git_object_free(tag);
	git_signature_free(sig);
}
Beispiel #10
0
void test_checkout_typechange__checkout_with_conflicts(void)
{
    int i;
    git_object *obj;
    git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
    notify_counts cts = {0};

    opts.notify_flags =
        GIT_CHECKOUT_NOTIFY_CONFLICT | GIT_CHECKOUT_NOTIFY_UNTRACKED;
    opts.notify_cb = notify_counter;
    opts.notify_payload = &cts;

    for (i = 0; g_typechange_oids[i] != NULL; ++i) {
        cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i]));

        force_create_file("typechanges/a/blocker");
        force_create_file("typechanges/b");
        force_create_file("typechanges/c/sub/sub/file");
        git_futils_rmdir_r("typechanges/d", NULL, GIT_RMDIR_REMOVE_FILES);
        p_mkdir("typechanges/d", 0777); /* intentionally empty dir */
        force_create_file("typechanges/untracked");

        opts.checkout_strategy = GIT_CHECKOUT_SAFE;
        memset(&cts, 0, sizeof(cts));

        cl_git_fail(git_checkout_tree(g_repo, obj, &opts));
        cl_assert(cts.conflicts > 0);
        cl_assert(cts.untracked > 0);

        opts.checkout_strategy =
            GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;
        memset(&cts, 0, sizeof(cts));

        cl_assert(git_path_exists("typechanges/untracked"));

        cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
        cl_assert_equal_i(0, cts.conflicts);

        cl_assert(!git_path_exists("typechanges/untracked"));

        cl_git_pass(
            git_repository_set_head_detached(g_repo, git_object_id(obj)));

        assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true);

        git_object_free(obj);
    }
}
Beispiel #11
0
void test_checkout_tree__can_disable_pattern_match(void)
{
	char *entries[] = { "b*.txt" };

	/* reset to beginning of history (i.e. just a README file) */

	g_opts.checkout_strategy =
		GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;

	cl_git_pass(git_revparse_single(&g_object, g_repo, "8496071c1b46c854b31185ea97743be6a8774479"));

	cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
	cl_git_pass(
		git_repository_set_head_detached(g_repo, git_object_id(g_object)));

	git_object_free(g_object);
	g_object = NULL;

	cl_assert(!git_path_isfile("testrepo/branch_file.txt"));

	/* now to a narrow patterned checkout, but disable pattern */

	g_opts.checkout_strategy =
		GIT_CHECKOUT_SAFE |
		GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH;
	g_opts.paths.strings = entries;
	g_opts.paths.count = 1;

	cl_git_pass(git_revparse_single(&g_object, g_repo, "refs/heads/master"));

	cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));

	cl_assert(!git_path_isfile("testrepo/branch_file.txt"));

	/* let's try that again, but allow the pattern match */

	g_opts.checkout_strategy = GIT_CHECKOUT_SAFE;

	cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));

	cl_assert(git_path_isfile("testrepo/branch_file.txt"));
}
Beispiel #12
0
void test_checkout_typechange__checkout_typechanges_safe(void)
{
    int i;
    git_object *obj;
    git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;

    for (i = 0; g_typechange_oids[i] != NULL; ++i) {
        cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i]));

        opts.checkout_strategy = GIT_CHECKOUT_FORCE;

        /* There are bugs in some submodule->tree changes that prevent
         * SAFE from passing here, even though the following should work:
         */
        /* !i ? GIT_CHECKOUT_FORCE : GIT_CHECKOUT_SAFE; */

        cl_git_pass(git_checkout_tree(g_repo, obj, &opts));

        cl_git_pass(
            git_repository_set_head_detached(g_repo, git_object_id(obj)));

        assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true);

        git_object_free(obj);

        if (!g_typechange_empty[i]) {
            cl_assert(git_path_isdir("typechanges"));
            cl_assert(git_path_exists("typechanges/a"));
            cl_assert(git_path_exists("typechanges/b"));
            cl_assert(git_path_exists("typechanges/c"));
            cl_assert(git_path_exists("typechanges/d"));
            cl_assert(git_path_exists("typechanges/e"));
        } else {
            cl_assert(git_path_isdir("typechanges"));
            cl_assert(!git_path_exists("typechanges/a"));
            cl_assert(!git_path_exists("typechanges/b"));
            cl_assert(!git_path_exists("typechanges/c"));
            cl_assert(!git_path_exists("typechanges/d"));
            cl_assert(!git_path_exists("typechanges/e"));
        }
    }
}
Beispiel #13
0
void test_repo_head__setting_head_updates_reflog(void)
{
    git_object *tag;
    git_signature *sig;

    cl_git_pass(git_signature_now(&sig, "me", "*****@*****.**"));

    cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", sig, "message1"));
    cl_git_pass(git_repository_set_head(repo, "refs/heads/unborn", sig, "message2"));
    cl_git_pass(git_revparse_single(&tag, repo, "tags/test"));
    cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag), sig, "message3"));
    cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", sig, "message4"));

    test_reflog(repo, 2, NULL, "refs/heads/haacked", "*****@*****.**", "message1");
    test_reflog(repo, 1, NULL, "tags/test^{commit}", "*****@*****.**", "message3");
    test_reflog(repo, 0, "tags/test^{commit}", "refs/heads/haacked", "*****@*****.**", "message4");

    git_object_free(tag);
    git_signature_free(sig);
}
Beispiel #14
0
void test_repo_head__detaching_writes_reflog(void)
{
    git_signature *sig;
    git_oid id;
    const char *msg;

    cl_git_pass(git_signature_now(&sig, "me", "*****@*****.**"));

    msg = "message1";
    git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d");
    cl_git_pass(git_repository_set_head_detached(repo, &id, sig, msg));
    assert_head_reflog(repo, 0, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
                       "e90810b8df3e80c413d903f631643c716887138d", msg);

    msg = "message2";
    cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", sig, msg));
    assert_head_reflog(repo, 0, "e90810b8df3e80c413d903f631643c716887138d",
                       "258f0e2a959a364e40ed6603d5d44fbb24765b10", msg);

    git_signature_free(sig);
}
Beispiel #15
0
/**
 * Make the repository HEAD directly point to the commit.
 *
 * @param commit S4 class git_commit
 * @return R_NilValue
 */
SEXP git2r_repository_set_head_detached(SEXP commit)
{
    int err;
    SEXP sha;
    git_oid oid;
    git_commit *treeish = NULL;
    git_repository *repository = NULL;

    if (git2r_arg_check_commit(commit))
        git2r_error(git2r_err_commit_arg, __func__, "commit");

    repository = git2r_repository_open(GET_SLOT(commit, Rf_install("repo")));
    if (!repository)
        git2r_error(git2r_err_invalid_repository, __func__, NULL);

    sha = GET_SLOT(commit, Rf_install("sha"));
    err = git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0)));
    if (GIT_OK != err)
        goto cleanup;

    err = git_commit_lookup(&treeish, repository, &oid);
    if (GIT_OK != err)
        goto cleanup;

    err = git_repository_set_head_detached(
        repository,
        git_commit_id(treeish));

cleanup:
    if (treeish)
        git_commit_free(treeish);

    if (repository)
        git_repository_free(repository);

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

    return R_NilValue;
}
Beispiel #16
0
void test_submodule_init__relative_url_detached_head(void)
{
    git_submodule *sm;
    git_config *cfg;
    git_buf absolute_url = GIT_BUF_INIT;
    const char *config_url;
    git_reference *head_ref = NULL;
    git_object *head_commit = NULL;

    g_repo = setup_fixture_submodule_simple();

    /* Put the parent repository into a detached head state. */
    cl_git_pass(git_repository_head(&head_ref, g_repo));
    cl_git_pass(git_reference_peel(&head_commit, head_ref, GIT_OBJ_COMMIT));

    cl_git_pass(git_repository_set_head_detached(g_repo, git_commit_id((git_commit *)head_commit)));

    cl_assert(git_path_dirname_r(&absolute_url, git_repository_workdir(g_repo)) > 0);
    cl_git_pass(git_buf_joinpath(&absolute_url, absolute_url.ptr, "testrepo.git"));

    cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo"));

    /* verify that the .gitmodules is set with an absolute path*/
    cl_assert_equal_s("../testrepo.git", git_submodule_url(sm));

    /* init and verify that absolute path is written to .git/config */
    cl_git_pass(git_submodule_init(sm, false));

    cl_git_pass(git_repository_config_snapshot(&cfg, g_repo));

    cl_git_pass(git_config_get_string(&config_url, cfg, "submodule.testrepo.url"));
    cl_assert_equal_s(absolute_url.ptr, config_url);

    git_buf_free(&absolute_url);
    git_config_free(cfg);
    git_object_free(head_commit);
    git_reference_free(head_ref);
    git_submodule_free(sm);
}
Beispiel #17
0
void test_checkout_tree__can_checkout_with_pattern(void)
{
	char *entries[] = { "[l-z]*.txt" };

	/* reset to beginning of history (i.e. just a README file) */

	g_opts.checkout_strategy =
		GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;

	cl_git_pass(git_revparse_single(&g_object, g_repo, "8496071c1b46c854b31185ea97743be6a8774479"));

	cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
	cl_git_pass(
		git_repository_set_head_detached(g_repo, git_object_id(g_object)));

	git_object_free(g_object);
	g_object = NULL;

	cl_assert(git_path_exists("testrepo/README"));
	cl_assert(!git_path_exists("testrepo/branch_file.txt"));
	cl_assert(!git_path_exists("testrepo/link_to_new.txt"));
	cl_assert(!git_path_exists("testrepo/new.txt"));

	/* now to a narrow patterned checkout */

	g_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
	g_opts.paths.strings = entries;
	g_opts.paths.count = 1;

	cl_git_pass(git_revparse_single(&g_object, g_repo, "refs/heads/master"));

	cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));

	cl_assert(git_path_exists("testrepo/README"));
	cl_assert(!git_path_exists("testrepo/branch_file.txt"));
	cl_assert(git_path_exists("testrepo/link_to_new.txt"));
	cl_assert(git_path_exists("testrepo/new.txt"));
}
Beispiel #18
0
void test_clone_nonetwork__can_detached_head(void)
{
	git_object *obj;
	git_repository *cloned;
	git_reference *cloned_head;

	cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));

	cl_git_pass(git_revparse_single(&obj, g_repo, "master~1"));
	cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(obj)));

	cl_git_pass(git_clone(&cloned, "./foo", "./foo1", &g_options));

	cl_assert(git_repository_head_detached(cloned));

	cl_git_pass(git_repository_head(&cloned_head, cloned));
	cl_assert_equal_oid(git_object_id(obj), git_reference_target(cloned_head));

	git_object_free(obj);
	git_reference_free(cloned_head);
	git_repository_free(cloned);

	cl_fixture_cleanup("./foo1");
}
Beispiel #19
0
static int update_head_to_remote(git_repository *repo, git_remote *remote)
{
	int retcode = -1;
	git_refspec dummy_spec;
	git_remote_head *remote_head;
	struct head_info head_info;
	git_buf remote_master_name = GIT_BUF_INIT;

	/* Did we just clone an empty repository? */
	if (remote->refs.length == 0) {
		return setup_tracking_config(
			repo,
			"master",
			GIT_REMOTE_ORIGIN,
			GIT_REFS_HEADS_MASTER_FILE);
	}

	/* Get the remote's HEAD. This is always the first ref in remote->refs. */
	remote_head = NULL;

	if (!remote->transport->ls(remote->transport, get_head_callback, &remote_head))
		return -1;

	assert(remote_head);

	git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid);
	git_buf_init(&head_info.branchname, 16);
	head_info.repo = repo;
	head_info.refspec = git_remote__matching_refspec(remote, GIT_REFS_HEADS_MASTER_FILE);
	head_info.found = 0;

	if (head_info.refspec == NULL) {
		memset(&dummy_spec, 0, sizeof(git_refspec));
		head_info.refspec = &dummy_spec;
	}

	/* Determine the remote tracking reference name from the local master */
	if (git_refspec_transform_r(
		&remote_master_name,
		head_info.refspec,
		GIT_REFS_HEADS_MASTER_FILE) < 0)
			return -1;

	/* Check to see if the remote HEAD points to the remote master */
	if (reference_matches_remote_head(git_buf_cstr(&remote_master_name), &head_info) < 0)
		goto cleanup;

	if (head_info.found) {
		retcode = update_head_to_new_branch(
			repo,
			&head_info.remote_head_oid,
			git_buf_cstr(&head_info.branchname));

		goto cleanup;
	}

	/* Not master. Check all the other refs. */
	if (git_reference_foreach_name(
		repo,
		reference_matches_remote_head,
		&head_info) < 0)
			goto cleanup;

	if (head_info.found) {
		retcode = update_head_to_new_branch(
			repo,
			&head_info.remote_head_oid,
			git_buf_cstr(&head_info.branchname));

		goto cleanup;
	} else {
		retcode = git_repository_set_head_detached(
			repo,
			&head_info.remote_head_oid);
		goto cleanup;
	}

cleanup:
	git_buf_free(&remote_master_name);
	git_buf_free(&head_info.branchname);
	return retcode;
}
Beispiel #20
0
static int update_head_to_remote(
		git_repository *repo,
		git_remote *remote,
		const git_signature *signature,
		const char *reflog_message)
{
	int error = 0, found_branch = 0;
	size_t refs_len;
	git_refspec dummy_spec, *refspec;
	const git_remote_head *remote_head, **refs;
	const git_oid *remote_head_id;
	git_buf remote_master_name = GIT_BUF_INIT;
	git_buf branch = GIT_BUF_INIT;

	if ((error = git_remote_ls(&refs, &refs_len, remote)) < 0)
		return error;

	/* Did we just clone an empty repository? */
	if (refs_len == 0)
		return setup_tracking_config(
			repo, "master", GIT_REMOTE_ORIGIN, GIT_REFS_HEADS_MASTER_FILE);

	error = git_remote_default_branch(&branch, remote);
	if (error == GIT_ENOTFOUND) {
		git_buf_puts(&branch, GIT_REFS_HEADS_MASTER_FILE);
	} else {
		found_branch = 1;
	}

	/* Get the remote's HEAD. This is always the first ref in the list. */
	remote_head = refs[0];
	assert(remote_head);

	remote_head_id = &remote_head->oid;
	refspec = git_remote__matching_refspec(remote, git_buf_cstr(&branch));

	if (refspec == NULL) {
		memset(&dummy_spec, 0, sizeof(git_refspec));
		refspec = &dummy_spec;
	}

	/* Determine the remote tracking reference name from the local master */
	if ((error = git_refspec_transform(
		&remote_master_name,
		refspec,
		git_buf_cstr(&branch))) < 0)
		return error;

	if (found_branch) {
		error = update_head_to_new_branch(
			repo,
			remote_head_id,
			git_buf_cstr(&branch),
			signature, reflog_message);
	} else {
		error = git_repository_set_head_detached(
			repo, remote_head_id, signature, reflog_message);
	}

	git_buf_free(&remote_master_name);
	git_buf_free(&branch);
	return error;
}
Beispiel #21
0
static int handle(KDriver const *driver, KImplementation const *impl, int requested)
{
	char const *url = k_dictionary_get(k_implementation_get_values(impl), "href");
	char const *tag = k_dictionary_get(k_implementation_get_values(impl), "tag");
	char const *path = k_dictionary_get(k_implementation_get_meta(impl), "name");

	git_repository* repo = NULL;
	git_remote* origin = NULL;

	if (git_repository_open(&repo, path) == GIT_OK)
	{
		if (git_remote_load(&origin, repo, "origin") != GIT_OK)
		{
			git_repository_free(repo);
			return -1;
		}

		if (strcmp(url, git_remote_url(origin)) != 0)
		{
			giterr_set_str(GITERR_INVALID, "different origin");
			git_repository_free(repo);
			return -1;
		}
	}
	else
	{
		if (git_repository_init(&repo, path, 0) != GIT_OK)
		{
			return -1;
		}

		if (git_remote_create(&origin, repo, "origin", url) != GIT_OK)
		{
			git_repository_free(repo);
			return -1;
		}
	}

	git_remote_set_update_fetchhead(origin, 0);
	git_remote_set_cred_acquire_cb(origin, cred_acquire, NULL);

	if (git_remote_connect(origin, GIT_DIRECTION_FETCH) != GIT_OK)
	{
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	if (git_remote_download(origin, transfer_progress, NULL) != GIT_OK)
	{
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	if (git_remote_update_tips(origin) != GIT_OK)
	{
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	git_object* object = NULL;

	if (git_revparse_single(&object, repo, tag) != GIT_OK)
	{
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	if (git_repository_set_head_detached(repo, git_object_id(object)) != GIT_OK)
	{
		git_object_free(object);
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT;
	checkout_opts.version = GIT_CHECKOUT_OPTS_VERSION;
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
	checkout_opts.progress_cb = checkout_progress;
	checkout_opts.progress_payload = NULL;

	if (git_checkout_tree(repo, object, &checkout_opts) != GIT_OK)
	{
		git_object_free(object);
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	git_object_free(object);
	git_remote_free(origin);
	git_repository_free(repo);
	return 0;
}
Beispiel #22
0
void download(KImplementation const *impl, int requested, KError *error, void *ctx)
  {
  KDictionary const *values = k_implementation_get_values(impl);
  char const *href = k_dictionary_lookup(values, "href");
  char const *tag = k_dictionary_lookup(values, "tag");
  char const *path = k_implementation_get_name(impl);

  git_repository *repo = NULL;
  git_remote *origin = NULL;
  git_object *object = NULL;

  struct progress_data progress_data = {{0}};
  git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT;
  checkout_opts.version = GIT_CHECKOUT_OPTS_VERSION;
  checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
  checkout_opts.progress_cb = checkout_progress;
  checkout_opts.progress_payload = &progress_data;

  if (git_repository_open(&repo, path) == GIT_OK)
    {
    if (git_remote_load(&origin, repo, "origin") != GIT_OK)
      {
      k_error_set(error, giterr_last()->message);
      goto repository_free;
      }
    if (strcmp(git_remote_url(origin), href) != 0)
      {
      k_error_set(error, "different origin");
      goto remote_free;
      }
    }
  else
    {
    if (git_repository_init(&repo, path, 0) != GIT_OK)
      {
      k_error_set(error, giterr_last()->message);
      return;
      }
    if (git_remote_create(&origin, repo, "origin", href) != GIT_OK)
      {
      k_error_set(error, giterr_last()->message);
      goto repository_free;
      }
    }
  git_remote_set_update_fetchhead(origin, 0);
  git_remote_set_cred_acquire_cb(origin, cred_acquire, NULL);
  if (git_remote_connect(origin, GIT_DIRECTION_FETCH) != GIT_OK)
    {
    k_error_set(error, giterr_last()->message);
    goto remote_free;
    }
  if (git_remote_download(origin, fetch_progress, &progress_data) != GIT_OK)
    {
    k_error_set(error, giterr_last()->message);
    goto remote_disconnect;
    }
  if (git_remote_update_tips(origin) != GIT_OK)
    {
    k_error_set(error, giterr_last()->message);
    goto remote_disconnect;
    }
  if (git_revparse_single(&object, repo, tag) != GIT_OK)
    {
    k_error_set(error, giterr_last()->message);
    goto remote_disconnect;
    }
  if (git_repository_set_head_detached(repo, git_object_id(object)) != GIT_OK)
    {
    k_error_set(error, giterr_last()->message);
    goto remote_disconnect;
    }
  if (git_checkout_tree(repo, object, &checkout_opts) != GIT_OK)
    {
    k_error_set(error, giterr_last()->message);
    }
remote_disconnect:
  git_remote_disconnect(origin);
remote_free:
  git_remote_free(origin);
repository_free:
  git_repository_free(repo);
  }
Beispiel #23
0
static int update_head_to_remote(
		git_repository *repo,
		git_remote *remote,
		const char *reflog_message)
{
	int error = 0;
	size_t refs_len;
	git_refspec *refspec;
	const git_remote_head *remote_head, **refs;
	const git_oid *remote_head_id;
	git_buf remote_master_name = GIT_BUF_INIT;
	git_buf branch = GIT_BUF_INIT;

	if ((error = git_remote_ls(&refs, &refs_len, remote)) < 0)
		return error;

	/* We cloned an empty repository or one with an unborn HEAD */
	if (refs_len == 0 || strcmp(refs[0]->name, GIT_HEAD_FILE))
		return setup_tracking_config(
			repo, "master", GIT_REMOTE_ORIGIN, GIT_REFS_HEADS_MASTER_FILE);

	/* We know we have HEAD, let's see where it points */
	remote_head = refs[0];
	assert(remote_head);

	remote_head_id = &remote_head->oid;

	error = git_remote_default_branch(&branch, remote);
	if (error == GIT_ENOTFOUND) {
		error = git_repository_set_head_detached(
			repo, remote_head_id);
		goto cleanup;
	}

	refspec = git_remote__matching_refspec(remote, git_buf_cstr(&branch));

	if (refspec == NULL) {
		git_error_set(GIT_ERROR_NET, "the remote's default branch does not fit the refspec configuration");
		error = GIT_EINVALIDSPEC;
		goto cleanup;
	}

	/* Determine the remote tracking reference name from the local master */
	if ((error = git_refspec_transform(
		&remote_master_name,
		refspec,
		git_buf_cstr(&branch))) < 0)
		goto cleanup;

	error = update_head_to_new_branch(
		repo,
		remote_head_id,
		git_buf_cstr(&branch),
		reflog_message);

cleanup:
	git_buf_dispose(&remote_master_name);
	git_buf_dispose(&branch);

	return error;
}