Racy Git problems persist today, manifesting themselves in the performance of commands like "git diff" in new worktrees [1]. We have long had a build knob "USE_NSEC" to tell Git to use in-core nanosecond precision when available, which mitigates most if not all racy issues, but most builds we know about don't use it. In part, that's because someone distributing Git can't safely enable it at compile-time if they don't know exactly what platforms their distribution will be used on. [1]: https://lore.kernel.org/git/CALnO6CADMJSixqYvL1Yo8qKX5rWhKQ+2OoSEuPUh-yoeK9TseQ@mail.gmail.com These days, most platforms are likely to be safe for the USE_NSEC code. Regardless, we want to give users the ability to benefit from it. This requires exposing the compile-time gated code as a runtime option. In addition, update the Racy Git documentation and other mentions of USE_NSEC in the code. Due to the conversion from #ifdef to runtime check, using the flag "--ignore-space-change" may be particularly helpful when viewing changes from this patch. Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
798 lines
21 KiB
C
798 lines
21 KiB
C
/*
|
|
* We put all the git config variables in this same object
|
|
* file, so that programs can link against the config parser
|
|
* without having to link against all the rest of git.
|
|
*
|
|
* In particular, no need to bring in libz etc unless needed,
|
|
* even if you might want to know where the git directory etc
|
|
* are.
|
|
*/
|
|
|
|
#define USE_THE_REPOSITORY_VARIABLE
|
|
|
|
#include "git-compat-util.h"
|
|
#include "abspath.h"
|
|
#include "advice.h"
|
|
#include "attr.h"
|
|
#include "branch.h"
|
|
#include "color.h"
|
|
#include "convert.h"
|
|
#include "environment.h"
|
|
#include "gettext.h"
|
|
#include "git-zlib.h"
|
|
#include "ident.h"
|
|
#include "lockfile.h"
|
|
#include "mailmap.h"
|
|
#include "object-name.h"
|
|
#include "repository.h"
|
|
#include "config.h"
|
|
#include "refs.h"
|
|
#include "fmt-merge-msg.h"
|
|
#include "commit.h"
|
|
#include "strvec.h"
|
|
#include "pager.h"
|
|
#include "path.h"
|
|
#include "quote.h"
|
|
#include "chdir-notify.h"
|
|
#include "setup.h"
|
|
#include "ws.h"
|
|
#include "write-or-die.h"
|
|
|
|
static int pack_compression_seen;
|
|
static int zlib_compression_seen;
|
|
|
|
int minimum_abbrev = 4, default_abbrev = -1;
|
|
int assume_unchanged;
|
|
char *git_commit_encoding;
|
|
char *git_log_output_encoding;
|
|
int fsync_object_files = -1;
|
|
int use_fsync = -1;
|
|
enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;
|
|
enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT;
|
|
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
|
|
enum eol core_eol = EOL_UNSET;
|
|
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
|
|
char *check_roundtrip_encoding;
|
|
#ifndef OBJECT_CREATION_MODE
|
|
#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
|
|
#endif
|
|
int grafts_keep_true_parents;
|
|
unsigned long pack_size_limit_cfg;
|
|
|
|
#ifndef PROTECT_HFS_DEFAULT
|
|
#define PROTECT_HFS_DEFAULT 0
|
|
#endif
|
|
|
|
#ifndef PROTECT_NTFS_DEFAULT
|
|
#define PROTECT_NTFS_DEFAULT 1
|
|
#endif
|
|
|
|
/*
|
|
* The character that begins a commented line in user-editable file
|
|
* that is subject to stripspace.
|
|
*/
|
|
const char *comment_line_str = "#";
|
|
char *comment_line_str_to_free;
|
|
#ifndef WITH_BREAKING_CHANGES
|
|
int auto_comment_line_char;
|
|
bool warn_on_auto_comment_char;
|
|
#endif /* !WITH_BREAKING_CHANGES */
|
|
|
|
/*
|
|
* Repository-local GIT_* environment variables; see environment.h for details.
|
|
*/
|
|
const char * const local_repo_env[] = {
|
|
ALTERNATE_DB_ENVIRONMENT,
|
|
CONFIG_ENVIRONMENT,
|
|
CONFIG_DATA_ENVIRONMENT,
|
|
CONFIG_COUNT_ENVIRONMENT,
|
|
DB_ENVIRONMENT,
|
|
GIT_DIR_ENVIRONMENT,
|
|
GIT_WORK_TREE_ENVIRONMENT,
|
|
GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,
|
|
GRAFT_ENVIRONMENT,
|
|
INDEX_ENVIRONMENT,
|
|
NO_REPLACE_OBJECTS_ENVIRONMENT,
|
|
GIT_REPLACE_REF_BASE_ENVIRONMENT,
|
|
GIT_PREFIX_ENVIRONMENT,
|
|
GIT_SHALLOW_FILE_ENVIRONMENT,
|
|
GIT_COMMON_DIR_ENVIRONMENT,
|
|
NULL
|
|
};
|
|
|
|
const char *getenv_safe(struct strvec *argv, const char *name)
|
|
{
|
|
const char *value = getenv(name);
|
|
|
|
if (!value)
|
|
return NULL;
|
|
|
|
strvec_push(argv, value);
|
|
return argv->v[argv->nr - 1];
|
|
}
|
|
|
|
int is_bare_repository(struct repository *repo)
|
|
{
|
|
/* if core.bare is not 'false', let's see if there is a work tree */
|
|
return repo->bare_cfg && !repo_get_work_tree(repo);
|
|
}
|
|
|
|
int repo_protect_ntfs(struct repository *repo)
|
|
{
|
|
return (repo && repo->initialized) ?
|
|
repo_config_values(repo)->protect_ntfs :
|
|
PROTECT_NTFS_DEFAULT;
|
|
}
|
|
|
|
int repo_protect_hfs(struct repository *repo)
|
|
{
|
|
return (repo && repo->initialized) ?
|
|
repo_config_values(repo)->protect_hfs :
|
|
PROTECT_HFS_DEFAULT;
|
|
}
|
|
|
|
int repo_ignore_case(struct repository *repo)
|
|
{
|
|
return (repo && repo->initialized) ?
|
|
repo_config_values(repo)->ignore_case :
|
|
0;
|
|
}
|
|
|
|
int repo_trust_executable_bit(struct repository *repo)
|
|
{
|
|
return repo->initialized
|
|
? repo_config_values(repo)->trust_executable_bit
|
|
: 1;
|
|
}
|
|
|
|
int repo_has_symlinks(struct repository *repo)
|
|
{
|
|
return repo->initialized
|
|
? repo_config_values(repo)->has_symlinks
|
|
: platform_has_symlinks();
|
|
}
|
|
|
|
const char *repo_excludes_file(struct repository *repo)
|
|
{
|
|
struct repo_config_values *cfg = repo_config_values(repo);
|
|
|
|
if (!cfg->excludes_file)
|
|
cfg->excludes_file = xdg_config_home("ignore");
|
|
|
|
return cfg->excludes_file;
|
|
}
|
|
|
|
int have_git_dir(void)
|
|
{
|
|
return startup_info->have_repository
|
|
|| the_repository->gitdir;
|
|
}
|
|
|
|
const char *get_git_namespace(void)
|
|
{
|
|
static const char *namespace;
|
|
struct strbuf buf = STRBUF_INIT;
|
|
const char *raw_namespace;
|
|
struct string_list components = STRING_LIST_INIT_DUP;
|
|
struct string_list_item *item;
|
|
|
|
if (namespace)
|
|
return namespace;
|
|
|
|
raw_namespace = getenv(GIT_NAMESPACE_ENVIRONMENT);
|
|
if (!raw_namespace || !*raw_namespace) {
|
|
namespace = "";
|
|
return namespace;
|
|
}
|
|
|
|
strbuf_addstr(&buf, raw_namespace);
|
|
|
|
string_list_split(&components, buf.buf, "/", -1);
|
|
strbuf_reset(&buf);
|
|
|
|
for_each_string_list_item(item, &components) {
|
|
if (item->string[0])
|
|
strbuf_addf(&buf, "refs/namespaces/%s/", item->string);
|
|
}
|
|
string_list_clear(&components, 0);
|
|
|
|
strbuf_trim_trailing_dir_sep(&buf);
|
|
if (check_refname_format(buf.buf, 0))
|
|
die(_("bad git namespace path \"%s\""), raw_namespace);
|
|
strbuf_addch(&buf, '/');
|
|
|
|
namespace = strbuf_detach(&buf, NULL);
|
|
|
|
return namespace;
|
|
}
|
|
|
|
const char *strip_namespace(const char *namespaced_ref)
|
|
{
|
|
const char *out;
|
|
if (skip_prefix(namespaced_ref, get_git_namespace(), &out))
|
|
return out;
|
|
return NULL;
|
|
}
|
|
|
|
const char *get_log_output_encoding(void)
|
|
{
|
|
return git_log_output_encoding ? git_log_output_encoding
|
|
: get_commit_output_encoding();
|
|
}
|
|
|
|
const char *get_commit_output_encoding(void)
|
|
{
|
|
return git_commit_encoding ? git_commit_encoding : "UTF-8";
|
|
}
|
|
|
|
int use_optional_locks(void)
|
|
{
|
|
return git_env_bool(GIT_OPTIONAL_LOCKS_ENVIRONMENT, 1);
|
|
}
|
|
|
|
int print_sha1_ellipsis(void)
|
|
{
|
|
/*
|
|
* Determine if the calling environment contains the variable
|
|
* GIT_PRINT_SHA1_ELLIPSIS set to "yes".
|
|
*/
|
|
static int cached_result = -1; /* unknown */
|
|
|
|
if (cached_result < 0) {
|
|
const char *v = getenv("GIT_PRINT_SHA1_ELLIPSIS");
|
|
cached_result = (v && !strcasecmp(v, "yes"));
|
|
}
|
|
return cached_result;
|
|
}
|
|
|
|
static const struct fsync_component_name {
|
|
const char *name;
|
|
enum fsync_component component_bits;
|
|
} fsync_component_names[] = {
|
|
{ "loose-object", FSYNC_COMPONENT_LOOSE_OBJECT },
|
|
{ "pack", FSYNC_COMPONENT_PACK },
|
|
{ "pack-metadata", FSYNC_COMPONENT_PACK_METADATA },
|
|
{ "commit-graph", FSYNC_COMPONENT_COMMIT_GRAPH },
|
|
{ "index", FSYNC_COMPONENT_INDEX },
|
|
{ "objects", FSYNC_COMPONENTS_OBJECTS },
|
|
{ "reference", FSYNC_COMPONENT_REFERENCE },
|
|
{ "derived-metadata", FSYNC_COMPONENTS_DERIVED_METADATA },
|
|
{ "committed", FSYNC_COMPONENTS_COMMITTED },
|
|
{ "added", FSYNC_COMPONENTS_ADDED },
|
|
{ "all", FSYNC_COMPONENTS_ALL },
|
|
};
|
|
|
|
static enum fsync_component parse_fsync_components(const char *var, const char *string)
|
|
{
|
|
enum fsync_component current = FSYNC_COMPONENTS_PLATFORM_DEFAULT;
|
|
enum fsync_component positive = 0, negative = 0;
|
|
|
|
while (string) {
|
|
size_t len;
|
|
const char *ep;
|
|
int negated = 0;
|
|
int found = 0;
|
|
|
|
string = string + strspn(string, ", \t\n\r");
|
|
ep = strchrnul(string, ',');
|
|
len = ep - string;
|
|
if (!strcmp(string, "none")) {
|
|
current = FSYNC_COMPONENT_NONE;
|
|
goto next_name;
|
|
}
|
|
|
|
if (*string == '-') {
|
|
negated = 1;
|
|
string++;
|
|
len--;
|
|
if (!len)
|
|
warning(_("invalid value for variable %s"), var);
|
|
}
|
|
|
|
if (!len)
|
|
break;
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(fsync_component_names); ++i) {
|
|
const struct fsync_component_name *n = &fsync_component_names[i];
|
|
|
|
if (strncmp(n->name, string, len))
|
|
continue;
|
|
|
|
found = 1;
|
|
if (negated)
|
|
negative |= n->component_bits;
|
|
else
|
|
positive |= n->component_bits;
|
|
}
|
|
|
|
if (!found) {
|
|
char *component = xstrndup(string, len);
|
|
warning(_("ignoring unknown core.fsync component '%s'"), component);
|
|
free(component);
|
|
}
|
|
|
|
next_name:
|
|
string = ep;
|
|
}
|
|
|
|
return (current & ~negative) | positive;
|
|
}
|
|
|
|
int git_default_core_config(const char *var, const char *value,
|
|
const struct config_context *ctx, void *cb)
|
|
{
|
|
struct repo_config_values *cfg = repo_config_values(the_repository);
|
|
|
|
/* This needs a better name */
|
|
if (!strcmp(var, "core.filemode")) {
|
|
cfg->trust_executable_bit = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
if (!strcmp(var, "core.trustctime")) {
|
|
cfg->trust_ctime = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
if (!strcmp(var, "core.checkstat")) {
|
|
if (!value)
|
|
return config_error_nonbool(var);
|
|
if (!strcasecmp(value, "default"))
|
|
cfg->check_stat = 1;
|
|
else if (!strcasecmp(value, "minimal"))
|
|
cfg->check_stat = 0;
|
|
else
|
|
return error(_("invalid value for '%s': '%s'"),
|
|
var, value);
|
|
}
|
|
|
|
if (!strcmp(var, "core.quotepath")) {
|
|
quote_path_fully = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.symlinks")) {
|
|
struct repo_config_values *cfg = repo_config_values(the_repository);
|
|
cfg->has_symlinks = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.ignorecase")) {
|
|
cfg->ignore_case = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.attributesfile")) {
|
|
FREE_AND_NULL(cfg->attributes_file);
|
|
return git_config_pathname(&cfg->attributes_file, var, value);
|
|
}
|
|
|
|
if (!strcmp(var, "core.bare")) {
|
|
the_repository->bare_cfg = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.ignorestat")) {
|
|
assume_unchanged = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.abbrev")) {
|
|
if (!value)
|
|
return config_error_nonbool(var);
|
|
if (!strcasecmp(value, "auto"))
|
|
default_abbrev = -1;
|
|
else if (!git_parse_maybe_bool_text(value))
|
|
default_abbrev = GIT_MAX_HEXSZ;
|
|
else {
|
|
int abbrev = git_config_int(var, value, ctx->kvi);
|
|
if (abbrev < minimum_abbrev)
|
|
return error(_("abbrev length out of range: %d"), abbrev);
|
|
default_abbrev = abbrev;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.disambiguate"))
|
|
return set_disambiguate_hint_config(var, value);
|
|
|
|
if (!strcmp(var, "core.loosecompression")) {
|
|
int level = git_config_int(var, value, ctx->kvi);
|
|
if (level == -1)
|
|
level = Z_DEFAULT_COMPRESSION;
|
|
else if (level < 0 || level > Z_BEST_COMPRESSION)
|
|
die(_("bad zlib compression level %d"), level);
|
|
cfg->zlib_compression_level = level;
|
|
zlib_compression_seen = 1;
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.compression")) {
|
|
int level = git_config_int(var, value, ctx->kvi);
|
|
if (level == -1)
|
|
level = Z_DEFAULT_COMPRESSION;
|
|
else if (level < 0 || level > Z_BEST_COMPRESSION)
|
|
die(_("bad zlib compression level %d"), level);
|
|
if (!zlib_compression_seen)
|
|
cfg->zlib_compression_level = level;
|
|
if (!pack_compression_seen)
|
|
cfg->pack_compression_level = level;
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.autocrlf")) {
|
|
if (value && !strcasecmp(value, "input")) {
|
|
auto_crlf = AUTO_CRLF_INPUT;
|
|
return 0;
|
|
}
|
|
auto_crlf = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.safecrlf")) {
|
|
int eol_rndtrp_die;
|
|
if (value && !strcasecmp(value, "warn")) {
|
|
global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
|
|
return 0;
|
|
}
|
|
eol_rndtrp_die = git_config_bool(var, value);
|
|
global_conv_flags_eol = eol_rndtrp_die ?
|
|
CONV_EOL_RNDTRP_DIE : 0;
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.eol")) {
|
|
if (value && !strcasecmp(value, "lf"))
|
|
core_eol = EOL_LF;
|
|
else if (value && !strcasecmp(value, "crlf"))
|
|
core_eol = EOL_CRLF;
|
|
else if (value && !strcasecmp(value, "native"))
|
|
core_eol = EOL_NATIVE;
|
|
else
|
|
core_eol = EOL_UNSET;
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.checkroundtripencoding")) {
|
|
FREE_AND_NULL(check_roundtrip_encoding);
|
|
return git_config_string(&check_roundtrip_encoding, var, value);
|
|
}
|
|
|
|
if (!strcmp(var, "core.editor")) {
|
|
FREE_AND_NULL(cfg->editor_program);
|
|
return git_config_string(&cfg->editor_program, var, value);
|
|
}
|
|
|
|
if (!strcmp(var, "core.commentchar") ||
|
|
!strcmp(var, "core.commentstring")) {
|
|
if (!value) {
|
|
return config_error_nonbool(var);
|
|
#ifndef WITH_BREAKING_CHANGES
|
|
} else if (!strcasecmp(value, "auto")) {
|
|
auto_comment_line_char = 1;
|
|
FREE_AND_NULL(comment_line_str_to_free);
|
|
comment_line_str = "#";
|
|
#endif /* !WITH_BREAKING_CHANGES */
|
|
} else if (value[0]) {
|
|
if (strchr(value, '\n'))
|
|
return error(_("%s cannot contain newline"), var);
|
|
comment_line_str = value;
|
|
FREE_AND_NULL(comment_line_str_to_free);
|
|
#ifndef WITH_BREAKING_CHANGES
|
|
auto_comment_line_char = 0;
|
|
#endif /* !WITH_BREAKING_CHANGES */
|
|
} else
|
|
return error(_("%s must have at least one character"), var);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.askpass")) {
|
|
FREE_AND_NULL(cfg->askpass_program);
|
|
return git_config_string(&cfg->askpass_program, var, value);
|
|
}
|
|
|
|
if (!strcmp(var, "core.excludesfile")) {
|
|
FREE_AND_NULL(cfg->excludes_file);
|
|
return git_config_pathname(&cfg->excludes_file, var, value);
|
|
}
|
|
|
|
if (!strcmp(var, "core.whitespace")) {
|
|
if (!value)
|
|
return config_error_nonbool(var);
|
|
whitespace_rule_cfg = parse_whitespace_rule(value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.fsync")) {
|
|
if (!value)
|
|
return config_error_nonbool(var);
|
|
fsync_components = parse_fsync_components(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.fsyncmethod")) {
|
|
if (!value)
|
|
return config_error_nonbool(var);
|
|
if (!strcmp(value, "fsync"))
|
|
fsync_method = FSYNC_METHOD_FSYNC;
|
|
else if (!strcmp(value, "writeout-only"))
|
|
fsync_method = FSYNC_METHOD_WRITEOUT_ONLY;
|
|
else if (!strcmp(value, "batch"))
|
|
fsync_method = FSYNC_METHOD_BATCH;
|
|
else
|
|
warning(_("ignoring unknown core.fsyncMethod value '%s'"), value);
|
|
|
|
}
|
|
|
|
if (!strcmp(var, "core.fsyncobjectfiles")) {
|
|
if (fsync_object_files < 0)
|
|
warning(_("core.fsyncObjectFiles is deprecated; use core.fsync instead"));
|
|
fsync_object_files = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.lockfilepid")) {
|
|
lockfile_pid_enabled = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.createobject")) {
|
|
if (!value)
|
|
return config_error_nonbool(var);
|
|
if (!strcmp(value, "rename"))
|
|
cfg->object_creation_mode = OBJECT_CREATION_USES_RENAMES;
|
|
else if (!strcmp(value, "link"))
|
|
cfg->object_creation_mode = OBJECT_CREATION_USES_HARDLINKS;
|
|
else
|
|
die(_("invalid mode for object creation: %s"), value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.sparsecheckout")) {
|
|
cfg->apply_sparse_checkout = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.sparsecheckoutcone")) {
|
|
cfg->core_sparse_checkout_cone = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.precomposeunicode")) {
|
|
cfg->precomposed_unicode = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.protecthfs")) {
|
|
cfg->protect_hfs = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "core.protectntfs")) {
|
|
cfg->protect_ntfs = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
#ifndef NO_NSEC
|
|
if (!strcmp(var, "core.usenanosec")) {
|
|
cfg->use_nanosec = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/* Add other config variables here and to Documentation/config.adoc. */
|
|
return platform_core_config(var, value, ctx, cb);
|
|
}
|
|
|
|
static int git_default_sparse_config(const char *var, const char *value)
|
|
{
|
|
struct repo_config_values *cfg = repo_config_values(the_repository);
|
|
|
|
if (!strcmp(var, "sparse.expectfilesoutsideofpatterns")) {
|
|
cfg->sparse_expect_files_outside_of_patterns = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
|
|
/* Add other config variables here and to Documentation/config/sparse.adoc. */
|
|
return 0;
|
|
}
|
|
|
|
static int git_default_i18n_config(const char *var, const char *value)
|
|
{
|
|
if (!strcmp(var, "i18n.commitencoding")) {
|
|
FREE_AND_NULL(git_commit_encoding);
|
|
return git_config_string(&git_commit_encoding, var, value);
|
|
}
|
|
|
|
if (!strcmp(var, "i18n.logoutputencoding")) {
|
|
FREE_AND_NULL(git_log_output_encoding);
|
|
return git_config_string(&git_log_output_encoding, var, value);
|
|
}
|
|
|
|
/* Add other config variables here and to Documentation/config.adoc. */
|
|
return 0;
|
|
}
|
|
|
|
static int git_default_branch_config(const char *var, const char *value)
|
|
{
|
|
struct repo_config_values *cfg = repo_config_values(the_repository);
|
|
|
|
if (!strcmp(var, "branch.autosetupmerge")) {
|
|
if (value && !strcmp(value, "always")) {
|
|
cfg->branch_track = BRANCH_TRACK_ALWAYS;
|
|
return 0;
|
|
} else if (value && !strcmp(value, "inherit")) {
|
|
cfg->branch_track = BRANCH_TRACK_INHERIT;
|
|
return 0;
|
|
} else if (value && !strcmp(value, "simple")) {
|
|
cfg->branch_track = BRANCH_TRACK_SIMPLE;
|
|
return 0;
|
|
}
|
|
cfg->branch_track = git_config_bool(var, value);
|
|
return 0;
|
|
}
|
|
if (!strcmp(var, "branch.autosetuprebase")) {
|
|
if (!value)
|
|
return config_error_nonbool(var);
|
|
else if (!strcmp(value, "never"))
|
|
cfg->autorebase = AUTOREBASE_NEVER;
|
|
else if (!strcmp(value, "local"))
|
|
cfg->autorebase = AUTOREBASE_LOCAL;
|
|
else if (!strcmp(value, "remote"))
|
|
cfg->autorebase = AUTOREBASE_REMOTE;
|
|
else if (!strcmp(value, "always"))
|
|
cfg->autorebase = AUTOREBASE_ALWAYS;
|
|
else
|
|
return error(_("malformed value for %s"), var);
|
|
return 0;
|
|
}
|
|
|
|
/* Add other config variables here and to Documentation/config.adoc. */
|
|
return 0;
|
|
}
|
|
|
|
static int git_default_push_config(const char *var, const char *value)
|
|
{
|
|
struct repo_config_values *cfg = repo_config_values(the_repository);
|
|
|
|
if (!strcmp(var, "push.default")) {
|
|
if (!value)
|
|
return config_error_nonbool(var);
|
|
else if (!strcmp(value, "nothing"))
|
|
cfg->push_default = PUSH_DEFAULT_NOTHING;
|
|
else if (!strcmp(value, "matching"))
|
|
cfg->push_default = PUSH_DEFAULT_MATCHING;
|
|
else if (!strcmp(value, "simple"))
|
|
cfg->push_default = PUSH_DEFAULT_SIMPLE;
|
|
else if (!strcmp(value, "upstream"))
|
|
cfg->push_default = PUSH_DEFAULT_UPSTREAM;
|
|
else if (!strcmp(value, "tracking")) /* deprecated */
|
|
cfg->push_default = PUSH_DEFAULT_UPSTREAM;
|
|
else if (!strcmp(value, "current"))
|
|
cfg->push_default = PUSH_DEFAULT_CURRENT;
|
|
else {
|
|
error(_("malformed value for %s: %s"), var, value);
|
|
return error(_("must be one of nothing, matching, simple, "
|
|
"upstream or current"));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Add other config variables here and to Documentation/config.adoc. */
|
|
return 0;
|
|
}
|
|
|
|
static int git_default_attr_config(const char *var, const char *value)
|
|
{
|
|
if (!strcmp(var, "attr.tree")) {
|
|
FREE_AND_NULL(git_attr_tree);
|
|
return git_config_string(&git_attr_tree, var, value);
|
|
}
|
|
|
|
/*
|
|
* Add other attribute related config variables here and to
|
|
* Documentation/config/attr.adoc.
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
int git_default_config(const char *var, const char *value,
|
|
const struct config_context *ctx, void *cb)
|
|
{
|
|
struct repo_config_values *cfg = repo_config_values(the_repository);
|
|
|
|
if (starts_with(var, "core."))
|
|
return git_default_core_config(var, value, ctx, cb);
|
|
|
|
if (starts_with(var, "user.") ||
|
|
starts_with(var, "author.") ||
|
|
starts_with(var, "committer."))
|
|
return git_ident_config(var, value, ctx, cb);
|
|
|
|
if (starts_with(var, "i18n."))
|
|
return git_default_i18n_config(var, value);
|
|
|
|
if (starts_with(var, "branch."))
|
|
return git_default_branch_config(var, value);
|
|
|
|
if (starts_with(var, "push."))
|
|
return git_default_push_config(var, value);
|
|
|
|
if (starts_with(var, "attr."))
|
|
return git_default_attr_config(var, value);
|
|
|
|
if (starts_with(var, "advice.") || starts_with(var, "color.advice"))
|
|
return git_default_advice_config(var, value);
|
|
|
|
if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
|
|
pager_use_color = git_config_bool(var,value);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "pack.packsizelimit")) {
|
|
pack_size_limit_cfg = git_config_ulong(var, value, ctx->kvi);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(var, "pack.compression")) {
|
|
int level = git_config_int(var, value, ctx->kvi);
|
|
if (level == -1)
|
|
level = Z_DEFAULT_COMPRESSION;
|
|
else if (level < 0 || level > Z_BEST_COMPRESSION)
|
|
die(_("bad pack compression level %d"), level);
|
|
cfg->pack_compression_level = level;
|
|
pack_compression_seen = 1;
|
|
return 0;
|
|
}
|
|
|
|
if (starts_with(var, "sparse."))
|
|
return git_default_sparse_config(var, value);
|
|
|
|
/* Add other config variables here and to Documentation/config.adoc. */
|
|
return 0;
|
|
}
|
|
|
|
void repo_config_values_init(struct repo_config_values *cfg)
|
|
{
|
|
/* section "core" config values */
|
|
cfg->attributes_file = NULL;
|
|
cfg->excludes_file = NULL;
|
|
cfg->editor_program = NULL;
|
|
cfg->pager_program = NULL;
|
|
cfg->askpass_program = NULL;
|
|
cfg->apply_default_whitespace = NULL;
|
|
cfg->apply_default_ignorewhitespace = NULL;
|
|
cfg->push_default = PUSH_DEFAULT_UNSPECIFIED;
|
|
cfg->autorebase = AUTOREBASE_NEVER;
|
|
cfg->object_creation_mode = OBJECT_CREATION_MODE;
|
|
cfg->apply_sparse_checkout = 0;
|
|
cfg->trust_ctime = 1;
|
|
cfg->check_stat = 1;
|
|
cfg->zlib_compression_level = Z_BEST_SPEED;
|
|
cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
|
|
cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
|
|
cfg->core_sparse_checkout_cone = 0;
|
|
cfg->warn_on_object_refname_ambiguity = 1;
|
|
cfg->protect_hfs = PROTECT_HFS_DEFAULT;
|
|
cfg->protect_ntfs = PROTECT_NTFS_DEFAULT;
|
|
cfg->ignore_case = 0;
|
|
cfg->trust_executable_bit = 1;
|
|
cfg->has_symlinks = platform_has_symlinks();
|
|
cfg->use_nanosec = 0;
|
|
|
|
/* section "sparse" config values */
|
|
cfg->sparse_expect_files_outside_of_patterns = 0;
|
|
|
|
/* section "branch" config values */
|
|
cfg->branch_track = BRANCH_TRACK_REMOTE;
|
|
}
|
|
|
|
void repo_config_values_clear(struct repo_config_values *cfg)
|
|
{
|
|
FREE_AND_NULL(cfg->attributes_file);
|
|
FREE_AND_NULL(cfg->excludes_file);
|
|
FREE_AND_NULL(cfg->editor_program);
|
|
FREE_AND_NULL(cfg->pager_program);
|
|
FREE_AND_NULL(cfg->askpass_program);
|
|
FREE_AND_NULL(cfg->apply_default_whitespace);
|
|
FREE_AND_NULL(cfg->apply_default_ignorewhitespace);
|
|
}
|