13
#include "hashmap.h"
14
#include "string-list.h"
15
#include "utf8.h"
16
+#include "dir.h"
17
18
struct config_source {
19
struct config_source *prev;
171
return ret;
172
}
173
174
+static int prepare_include_condition_pattern(struct strbuf *pat)
175
+{
176
+ struct strbuf path = STRBUF_INIT;
177
+ char *expanded;
178
+ int prefix = 0;
179
+
180
+ expanded = expand_user_path(pat->buf);
181
+ if (expanded) {
182
+ strbuf_reset(pat);
183
+ strbuf_addstr(pat, expanded);
184
+ free(expanded);
185
+ }
186
+
187
+ if (pat->buf[0] == '.' && is_dir_sep(pat->buf[1])) {
188
+ const char *slash;
189
+
190
+ if (!cf || !cf->path)
191
+ return error(_("relative config include "
192
+ "conditionals must come from files"));
193
+
194
+ strbuf_add_absolute_path(&path, cf->path);
195
+ slash = find_last_dir_sep(path.buf);
196
+ if (!slash)
197
+ die("BUG: how is this possible?");
198
+ strbuf_splice(pat, 0, 1, path.buf, slash - path.buf);
199
+ prefix = slash - path.buf + 1 /* slash */;
200
+ } else if (!is_absolute_path(pat->buf))
201
+ strbuf_insert(pat, 0, "**/", 3);
202
+
203
+ if (pat->len && is_dir_sep(pat->buf[pat->len - 1]))
204
+ strbuf_addstr(pat, "**");
205
+
206
+ strbuf_release(&path);
207
+ return prefix;
208
+}
209
+
210
+static int include_by_gitdir(const char *cond, size_t cond_len, int icase)
211
+{
212
+ struct strbuf text = STRBUF_INIT;
213
+ struct strbuf pattern = STRBUF_INIT;
214
+ int ret = 0, prefix;
215
+
216
+ strbuf_add_absolute_path(&text, get_git_dir());
217
+ strbuf_add(&pattern, cond, cond_len);
218
+ prefix = prepare_include_condition_pattern(&pattern);
219
+
220
+ if (prefix < 0)
221
+ goto done;
222
+
223
+ if (prefix > 0) {
224
+ /*
225
+ * perform literal matching on the prefix part so that
226
+ * any wildcard character in it can't create side effects.
227
+ */
228
+ if (text.len < prefix)
229
+ goto done;
230
+ if (!icase && strncmp(pattern.buf, text.buf, prefix))
231
+ goto done;
232
+ if (icase && strncasecmp(pattern.buf, text.buf, prefix))
233
+ goto done;
234
+ }
235
+
236
+ ret = !wildmatch(pattern.buf + prefix, text.buf + prefix,
237
+ icase ? WM_CASEFOLD : 0, NULL);
238
+
239
+done:
240
+ strbuf_release(&pattern);
241
+ strbuf_release(&text);
242
+ return ret;
243
+}
244
+
245
+static int include_condition_is_true(const char *cond, size_t cond_len)
246
+{
247
+
248
+ if (skip_prefix_mem(cond, cond_len, "gitdir:", &cond, &cond_len))
249
+ return include_by_gitdir(cond, cond_len, 0);
250
+ else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len))
251
+ return include_by_gitdir(cond, cond_len, 1);
252
+
253
+ /* unknown conditionals are always false */
254
+ return 0;
255
+}
256
+
257
int git_config_include(const char *var, const char *value, void *data)
258
{
259
struct config_include_data *inc = data;
260
+ const char *cond, *key;
261
+ int cond_len;
262
int ret;
263
264
/*
271
272
if (!strcmp(var, "include.path"))
273
ret = handle_path_include(value, inc);
274
+
275
+ if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) &&
276
+ (cond && include_condition_is_true(cond, cond_len)) &&
277
+ !strcmp(key, "path"))
278
+ ret = handle_path_include(value, inc);
279
+
280
return ret;
281
}
282