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; }
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; }
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; }
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; }
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); }
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; }
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); }
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; }
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; }
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; }
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/*"); }
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; }
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); }
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; }
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; }
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; }
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; }
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; }
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; }