2006-08-03 01:51:59 +04:00
|
|
|
#include "builtin.h"
|
2005-11-18 00:44:55 +03:00
|
|
|
#include "cache.h"
|
2007-11-28 09:41:05 +03:00
|
|
|
#include "color.h"
|
2009-02-21 03:49:25 +03:00
|
|
|
#include "parse-options.h"
|
2005-11-18 00:44:55 +03:00
|
|
|
|
2009-02-21 03:49:25 +03:00
|
|
|
static const char *const builtin_config_usage[] = {
|
|
|
|
"git config [options]",
|
|
|
|
NULL
|
|
|
|
};
|
2005-11-20 08:52:22 +03:00
|
|
|
|
2006-08-15 21:23:48 +04:00
|
|
|
static char *key;
|
|
|
|
static regex_t *key_regexp;
|
|
|
|
static regex_t *regexp;
|
|
|
|
static int show_keys;
|
|
|
|
static int use_key_regexp;
|
|
|
|
static int do_all;
|
|
|
|
static int do_not_match;
|
|
|
|
static int seen;
|
2007-06-25 18:03:55 +04:00
|
|
|
static char delim = '=';
|
|
|
|
static char key_delim = ' ';
|
|
|
|
static char term = '\n';
|
2005-11-20 08:52:22 +03:00
|
|
|
|
2010-08-04 05:59:23 +04:00
|
|
|
static int use_global_config, use_system_config, use_local_config;
|
2009-02-21 03:49:25 +03:00
|
|
|
static const char *given_config_file;
|
2009-02-21 03:49:27 +03:00
|
|
|
static int actions, types;
|
2009-02-21 03:49:25 +03:00
|
|
|
static const char *get_color_slot, *get_colorbool_slot;
|
|
|
|
static int end_null;
|
|
|
|
|
|
|
|
#define ACTION_GET (1<<0)
|
|
|
|
#define ACTION_GET_ALL (1<<1)
|
|
|
|
#define ACTION_GET_REGEXP (1<<2)
|
|
|
|
#define ACTION_REPLACE_ALL (1<<3)
|
|
|
|
#define ACTION_ADD (1<<4)
|
|
|
|
#define ACTION_UNSET (1<<5)
|
|
|
|
#define ACTION_UNSET_ALL (1<<6)
|
|
|
|
#define ACTION_RENAME_SECTION (1<<7)
|
|
|
|
#define ACTION_REMOVE_SECTION (1<<8)
|
|
|
|
#define ACTION_LIST (1<<9)
|
|
|
|
#define ACTION_EDIT (1<<10)
|
|
|
|
#define ACTION_SET (1<<11)
|
|
|
|
#define ACTION_SET_ALL (1<<12)
|
|
|
|
#define ACTION_GET_COLOR (1<<13)
|
|
|
|
#define ACTION_GET_COLORBOOL (1<<14)
|
|
|
|
|
2009-02-21 03:49:27 +03:00
|
|
|
#define TYPE_BOOL (1<<0)
|
|
|
|
#define TYPE_INT (1<<1)
|
|
|
|
#define TYPE_BOOL_OR_INT (1<<2)
|
2009-12-30 19:51:53 +03:00
|
|
|
#define TYPE_PATH (1<<3)
|
2009-02-21 03:49:27 +03:00
|
|
|
|
2009-02-21 03:49:25 +03:00
|
|
|
static struct option builtin_config_options[] = {
|
|
|
|
OPT_GROUP("Config file location"),
|
|
|
|
OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"),
|
|
|
|
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
|
2010-08-04 05:59:23 +04:00
|
|
|
OPT_BOOLEAN(0, "local", &use_local_config, "use repository config file"),
|
2011-02-15 16:09:12 +03:00
|
|
|
OPT_STRING('f', "file", &given_config_file, "file", "use given config file"),
|
2009-02-21 03:49:25 +03:00
|
|
|
OPT_GROUP("Action"),
|
|
|
|
OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET),
|
|
|
|
OPT_BIT(0, "get-all", &actions, "get all values: key [value-regex]", ACTION_GET_ALL),
|
|
|
|
OPT_BIT(0, "get-regexp", &actions, "get values for regexp: name-regex [value-regex]", ACTION_GET_REGEXP),
|
2009-03-17 12:46:37 +03:00
|
|
|
OPT_BIT(0, "replace-all", &actions, "replace all matching variables: name value [value_regex]", ACTION_REPLACE_ALL),
|
2009-02-21 03:49:25 +03:00
|
|
|
OPT_BIT(0, "add", &actions, "adds a new variable: name value", ACTION_ADD),
|
|
|
|
OPT_BIT(0, "unset", &actions, "removes a variable: name [value-regex]", ACTION_UNSET),
|
|
|
|
OPT_BIT(0, "unset-all", &actions, "removes all matches: name [value-regex]", ACTION_UNSET_ALL),
|
|
|
|
OPT_BIT(0, "rename-section", &actions, "rename section: old-name new-name", ACTION_RENAME_SECTION),
|
|
|
|
OPT_BIT(0, "remove-section", &actions, "remove a section: name", ACTION_REMOVE_SECTION),
|
|
|
|
OPT_BIT('l', "list", &actions, "list all", ACTION_LIST),
|
|
|
|
OPT_BIT('e', "edit", &actions, "opens an editor", ACTION_EDIT),
|
|
|
|
OPT_STRING(0, "get-color", &get_color_slot, "slot", "find the color configured: [default]"),
|
|
|
|
OPT_STRING(0, "get-colorbool", &get_colorbool_slot, "slot", "find the color setting: [stdout-is-tty]"),
|
|
|
|
OPT_GROUP("Type"),
|
2009-02-21 03:49:27 +03:00
|
|
|
OPT_BIT(0, "bool", &types, "value is \"true\" or \"false\"", TYPE_BOOL),
|
|
|
|
OPT_BIT(0, "int", &types, "value is decimal number", TYPE_INT),
|
2009-03-07 20:14:05 +03:00
|
|
|
OPT_BIT(0, "bool-or-int", &types, "value is --bool or --int", TYPE_BOOL_OR_INT),
|
2009-12-30 19:51:53 +03:00
|
|
|
OPT_BIT(0, "path", &types, "value is a path (file or directory name)", TYPE_PATH),
|
2009-02-21 03:49:25 +03:00
|
|
|
OPT_GROUP("Other"),
|
|
|
|
OPT_BOOLEAN('z', "null", &end_null, "terminate values with NUL byte"),
|
|
|
|
OPT_END(),
|
|
|
|
};
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2008-05-14 21:46:53 +04:00
|
|
|
static int show_all_config(const char *key_, const char *value_, void *cb)
|
2006-04-25 02:59:25 +04:00
|
|
|
{
|
|
|
|
if (value_)
|
2007-06-25 18:03:55 +04:00
|
|
|
printf("%s%c%s%c", key_, delim, value_, term);
|
2006-04-25 02:59:25 +04:00
|
|
|
else
|
2007-06-25 18:03:55 +04:00
|
|
|
printf("%s%c", key_, term);
|
2006-04-25 02:59:25 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-21 03:48:53 +03:00
|
|
|
static int show_config(const char *key_, const char *value_, void *cb)
|
2005-11-20 08:52:22 +03:00
|
|
|
{
|
2006-05-03 08:06:56 +04:00
|
|
|
char value[256];
|
|
|
|
const char *vptr = value;
|
2009-12-30 19:51:53 +03:00
|
|
|
int must_free_vptr = 0;
|
2006-05-03 16:41:03 +04:00
|
|
|
int dup_error = 0;
|
2006-05-03 08:06:56 +04:00
|
|
|
|
2006-05-03 16:41:03 +04:00
|
|
|
if (!use_key_regexp && strcmp(key_, key))
|
|
|
|
return 0;
|
|
|
|
if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0))
|
|
|
|
return 0;
|
|
|
|
if (regexp != NULL &&
|
2007-12-05 18:11:24 +03:00
|
|
|
(do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0)))
|
2006-05-03 16:41:03 +04:00
|
|
|
return 0;
|
|
|
|
|
2007-06-25 18:03:54 +04:00
|
|
|
if (show_keys) {
|
|
|
|
if (value_)
|
2007-06-25 18:03:55 +04:00
|
|
|
printf("%s%c", key_, key_delim);
|
2007-06-25 18:03:54 +04:00
|
|
|
else
|
|
|
|
printf("%s", key_);
|
|
|
|
}
|
2006-05-03 16:41:03 +04:00
|
|
|
if (seen && !do_all)
|
|
|
|
dup_error = 1;
|
2009-02-21 03:49:27 +03:00
|
|
|
if (types == TYPE_INT)
|
2006-06-24 16:19:30 +04:00
|
|
|
sprintf(value, "%d", git_config_int(key_, value_?value_:""));
|
2009-02-21 03:49:27 +03:00
|
|
|
else if (types == TYPE_BOOL)
|
2006-05-03 16:41:03 +04:00
|
|
|
vptr = git_config_bool(key_, value_) ? "true" : "false";
|
2009-02-21 03:49:27 +03:00
|
|
|
else if (types == TYPE_BOOL_OR_INT) {
|
2008-04-13 23:11:11 +04:00
|
|
|
int is_bool, v;
|
|
|
|
v = git_config_bool_or_int(key_, value_, &is_bool);
|
|
|
|
if (is_bool)
|
|
|
|
vptr = v ? "true" : "false";
|
|
|
|
else
|
|
|
|
sprintf(value, "%d", v);
|
2009-12-30 19:51:53 +03:00
|
|
|
} else if (types == TYPE_PATH) {
|
|
|
|
git_config_pathname(&vptr, key_, value_);
|
|
|
|
must_free_vptr = 1;
|
2008-04-13 23:11:11 +04:00
|
|
|
}
|
2006-05-03 16:41:03 +04:00
|
|
|
else
|
2006-06-24 16:19:30 +04:00
|
|
|
vptr = value_?value_:"";
|
2006-05-03 16:41:03 +04:00
|
|
|
seen++;
|
|
|
|
if (dup_error) {
|
|
|
|
error("More than one value for the key %s: %s",
|
|
|
|
key_, vptr);
|
2005-11-20 08:52:22 +03:00
|
|
|
}
|
2006-05-03 16:41:03 +04:00
|
|
|
else
|
2007-06-25 18:03:55 +04:00
|
|
|
printf("%s%c", vptr, term);
|
2009-12-30 19:51:53 +03:00
|
|
|
if (must_free_vptr)
|
|
|
|
/* If vptr must be freed, it's a pointer to a
|
|
|
|
* dynamically allocated buffer, it's safe to cast to
|
|
|
|
* const.
|
|
|
|
*/
|
|
|
|
free((char *)vptr);
|
2006-05-03 16:41:03 +04:00
|
|
|
|
2005-11-20 08:52:22 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-21 03:48:53 +03:00
|
|
|
static int get_value(const char *key_, const char *regex_)
|
2005-11-20 08:52:22 +03:00
|
|
|
{
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
int ret = -1;
|
|
|
|
char *global = NULL, *repo_config = NULL;
|
2007-02-14 14:48:14 +03:00
|
|
|
const char *system_wide = NULL, *local;
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
|
2008-06-30 11:37:47 +04:00
|
|
|
local = config_exclusive_filename;
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
if (!local) {
|
|
|
|
const char *home = getenv("HOME");
|
2008-10-27 13:22:09 +03:00
|
|
|
local = repo_config = git_pathdup("config");
|
2011-03-15 12:04:49 +03:00
|
|
|
if (home)
|
2006-09-02 08:16:31 +04:00
|
|
|
global = xstrdup(mkpath("%s/.gitconfig", home));
|
2008-02-06 13:11:18 +03:00
|
|
|
if (git_config_system())
|
|
|
|
system_wide = git_etc_gitconfig();
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
}
|
2005-11-20 08:52:22 +03:00
|
|
|
|
2006-05-02 16:22:48 +04:00
|
|
|
if (use_key_regexp) {
|
2011-01-30 22:40:41 +03:00
|
|
|
char *tl;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NEEDSWORK: this naive pattern lowercasing obviously does not
|
|
|
|
* work for more complex patterns like "^[^.]*Foo.*bar".
|
|
|
|
* Perhaps we should deprecate this altogether someday.
|
|
|
|
*/
|
|
|
|
|
|
|
|
key = xstrdup(key_);
|
|
|
|
for (tl = key + strlen(key) - 1;
|
|
|
|
tl >= key && *tl != '.';
|
|
|
|
tl--)
|
|
|
|
*tl = tolower(*tl);
|
|
|
|
for (tl = key; *tl && *tl != '.'; tl++)
|
|
|
|
*tl = tolower(*tl);
|
|
|
|
|
2006-09-01 02:32:39 +04:00
|
|
|
key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
|
2006-05-02 16:22:48 +04:00
|
|
|
if (regcomp(key_regexp, key, REG_EXTENDED)) {
|
2006-05-03 08:06:56 +04:00
|
|
|
fprintf(stderr, "Invalid key pattern: %s\n", key_);
|
2011-01-30 22:40:41 +03:00
|
|
|
free(key);
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
goto free_strings;
|
2006-05-02 16:22:48 +04:00
|
|
|
}
|
2011-01-30 22:40:41 +03:00
|
|
|
} else {
|
|
|
|
if (git_config_parse_key(key_, &key, NULL))
|
|
|
|
goto free_strings;
|
2006-05-02 16:22:48 +04:00
|
|
|
}
|
|
|
|
|
2005-11-20 08:52:22 +03:00
|
|
|
if (regex_) {
|
2005-11-20 15:24:18 +03:00
|
|
|
if (regex_[0] == '!') {
|
|
|
|
do_not_match = 1;
|
|
|
|
regex_++;
|
|
|
|
}
|
|
|
|
|
2006-09-01 02:32:39 +04:00
|
|
|
regexp = (regex_t*)xmalloc(sizeof(regex_t));
|
2006-01-05 03:31:02 +03:00
|
|
|
if (regcomp(regexp, regex_, REG_EXTENDED)) {
|
2005-11-20 08:52:22 +03:00
|
|
|
fprintf(stderr, "Invalid pattern: %s\n", regex_);
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
goto free_strings;
|
2005-11-20 08:52:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-02-14 14:48:14 +03:00
|
|
|
if (do_all && system_wide)
|
2008-05-14 21:46:53 +04:00
|
|
|
git_config_from_file(show_config, system_wide, NULL);
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
if (do_all && global)
|
2008-05-14 21:46:53 +04:00
|
|
|
git_config_from_file(show_config, global, NULL);
|
2010-03-27 01:53:57 +03:00
|
|
|
if (do_all)
|
|
|
|
git_config_from_file(show_config, local, NULL);
|
|
|
|
git_config_from_parameters(show_config, NULL);
|
|
|
|
if (!do_all && !seen)
|
|
|
|
git_config_from_file(show_config, local, NULL);
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
if (!do_all && !seen && global)
|
2008-05-14 21:46:53 +04:00
|
|
|
git_config_from_file(show_config, global, NULL);
|
2007-02-14 14:48:14 +03:00
|
|
|
if (!do_all && !seen && system_wide)
|
2008-05-14 21:46:53 +04:00
|
|
|
git_config_from_file(show_config, system_wide, NULL);
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
|
2005-11-20 08:52:22 +03:00
|
|
|
free(key);
|
2006-01-05 03:31:02 +03:00
|
|
|
if (regexp) {
|
|
|
|
regfree(regexp);
|
|
|
|
free(regexp);
|
2005-11-20 08:52:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (do_all)
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
ret = !seen;
|
|
|
|
else
|
2006-07-04 00:47:55 +04:00
|
|
|
ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1;
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
|
|
|
|
free_strings:
|
2006-08-28 08:19:39 +04:00
|
|
|
free(repo_config);
|
|
|
|
free(global);
|
Read configuration also from $HOME/.gitconfig
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 03:48:03 +04:00
|
|
|
return ret;
|
2005-11-20 08:52:22 +03:00
|
|
|
}
|
2005-11-18 00:44:55 +03:00
|
|
|
|
2008-07-24 03:09:35 +04:00
|
|
|
static char *normalize_value(const char *key, const char *value)
|
2007-06-25 18:00:24 +04:00
|
|
|
{
|
|
|
|
char *normalized;
|
|
|
|
|
|
|
|
if (!value)
|
|
|
|
return NULL;
|
|
|
|
|
2009-12-30 19:51:53 +03:00
|
|
|
if (types == 0 || types == TYPE_PATH)
|
|
|
|
/*
|
|
|
|
* We don't do normalization for TYPE_PATH here: If
|
|
|
|
* the path is like ~/foobar/, we prefer to store
|
|
|
|
* "~/foobar/" in the config file, and to expand the ~
|
|
|
|
* when retrieving the value.
|
|
|
|
*/
|
2007-06-25 18:00:24 +04:00
|
|
|
normalized = xstrdup(value);
|
|
|
|
else {
|
|
|
|
normalized = xmalloc(64);
|
2009-02-21 03:49:27 +03:00
|
|
|
if (types == TYPE_INT) {
|
2007-06-25 18:00:24 +04:00
|
|
|
int v = git_config_int(key, value);
|
|
|
|
sprintf(normalized, "%d", v);
|
|
|
|
}
|
2009-02-21 03:49:27 +03:00
|
|
|
else if (types == TYPE_BOOL)
|
2007-06-25 18:00:24 +04:00
|
|
|
sprintf(normalized, "%s",
|
|
|
|
git_config_bool(key, value) ? "true" : "false");
|
2009-02-21 03:49:27 +03:00
|
|
|
else if (types == TYPE_BOOL_OR_INT) {
|
2008-04-13 23:11:11 +04:00
|
|
|
int is_bool, v;
|
|
|
|
v = git_config_bool_or_int(key, value, &is_bool);
|
|
|
|
if (!is_bool)
|
|
|
|
sprintf(normalized, "%d", v);
|
|
|
|
else
|
|
|
|
sprintf(normalized, "%s", v ? "true" : "false");
|
|
|
|
}
|
2007-06-25 18:00:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return normalized;
|
|
|
|
}
|
|
|
|
|
2007-11-28 09:41:05 +03:00
|
|
|
static int get_color_found;
|
|
|
|
static const char *get_color_slot;
|
2009-02-21 03:48:56 +03:00
|
|
|
static const char *get_colorbool_slot;
|
2007-11-28 09:41:05 +03:00
|
|
|
static char parsed_color[COLOR_MAXLEN];
|
|
|
|
|
2008-05-14 21:46:53 +04:00
|
|
|
static int git_get_color_config(const char *var, const char *value, void *cb)
|
2007-11-28 09:41:05 +03:00
|
|
|
{
|
|
|
|
if (!strcmp(var, get_color_slot)) {
|
2008-02-11 21:48:12 +03:00
|
|
|
if (!value)
|
|
|
|
config_error_nonbool(var);
|
2007-11-28 09:41:05 +03:00
|
|
|
color_parse(value, var, parsed_color);
|
|
|
|
get_color_found = 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-21 03:48:57 +03:00
|
|
|
static void get_color(const char *def_color)
|
2007-11-28 09:41:05 +03:00
|
|
|
{
|
|
|
|
get_color_found = 0;
|
|
|
|
parsed_color[0] = '\0';
|
2008-05-14 21:46:53 +04:00
|
|
|
git_config(git_get_color_config, NULL);
|
2007-11-28 09:41:05 +03:00
|
|
|
|
|
|
|
if (!get_color_found && def_color)
|
|
|
|
color_parse(def_color, "command line", parsed_color);
|
|
|
|
|
|
|
|
fputs(parsed_color, stdout);
|
|
|
|
}
|
|
|
|
|
2007-12-06 04:26:11 +03:00
|
|
|
static int get_colorbool_found;
|
2007-12-06 09:12:07 +03:00
|
|
|
static int get_diff_color_found;
|
2008-05-14 21:46:53 +04:00
|
|
|
static int git_get_colorbool_config(const char *var, const char *value,
|
|
|
|
void *cb)
|
2007-12-06 04:26:11 +03:00
|
|
|
{
|
2011-08-18 09:03:48 +04:00
|
|
|
if (!strcmp(var, get_colorbool_slot))
|
|
|
|
get_colorbool_found = git_config_colorbool(var, value);
|
|
|
|
else if (!strcmp(var, "diff.color"))
|
|
|
|
get_diff_color_found = git_config_colorbool(var, value);
|
|
|
|
else if (!strcmp(var, "color.ui"))
|
|
|
|
git_use_color_default = git_config_colorbool(var, value);
|
2007-12-06 04:26:11 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-21 03:48:57 +03:00
|
|
|
static int get_colorbool(int print)
|
2007-12-06 04:26:11 +03:00
|
|
|
{
|
2007-12-06 09:12:07 +03:00
|
|
|
get_colorbool_found = -1;
|
|
|
|
get_diff_color_found = -1;
|
2008-05-14 21:46:53 +04:00
|
|
|
git_config(git_get_colorbool_config, NULL);
|
2007-12-06 04:26:11 +03:00
|
|
|
|
2007-12-06 09:12:07 +03:00
|
|
|
if (get_colorbool_found < 0) {
|
2009-02-21 03:48:56 +03:00
|
|
|
if (!strcmp(get_colorbool_slot, "color.diff"))
|
2007-12-06 09:12:07 +03:00
|
|
|
get_colorbool_found = get_diff_color_found;
|
|
|
|
if (get_colorbool_found < 0)
|
2008-04-09 23:32:06 +04:00
|
|
|
get_colorbool_found = git_use_color_default;
|
2007-12-06 09:12:07 +03:00
|
|
|
}
|
|
|
|
|
color: delay auto-color decision until point of use
When we read a color value either from a config file or from
the command line, we use git_config_colorbool to convert it
from the tristate always/never/auto into a single yes/no
boolean value.
This has some timing implications with respect to starting
a pager.
If we start (or decide not to start) the pager before
checking the colorbool, everything is fine. Either isatty(1)
will give us the right information, or we will properly
check for pager_in_use().
However, if we decide to start a pager after we have checked
the colorbool, things are not so simple. If stdout is a tty,
then we will have already decided to use color. However, the
user may also have configured color.pager not to use color
with the pager. In this case, we need to actually turn off
color. Unfortunately, the pager code has no idea which color
variables were turned on (and there are many of them
throughout the code, and they may even have been manipulated
after the colorbool selection by something like "--color" on
the command line).
This bug can be seen any time a pager is started after
config and command line options are checked. This has
affected "git diff" since 89d07f7 (diff: don't run pager if
user asked for a diff style exit code, 2007-08-12). It has
also affect the log family since 1fda91b (Fix 'git log'
early pager startup error case, 2010-08-24).
This patch splits the notion of parsing a colorbool and
actually checking the configuration. The "use_color"
variables now have an additional possible value,
GIT_COLOR_AUTO. Users of the variable should use the new
"want_color()" wrapper, which will lazily determine and
cache the auto-color decision.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-18 09:04:23 +04:00
|
|
|
get_colorbool_found = want_color(get_colorbool_found);
|
|
|
|
|
2009-02-21 03:48:57 +03:00
|
|
|
if (print) {
|
2007-12-06 04:26:11 +03:00
|
|
|
printf("%s\n", get_colorbool_found ? "true" : "false");
|
|
|
|
return 0;
|
2009-02-21 03:48:57 +03:00
|
|
|
} else
|
|
|
|
return get_colorbool_found ? 0 : 1;
|
2007-12-06 04:26:11 +03:00
|
|
|
}
|
|
|
|
|
2010-08-06 07:15:09 +04:00
|
|
|
int cmd_config(int argc, const char **argv, const char *prefix)
|
2005-11-18 00:44:55 +03:00
|
|
|
{
|
2010-08-06 07:15:09 +04:00
|
|
|
int nongit = !startup_info->have_repository;
|
2009-02-21 03:48:53 +03:00
|
|
|
char *value;
|
2006-02-12 06:14:48 +03:00
|
|
|
|
2008-06-30 11:37:47 +04:00
|
|
|
config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
|
|
|
|
|
2009-05-23 22:53:12 +04:00
|
|
|
argc = parse_options(argc, argv, prefix, builtin_config_options,
|
|
|
|
builtin_config_usage,
|
2009-02-21 03:49:25 +03:00
|
|
|
PARSE_OPT_STOP_AT_NON_OPTION);
|
|
|
|
|
2010-08-04 05:59:23 +04:00
|
|
|
if (use_global_config + use_system_config + use_local_config + !!given_config_file > 1) {
|
2009-02-21 03:49:26 +03:00
|
|
|
error("only one config file at a time.");
|
|
|
|
usage_with_options(builtin_config_usage, builtin_config_options);
|
|
|
|
}
|
|
|
|
|
2009-02-21 03:49:25 +03:00
|
|
|
if (use_global_config) {
|
|
|
|
char *home = getenv("HOME");
|
|
|
|
if (home) {
|
|
|
|
char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
|
|
|
|
config_exclusive_filename = user_config;
|
2007-06-25 18:00:24 +04:00
|
|
|
} else {
|
2009-02-21 03:49:25 +03:00
|
|
|
die("$HOME not set");
|
2007-06-25 18:00:24 +04:00
|
|
|
}
|
2009-02-21 03:49:25 +03:00
|
|
|
}
|
|
|
|
else if (use_system_config)
|
|
|
|
config_exclusive_filename = git_etc_gitconfig();
|
2010-08-04 05:59:23 +04:00
|
|
|
else if (use_local_config)
|
|
|
|
config_exclusive_filename = git_pathdup("config");
|
2009-02-21 03:49:25 +03:00
|
|
|
else if (given_config_file) {
|
|
|
|
if (!is_absolute_path(given_config_file) && prefix)
|
|
|
|
config_exclusive_filename = prefix_filename(prefix,
|
|
|
|
strlen(prefix),
|
2010-01-26 18:02:16 +03:00
|
|
|
given_config_file);
|
2009-02-21 03:49:25 +03:00
|
|
|
else
|
|
|
|
config_exclusive_filename = given_config_file;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (end_null) {
|
|
|
|
term = '\0';
|
|
|
|
delim = '\n';
|
|
|
|
key_delim = '\n';
|
|
|
|
}
|
|
|
|
|
2009-02-21 03:49:27 +03:00
|
|
|
if (HAS_MULTI_BITS(types)) {
|
|
|
|
error("only one type at a time.");
|
|
|
|
usage_with_options(builtin_config_usage, builtin_config_options);
|
|
|
|
}
|
|
|
|
|
2009-02-21 03:49:25 +03:00
|
|
|
if (get_color_slot)
|
|
|
|
actions |= ACTION_GET_COLOR;
|
|
|
|
if (get_colorbool_slot)
|
|
|
|
actions |= ACTION_GET_COLORBOOL;
|
|
|
|
|
2009-02-21 03:49:29 +03:00
|
|
|
if ((get_color_slot || get_colorbool_slot) && types) {
|
|
|
|
error("--get-color and variable type are incoherent");
|
|
|
|
usage_with_options(builtin_config_usage, builtin_config_options);
|
|
|
|
}
|
|
|
|
|
2009-02-21 03:49:25 +03:00
|
|
|
if (HAS_MULTI_BITS(actions)) {
|
|
|
|
error("only one action at a time.");
|
|
|
|
usage_with_options(builtin_config_usage, builtin_config_options);
|
|
|
|
}
|
|
|
|
if (actions == 0)
|
|
|
|
switch (argc) {
|
|
|
|
case 1: actions = ACTION_GET; break;
|
|
|
|
case 2: actions = ACTION_SET; break;
|
|
|
|
case 3: actions = ACTION_SET_ALL; break;
|
|
|
|
default:
|
|
|
|
usage_with_options(builtin_config_usage, builtin_config_options);
|
2007-06-25 18:00:24 +04:00
|
|
|
}
|
2009-02-21 03:49:25 +03:00
|
|
|
|
|
|
|
if (actions == ACTION_LIST) {
|
2009-02-21 03:49:28 +03:00
|
|
|
check_argc(argc, 0, 0);
|
2009-02-21 03:49:25 +03:00
|
|
|
if (git_config(show_all_config, NULL) < 0) {
|
|
|
|
if (config_exclusive_filename)
|
2009-06-27 19:58:46 +04:00
|
|
|
die_errno("unable to read config file '%s'",
|
|
|
|
config_exclusive_filename);
|
2009-02-21 03:49:25 +03:00
|
|
|
else
|
|
|
|
die("error processing config file(s)");
|
2007-06-25 18:00:24 +04:00
|
|
|
}
|
2005-11-18 00:44:55 +03:00
|
|
|
}
|
2009-02-21 03:49:25 +03:00
|
|
|
else if (actions == ACTION_EDIT) {
|
2009-02-21 03:49:28 +03:00
|
|
|
check_argc(argc, 0, 0);
|
2009-04-30 02:49:47 +04:00
|
|
|
if (!config_exclusive_filename && nongit)
|
|
|
|
die("not in a git directory");
|
2009-02-21 03:49:25 +03:00
|
|
|
git_config(git_default_config, NULL);
|
|
|
|
launch_editor(config_exclusive_filename ?
|
|
|
|
config_exclusive_filename : git_path("config"),
|
|
|
|
NULL, NULL);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_SET) {
|
2011-05-17 19:38:53 +04:00
|
|
|
int ret;
|
2009-02-21 03:49:25 +03:00
|
|
|
check_argc(argc, 2, 2);
|
|
|
|
value = normalize_value(argv[0], argv[1]);
|
2011-05-17 19:38:53 +04:00
|
|
|
ret = git_config_set(argv[0], value);
|
|
|
|
if (ret == CONFIG_NOTHING_SET)
|
|
|
|
error("cannot overwrite multiple values with a single value\n"
|
|
|
|
" Use a regexp, --add or --set-all to change %s.", argv[0]);
|
|
|
|
return ret;
|
2009-02-21 03:49:25 +03:00
|
|
|
}
|
|
|
|
else if (actions == ACTION_SET_ALL) {
|
|
|
|
check_argc(argc, 2, 3);
|
|
|
|
value = normalize_value(argv[0], argv[1]);
|
|
|
|
return git_config_set_multivar(argv[0], value, argv[2], 0);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_ADD) {
|
|
|
|
check_argc(argc, 2, 2);
|
|
|
|
value = normalize_value(argv[0], argv[1]);
|
|
|
|
return git_config_set_multivar(argv[0], value, "^$", 0);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_REPLACE_ALL) {
|
|
|
|
check_argc(argc, 2, 3);
|
|
|
|
value = normalize_value(argv[0], argv[1]);
|
|
|
|
return git_config_set_multivar(argv[0], value, argv[2], 1);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_GET) {
|
|
|
|
check_argc(argc, 1, 2);
|
|
|
|
return get_value(argv[0], argv[1]);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_GET_ALL) {
|
|
|
|
do_all = 1;
|
|
|
|
check_argc(argc, 1, 2);
|
|
|
|
return get_value(argv[0], argv[1]);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_GET_REGEXP) {
|
|
|
|
show_keys = 1;
|
|
|
|
use_key_regexp = 1;
|
|
|
|
do_all = 1;
|
|
|
|
check_argc(argc, 1, 2);
|
|
|
|
return get_value(argv[0], argv[1]);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_UNSET) {
|
|
|
|
check_argc(argc, 1, 2);
|
|
|
|
if (argc == 2)
|
|
|
|
return git_config_set_multivar(argv[0], NULL, argv[1], 0);
|
|
|
|
else
|
|
|
|
return git_config_set(argv[0], NULL);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_UNSET_ALL) {
|
|
|
|
check_argc(argc, 1, 2);
|
|
|
|
return git_config_set_multivar(argv[0], NULL, argv[1], 1);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_RENAME_SECTION) {
|
|
|
|
int ret;
|
|
|
|
check_argc(argc, 2, 2);
|
|
|
|
ret = git_config_rename_section(argv[0], argv[1]);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
if (ret == 0)
|
|
|
|
die("No such section!");
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_REMOVE_SECTION) {
|
|
|
|
int ret;
|
|
|
|
check_argc(argc, 1, 1);
|
|
|
|
ret = git_config_rename_section(argv[0], NULL);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
if (ret == 0)
|
|
|
|
die("No such section!");
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_GET_COLOR) {
|
|
|
|
get_color(argv[0]);
|
|
|
|
}
|
|
|
|
else if (actions == ACTION_GET_COLORBOOL) {
|
|
|
|
if (argc == 1)
|
2011-08-18 09:03:48 +04:00
|
|
|
color_stdout_is_tty = git_config_bool("command line", argv[0]);
|
2009-02-21 03:49:25 +03:00
|
|
|
return get_colorbool(argc != 0);
|
|
|
|
}
|
|
|
|
|
2005-11-18 00:44:55 +03:00
|
|
|
return 0;
|
|
|
|
}
|
2011-02-12 16:24:10 +03:00
|
|
|
|
|
|
|
int cmd_repo_config(int argc, const char **argv, const char *prefix)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "WARNING: git repo-config is deprecated in favor of git config.\n");
|
|
|
|
return cmd_config(argc, argv, prefix);
|
|
|
|
}
|