config.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. #include "builtin.h"
  2. #include "cache.h"
  3. #include "config.h"
  4. #include "color.h"
  5. #include "parse-options.h"
  6. #include "urlmatch.h"
  7. #include "quote.h"
  8. #include "worktree.h"
  9. static const char *const builtin_config_usage[] = {
  10. N_("git config [<options>]"),
  11. NULL
  12. };
  13. static char *key;
  14. static regex_t *key_regexp;
  15. static regex_t *regexp;
  16. static int show_keys;
  17. static int omit_values;
  18. static int use_key_regexp;
  19. static int do_all;
  20. static int do_not_match;
  21. static char delim = '=';
  22. static char key_delim = ' ';
  23. static char term = '\n';
  24. static int use_global_config, use_system_config, use_local_config;
  25. static int use_worktree_config;
  26. static struct git_config_source given_config_source;
  27. static int actions, type;
  28. static char *default_value;
  29. static int end_nul;
  30. static int respect_includes_opt = -1;
  31. static struct config_options config_options;
  32. static int show_origin;
  33. static int show_scope;
  34. #define ACTION_GET (1<<0)
  35. #define ACTION_GET_ALL (1<<1)
  36. #define ACTION_GET_REGEXP (1<<2)
  37. #define ACTION_REPLACE_ALL (1<<3)
  38. #define ACTION_ADD (1<<4)
  39. #define ACTION_UNSET (1<<5)
  40. #define ACTION_UNSET_ALL (1<<6)
  41. #define ACTION_RENAME_SECTION (1<<7)
  42. #define ACTION_REMOVE_SECTION (1<<8)
  43. #define ACTION_LIST (1<<9)
  44. #define ACTION_EDIT (1<<10)
  45. #define ACTION_SET (1<<11)
  46. #define ACTION_SET_ALL (1<<12)
  47. #define ACTION_GET_COLOR (1<<13)
  48. #define ACTION_GET_COLORBOOL (1<<14)
  49. #define ACTION_GET_URLMATCH (1<<15)
  50. /*
  51. * The actions "ACTION_LIST | ACTION_GET_*" which may produce more than
  52. * one line of output and which should therefore be paged.
  53. */
  54. #define PAGING_ACTIONS (ACTION_LIST | ACTION_GET_ALL | \
  55. ACTION_GET_REGEXP | ACTION_GET_URLMATCH)
  56. #define TYPE_BOOL 1
  57. #define TYPE_INT 2
  58. #define TYPE_BOOL_OR_INT 3
  59. #define TYPE_PATH 4
  60. #define TYPE_EXPIRY_DATE 5
  61. #define TYPE_COLOR 6
  62. #define TYPE_BOOL_OR_STR 7
  63. #define OPT_CALLBACK_VALUE(s, l, v, h, i) \
  64. { OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
  65. PARSE_OPT_NONEG, option_parse_type, (i) }
  66. static NORETURN void usage_builtin_config(void);
  67. static int option_parse_type(const struct option *opt, const char *arg,
  68. int unset)
  69. {
  70. int new_type, *to_type;
  71. if (unset) {
  72. *((int *) opt->value) = 0;
  73. return 0;
  74. }
  75. /*
  76. * To support '--<type>' style flags, begin with new_type equal to
  77. * opt->defval.
  78. */
  79. new_type = opt->defval;
  80. if (!new_type) {
  81. if (!strcmp(arg, "bool"))
  82. new_type = TYPE_BOOL;
  83. else if (!strcmp(arg, "int"))
  84. new_type = TYPE_INT;
  85. else if (!strcmp(arg, "bool-or-int"))
  86. new_type = TYPE_BOOL_OR_INT;
  87. else if (!strcmp(arg, "bool-or-str"))
  88. new_type = TYPE_BOOL_OR_STR;
  89. else if (!strcmp(arg, "path"))
  90. new_type = TYPE_PATH;
  91. else if (!strcmp(arg, "expiry-date"))
  92. new_type = TYPE_EXPIRY_DATE;
  93. else if (!strcmp(arg, "color"))
  94. new_type = TYPE_COLOR;
  95. else
  96. die(_("unrecognized --type argument, %s"), arg);
  97. }
  98. to_type = opt->value;
  99. if (*to_type && *to_type != new_type) {
  100. /*
  101. * Complain when there is a new type not equal to the old type.
  102. * This allows for combinations like '--int --type=int' and
  103. * '--type=int --type=int', but disallows ones like '--type=bool
  104. * --int' and '--type=bool
  105. * --type=int'.
  106. */
  107. error(_("only one type at a time"));
  108. usage_builtin_config();
  109. }
  110. *to_type = new_type;
  111. return 0;
  112. }
  113. static struct option builtin_config_options[] = {
  114. OPT_GROUP(N_("Config file location")),
  115. OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
  116. OPT_BOOL(0, "system", &use_system_config, N_("use system config file")),
  117. OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
  118. OPT_BOOL(0, "worktree", &use_worktree_config, N_("use per-worktree config file")),
  119. OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")),
  120. OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")),
  121. OPT_GROUP(N_("Action")),
  122. OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
  123. OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
  124. OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-regex]"), ACTION_GET_REGEXP),
  125. OPT_BIT(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
  126. OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value_regex]"), ACTION_REPLACE_ALL),
  127. OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
  128. OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-regex]"), ACTION_UNSET),
  129. OPT_BIT(0, "unset-all", &actions, N_("remove all matches: name [value-regex]"), ACTION_UNSET_ALL),
  130. OPT_BIT(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
  131. OPT_BIT(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
  132. OPT_BIT('l', "list", &actions, N_("list all"), ACTION_LIST),
  133. OPT_BIT('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
  134. OPT_BIT(0, "get-color", &actions, N_("find the color configured: slot [default]"), ACTION_GET_COLOR),
  135. OPT_BIT(0, "get-colorbool", &actions, N_("find the color setting: slot [stdout-is-tty]"), ACTION_GET_COLORBOOL),
  136. OPT_GROUP(N_("Type")),
  137. OPT_CALLBACK('t', "type", &type, "", N_("value is given this type"), option_parse_type),
  138. OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL),
  139. OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT),
  140. OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
  141. OPT_CALLBACK_VALUE(0, "bool-or-str", &type, N_("value is --bool or string"), TYPE_BOOL_OR_STR),
  142. OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
  143. OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
  144. OPT_GROUP(N_("Other")),
  145. OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
  146. OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
  147. OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
  148. OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
  149. OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
  150. OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
  151. OPT_END(),
  152. };
  153. static NORETURN void usage_builtin_config(void)
  154. {
  155. usage_with_options(builtin_config_usage, builtin_config_options);
  156. }
  157. static void check_argc(int argc, int min, int max)
  158. {
  159. if (argc >= min && argc <= max)
  160. return;
  161. if (min == max)
  162. error(_("wrong number of arguments, should be %d"), min);
  163. else
  164. error(_("wrong number of arguments, should be from %d to %d"),
  165. min, max);
  166. usage_builtin_config();
  167. }
  168. static void show_config_origin(struct strbuf *buf)
  169. {
  170. const char term = end_nul ? '\0' : '\t';
  171. strbuf_addstr(buf, current_config_origin_type());
  172. strbuf_addch(buf, ':');
  173. if (end_nul)
  174. strbuf_addstr(buf, current_config_name());
  175. else
  176. quote_c_style(current_config_name(), buf, NULL, 0);
  177. strbuf_addch(buf, term);
  178. }
  179. static void show_config_scope(struct strbuf *buf)
  180. {
  181. const char term = end_nul ? '\0' : '\t';
  182. const char *scope = config_scope_name(current_config_scope());
  183. strbuf_addstr(buf, N_(scope));
  184. strbuf_addch(buf, term);
  185. }
  186. static int show_all_config(const char *key_, const char *value_, void *cb)
  187. {
  188. if (show_origin || show_scope) {
  189. struct strbuf buf = STRBUF_INIT;
  190. if (show_scope)
  191. show_config_scope(&buf);
  192. if (show_origin)
  193. show_config_origin(&buf);
  194. /* Use fwrite as "buf" can contain \0's if "end_null" is set. */
  195. fwrite(buf.buf, 1, buf.len, stdout);
  196. strbuf_release(&buf);
  197. }
  198. if (!omit_values && value_)
  199. printf("%s%c%s%c", key_, delim, value_, term);
  200. else
  201. printf("%s%c", key_, term);
  202. return 0;
  203. }
  204. struct strbuf_list {
  205. struct strbuf *items;
  206. int nr;
  207. int alloc;
  208. };
  209. static int format_config(struct strbuf *buf, const char *key_, const char *value_)
  210. {
  211. if (show_scope)
  212. show_config_scope(buf);
  213. if (show_origin)
  214. show_config_origin(buf);
  215. if (show_keys)
  216. strbuf_addstr(buf, key_);
  217. if (!omit_values) {
  218. if (show_keys)
  219. strbuf_addch(buf, key_delim);
  220. if (type == TYPE_INT)
  221. strbuf_addf(buf, "%"PRId64,
  222. git_config_int64(key_, value_ ? value_ : ""));
  223. else if (type == TYPE_BOOL)
  224. strbuf_addstr(buf, git_config_bool(key_, value_) ?
  225. "true" : "false");
  226. else if (type == TYPE_BOOL_OR_INT) {
  227. int is_bool, v;
  228. v = git_config_bool_or_int(key_, value_, &is_bool);
  229. if (is_bool)
  230. strbuf_addstr(buf, v ? "true" : "false");
  231. else
  232. strbuf_addf(buf, "%d", v);
  233. } else if (type == TYPE_BOOL_OR_STR) {
  234. int v = git_parse_maybe_bool(value_);
  235. if (v < 0)
  236. strbuf_addstr(buf, value_);
  237. else
  238. strbuf_addstr(buf, v ? "true" : "false");
  239. } else if (type == TYPE_PATH) {
  240. const char *v;
  241. if (git_config_pathname(&v, key_, value_) < 0)
  242. return -1;
  243. strbuf_addstr(buf, v);
  244. free((char *)v);
  245. } else if (type == TYPE_EXPIRY_DATE) {
  246. timestamp_t t;
  247. if (git_config_expiry_date(&t, key_, value_) < 0)
  248. return -1;
  249. strbuf_addf(buf, "%"PRItime, t);
  250. } else if (type == TYPE_COLOR) {
  251. char v[COLOR_MAXLEN];
  252. if (git_config_color(v, key_, value_) < 0)
  253. return -1;
  254. strbuf_addstr(buf, v);
  255. } else if (value_) {
  256. strbuf_addstr(buf, value_);
  257. } else {
  258. /* Just show the key name; back out delimiter */
  259. if (show_keys)
  260. strbuf_setlen(buf, buf->len - 1);
  261. }
  262. }
  263. strbuf_addch(buf, term);
  264. return 0;
  265. }
  266. static int collect_config(const char *key_, const char *value_, void *cb)
  267. {
  268. struct strbuf_list *values = cb;
  269. if (!use_key_regexp && strcmp(key_, key))
  270. return 0;
  271. if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0))
  272. return 0;
  273. if (regexp != NULL &&
  274. (do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0)))
  275. return 0;
  276. ALLOC_GROW(values->items, values->nr + 1, values->alloc);
  277. strbuf_init(&values->items[values->nr], 0);
  278. return format_config(&values->items[values->nr++], key_, value_);
  279. }
  280. static int get_value(const char *key_, const char *regex_)
  281. {
  282. int ret = CONFIG_GENERIC_ERROR;
  283. struct strbuf_list values = {NULL};
  284. int i;
  285. if (use_key_regexp) {
  286. char *tl;
  287. /*
  288. * NEEDSWORK: this naive pattern lowercasing obviously does not
  289. * work for more complex patterns like "^[^.]*Foo.*bar".
  290. * Perhaps we should deprecate this altogether someday.
  291. */
  292. key = xstrdup(key_);
  293. for (tl = key + strlen(key) - 1;
  294. tl >= key && *tl != '.';
  295. tl--)
  296. *tl = tolower(*tl);
  297. for (tl = key; *tl && *tl != '.'; tl++)
  298. *tl = tolower(*tl);
  299. key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
  300. if (regcomp(key_regexp, key, REG_EXTENDED)) {
  301. error(_("invalid key pattern: %s"), key_);
  302. FREE_AND_NULL(key_regexp);
  303. ret = CONFIG_INVALID_PATTERN;
  304. goto free_strings;
  305. }
  306. } else {
  307. if (git_config_parse_key(key_, &key, NULL)) {
  308. ret = CONFIG_INVALID_KEY;
  309. goto free_strings;
  310. }
  311. }
  312. if (regex_) {
  313. if (regex_[0] == '!') {
  314. do_not_match = 1;
  315. regex_++;
  316. }
  317. regexp = (regex_t*)xmalloc(sizeof(regex_t));
  318. if (regcomp(regexp, regex_, REG_EXTENDED)) {
  319. error(_("invalid pattern: %s"), regex_);
  320. FREE_AND_NULL(regexp);
  321. ret = CONFIG_INVALID_PATTERN;
  322. goto free_strings;
  323. }
  324. }
  325. config_with_options(collect_config, &values,
  326. &given_config_source, &config_options);
  327. if (!values.nr && default_value) {
  328. struct strbuf *item;
  329. ALLOC_GROW(values.items, values.nr + 1, values.alloc);
  330. item = &values.items[values.nr++];
  331. strbuf_init(item, 0);
  332. if (format_config(item, key_, default_value) < 0)
  333. die(_("failed to format default config value: %s"),
  334. default_value);
  335. }
  336. ret = !values.nr;
  337. for (i = 0; i < values.nr; i++) {
  338. struct strbuf *buf = values.items + i;
  339. if (do_all || i == values.nr - 1)
  340. fwrite(buf->buf, 1, buf->len, stdout);
  341. strbuf_release(buf);
  342. }
  343. free(values.items);
  344. free_strings:
  345. free(key);
  346. if (key_regexp) {
  347. regfree(key_regexp);
  348. free(key_regexp);
  349. }
  350. if (regexp) {
  351. regfree(regexp);
  352. free(regexp);
  353. }
  354. return ret;
  355. }
  356. static char *normalize_value(const char *key, const char *value)
  357. {
  358. if (!value)
  359. return NULL;
  360. if (type == 0 || type == TYPE_PATH || type == TYPE_EXPIRY_DATE)
  361. /*
  362. * We don't do normalization for TYPE_PATH here: If
  363. * the path is like ~/foobar/, we prefer to store
  364. * "~/foobar/" in the config file, and to expand the ~
  365. * when retrieving the value.
  366. * Also don't do normalization for expiry dates.
  367. */
  368. return xstrdup(value);
  369. if (type == TYPE_INT)
  370. return xstrfmt("%"PRId64, git_config_int64(key, value));
  371. if (type == TYPE_BOOL)
  372. return xstrdup(git_config_bool(key, value) ? "true" : "false");
  373. if (type == TYPE_BOOL_OR_INT) {
  374. int is_bool, v;
  375. v = git_config_bool_or_int(key, value, &is_bool);
  376. if (!is_bool)
  377. return xstrfmt("%d", v);
  378. else
  379. return xstrdup(v ? "true" : "false");
  380. }
  381. if (type == TYPE_BOOL_OR_STR) {
  382. int v = git_parse_maybe_bool(value);
  383. if (v < 0)
  384. return xstrdup(value);
  385. else
  386. return xstrdup(v ? "true" : "false");
  387. }
  388. if (type == TYPE_COLOR) {
  389. char v[COLOR_MAXLEN];
  390. if (git_config_color(v, key, value))
  391. die(_("cannot parse color '%s'"), value);
  392. /*
  393. * The contents of `v` now contain an ANSI escape
  394. * sequence, not suitable for including within a
  395. * configuration file. Treat the above as a
  396. * "sanity-check", and return the given value, which we
  397. * know is representable as valid color code.
  398. */
  399. return xstrdup(value);
  400. }
  401. BUG("cannot normalize type %d", type);
  402. }
  403. static int get_color_found;
  404. static const char *get_color_slot;
  405. static const char *get_colorbool_slot;
  406. static char parsed_color[COLOR_MAXLEN];
  407. static int git_get_color_config(const char *var, const char *value, void *cb)
  408. {
  409. if (!strcmp(var, get_color_slot)) {
  410. if (!value)
  411. config_error_nonbool(var);
  412. if (color_parse(value, parsed_color) < 0)
  413. return -1;
  414. get_color_found = 1;
  415. }
  416. return 0;
  417. }
  418. static void get_color(const char *var, const char *def_color)
  419. {
  420. get_color_slot = var;
  421. get_color_found = 0;
  422. parsed_color[0] = '\0';
  423. config_with_options(git_get_color_config, NULL,
  424. &given_config_source, &config_options);
  425. if (!get_color_found && def_color) {
  426. if (color_parse(def_color, parsed_color) < 0)
  427. die(_("unable to parse default color value"));
  428. }
  429. fputs(parsed_color, stdout);
  430. }
  431. static int get_colorbool_found;
  432. static int get_diff_color_found;
  433. static int get_color_ui_found;
  434. static int git_get_colorbool_config(const char *var, const char *value,
  435. void *cb)
  436. {
  437. if (!strcmp(var, get_colorbool_slot))
  438. get_colorbool_found = git_config_colorbool(var, value);
  439. else if (!strcmp(var, "diff.color"))
  440. get_diff_color_found = git_config_colorbool(var, value);
  441. else if (!strcmp(var, "color.ui"))
  442. get_color_ui_found = git_config_colorbool(var, value);
  443. return 0;
  444. }
  445. static int get_colorbool(const char *var, int print)
  446. {
  447. get_colorbool_slot = var;
  448. get_colorbool_found = -1;
  449. get_diff_color_found = -1;
  450. get_color_ui_found = -1;
  451. config_with_options(git_get_colorbool_config, NULL,
  452. &given_config_source, &config_options);
  453. if (get_colorbool_found < 0) {
  454. if (!strcmp(get_colorbool_slot, "color.diff"))
  455. get_colorbool_found = get_diff_color_found;
  456. if (get_colorbool_found < 0)
  457. get_colorbool_found = get_color_ui_found;
  458. }
  459. if (get_colorbool_found < 0)
  460. /* default value if none found in config */
  461. get_colorbool_found = GIT_COLOR_AUTO;
  462. get_colorbool_found = want_color(get_colorbool_found);
  463. if (print) {
  464. printf("%s\n", get_colorbool_found ? "true" : "false");
  465. return 0;
  466. } else
  467. return get_colorbool_found ? 0 : 1;
  468. }
  469. static void check_write(void)
  470. {
  471. if (!given_config_source.file && !startup_info->have_repository)
  472. die(_("not in a git directory"));
  473. if (given_config_source.use_stdin)
  474. die(_("writing to stdin is not supported"));
  475. if (given_config_source.blob)
  476. die(_("writing config blobs is not supported"));
  477. }
  478. struct urlmatch_current_candidate_value {
  479. char value_is_null;
  480. struct strbuf value;
  481. };
  482. static int urlmatch_collect_fn(const char *var, const char *value, void *cb)
  483. {
  484. struct string_list *values = cb;
  485. struct string_list_item *item = string_list_insert(values, var);
  486. struct urlmatch_current_candidate_value *matched = item->util;
  487. if (!matched) {
  488. matched = xmalloc(sizeof(*matched));
  489. strbuf_init(&matched->value, 0);
  490. item->util = matched;
  491. } else {
  492. strbuf_reset(&matched->value);
  493. }
  494. if (value) {
  495. strbuf_addstr(&matched->value, value);
  496. matched->value_is_null = 0;
  497. } else {
  498. matched->value_is_null = 1;
  499. }
  500. return 0;
  501. }
  502. static int get_urlmatch(const char *var, const char *url)
  503. {
  504. int ret;
  505. char *section_tail;
  506. struct string_list_item *item;
  507. struct urlmatch_config config = { STRING_LIST_INIT_DUP };
  508. struct string_list values = STRING_LIST_INIT_DUP;
  509. config.collect_fn = urlmatch_collect_fn;
  510. config.cascade_fn = NULL;
  511. config.cb = &values;
  512. if (!url_normalize(url, &config.url))
  513. die("%s", config.url.err);
  514. config.section = xstrdup_tolower(var);
  515. section_tail = strchr(config.section, '.');
  516. if (section_tail) {
  517. *section_tail = '\0';
  518. config.key = section_tail + 1;
  519. show_keys = 0;
  520. } else {
  521. config.key = NULL;
  522. show_keys = 1;
  523. }
  524. config_with_options(urlmatch_config_entry, &config,
  525. &given_config_source, &config_options);
  526. ret = !values.nr;
  527. for_each_string_list_item(item, &values) {
  528. struct urlmatch_current_candidate_value *matched = item->util;
  529. struct strbuf buf = STRBUF_INIT;
  530. format_config(&buf, item->string,
  531. matched->value_is_null ? NULL : matched->value.buf);
  532. fwrite(buf.buf, 1, buf.len, stdout);
  533. strbuf_release(&buf);
  534. strbuf_release(&matched->value);
  535. }
  536. string_list_clear(&config.vars, 1);
  537. string_list_clear(&values, 1);
  538. free(config.url.url);
  539. free((void *)config.section);
  540. return ret;
  541. }
  542. static char *default_user_config(void)
  543. {
  544. struct strbuf buf = STRBUF_INIT;
  545. strbuf_addf(&buf,
  546. _("# This is Git's per-user configuration file.\n"
  547. "[user]\n"
  548. "# Please adapt and uncomment the following lines:\n"
  549. "# name = %s\n"
  550. "# email = %s\n"),
  551. ident_default_name(),
  552. ident_default_email());
  553. return strbuf_detach(&buf, NULL);
  554. }
  555. int cmd_config(int argc, const char **argv, const char *prefix)
  556. {
  557. int nongit = !startup_info->have_repository;
  558. char *value;
  559. given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
  560. argc = parse_options(argc, argv, prefix, builtin_config_options,
  561. builtin_config_usage,
  562. PARSE_OPT_STOP_AT_NON_OPTION);
  563. if (use_global_config + use_system_config + use_local_config +
  564. use_worktree_config +
  565. !!given_config_source.file + !!given_config_source.blob > 1) {
  566. error(_("only one config file at a time"));
  567. usage_builtin_config();
  568. }
  569. if (nongit) {
  570. if (use_local_config)
  571. die(_("--local can only be used inside a git repository"));
  572. if (given_config_source.blob)
  573. die(_("--blob can only be used inside a git repository"));
  574. if (use_worktree_config)
  575. die(_("--worktree can only be used inside a git repository"));
  576. }
  577. if (given_config_source.file &&
  578. !strcmp(given_config_source.file, "-")) {
  579. given_config_source.file = NULL;
  580. given_config_source.use_stdin = 1;
  581. given_config_source.scope = CONFIG_SCOPE_COMMAND;
  582. }
  583. if (use_global_config) {
  584. char *user_config = expand_user_path("~/.gitconfig", 0);
  585. char *xdg_config = xdg_config_home("config");
  586. if (!user_config)
  587. /*
  588. * It is unknown if HOME/.gitconfig exists, so
  589. * we do not know if we should write to XDG
  590. * location; error out even if XDG_CONFIG_HOME
  591. * is set and points at a sane location.
  592. */
  593. die(_("$HOME not set"));
  594. given_config_source.scope = CONFIG_SCOPE_GLOBAL;
  595. if (access_or_warn(user_config, R_OK, 0) &&
  596. xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
  597. given_config_source.file = xdg_config;
  598. free(user_config);
  599. } else {
  600. given_config_source.file = user_config;
  601. free(xdg_config);
  602. }
  603. }
  604. else if (use_system_config) {
  605. given_config_source.file = git_etc_gitconfig();
  606. given_config_source.scope = CONFIG_SCOPE_SYSTEM;
  607. } else if (use_local_config) {
  608. given_config_source.file = git_pathdup("config");
  609. given_config_source.scope = CONFIG_SCOPE_LOCAL;
  610. } else if (use_worktree_config) {
  611. struct worktree **worktrees = get_worktrees();
  612. if (repository_format_worktree_config)
  613. given_config_source.file = git_pathdup("config.worktree");
  614. else if (worktrees[0] && worktrees[1])
  615. die(_("--worktree cannot be used with multiple "
  616. "working trees unless the config\n"
  617. "extension worktreeConfig is enabled. "
  618. "Please read \"CONFIGURATION FILE\"\n"
  619. "section in \"git help worktree\" for details"));
  620. else
  621. given_config_source.file = git_pathdup("config");
  622. given_config_source.scope = CONFIG_SCOPE_LOCAL;
  623. free_worktrees(worktrees);
  624. } else if (given_config_source.file) {
  625. if (!is_absolute_path(given_config_source.file) && prefix)
  626. given_config_source.file =
  627. prefix_filename(prefix, given_config_source.file);
  628. given_config_source.scope = CONFIG_SCOPE_COMMAND;
  629. } else if (given_config_source.blob) {
  630. given_config_source.scope = CONFIG_SCOPE_COMMAND;
  631. }
  632. if (respect_includes_opt == -1)
  633. config_options.respect_includes = !given_config_source.file;
  634. else
  635. config_options.respect_includes = respect_includes_opt;
  636. if (!nongit) {
  637. config_options.commondir = get_git_common_dir();
  638. config_options.git_dir = get_git_dir();
  639. }
  640. if (end_nul) {
  641. term = '\0';
  642. delim = '\n';
  643. key_delim = '\n';
  644. }
  645. if ((actions & (ACTION_GET_COLOR|ACTION_GET_COLORBOOL)) && type) {
  646. error(_("--get-color and variable type are incoherent"));
  647. usage_builtin_config();
  648. }
  649. if (HAS_MULTI_BITS(actions)) {
  650. error(_("only one action at a time"));
  651. usage_builtin_config();
  652. }
  653. if (actions == 0)
  654. switch (argc) {
  655. case 1: actions = ACTION_GET; break;
  656. case 2: actions = ACTION_SET; break;
  657. case 3: actions = ACTION_SET_ALL; break;
  658. default:
  659. usage_builtin_config();
  660. }
  661. if (omit_values &&
  662. !(actions == ACTION_LIST || actions == ACTION_GET_REGEXP)) {
  663. error(_("--name-only is only applicable to --list or --get-regexp"));
  664. usage_builtin_config();
  665. }
  666. if (show_origin && !(actions &
  667. (ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST))) {
  668. error(_("--show-origin is only applicable to --get, --get-all, "
  669. "--get-regexp, and --list"));
  670. usage_builtin_config();
  671. }
  672. if (default_value && !(actions & ACTION_GET)) {
  673. error(_("--default is only applicable to --get"));
  674. usage_builtin_config();
  675. }
  676. if (actions & PAGING_ACTIONS)
  677. setup_auto_pager("config", 1);
  678. if (actions == ACTION_LIST) {
  679. check_argc(argc, 0, 0);
  680. if (config_with_options(show_all_config, NULL,
  681. &given_config_source,
  682. &config_options) < 0) {
  683. if (given_config_source.file)
  684. die_errno(_("unable to read config file '%s'"),
  685. given_config_source.file);
  686. else
  687. die(_("error processing config file(s)"));
  688. }
  689. }
  690. else if (actions == ACTION_EDIT) {
  691. char *config_file;
  692. check_argc(argc, 0, 0);
  693. if (!given_config_source.file && nongit)
  694. die(_("not in a git directory"));
  695. if (given_config_source.use_stdin)
  696. die(_("editing stdin is not supported"));
  697. if (given_config_source.blob)
  698. die(_("editing blobs is not supported"));
  699. git_config(git_default_config, NULL);
  700. config_file = given_config_source.file ?
  701. xstrdup(given_config_source.file) :
  702. git_pathdup("config");
  703. if (use_global_config) {
  704. int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
  705. if (fd >= 0) {
  706. char *content = default_user_config();
  707. write_str_in_full(fd, content);
  708. free(content);
  709. close(fd);
  710. }
  711. else if (errno != EEXIST)
  712. die_errno(_("cannot create configuration file %s"), config_file);
  713. }
  714. launch_editor(config_file, NULL, NULL);
  715. free(config_file);
  716. }
  717. else if (actions == ACTION_SET) {
  718. int ret;
  719. check_write();
  720. check_argc(argc, 2, 2);
  721. value = normalize_value(argv[0], argv[1]);
  722. UNLEAK(value);
  723. ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value);
  724. if (ret == CONFIG_NOTHING_SET)
  725. error(_("cannot overwrite multiple values with a single value\n"
  726. " Use a regexp, --add or --replace-all to change %s."), argv[0]);
  727. return ret;
  728. }
  729. else if (actions == ACTION_SET_ALL) {
  730. check_write();
  731. check_argc(argc, 2, 3);
  732. value = normalize_value(argv[0], argv[1]);
  733. UNLEAK(value);
  734. return git_config_set_multivar_in_file_gently(given_config_source.file,
  735. argv[0], value, argv[2], 0);
  736. }
  737. else if (actions == ACTION_ADD) {
  738. check_write();
  739. check_argc(argc, 2, 2);
  740. value = normalize_value(argv[0], argv[1]);
  741. UNLEAK(value);
  742. return git_config_set_multivar_in_file_gently(given_config_source.file,
  743. argv[0], value,
  744. CONFIG_REGEX_NONE, 0);
  745. }
  746. else if (actions == ACTION_REPLACE_ALL) {
  747. check_write();
  748. check_argc(argc, 2, 3);
  749. value = normalize_value(argv[0], argv[1]);
  750. UNLEAK(value);
  751. return git_config_set_multivar_in_file_gently(given_config_source.file,
  752. argv[0], value, argv[2], 1);
  753. }
  754. else if (actions == ACTION_GET) {
  755. check_argc(argc, 1, 2);
  756. return get_value(argv[0], argv[1]);
  757. }
  758. else if (actions == ACTION_GET_ALL) {
  759. do_all = 1;
  760. check_argc(argc, 1, 2);
  761. return get_value(argv[0], argv[1]);
  762. }
  763. else if (actions == ACTION_GET_REGEXP) {
  764. show_keys = 1;
  765. use_key_regexp = 1;
  766. do_all = 1;
  767. check_argc(argc, 1, 2);
  768. return get_value(argv[0], argv[1]);
  769. }
  770. else if (actions == ACTION_GET_URLMATCH) {
  771. check_argc(argc, 2, 2);
  772. return get_urlmatch(argv[0], argv[1]);
  773. }
  774. else if (actions == ACTION_UNSET) {
  775. check_write();
  776. check_argc(argc, 1, 2);
  777. if (argc == 2)
  778. return git_config_set_multivar_in_file_gently(given_config_source.file,
  779. argv[0], NULL, argv[1], 0);
  780. else
  781. return git_config_set_in_file_gently(given_config_source.file,
  782. argv[0], NULL);
  783. }
  784. else if (actions == ACTION_UNSET_ALL) {
  785. check_write();
  786. check_argc(argc, 1, 2);
  787. return git_config_set_multivar_in_file_gently(given_config_source.file,
  788. argv[0], NULL, argv[1], 1);
  789. }
  790. else if (actions == ACTION_RENAME_SECTION) {
  791. int ret;
  792. check_write();
  793. check_argc(argc, 2, 2);
  794. ret = git_config_rename_section_in_file(given_config_source.file,
  795. argv[0], argv[1]);
  796. if (ret < 0)
  797. return ret;
  798. if (ret == 0)
  799. die(_("no such section: %s"), argv[0]);
  800. }
  801. else if (actions == ACTION_REMOVE_SECTION) {
  802. int ret;
  803. check_write();
  804. check_argc(argc, 1, 1);
  805. ret = git_config_rename_section_in_file(given_config_source.file,
  806. argv[0], NULL);
  807. if (ret < 0)
  808. return ret;
  809. if (ret == 0)
  810. die(_("no such section: %s"), argv[0]);
  811. }
  812. else if (actions == ACTION_GET_COLOR) {
  813. check_argc(argc, 1, 2);
  814. get_color(argv[0], argv[1]);
  815. }
  816. else if (actions == ACTION_GET_COLORBOOL) {
  817. check_argc(argc, 1, 2);
  818. if (argc == 2)
  819. color_stdout_is_tty = git_config_bool("command line", argv[1]);
  820. return get_colorbool(argv[0], argc == 2);
  821. }
  822. return 0;
  823. }