Raw
1 #define DISABLE_SIGN_COMPARE_WARNINGS
2
3 #include "git-compat-util.h"
4 #include "config.h"
5 #include "dir.h"
6 #include "tr2_sysenv.h"
7
8 /*
9 * Each entry represents a trace2 setting.
10 * See Documentation/technical/api-trace2.adoc
11 */
12 struct tr2_sysenv_entry {
13 const char *env_var_name;
14 const char *git_config_name;
15
16 char *value;
17 unsigned int getenv_called : 1;
18 };
19
20 /*
21 * This table must match "enum tr2_sysenv_variable" in tr2_sysenv.h.
22 *
23 * The strings in this table are constant and must match the published
24 * config and environment variable names as described in the documentation.
25 *
26 * We do not define entries for the GIT_TRACE2_PARENT_* environment
27 * variables because they are transient and used to pass information
28 * from parent to child git processes, rather than settings.
29 */
30 /* clang-format off */
31 static struct tr2_sysenv_entry tr2_sysenv_settings[] = {
32 [TR2_SYSENV_CFG_PARAM] = { "GIT_TRACE2_CONFIG_PARAMS",
33 "trace2.configparams" },
34 [TR2_SYSENV_ENV_VARS] = { "GIT_TRACE2_ENV_VARS",
35 "trace2.envvars" },
36
37 [TR2_SYSENV_DST_DEBUG] = { "GIT_TRACE2_DST_DEBUG",
38 "trace2.destinationdebug" },
39
40 [TR2_SYSENV_NORMAL] = { "GIT_TRACE2",
41 "trace2.normaltarget" },
42 [TR2_SYSENV_NORMAL_BRIEF] = { "GIT_TRACE2_BRIEF",
43 "trace2.normalbrief" },
44
45 [TR2_SYSENV_EVENT] = { "GIT_TRACE2_EVENT",
46 "trace2.eventtarget" },
47 [TR2_SYSENV_EVENT_BRIEF] = { "GIT_TRACE2_EVENT_BRIEF",
48 "trace2.eventbrief" },
49 [TR2_SYSENV_EVENT_NESTING] = { "GIT_TRACE2_EVENT_NESTING",
50 "trace2.eventnesting" },
51
52 [TR2_SYSENV_PERF] = { "GIT_TRACE2_PERF",
53 "trace2.perftarget" },
54 [TR2_SYSENV_PERF_BRIEF] = { "GIT_TRACE2_PERF_BRIEF",
55 "trace2.perfbrief" },
56
57 [TR2_SYSENV_MAX_FILES] = { "GIT_TRACE2_MAX_FILES",
58 "trace2.maxfiles" },
59 };
60 /* clang-format on */
61
62 static int tr2_sysenv_cb(const char *key, const char *value,
63 const struct config_context *ctx UNUSED,
64 void *d UNUSED)
65 {
66 int k;
67
68 if (!starts_with(key, "trace2."))
69 return 0;
70
71 for (k = 0; k < ARRAY_SIZE(tr2_sysenv_settings); k++) {
72 if (!strcmp(key, tr2_sysenv_settings[k].git_config_name)) {
73 if (!value)
74 return config_error_nonbool(key);
75 free(tr2_sysenv_settings[k].value);
76 tr2_sysenv_settings[k].value = xstrdup(value);
77 return 0;
78 }
79 }
80
81 return 0;
82 }
83
84 /*
85 * Load Trace2 settings from the system config (usually "/etc/gitconfig"
86 * unless we were built with a runtime-prefix). These are intended to
87 * define the default values for Trace2 as requested by the administrator.
88 *
89 * Then override with the Trace2 settings from the global config.
90 */
91 void tr2_sysenv_load(void)
92 {
93 if (ARRAY_SIZE(tr2_sysenv_settings) != TR2_SYSENV_MUST_BE_LAST)
94 BUG("tr2_sysenv_settings size is wrong");
95
96 read_very_early_config(tr2_sysenv_cb, NULL);
97 }
98
99 /*
100 * Return the value for the requested Trace2 setting from these sources:
101 * the system config, the global config, and the environment.
102 */
103 const char *tr2_sysenv_get(enum tr2_sysenv_variable var)
104 {
105 if (var >= TR2_SYSENV_MUST_BE_LAST)
106 BUG("tr2_sysenv_get invalid var '%d'", var);
107
108 if (!tr2_sysenv_settings[var].getenv_called) {
109 const char *v = getenv(tr2_sysenv_settings[var].env_var_name);
110 if (v && *v) {
111 free(tr2_sysenv_settings[var].value);
112 tr2_sysenv_settings[var].value = xstrdup(v);
113 }
114 tr2_sysenv_settings[var].getenv_called = 1;
115 }
116
117 return tr2_sysenv_settings[var].value;
118 }
119
120 /*
121 * Return a friendly name for this setting that is suitable for printing
122 * in an error messages.
123 */
124 const char *tr2_sysenv_display_name(enum tr2_sysenv_variable var)
125 {
126 if (var >= TR2_SYSENV_MUST_BE_LAST)
127 BUG("tr2_sysenv_get invalid var '%d'", var);
128
129 return tr2_sysenv_settings[var].env_var_name;
130 }
131
132 void tr2_sysenv_release(void)
133 {
134 int k;
135
136 for (k = 0; k < ARRAY_SIZE(tr2_sysenv_settings); k++)
137 free(tr2_sysenv_settings[k].value);
138 }