Exemplo n.º 1
0
void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_collide_with_an_existing_one(void)
{
	git_reference *original_ref, *new_ref;
	git_config *config;
	git_buf buf = GIT_BUF_INIT;
	char *original_remote, *original_merge;
	const char *str;

	cl_git_pass(git_repository_config_snapshot(&config, repo));

	cl_git_pass(git_config_get_string_buf(&buf, config, "branch.master.remote"));
	original_remote = git_buf_detach(&buf);
	cl_git_pass(git_config_get_string_buf(&buf, config, "branch.master.merge"));
	original_merge  = git_buf_detach(&buf);
	git_config_free(config);

	cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));

	cl_assert_equal_i(GIT_EEXISTS,
		git_branch_move(&new_ref, original_ref, "master", 0));

	cl_assert(giterr_last()->message != NULL);

	cl_git_pass(git_repository_config_snapshot(&config, repo));
	cl_git_pass(git_config_get_string(&str, config, "branch.master.remote"));
	cl_assert_equal_s(original_remote, str);
	cl_git_pass(git_config_get_string(&str, config, "branch.master.merge"));
	cl_assert_equal_s(original_merge,  str);
	git_config_free(config);

	cl_assert_equal_i(GIT_EEXISTS,
		git_branch_move(&new_ref, original_ref, "cannot-fetch", 0));

	cl_assert(giterr_last()->message != NULL);

	cl_git_pass(git_repository_config_snapshot(&config, repo));
	cl_git_pass(git_config_get_string(&str, config, "branch.master.remote"));
	cl_assert_equal_s(original_remote, str);
	cl_git_pass(git_config_get_string(&str, config, "branch.master.merge"));
	cl_assert_equal_s(original_merge,  str);
	git_config_free(config);

	git_reference_free(original_ref);
	cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/track-local"));

	cl_assert_equal_i(GIT_EEXISTS,
		git_branch_move(&new_ref, original_ref, "master", 0));

	cl_assert(giterr_last()->message != NULL);

	cl_git_pass(git_repository_config_snapshot(&config, repo));
	cl_git_pass(git_config_get_string(&str, config, "branch.master.remote"));
	cl_assert_equal_s(original_remote, str);
	cl_git_pass(git_config_get_string(&str, config, "branch.master.merge"));
	cl_assert_equal_s(original_merge,  str);

	git__free(original_remote); git__free(original_merge);
	git_reference_free(original_ref);
	git_config_free(config);
}
Exemplo n.º 2
0
void test_status_ignore__subdir_doesnt_match_above(void)
{
	int ignored, icase = 0, error;
	git_config *cfg;

	g_repo = cl_git_sandbox_init("empty_standard_repo");

	cl_git_pass(git_repository_config_snapshot(&cfg, g_repo));
	error = git_config_get_bool(&icase, cfg, "core.ignorecase");
	git_config_free(cfg);
	if (error == GIT_ENOTFOUND)
		error = 0;

	cl_git_pass(error);

	cl_git_pass(p_mkdir("empty_standard_repo/src", 0777));
	cl_git_pass(p_mkdir("empty_standard_repo/src/src", 0777));
	cl_git_mkfile("empty_standard_repo/src/.gitignore", "src\n");
	cl_git_mkfile("empty_standard_repo/.gitignore", "");

	cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/test.txt"));
	cl_assert_equal_i(0, ignored);
	cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/src/test.txt"));
	cl_assert_equal_i(1, ignored);
	cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/foo/test.txt"));
	cl_assert_equal_i(0, ignored);

	cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "SRC/src/test.txt"));
	cl_assert_equal_i(icase, ignored);
	cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/SRC/test.txt"));
	cl_assert_equal_i(icase, ignored);
}
Exemplo n.º 3
0
void test_submodule_modify__init(void)
{
	git_config *cfg;
	const char *str;

	/* erase submodule data from .git/config */
	cl_git_pass(git_repository_config(&cfg, g_repo));
	cl_git_pass(
		git_config_foreach_match(cfg, "submodule\\..*", delete_one_config, cfg));
	git_config_free(cfg);

	/* confirm no submodule data in config */
	cl_git_pass(git_repository_config(&cfg, g_repo));
	cl_git_fail(git_config_get_string(&str, cfg, "submodule.sm_unchanged.url"));
	cl_git_fail(git_config_get_string(&str, cfg, "submodule.sm_changed_head.url"));
	cl_git_fail(git_config_get_string(&str, cfg, "submodule.sm_added_and_uncommited.url"));
	git_config_free(cfg);

	/* call init and see that settings are copied */
	cl_git_pass(git_submodule_foreach(g_repo, init_one_submodule, NULL));

	git_submodule_reload_all(g_repo, 1);

	/* confirm submodule data in config */
	cl_git_pass(git_repository_config_snapshot(&cfg, g_repo));
	cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_unchanged.url"));
	cl_assert(git__suffixcmp(str, "/submod2_target") == 0);
	cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_changed_head.url"));
	cl_assert(git__suffixcmp(str, "/submod2_target") == 0);
	cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_added_and_uncommited.url"));
	cl_assert(git__suffixcmp(str, "/submod2_target") == 0);
	git_config_free(cfg);
}
Exemplo n.º 4
0
Arquivo: init.c Projeto: azyx3/libgit2
void test_submodule_init__relative_url(void)
{
    git_submodule *sm;
    git_config *cfg;
    git_buf absolute_url = GIT_BUF_INIT;
    const char *config_url;

    g_repo = setup_fixture_submodule_simple();

    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_submodule_free(sm);
}
Exemplo n.º 5
0
int git_signature_default(git_signature **out, git_repository *repo)
{
	int error;
	git_config *cfg;
	const char *user_name, *user_email;

	if ((error = git_repository_config_snapshot(&cfg, repo)) < 0)
		return error;

	if (!(error = git_config_get_string(&user_name, cfg, "user.name")) &&
		!(error = git_config_get_string(&user_email, cfg, "user.email")))
		error = git_signature_now(out, user_name, user_email);

	git_config_free(cfg);
	return error;
}
Exemplo n.º 6
0
void test_submodule_modify__sync(void)
{
	git_submodule *sm1, *sm2, *sm3;
	git_config *cfg;
	const char *str;

#define SM1 "sm_unchanged"
#define SM2 "sm_changed_head"
#define SM3 "sm_added_and_uncommited"

	/* look up some submodules */
	cl_git_pass(git_submodule_lookup(&sm1, g_repo, SM1));
	cl_git_pass(git_submodule_lookup(&sm2, g_repo, SM2));
	cl_git_pass(git_submodule_lookup(&sm3, g_repo, SM3));

	/* At this point, the .git/config URLs for the submodules have
	 * not be rewritten with the absolute paths (although the
	 * .gitmodules have.  Let's confirm that they DO NOT match
	 * yet, then we can do a sync to make them match...
	 */

	/* check submodule info does not match before sync */
	cl_git_pass(git_repository_config_snapshot(&cfg, g_repo));
	cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM1".url"));
	cl_assert(strcmp(git_submodule_url(sm1), str) != 0);
	cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM2".url"));
	cl_assert(strcmp(git_submodule_url(sm2), str) != 0);
	cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM3".url"));
	cl_assert(strcmp(git_submodule_url(sm3), str) != 0);
	git_config_free(cfg);

	/* sync all the submodules */
	cl_git_pass(git_submodule_foreach(g_repo, sync_one_submodule, NULL));

	/* check that submodule config is updated */
	assert_submodule_url_is_synced(
		sm1, "submodule."SM1".url", "branch.origin.remote");
	assert_submodule_url_is_synced(
		sm2, "submodule."SM2".url", "branch.origin.remote");
	assert_submodule_url_is_synced(
		sm3, "submodule."SM3".url", "branch.origin.remote");

	git_submodule_free(sm1);
	git_submodule_free(sm2);
	git_submodule_free(sm3);
}
Exemplo n.º 7
0
int git_repository_open_ext(
	git_repository **repo_ptr,
	const char *start_path,
	unsigned int flags,
	const char *ceiling_dirs)
{
	int error;
	git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT;
	git_repository *repo;

	if (repo_ptr)
		*repo_ptr = NULL;

	error = find_repo(&path, &parent, start_path, flags, ceiling_dirs);
	if (error < 0 || !repo_ptr)
		return error;

	repo = repository_alloc();
	GITERR_CHECK_ALLOC(repo);

	repo->path_repository = git_buf_detach(&path);
	GITERR_CHECK_ALLOC(repo->path_repository);

	if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
		repo->is_bare = 1;
	else {
		git_config *config = NULL;

		if ((error = git_repository_config_snapshot(&config, repo)) < 0 ||
			(error = load_config_data(repo, config)) < 0 ||
			(error = load_workdir(repo, config, &parent)) < 0)
			git_repository_free(repo);

		git_config_free(config);
	}

	if (!error)
		*repo_ptr = repo;
	git_buf_free(&parent);

	return error;
}
Exemplo n.º 8
0
void test_checkout_icase__initialize(void)
{
	git_oid id;
	git_config *cfg;
	int icase = 0;

	repo = cl_git_sandbox_init("testrepo");

	cl_git_pass(git_repository_config_snapshot(&cfg, repo));
	git_config_get_bool(&icase, cfg, "core.ignorecase");
	git_config_free(cfg);

	if (!icase)
		cl_skip();

	cl_git_pass(git_reference_name_to_id(&id, repo, "refs/heads/dir"));
	cl_git_pass(git_object_lookup(&obj, repo, &id, GIT_OBJ_ANY));

	git_checkout_init_options(&checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION);
	checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;
}
Exemplo n.º 9
0
Arquivo: init.c Projeto: azyx3/libgit2
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);
}
Exemplo n.º 10
0
void test_clone_nonetwork__clone_from_empty_sets_upstream(void)
{
	git_config *config;
	git_repository *repo;
	const char *str;

	/* Create an empty repo to clone from */
	cl_set_cleanup(&cleanup_repository, "./test1");
	cl_git_pass(git_repository_init(&g_repo, "./test1", 0));
	cl_set_cleanup(&cleanup_repository, "./repowithunborn");
	cl_git_pass(git_clone(&repo, "./test1", "./repowithunborn", NULL));

	cl_git_pass(git_repository_config_snapshot(&config, repo));

	cl_git_pass(git_config_get_string(&str, config, "branch.master.remote"));
	cl_assert_equal_s("origin", str);
	cl_git_pass(git_config_get_string(&str, config, "branch.master.merge"));
	cl_assert_equal_s("refs/heads/master", str);

	git_config_free(config);
	git_repository_free(repo);
	cl_fixture_cleanup("./repowithunborn");
}
Exemplo n.º 11
0
int git_branch_upstream_name(
	git_buf *out,
	git_repository *repo,
	const char *refname)
{
	git_buf remote_name = GIT_BUF_INIT;
	git_buf merge_name = GIT_BUF_INIT;
	git_buf buf = GIT_BUF_INIT;
	int error = -1;
	git_remote *remote = NULL;
	const git_refspec *refspec;
	git_config *config;

	assert(out && refname);

	git_buf_sanitize(out);

	if (!git_reference__is_branch(refname))
		return not_a_local_branch(refname);

	if ((error = git_repository_config_snapshot(&config, repo)) < 0)
		return error;

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

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

	if (git_buf_len(&remote_name) == 0 || git_buf_len(&merge_name) == 0) {
		giterr_set(GITERR_REFERENCE,
			"branch '%s' does not have an upstream", refname);
		error = GIT_ENOTFOUND;
		goto cleanup;
	}

	if (strcmp(".", git_buf_cstr(&remote_name)) != 0) {
		if ((error = git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name))) < 0)
			goto cleanup;

		refspec = git_remote__matching_refspec(remote, git_buf_cstr(&merge_name));
		if (!refspec) {
			error = GIT_ENOTFOUND;
			goto cleanup;
		}

		if (git_refspec_transform(&buf, refspec, git_buf_cstr(&merge_name)) < 0)
			goto cleanup;
	} else
		if (git_buf_set(&buf, git_buf_cstr(&merge_name), git_buf_len(&merge_name)) < 0)
			goto cleanup;

	error = git_buf_set(out, git_buf_cstr(&buf), git_buf_len(&buf));

cleanup:
	git_config_free(config);
	git_remote_free(remote);
	git_buf_free(&remote_name);
	git_buf_free(&merge_name);
	git_buf_free(&buf);
	return error;
}
Exemplo n.º 12
0
int cmd_config(git_repository *repo, int argc, char **argv)
{
	int rc = EXIT_FAILURE;
	int err = 0;

	git_config *config = NULL;

	struct cli cli = {0};

	if (!parse_cli(argc, argv, &cli, POF_VALIDATE))
	{
		return GIT_ERROR;
	}

	if (usage_cli(argv[0], &cli))
	{
		return GIT_OK;
	}

	if (repo && !cli.global)
	{
		if (!cli.value)
		{
			if ((err = git_repository_config_snapshot(&config,repo)) != GIT_OK)
				goto out;
		} else
		{
			if ((err = git_repository_config(&config,repo)) != GIT_OK)
				goto out;
		}
	} else
	{
#ifdef __amigaos4__
		FILE *f = fopen("ENVARC:gitconfig", "rb");
		if (!f)
		{
			if ((f = fopen("ENVARC:gitconfig", "wb")))
			{
				fprintf(stderr, "Created global config in ENVARC:gitconfig\n");
			} else
			{
				fprintf(stderr, "Unable to create ENVARC:gitconfig\n");
			}
		}
		if (f)
		{
			fclose(f);
		}
#endif
		if ((err = git_config_open_default(&config)))
			goto out;

		if (!cli.value)
		{
			git_config *snapshot;

			if ((err = git_config_snapshot(&snapshot, config)))
				goto out;

			git_config_free(config);
			config = snapshot;
		}
	}

	if (!cli.name)
	{
		fprintf(stderr,"Invalid or not supported command line format!\n");
		goto out;
	}

	if (cli.value)
	{
		if ((err = git_config_set_string(config, cli.name, cli.value)))
			goto out;
	} else
	{
		const char *val;

		if ((err = git_config_get_string(&val, config, cli.name)) != GIT_OK)
			goto out;
		printf("%s\n",val);
	}

	rc = EXIT_SUCCESS;
out:
	if (err) libgit_error();
	if (config) git_config_free(config);

	return rc;
}
Exemplo n.º 13
0
static int git_diff_driver_load(
	git_diff_driver **out, git_repository *repo, const char *driver_name)
{
	int error = 0;
	git_diff_driver_registry *reg;
	git_diff_driver *drv = NULL;
	size_t namelen = strlen(driver_name);
	khiter_t pos;
	git_config *cfg;
	git_buf name = GIT_BUF_INIT;
	const git_config_entry *ce;
	bool found_driver = false;

	if ((reg = git_repository_driver_registry(repo)) == NULL)
		return -1;

	pos = git_strmap_lookup_index(reg->drivers, driver_name);
	if (git_strmap_valid_index(reg->drivers, pos)) {
		*out = git_strmap_value_at(reg->drivers, pos);
		return 0;
	}

	drv = git__calloc(1, sizeof(git_diff_driver) + namelen + 1);
	GITERR_CHECK_ALLOC(drv);
	drv->type = DIFF_DRIVER_AUTO;
	memcpy(drv->name, driver_name, namelen);

	/* if you can't read config for repo, just use default driver */
	if (git_repository_config_snapshot(&cfg, repo) < 0) {
		giterr_clear();
		goto done;
	}

	if ((error = git_buf_printf(&name, "diff.%s.binary", driver_name)) < 0)
		goto done;

	switch (git_config__get_bool_force(cfg, name.ptr, -1)) {
	case true:
		/* if diff.<driver>.binary is true, just return the binary driver */
		*out = &global_drivers[DIFF_DRIVER_BINARY];
		goto done;
	case false:
		/* if diff.<driver>.binary is false, force binary checks off */
		/* but still may have custom function context patterns, etc. */
		drv->binary_flags = GIT_DIFF_FORCE_TEXT;
		found_driver = true;
		break;
	default:
		/* diff.<driver>.binary unspecified or "auto", so just continue */
		break;
	}

	/* TODO: warn if diff.<name>.command or diff.<name>.textconv are set */

	git_buf_truncate(&name, namelen + strlen("diff.."));
	git_buf_put(&name, "xfuncname", strlen("xfuncname"));
	if ((error = git_config_get_multivar_foreach(
			cfg, name.ptr, NULL, diff_driver_xfuncname, drv)) < 0) {
		if (error != GIT_ENOTFOUND)
			goto done;
		giterr_clear(); /* no diff.<driver>.xfuncname, so just continue */
	}

	git_buf_truncate(&name, namelen + strlen("diff.."));
	git_buf_put(&name, "funcname", strlen("funcname"));
	if ((error = git_config_get_multivar_foreach(
			cfg, name.ptr, NULL, diff_driver_funcname, drv)) < 0) {
		if (error != GIT_ENOTFOUND)
			goto done;
		giterr_clear(); /* no diff.<driver>.funcname, so just continue */
	}

	/* if we found any patterns, set driver type to use correct callback */
	if (git_array_size(drv->fn_patterns) > 0) {
		drv->type = DIFF_DRIVER_PATTERNLIST;
		found_driver = true;
	}

	git_buf_truncate(&name, namelen + strlen("diff.."));
	git_buf_put(&name, "wordregex", strlen("wordregex"));
	if ((error = git_config__lookup_entry(&ce, cfg, name.ptr, false)) < 0)
		goto done;
	if (!ce || !ce->value)
		/* no diff.<driver>.wordregex, so just continue */;
	else if (!(error = regcomp(&drv->word_pattern, ce->value, REG_EXTENDED)))
		found_driver = true;
	else {
		/* TODO: warn about bad regex instead of failure */
		error = giterr_set_regex(&drv->word_pattern, error);
		goto done;
	}

	/* TODO: look up diff.<driver>.algorithm to turn on minimal / patience
	 * diff in drv->other_flags
	 */

	/* if no driver config found at all, fall back on AUTO driver */
	if (!found_driver)
		goto done;

	/* store driver in registry */
	git_strmap_insert(reg->drivers, drv->name, drv, error);
	if (error < 0)
		goto done;
	error = 0;

	*out = drv;

done:
	git_buf_free(&name);
	git_config_free(cfg);

	if (!*out) {
		int error2 = git_diff_driver_builtin(out, reg, driver_name);
		if (!error)
			error = error2;
	}

	if (drv && drv != *out)
		git_diff_driver_free(drv);

	return error;
}
Exemplo n.º 14
0
int git_remote_load(git_remote **out, git_repository *repo, const char *name)
{
	git_remote *remote;
	git_buf buf = GIT_BUF_INIT;
	const char *val;
	int error = 0;
	git_config *config;
	struct refspec_cb_data data = { NULL };
	bool optional_setting_found = false, found;

	assert(out && repo && name);

	if ((error = ensure_remote_name_is_valid(name)) < 0)
		return error;

	if ((error = git_repository_config_snapshot(&config, repo)) < 0)
		return error;

	remote = git__malloc(sizeof(git_remote));
	GITERR_CHECK_ALLOC(remote);

	memset(remote, 0x0, sizeof(git_remote));
	remote->update_fetchhead = 1;
	remote->name = git__strdup(name);
	GITERR_CHECK_ALLOC(remote->name);

	if ((error = get_check_cert(&remote->check_cert, repo)) < 0)
		goto cleanup;

	if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
	    git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
	    git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
		error = -1;
		goto cleanup;
	}

	if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0)
		goto cleanup;

	if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
		goto cleanup;

	optional_setting_found |= found;

	remote->repo = repo;

	if (found && strlen(val) > 0) {
		remote->url = git__strdup(val);
		GITERR_CHECK_ALLOC(remote->url);
	}

	val = NULL;
	git_buf_clear(&buf);
	git_buf_printf(&buf, "remote.%s.pushurl", name);

	if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
		goto cleanup;

	optional_setting_found |= found;

	if (!optional_setting_found) {
		error = GIT_ENOTFOUND;
		giterr_set(GITERR_CONFIG, "Remote '%s' does not exist.", name);
		goto cleanup;
	}

	if (found && strlen(val) > 0) {
		remote->pushurl = git__strdup(val);
		GITERR_CHECK_ALLOC(remote->pushurl);
	}

	data.remote = remote;
	data.fetch = true;

	git_buf_clear(&buf);
	git_buf_printf(&buf, "remote.%s.fetch", name);

	if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
		goto cleanup;

	data.fetch = false;
	git_buf_clear(&buf);
	git_buf_printf(&buf, "remote.%s.push", name);

	if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
		goto cleanup;

	if (download_tags_value(remote, config) < 0)
		goto cleanup;

	/* Move the data over to where the matching functions can find them */
	if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0)
		goto cleanup;

	*out = remote;

cleanup:
	git_config_free(config);
	git_buf_free(&buf);

	if (error < 0)
		git_remote_free(remote);

	return error;
}