Beispiel #1
0
static int load_workdir(git_repository *repo, git_buf *parent_path)
{
	int         error;
	git_config *config;
	const char *worktree;
	git_buf     worktree_buf = GIT_BUF_INIT;

	if (repo->is_bare)
		return 0;

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

	error = git_config_get_string(&worktree, config, "core.worktree");
	if (!error && worktree != NULL)
		repo->workdir = git__strdup(worktree);
	else if (error != GIT_ENOTFOUND)
		return error;
	else {
		giterr_clear();

		if (parent_path && git_path_isdir(parent_path->ptr))
			repo->workdir = git_buf_detach(parent_path);
		else {
			git_path_dirname_r(&worktree_buf, repo->path_repository);
			git_path_to_dir(&worktree_buf);
			repo->workdir = git_buf_detach(&worktree_buf);
		}
	}

	GITERR_CHECK_ALLOC(repo->workdir);

	return 0;
}
Beispiel #2
0
static int get_check_cert(int *out, git_repository *repo)
{
	git_config *cfg;
	const char *val;
	int error = 0;

	assert(out && repo);

	/* By default, we *DO* want to verify the certificate. */
	*out = 1;

	/* Go through the possible sources for SSL verification settings, from
	 * most specific to least specific. */

	/* GIT_SSL_NO_VERIFY environment variable */
	if ((val = getenv("GIT_SSL_NO_VERIFY")) != NULL)
		return git_config_parse_bool(out, val);

	/* http.sslVerify config setting */
	if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
		return error;

	*out = git_config__get_bool_force(cfg, "http.sslverify", 1);
	return 0;
}
int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar)
{
	*out = repo->cvar_cache[(int)cvar];

	if (*out == GIT_CVAR_NOT_CACHED) {
		struct map_data *data = &_cvar_maps[(int)cvar];
		git_config *config;
		int error;

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

		if (data->maps)
			error = git_config_get_mapped(
				out, config, data->cvar_name, data->maps, data->map_count);
		else
			error = git_config_get_bool(out, config, data->cvar_name);

		if (error == GIT_ENOTFOUND) {
			giterr_clear();
			*out = data->default_value;
		}
		else if (error < 0)
			return error;

		repo->cvar_cache[(int)cvar] = *out;
	}

	return 0;
}
Beispiel #4
0
static int setup_tracking_config(
	git_repository *repo,
	const char *branch_name,
	const char *remote_name,
	const char *merge_target)
{
	git_config *cfg;
	git_buf remote_key = GIT_BUF_INIT, merge_key = GIT_BUF_INIT;
	int error = -1;

	if (git_repository_config__weakptr(&cfg, repo) < 0)
		return -1;

	if (git_buf_printf(&remote_key, "branch.%s.remote", branch_name) < 0)
		goto cleanup;

	if (git_buf_printf(&merge_key, "branch.%s.merge", branch_name) < 0)
		goto cleanup;

	if (git_config_set_string(cfg, git_buf_cstr(&remote_key), remote_name) < 0)
		goto cleanup;

	if (git_config_set_string(cfg, git_buf_cstr(&merge_key), merge_target) < 0)
		goto cleanup;

	error = 0;

cleanup:
	git_buf_free(&remote_key);
	git_buf_free(&merge_key);
	return error;
}
int git_repository_config(git_config **out, git_repository *repo)
{
	if (git_repository_config__weakptr(out, repo) < 0)
		return -1;

	GIT_REFCOUNT_INC(*out);
	return 0;
}
Beispiel #6
0
int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url)
{
	git_config *cfg;
	const git_config_entry *ce;
	const char *val = NULL;
	int error;

	assert(remote);

	if (!proxy_url || !remote->repo)
		return -1;

	*proxy_url = NULL;

	if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0)
		return error;

	/* Go through the possible sources for proxy configuration, from most specific
	 * to least specific. */

	/* remote.<name>.proxy config setting */
	if (remote->name && remote->name[0]) {
		git_buf buf = GIT_BUF_INIT;

		if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0)
			return error;

		error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
		git_buf_free(&buf);

		if (error < 0)
			return error;

		if (ce && ce->value) {
			val = ce->value;
			goto found;
		}
	}

	/* http.proxy config setting */
	if ((error = git_config__lookup_entry(&ce, cfg, "http.proxy", false)) < 0)
		return error;
	if (ce && ce->value) {
		val = ce->value;
		goto found;
	}

	/* HTTP_PROXY / HTTPS_PROXY environment variables */
	val = use_ssl ? getenv("HTTPS_PROXY") : getenv("HTTP_PROXY");

found:
	if (val && val[0]) {
		*proxy_url = git__strdup(val);
		GITERR_CHECK_ALLOC(*proxy_url);
	}

	return 0;
}
Beispiel #7
0
static int note_get_default_ref(const char **out, git_repository *repo)
{
	git_config *cfg;
	int ret = git_repository_config__weakptr(&cfg, repo);

	*out = (ret != 0) ? NULL : git_config__get_string_force(
		cfg, "core.notesref", GIT_NOTES_DEFAULT_REF);

	return ret;
}
int git_repository_config_snapshot(git_config **out, git_repository *repo)
{
	int error;
	git_config *weak;

	if ((error = git_repository_config__weakptr(&weak, repo)) < 0)
		return error;

	return git_config_snapshot(out, weak);
}
Beispiel #9
0
static int load_config_data(git_repository *repo)
{
	int is_bare;
	git_config *config;

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

	if (git_config_get_bool(&is_bare, config, "core.bare") < 0)
		return -1; /* FIXME: We assume that a missing core.bare
					  variable is an error. Is this right? */

	repo->is_bare = is_bare;
	return 0;
}
Beispiel #10
0
void test_network_remoterename__renaming_a_remote_without_a_fetchrefspec_doesnt_create_one(void)
{
	git_config *config;

	git_remote_free(_remote);
	cl_git_pass(git_repository_config__weakptr(&config, _repo));
	cl_git_pass(git_config_delete(config, "remote.test.fetch"));

	cl_git_pass(git_remote_load(&_remote, _repo, "test"));

	assert_config_entry_existence(_repo, "remote.test.fetch", false);

	cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL));

	assert_config_entry_existence(_repo, "remote.just/renamed.fetch", false);
}
Beispiel #11
0
int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar)
{
	*out = repo->cvar_cache[(int)cvar];

	if (*out == GIT_CVAR_NOT_CACHED) {
		int error;
		git_config *config;

		if ((error = git_repository_config__weakptr(&config, repo)) < 0 ||
			(error = git_config__cvar(out, config, cvar)) < 0)
			return error;

		repo->cvar_cache[(int)cvar] = *out;
	}

	return 0;
}
Beispiel #12
0
static int note_get_default_ref(const char **out, git_repository *repo)
{
	int ret;
	git_config *cfg;

	*out = NULL;

	if (git_repository_config__weakptr(&cfg, repo) < 0)
		return -1;

	ret = git_config_get_string(out, cfg, "core.notesRef");
	if (ret == GIT_ENOTFOUND) {
		*out = GIT_NOTES_DEFAULT_REF;
		return 0;
	}

	return ret;
}
Beispiel #13
0
static int retrieve_tracking_configuration(
	const char **out, git_reference *branch, const char *format)
{
	git_config *config;
	git_buf buf = GIT_BUF_INIT;
	int error;

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

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

	error = git_config_get_string(out, config, git_buf_cstr(&buf));
	git_buf_free(&buf);
	return error;
}
Beispiel #14
0
void test_network_remoterename__renaming_a_remote_notifies_of_non_default_fetchrefspec(void)
{
	git_config *config;

	char *expected_refspecs[] = {
		"+refs/*:refs/*",
		NULL
	};

	git_remote_free(_remote);
	cl_git_pass(git_repository_config__weakptr(&config, _repo));
	cl_git_pass(git_config_set_string(config, "remote.test.fetch", "+refs/*:refs/*"));
	cl_git_pass(git_remote_load(&_remote, _repo, "test"));

	cl_git_pass(git_remote_rename(_remote, "just/renamed", ensure_refspecs, &expected_refspecs));

	assert_config_entry_value(_repo, "remote.just/renamed.fetch", "+refs/*:refs/*");
}
Beispiel #15
0
static int check_repositoryformatversion(git_repository *repo)
{
	git_config *config;
	int version;

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

	if (git_config_get_int32(&version, config, "core.repositoryformatversion") < 0)
		return -1;

	if (GIT_REPO_VERSION < version) {
		giterr_set(GITERR_REPOSITORY,
			"Unsupported repository version %d. Only versions up to %d are supported.",
			version, GIT_REPO_VERSION);
		return -1;
	}

	return 0;
}
Beispiel #16
0
void test_network_remote_rename__renaming_a_remote_without_a_fetchrefspec_doesnt_create_one(void)
{
	git_config *config;
	git_remote *remote;
	git_strarray problems = {0};

	cl_git_pass(git_repository_config__weakptr(&config, _repo));
	cl_git_pass(git_config_delete_entry(config, "remote.test.fetch"));

	cl_git_pass(git_remote_lookup(&remote, _repo, "test"));
	git_remote_free(remote);

	assert_config_entry_existence(_repo, "remote.test.fetch", false);

	cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just/renamed"));
	cl_assert_equal_i(0, problems.count);
	git_strarray_free(&problems);

	assert_config_entry_existence(_repo, "remote.just/renamed.fetch", false);
}
Beispiel #17
0
void test_network_remote_rename__renaming_a_remote_notifies_of_non_default_fetchrefspec(void)
{
	git_config *config;
	git_remote *remote;
	git_strarray problems = {0};

	cl_git_pass(git_repository_config__weakptr(&config, _repo));
	cl_git_pass(git_config_set_string(config, "remote.test.fetch", "+refs/*:refs/*"));
	cl_git_pass(git_remote_lookup(&remote, _repo, "test"));
	git_remote_free(remote);

	cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just/renamed"));
	cl_assert_equal_i(1, problems.count);
	cl_assert_equal_s("+refs/*:refs/*", problems.strings[0]);
	git_strarray_free(&problems);

	assert_config_entry_value(_repo, "remote.just/renamed.fetch", "+refs/*:refs/*");

	git_strarray_free(&problems);
}
static int retrieve_upstream_configuration(
	const char **out,
	git_repository *repo,
	const char *canonical_branch_name,
	const char *format)
{
	git_config *config;
	git_buf buf = GIT_BUF_INIT;
	int error;

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

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

	error = git_config_get_string(out, config, git_buf_cstr(&buf));
	git_buf_free(&buf);
	return error;
}
static int retrieve_symlink_capabilities(git_repository *repo, bool *can_symlink)
{
	git_config *cfg;
	int error;

	if (git_repository_config__weakptr(&cfg, repo) < 0)
		return -1;

	error = git_config_get_bool((int *)can_symlink, cfg, "core.symlinks");

	/*
	 * When no "core.symlinks" entry is found in any of the configuration
	 * store (local, global or system), default value is "true".
	 */
	if (error == GIT_ENOTFOUND) {
		*can_symlink = true;
		error = 0;
	}

	return error;
}
Beispiel #20
0
static int repo_local_config(
	git_config **out,
	git_buf *config_dir,
	git_repository *repo,
	const char *repo_dir)
{
	int error = 0;
	git_config *parent;
	const char *cfg_path;

	if (git_buf_joinpath(config_dir, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
		return -1;
	cfg_path = git_buf_cstr(config_dir);

	/* make LOCAL config if missing */
	if (!git_path_isfile(cfg_path) &&
		(error = create_empty_file(cfg_path, GIT_CONFIG_FILE_MODE)) < 0)
		return error;

	/* if no repo, just open that file directly */
	if (!repo)
		return git_config_open_ondisk(out, cfg_path);

	/* otherwise, open parent config and get that level */
	if ((error = git_repository_config__weakptr(&parent, repo)) < 0)
		return error;

	if (git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL) < 0) {
		giterr_clear();

		if (!(error = git_config_add_file_ondisk(
				parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, false)))
			error = git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL);
	}

	git_config_free(parent);

	return error;
}
Beispiel #21
0
int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname)
{
	int error;
	git_config *cfg;

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

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

	git_buf_sanitize(buf);

	if ((error = retrieve_upstream_configuration(buf, cfg, refname, "branch.%s.remote")) < 0)
		return error;

	if (git_buf_len(buf) == 0) {
		giterr_set(GITERR_REFERENCE, "branch '%s' does not have an upstream remote", refname);
		error = GIT_ENOTFOUND;
		git_buf_clear(buf);
	}

	return error;
}
Beispiel #22
0
int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
{
	git_buf key = GIT_BUF_INIT, value = GIT_BUF_INIT;
	git_reference *upstream;
	git_repository *repo;
	git_remote *remote = NULL;
	git_config *config;
	const char *name, *shortname;
	int local, error;
	const git_refspec *fetchspec;

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

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

	shortname = name + strlen(GIT_REFS_HEADS_DIR);

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

	repo = git_reference_owner(branch);

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

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

	if (error < 0)
		goto on_error;

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

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

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

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

		git_remote_free(remote);
		remote = NULL;
	}

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

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

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

	return 0;

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

	return -1;
}
Beispiel #23
0
int git_remote_save(const git_remote *remote)
{
	int error;
	git_config *cfg;
	const char *tagopt = NULL;
	git_buf buf = GIT_BUF_INIT;
	const git_config_entry *existing;

	assert(remote);

	if (!remote->name) {
		giterr_set(GITERR_INVALID, "Can't save an anonymous remote.");
		return GIT_EINVALIDSPEC;
	}

	if ((error = ensure_remote_name_is_valid(remote->name)) < 0)
		return error;

	if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0)
		return error;

	if ((error = git_buf_printf(&buf, "remote.%s.url", remote->name)) < 0)
		return error;

	/* after this point, buffer is allocated so end with cleanup */

	if ((error = git_config_set_string(
			cfg, git_buf_cstr(&buf), remote->url)) < 0)
		goto cleanup;

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

	if ((error = git_config__update_entry(
			cfg, git_buf_cstr(&buf), remote->pushurl, true, false)) < 0)
		goto cleanup;

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

	if ((error = update_config_refspec(remote, cfg, GIT_DIRECTION_PUSH)) < 0)
		goto cleanup;

	/*
	 * What action to take depends on the old and new values. This
	 * is describes by the table below. tagopt means whether the
	 * is already a value set in the config
	 *
	 *            AUTO     ALL or NONE
	 *         +-----------------------+
	 *  tagopt | remove  |     set     |
	 *         +---------+-------------|
	 * !tagopt | nothing |     set     |
	 *         +---------+-------------+
	 */

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

	if ((error = git_config__lookup_entry(
			&existing, cfg, git_buf_cstr(&buf), false)) < 0)
		goto cleanup;

	if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL)
		tagopt = "--tags";
	else if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_NONE)
		tagopt = "--no-tags";
	else if (existing != NULL)
		tagopt = NULL;

	error = git_config__update_entry(
		cfg, git_buf_cstr(&buf), tagopt, true, false);

cleanup:
	git_buf_free(&buf);
	return error;
}
Beispiel #24
0
static int filter_apply(
	git_filter				*self,
	void					**payload, /* may be read and/or set */
	git_buf					*to,
	const git_buf			*from,
	const git_filter_source	*src)
{
	struct filter_filter *ffs = (struct filter_filter *)self;
	git_config *config;
	git_buf configKey = GIT_BUF_INIT;
	int isRequired = FALSE;
	int error;
	const char *cmd = NULL;
	git_buf cmdBuf = GIT_BUF_INIT;
	wchar_t *wide_cmd;
	COMMAND_HANDLE commandHandle = COMMAND_HANDLE_INIT;
	git_buf errBuf = GIT_BUF_INIT;
	DWORD exitCode;

	if (!*payload)
		return GIT_PASSTHROUGH;

	if (git_repository_config__weakptr(&config, git_filter_source_repo(src)))
		return -1;

	git_buf_join3(&configKey, '.', "filter", *payload, "required");
	if (git_buf_oom(&configKey)) {
		giterr_set_oom();
		return -1;
	}

	error = git_config_get_bool(&isRequired, config, configKey.ptr);
	git_buf_free(&configKey);
	if (error && error != GIT_ENOTFOUND)
		return -1;

	git_buf_join(&configKey, '.', "filter", *payload);
	if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE) {
		git_buf_puts(&configKey, ".smudge");
	} else {
		git_buf_puts(&configKey, ".clean");
	}
	if (git_buf_oom(&configKey)) {
		giterr_set_oom();
		return -1;
	}

	error = git_config_get_string(&cmd, config, configKey.ptr);
	git_buf_free(&configKey);
	if (error && error != GIT_ENOTFOUND)
		return -1;

	if (error == GIT_ENOTFOUND) {
		if (isRequired)
			return -1;
		return GIT_PASSTHROUGH;
	}

	git_buf_puts(&cmdBuf, cmd);
	if (git_buf_oom(&cmdBuf)) {
		giterr_set_oom();
		return -1;
	}

	if (expandPerCentF(&cmdBuf, git_filter_source_path(src)))
		return -1;

	if (ffs->shexepath) {
		// build params for sh.exe
		git_buf shParams = GIT_BUF_INIT;
		git_buf_puts(&shParams, " -c \"");
		git_buf_text_puts_escaped(&shParams, cmdBuf.ptr, "\"\\", "\\");
		git_buf_puts(&shParams, "\"");
		if (git_buf_oom(&shParams)) {
			git_buf_free(&cmdBuf);
			giterr_set_oom();
			return -1;
		}
		git_buf_swap(&shParams, &cmdBuf);
		git_buf_free(&shParams);
	}

	if (git__utf8_to_16_alloc(&wide_cmd, cmdBuf.ptr) < 0)
	{
		git_buf_free(&cmdBuf);
		giterr_set_oom();
		return -1;
	}
	git_buf_free(&cmdBuf);

	if (ffs->shexepath) {
		// build cmd, i.e. shexepath + params
		size_t len = wcslen(ffs->shexepath) + wcslen(wide_cmd) + 1;
		wchar_t *tmp = git__calloc(len, sizeof(wchar_t));
		if (!tmp) {
			git__free(wide_cmd);
			giterr_set_oom();
			return -1;
		}
		wcscat_s(tmp, len, ffs->shexepath);
		wcscat_s(tmp, len, wide_cmd);
		git__free(wide_cmd);
		wide_cmd = tmp;
	}

	commandHandle.errBuf = &errBuf;
	if (command_start(wide_cmd, &commandHandle, ffs->pEnv)) {
		git__free(wide_cmd);
		if (isRequired)
			return -1;
		return GIT_PASSTHROUGH;
	}
	git__free(wide_cmd);

	if (commmand_start_stdout_reading_thread(&commandHandle, to)) {
		command_close(&commandHandle);
		return -1;
	}

	if (command_write_gitbuf(&commandHandle, from)) {
		DWORD exitCode = command_close(&commandHandle);
		if (exitCode)
			setProcessError(exitCode, &errBuf);
		git_buf_free(&errBuf);
		if (isRequired)
			return -1;
		return GIT_PASSTHROUGH;
	}
	command_close_stdin(&commandHandle);

	if (command_wait_stdout_reading_thread(&commandHandle)) {
		DWORD exitCode = command_close(&commandHandle);
		if (exitCode)
			setProcessError(exitCode, &errBuf);
		git_buf_free(&errBuf);
		if (isRequired)
			return -1;
		return GIT_PASSTHROUGH;
	}

	exitCode = command_close(&commandHandle);
	if (exitCode) {
		if (isRequired) {
			setProcessError(exitCode, &errBuf);
			git_buf_free(&errBuf);
			return -1;
		}
		git_buf_free(&errBuf);
		return GIT_PASSTHROUGH;
	}

	git_buf_free(&errBuf);

	return 0;
}