X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=config.c;h=b82907cb857c9f745a2afa7abe786ee0c7ae1ff8;hb=355885d531568e144ce5c9a2f65792a3aa8b5528;hp=9a5c5470cc5ac893399bcf2126e4d5ba601718ef;hpb=dfaf75b4698833d820e77e9f42ef93f3b6d3669d;p=git.git diff --git a/config.c b/config.c index 9a5c5470c..b82907cb8 100644 --- a/config.c +++ b/config.c @@ -13,6 +13,7 @@ static FILE *config_file; static const char *config_file_name; static int config_linenr; +static int config_file_eof; static int zlib_compression_seen; static int get_next_char(void) @@ -34,7 +35,7 @@ static int get_next_char(void) if (c == '\n') config_linenr++; if (c == EOF) { - config_file = NULL; + config_file_eof = 1; c = '\n'; } } @@ -118,7 +119,7 @@ static int get_value(config_fn_t fn, char *name, unsigned int len) /* Get the full name */ for (;;) { c = get_next_char(); - if (c == EOF) + if (config_file_eof) break; if (!iskeychar(c)) break; @@ -182,7 +183,7 @@ static int get_base_var(char *name) for (;;) { int c = get_next_char(); - if (c == EOF) + if (config_file_eof) return -1; if (c == ']') return baselen; @@ -205,8 +206,7 @@ static int git_parse_file(config_fn_t fn) for (;;) { int c = get_next_char(); if (c == '\n') { - /* EOF? */ - if (!config_file) + if (config_file_eof) return 0; comment = 0; continue; @@ -234,17 +234,23 @@ static int git_parse_file(config_fn_t fn) die("bad config file line %d in %s", config_linenr, config_file_name); } -static unsigned long get_unit_factor(const char *end) +static int parse_unit_factor(const char *end, unsigned long *val) { 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); + else if (!strcasecmp(end, "k")) { + *val *= 1024; + return 1; + } + else if (!strcasecmp(end, "m")) { + *val *= 1024 * 1024; + return 1; + } + else if (!strcasecmp(end, "g")) { + *val *= 1024 * 1024 * 1024; + return 1; + } + return 0; } int git_parse_long(const char *value, long *ret) @@ -252,7 +258,10 @@ int git_parse_long(const char *value, long *ret) if (value && *value) { char *end; long val = strtol(value, &end, 0); - *ret = val * get_unit_factor(end); + unsigned long factor = 1; + if (!parse_unit_factor(end, &factor)) + return 0; + *ret = val * factor; return 1; } return 0; @@ -263,7 +272,9 @@ 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); + if (!parse_unit_factor(end, &val)) + return 0; + *ret = val; return 1; } return 0; @@ -298,6 +309,14 @@ int git_config_bool(const char *name, const char *value) return git_config_int(name, value) != 0; } +int git_config_string(const char **dest, const char *var, const char *value) +{ + if (!value) + return config_error_nonbool(var); + *dest = xstrdup(value); + return 0; +} + int git_default_config(const char *var, const char *value) { /* This needs a better name */ @@ -397,49 +416,42 @@ int git_default_config(const char *var, const char *value) } if (!strcmp(var, "user.name")) { + if (!value) + return config_error_nonbool(var); strlcpy(git_default_name, value, sizeof(git_default_name)); return 0; } if (!strcmp(var, "user.email")) { + if (!value) + return config_error_nonbool(var); strlcpy(git_default_email, value, sizeof(git_default_email)); return 0; } - if (!strcmp(var, "i18n.commitencoding")) { - git_commit_encoding = xstrdup(value); - return 0; - } - - if (!strcmp(var, "i18n.logoutputencoding")) { - git_log_output_encoding = xstrdup(value); - return 0; - } + if (!strcmp(var, "i18n.commitencoding")) + return git_config_string(&git_commit_encoding, var, value); + if (!strcmp(var, "i18n.logoutputencoding")) + return git_config_string(&git_log_output_encoding, var, value); if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) { pager_use_color = git_config_bool(var,value); return 0; } - if (!strcmp(var, "core.pager")) { - pager_program = xstrdup(value); - return 0; - } + if (!strcmp(var, "core.pager")) + return git_config_string(&pager_program, var, value); - if (!strcmp(var, "core.editor")) { - editor_program = xstrdup(value); - return 0; - } + if (!strcmp(var, "core.editor")) + return git_config_string(&editor_program, var, value); - if (!strcmp(var, "core.excludesfile")) { - if (!value) - die("core.excludesfile without value"); - excludes_file = xstrdup(value); - return 0; - } + if (!strcmp(var, "core.excludesfile")) + return git_config_string(&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; } @@ -458,6 +470,7 @@ int git_config_from_file(config_fn_t fn, const char *filename) config_file = f; config_file_name = filename; config_linenr = 1; + config_file_eof = 0; ret = git_parse_file(fn); fclose(f); config_file_name = NULL; @@ -689,12 +702,17 @@ static ssize_t find_beginning_of_line(const char* contents, size_t size, size_t equal_offset = size, bracket_offset = size; ssize_t offset; +contline: for (offset = offset_-2; offset > 0 && contents[offset] != '\n'; offset--) switch (contents[offset]) { case '=': equal_offset = offset; break; case ']': bracket_offset = offset; break; } + if (offset > 0 && contents[offset-1] == '\\') { + offset_ = offset; + goto contline; + } if (bracket_offset < equal_offset) { *found_bracket = 1; offset = bracket_offset+1; @@ -907,6 +925,9 @@ int git_config_set_multivar(const char* key, const char* value, contents, contents_sz, store.offset[i]-2, &new_line); + if (copy_end > 0 && contents[copy_end-1] != '\n') + new_line = 1; + /* write the first part of the config */ if (copy_end > copy_begin) { if (write_in_full(fd, contents + copy_begin, @@ -940,14 +961,12 @@ int git_config_set_multivar(const char* key, const char* value, munmap(contents, contents_sz); } - if (close(fd) || commit_lock_file(lock) < 0) { + if (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 @@ -958,8 +977,6 @@ int git_config_set_multivar(const char* key, const char* value, ret = 0; out_free: - if (0 <= fd) - close(fd); if (lock) rollback_lock_file(lock); free(config_filename); @@ -1057,9 +1074,18 @@ int git_config_rename_section(const char *old_name, const char *new_name) } fclose(config_file); unlock_and_out: - if (close(out_fd) || commit_lock_file(lock) < 0) + if (commit_lock_file(lock) < 0) ret = error("Cannot commit config file!"); out: free(config_filename); return ret; } + +/* + * Call this to report error for your variable that should not + * get a boolean value (i.e. "[my] var" means "true"). + */ +int config_error_nonbool(const char *var) +{ + return error("Missing value for '%s'", var); +}