Merge branch 'es/format-patch-interdiff' into es/format-patch-rangediff
[gitweb.git] / builtin / config.c
index 24d735e16a390ca54577199423c773f4028885a3..2c93a289a7255c69260a806cc064f00170453531 100644 (file)
@@ -26,6 +26,7 @@ static char term = '\n';
 static int use_global_config, use_system_config, use_local_config;
 static struct git_config_source given_config_source;
 static int actions, type;
+static char *default_value;
 static int end_null;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
@@ -60,12 +61,13 @@ static int show_origin;
 #define TYPE_BOOL_OR_INT       3
 #define TYPE_PATH              4
 #define TYPE_EXPIRY_DATE       5
+#define TYPE_COLOR             6
 
 #define OPT_CALLBACK_VALUE(s, l, v, h, i) \
        { OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
        PARSE_OPT_NONEG, option_parse_type, (i) }
 
-static struct option builtin_config_options[];
+static NORETURN void usage_builtin_config(void);
 
 static int option_parse_type(const struct option *opt, const char *arg,
                             int unset)
@@ -93,6 +95,8 @@ static int option_parse_type(const struct option *opt, const char *arg,
                        new_type = TYPE_PATH;
                else if (!strcmp(arg, "expiry-date"))
                        new_type = TYPE_EXPIRY_DATE;
+               else if (!strcmp(arg, "color"))
+                       new_type = TYPE_COLOR;
                else
                        die(_("unrecognized --type argument, %s"), arg);
        }
@@ -107,8 +111,7 @@ static int option_parse_type(const struct option *opt, const char *arg,
                 * --type=int'.
                 */
                error("only one type at a time.");
-               usage_with_options(builtin_config_usage,
-                       builtin_config_options);
+               usage_builtin_config();
        }
        *to_type = new_type;
 
@@ -149,14 +152,20 @@ static struct option builtin_config_options[] = {
        OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
        OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
        OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+       OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
        OPT_END(),
 };
 
+static NORETURN void usage_builtin_config(void)
+{
+       usage_with_options(builtin_config_usage, builtin_config_options);
+}
+
 static void check_argc(int argc, int min, int max) {
        if (argc >= min && argc <= max)
                return;
        error("wrong number of arguments");
-       usage_with_options(builtin_config_usage, builtin_config_options);
+       usage_builtin_config();
 }
 
 static void show_config_origin(struct strbuf *buf)
@@ -228,6 +237,11 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
                        if (git_config_expiry_date(&t, key_, value_) < 0)
                                return -1;
                        strbuf_addf(buf, "%"PRItime, t);
+               } else if (type == TYPE_COLOR) {
+                       char v[COLOR_MAXLEN];
+                       if (git_config_color(v, key_, value_) < 0)
+                               return -1;
+                       strbuf_addstr(buf, v);
                } else if (value_) {
                        strbuf_addstr(buf, value_);
                } else {
@@ -313,6 +327,16 @@ static int get_value(const char *key_, const char *regex_)
        config_with_options(collect_config, &values,
                            &given_config_source, &config_options);
 
+       if (!values.nr && default_value) {
+               struct strbuf *item;
+               ALLOC_GROW(values.items, values.nr + 1, values.alloc);
+               item = &values.items[values.nr++];
+               strbuf_init(item, 0);
+               if (format_config(item, key_, default_value) < 0)
+                       die(_("failed to format default config value: %s"),
+                               default_value);
+       }
+
        ret = !values.nr;
 
        for (i = 0; i < values.nr; i++) {
@@ -363,8 +387,22 @@ static char *normalize_value(const char *key, const char *value)
                else
                        return xstrdup(v ? "true" : "false");
        }
+       if (type == TYPE_COLOR) {
+               char v[COLOR_MAXLEN];
+               if (git_config_color(v, key, value))
+                       die("cannot parse color '%s'", value);
 
-       die("BUG: cannot normalize type %d", type);
+               /*
+                * The contents of `v` now contain an ANSI escape
+                * sequence, not suitable for including within a
+                * configuration file. Treat the above as a
+                * "sanity-check", and return the given value, which we
+                * know is representable as valid color code.
+                */
+               return xstrdup(value);
+       }
+
+       BUG("cannot normalize type %d", type);
 }
 
 static int get_color_found;
@@ -562,12 +600,15 @@ int cmd_config(int argc, const char **argv, const char *prefix)
        if (use_global_config + use_system_config + use_local_config +
            !!given_config_source.file + !!given_config_source.blob > 1) {
                error("only one config file at a time.");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
        }
 
        if (use_local_config && nongit)
                die(_("--local can only be used inside a git repository"));
 
+       if (given_config_source.blob && nongit)
+               die(_("--blob can only be used inside a git repository"));
+
        if (given_config_source.file &&
                        !strcmp(given_config_source.file, "-")) {
                given_config_source.file = NULL;
@@ -623,12 +664,12 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 
        if ((actions & (ACTION_GET_COLOR|ACTION_GET_COLORBOOL)) && type) {
                error("--get-color and variable type are incoherent");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
        }
 
        if (HAS_MULTI_BITS(actions)) {
                error("only one action at a time.");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
        }
        if (actions == 0)
                switch (argc) {
@@ -636,19 +677,24 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                case 2: actions = ACTION_SET; break;
                case 3: actions = ACTION_SET_ALL; break;
                default:
-                       usage_with_options(builtin_config_usage, builtin_config_options);
+                       usage_builtin_config();
                }
        if (omit_values &&
            !(actions == ACTION_LIST || actions == ACTION_GET_REGEXP)) {
                error("--name-only is only applicable to --list or --get-regexp");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
        }
 
        if (show_origin && !(actions &
                (ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST))) {
                error("--show-origin is only applicable to --get, --get-all, "
                          "--get-regexp, and --list.");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
+       }
+
+       if (default_value && !(actions & ACTION_GET)) {
+               error("--default is only applicable to --get");
+               usage_builtin_config();
        }
 
        if (actions & PAGING_ACTIONS)