Make :/ accept a regex rather than a fixed pattern
[gitweb.git] / config.c
index 738b24419dcd0deb4bb0700f25f8984b8862d14f..9b6b1df212252901b2e577009651ba8d26e4f25a 100644 (file)
--- a/config.c
+++ b/config.c
@@ -7,6 +7,7 @@
  */
 #include "cache.h"
 #include "exec_cmd.h"
+#include "strbuf.h"
 
 #define MAXNAME (256)
 
@@ -18,6 +19,48 @@ static int zlib_compression_seen;
 
 const char *config_exclusive_filename = NULL;
 
+struct config_item
+{
+       struct config_item *next;
+       char *name;
+       char *value;
+};
+static struct config_item *config_parameters;
+static struct config_item **config_parameters_tail = &config_parameters;
+
+static void lowercase(char *p)
+{
+       for (; *p; p++)
+               *p = tolower(*p);
+}
+
+int git_config_parse_parameter(const char *text)
+{
+       struct config_item *ct;
+       struct strbuf tmp = STRBUF_INIT;
+       struct strbuf **pair;
+       strbuf_addstr(&tmp, text);
+       pair = strbuf_split(&tmp, '=');
+       if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=')
+               strbuf_setlen(pair[0], pair[0]->len - 1);
+       strbuf_trim(pair[0]);
+       if (!pair[0]->len) {
+               strbuf_list_free(pair);
+               return -1;
+       }
+       ct = xcalloc(1, sizeof(struct config_item));
+       ct->name = strbuf_detach(pair[0], NULL);
+       if (pair[1]) {
+               strbuf_trim(pair[1]);
+               ct->value = strbuf_detach(pair[1], NULL);
+       }
+       strbuf_list_free(pair);
+       lowercase(ct->name);
+       *config_parameters_tail = ct;
+       config_parameters_tail = &ct->next;
+       return 0;
+}
+
 static int get_next_char(void)
 {
        int c;
@@ -62,7 +105,8 @@ static char *parse_value(void)
                if (comment)
                        continue;
                if (isspace(c) && !quote) {
-                       space = 1;
+                       if (len)
+                               space++;
                        continue;
                }
                if (!quote) {
@@ -71,11 +115,8 @@ static char *parse_value(void)
                                continue;
                        }
                }
-               if (space) {
-                       if (len)
-                               value[len++] = ' ';
-                       space = 0;
-               }
+               for (; space; space--)
+                       value[len++] = ' ';
                if (c == '\\') {
                        c = get_next_char();
                        switch (c) {
@@ -324,17 +365,30 @@ unsigned long git_config_ulong(const char *name, const char *value)
        return ret;
 }
 
-int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
+int git_config_maybe_bool(const char *name, const char *value)
 {
-       *is_bool = 1;
        if (!value)
                return 1;
        if (!*value)
                return 0;
-       if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on"))
+       if (!strcasecmp(value, "true")
+           || !strcasecmp(value, "yes")
+           || !strcasecmp(value, "on"))
                return 1;
-       if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off"))
+       if (!strcasecmp(value, "false")
+           || !strcasecmp(value, "no")
+           || !strcasecmp(value, "off"))
                return 0;
+       return -1;
+}
+
+int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
+{
+       int v = git_config_maybe_bool(name, value);
+       if (0 <= v) {
+               *is_bool = 1;
+               return v;
+       }
        *is_bool = 0;
        return git_config_int(name, value);
 }
@@ -353,6 +407,16 @@ int git_config_string(const char **dest, const char *var, const char *value)
        return 0;
 }
 
+int git_config_pathname(const char **dest, const char *var, const char *value)
+{
+       if (!value)
+               return config_error_nonbool(var);
+       *dest = expand_user_path(value);
+       if (!*dest)
+               die("Failed to expand user dir in: '%s'", value);
+       return 0;
+}
+
 static int git_default_core_config(const char *var, const char *value)
 {
        /* This needs a better name */
@@ -469,6 +533,11 @@ static int git_default_core_config(const char *var, const char *value)
                return 0;
        }
 
+       if (!strcmp(var, "core.notesref")) {
+               notes_ref_name = xstrdup(value);
+               return 0;
+       }
+
        if (!strcmp(var, "core.pager"))
                return git_config_string(&pager_program, var, value);
 
@@ -476,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value)
                return git_config_string(&editor_program, var, value);
 
        if (!strcmp(var, "core.excludesfile"))
-               return git_config_string(&excludes_file, var, value);
+               return git_config_pathname(&excludes_file, var, value);
 
        if (!strcmp(var, "core.whitespace")) {
                if (!value)
@@ -505,6 +574,11 @@ static int git_default_core_config(const char *var, const char *value)
                return 0;
        }
 
+       if (!strcmp(var, "core.sparsecheckout")) {
+               core_apply_sparse_checkout = git_config_bool(var, value);
+               return 0;
+       }
+
        /* Add other config variables here and to Documentation/config.txt. */
        return 0;
 }
@@ -515,8 +589,7 @@ static int git_default_user_config(const char *var, const char *value)
                if (!value)
                        return config_error_nonbool(var);
                strlcpy(git_default_name, value, sizeof(git_default_name));
-               if (git_default_email[0])
-                       user_ident_explicitly_given = 1;
+               user_ident_explicitly_given |= IDENT_NAME_GIVEN;
                return 0;
        }
 
@@ -524,8 +597,7 @@ static int git_default_user_config(const char *var, const char *value)
                if (!value)
                        return config_error_nonbool(var);
                strlcpy(git_default_email, value, sizeof(git_default_email));
-               if (git_default_name[0])
-                       user_ident_explicitly_given = 1;
+               user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
                return 0;
        }
 
@@ -629,6 +701,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
        if (!prefixcmp(var, "mailmap."))
                return git_default_mailmap_config(var, value);
 
+       if (!prefixcmp(var, "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;
@@ -664,7 +739,7 @@ const char *git_etc_gitconfig(void)
        return system_wide;
 }
 
-static int git_env_bool(const char *k, int def)
+int git_env_bool(const char *k, int def)
 {
        const char *v = getenv(k);
        return v ? git_config_bool(k, v) : def;
@@ -680,6 +755,15 @@ int git_config_global(void)
        return !git_env_bool("GIT_CONFIG_NOGLOBAL", 0);
 }
 
+int git_config_from_parameters(config_fn_t fn, void *data)
+{
+       const struct config_item *ct;
+       for (ct = config_parameters; ct; ct = ct->next)
+               if (fn(ct->name, ct->value, data) < 0)
+                       return -1;
+       return 0;
+}
+
 int git_config(config_fn_t fn, void *data)
 {
        int ret = 0, found = 0;
@@ -711,6 +795,12 @@ int git_config(config_fn_t fn, void *data)
                found += 1;
        }
        free(repo_config);
+
+       if (config_parameters) {
+               ret += git_config_from_parameters(fn, data);
+               found += 1;
+       }
+
        if (found == 0)
                return -1;
        return ret;
@@ -1118,7 +1208,7 @@ int git_config_set_multivar(const char *key, const char *value,
                                    copy_end - copy_begin)
                                        goto write_err_out;
                                if (new_line &&
-                                   write_in_full(fd, "\n", 1) != 1)
+                                   write_str_in_full(fd, "\n") != 1)
                                        goto write_err_out;
                        }
                        copy_begin = store.offset[i];