diff options
Diffstat (limited to 'config.c')
-rw-r--r-- | config.c | 125 |
1 files changed, 95 insertions, 30 deletions
@@ -12,6 +12,8 @@ static FILE *config_file; static const char *config_file_name; static int config_linenr; +static int zlib_compression_seen; + static int get_next_char(void) { int c; @@ -231,21 +233,55 @@ static int git_parse_file(config_fn_t fn) die("bad config file line %d in %s", config_linenr, config_file_name); } -int git_config_int(const char *name, const char *value) +static unsigned long get_unit_factor(const char *end) +{ + if (!*end) + return 1; + else if (!strcasecmp(end, "k")) + return 1024; + else if (!strcasecmp(end, "m")) + return 1024 * 1024; + else if (!strcasecmp(end, "g")) + return 1024 * 1024 * 1024; + die("unknown unit: '%s'", end); +} + +int git_parse_long(const char *value, long *ret) { if (value && *value) { char *end; - int val = strtol(value, &end, 0); - if (!*end) - return val; - if (!strcasecmp(end, "k")) - return val * 1024; - if (!strcasecmp(end, "m")) - return val * 1024 * 1024; - if (!strcasecmp(end, "g")) - return val * 1024 * 1024 * 1024; - } - die("bad config value for '%s' in %s", name, config_file_name); + long val = strtol(value, &end, 0); + *ret = val * get_unit_factor(end); + return 1; + } + return 0; +} + +int git_parse_ulong(const char *value, unsigned long *ret) +{ + if (value && *value) { + char *end; + unsigned long val = strtoul(value, &end, 0); + *ret = val * get_unit_factor(end); + return 1; + } + return 0; +} + +int git_config_int(const char *name, const char *value) +{ + long ret; + if (!git_parse_long(value, &ret)) + die("bad config value for '%s' in %s", name, config_file_name); + return ret; +} + +unsigned long git_config_ulong(const char *name, const char *value) +{ + unsigned long ret; + if (!git_parse_ulong(value, &ret)) + die("bad config value for '%s' in %s", name, config_file_name); + return ret; } int git_config_bool(const char *name, const char *value) @@ -269,6 +305,11 @@ int git_default_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.quotepath")) { + quote_path_fully = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "core.symlinks")) { has_symlinks = git_config_bool(var, value); return 0; @@ -299,8 +340,14 @@ int git_default_config(const char *var, const char *value) return 0; } - if (!strcmp(var, "core.legacyheaders")) { - use_legacy_headers = git_config_bool(var, value); + if (!strcmp(var, "core.loosecompression")) { + int level = git_config_int(var, value); + if (level == -1) + level = Z_DEFAULT_COMPRESSION; + else if (level < 0 || level > Z_BEST_COMPRESSION) + die("bad zlib compression level %d", level); + zlib_compression_level = level; + zlib_compression_seen = 1; return 0; } @@ -310,7 +357,10 @@ int git_default_config(const char *var, const char *value) level = Z_DEFAULT_COMPRESSION; else if (level < 0 || level > Z_BEST_COMPRESSION) die("bad zlib compression level %d", level); - zlib_compression_level = level; + core_compression_level = level; + core_compression_seen = 1; + if (!zlib_compression_seen) + zlib_compression_level = level; return 0; } @@ -371,6 +421,16 @@ int git_default_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.pager")) { + pager_program = xstrdup(value); + return 0; + } + + if (!strcmp(var, "core.editor")) { + editor_program = xstrdup(value); + return 0; + } + /* Add other config variables here and to Documentation/config.txt. */ return 0; } @@ -512,7 +572,7 @@ static int store_aux(const char* key, const char* value) return 0; } -static int write_error() +static int write_error(void) { fprintf(stderr, "Failed to write new configuration file\n"); @@ -610,7 +670,7 @@ static ssize_t find_beginning_of_line(const char* contents, size_t size, size_t equal_offset = size, bracket_offset = size; ssize_t offset; - for (offset = offset_-2; offset > 0 + for (offset = offset_-2; offset > 0 && contents[offset] != '\n'; offset--) switch (contents[offset]) { case '=': equal_offset = offset; break; @@ -660,7 +720,7 @@ int git_config_set_multivar(const char* key, const char* value, int fd = -1, in_fd; int ret; char* config_filename; - char* lock_file; + struct lock_file *lock = NULL; const char* last_dot = strrchr(key, '.'); config_filename = getenv(CONFIG_ENVIRONMENT); @@ -670,7 +730,6 @@ int git_config_set_multivar(const char* key, const char* value, config_filename = git_path("config"); } config_filename = xstrdup(config_filename); - lock_file = xstrdup(mkpath("%s.lock", config_filename)); /* * Since "key" actually contains the section name and the real @@ -715,11 +774,12 @@ int git_config_set_multivar(const char* key, const char* value, store.key[i] = 0; /* - * The lock_file serves a purpose in addition to locking: the new + * The lock serves a purpose in addition to locking: the new * contents of .git/config will be written into it. */ - fd = open(lock_file, O_WRONLY | O_CREAT | O_EXCL, 0666); - if (fd < 0 || adjust_shared_perm(lock_file)) { + lock = xcalloc(sizeof(struct lock_file), 1); + fd = hold_lock_file_for_update(lock, config_filename, 0); + if (fd < 0) { fprintf(stderr, "could not lock config file\n"); free(store.key); ret = -1; @@ -859,25 +919,31 @@ int git_config_set_multivar(const char* key, const char* value, goto write_err_out; munmap(contents, contents_sz); - unlink(config_filename); } - if (rename(lock_file, config_filename) < 0) { - fprintf(stderr, "Could not rename the lock file?\n"); + if (close(fd) || commit_lock_file(lock) < 0) { + fprintf(stderr, "Cannot commit config file!\n"); ret = 4; goto out_free; } + /* fd is closed, so don't try to close it below. */ + fd = -1; + /* + * lock is committed, so don't try to roll it back below. + * NOTE: Since lockfile.c keeps a linked list of all created + * lock_file structures, it isn't safe to free(lock). It's + * better to just leave it hanging around. + */ + lock = NULL; ret = 0; out_free: if (0 <= fd) close(fd); + if (lock) + rollback_lock_file(lock); free(config_filename); - if (lock_file) { - unlink(lock_file); - free(lock_file); - } return ret; write_err_out: @@ -978,4 +1044,3 @@ int git_config_rename_section(const char *old_name, const char *new_name) free(config_filename); return ret; } - |