125
config_fn_t fn;
126
void *data;
127
const struct config_options *opts;
128
+ struct git_config_source *config_source;
129
+
130
+ /*
131
+ * All remote URLs discovered when reading all config files.
132
+ */
133
+ struct string_list *remote_urls;
134
};
135
#define CONFIG_INCLUDE_INIT { 0 }
136
310
return ret;
311
}
312
307
-static int include_condition_is_true(const struct config_options *opts,
313
+static int add_remote_url(const char *var, const char *value, void *data)
314
+{
315
+ struct string_list *remote_urls = data;
316
+ const char *remote_name;
317
+ size_t remote_name_len;
318
+ const char *key;
319
+
320
+ if (!parse_config_key(var, "remote", &remote_name, &remote_name_len,
321
+ &key) &&
322
+ remote_name &&
323
+ !strcmp(key, "url"))
324
+ string_list_append(remote_urls, value);
325
+ return 0;
326
+}
327
+
328
+static void populate_remote_urls(struct config_include_data *inc)
329
+{
330
+ struct config_options opts;
331
+
332
+ struct config_source *store_cf = cf;
333
+ struct key_value_info *store_kvi = current_config_kvi;
334
+ enum config_scope store_scope = current_parsing_scope;
335
+
336
+ opts = *inc->opts;
337
+ opts.unconditional_remote_url = 1;
338
+
339
+ cf = NULL;
340
+ current_config_kvi = NULL;
341
+ current_parsing_scope = 0;
342
+
343
+ inc->remote_urls = xmalloc(sizeof(*inc->remote_urls));
344
+ string_list_init_dup(inc->remote_urls);
345
+ config_with_options(add_remote_url, inc->remote_urls, inc->config_source, &opts);
346
+
347
+ cf = store_cf;
348
+ current_config_kvi = store_kvi;
349
+ current_parsing_scope = store_scope;
350
+}
351
+
352
+static int forbid_remote_url(const char *var, const char *value, void *data)
353
+{
354
+ const char *remote_name;
355
+ size_t remote_name_len;
356
+ const char *key;
357
+
358
+ if (!parse_config_key(var, "remote", &remote_name, &remote_name_len,
359
+ &key) &&
360
+ remote_name &&
361
+ !strcmp(key, "url"))
362
+ die(_("remote URLs cannot be configured in file directly or indirectly included by includeIf.hasconfig:remote.*.url"));
363
+ return 0;
364
+}
365
+
366
+static int at_least_one_url_matches_glob(const char *glob, int glob_len,
367
+ struct string_list *remote_urls)
368
+{
369
+ struct strbuf pattern = STRBUF_INIT;
370
+ struct string_list_item *url_item;
371
+ int found = 0;
372
+
373
+ strbuf_add(&pattern, glob, glob_len);
374
+ for_each_string_list_item(url_item, remote_urls) {
375
+ if (!wildmatch(pattern.buf, url_item->string, WM_PATHNAME)) {
376
+ found = 1;
377
+ break;
378
+ }
379
+ }
380
+ strbuf_release(&pattern);
381
+ return found;
382
+}
383
+
384
+static int include_by_remote_url(struct config_include_data *inc,
385
+ const char *cond, size_t cond_len)
386
+{
387
+ if (inc->opts->unconditional_remote_url)
388
+ return 1;
389
+ if (!inc->remote_urls)
390
+ populate_remote_urls(inc);
391
+ return at_least_one_url_matches_glob(cond, cond_len,
392
+ inc->remote_urls);
393
+}
394
+
395
+static int include_condition_is_true(struct config_include_data *inc,
396
const char *cond, size_t cond_len)
397
{
398
+ const struct config_options *opts = inc->opts;
399
400
if (skip_prefix_mem(cond, cond_len, "gitdir:", &cond, &cond_len))
401
return include_by_gitdir(opts, cond, cond_len, 0);
403
return include_by_gitdir(opts, cond, cond_len, 1);
404
else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len))
405
return include_by_branch(cond, cond_len);
406
+ else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
407
+ &cond_len))
408
+ return include_by_remote_url(inc, cond, cond_len);
409
410
/* unknown conditionals are always false */
411
return 0;
430
ret = handle_path_include(value, inc);
431
432
if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) &&
341
- (cond && include_condition_is_true(inc->opts, cond, cond_len)) &&
342
- !strcmp(key, "path"))
433
+ cond && include_condition_is_true(inc, cond, cond_len) &&
434
+ !strcmp(key, "path")) {
435
+ config_fn_t old_fn = inc->fn;
436
+
437
+ if (inc->opts->unconditional_remote_url)
438
+ inc->fn = forbid_remote_url;
439
ret = handle_path_include(value, inc);
440
+ inc->fn = old_fn;
441
+ }
442
443
return ret;
444
}
2034
const struct config_options *opts)
2035
{
2036
struct config_include_data inc = CONFIG_INCLUDE_INIT;
2037
+ int ret;
2038
2039
if (opts->respect_includes) {
2040
inc.fn = fn;
2041
inc.data = data;
2042
inc.opts = opts;
2043
+ inc.config_source = config_source;
2044
fn = git_config_include;
2045
data = &inc;
2046
}
2053
* regular lookup sequence.
2054
*/
2055
if (config_source && config_source->use_stdin) {
1956
- return git_config_from_stdin(fn, data);
2056
+ ret = git_config_from_stdin(fn, data);
2057
} else if (config_source && config_source->file) {
1958
- return git_config_from_file(fn, config_source->file, data);
2058
+ ret = git_config_from_file(fn, config_source->file, data);
2059
} else if (config_source && config_source->blob) {
2060
struct repository *repo = config_source->repo ?
2061
config_source->repo : the_repository;
1962
- return git_config_from_blob_ref(fn, repo, config_source->blob,
2062
+ ret = git_config_from_blob_ref(fn, repo, config_source->blob,
2063
data);
2064
+ } else {
2065
+ ret = do_git_config_sequence(opts, fn, data);
2066
}
2067
1966
- return do_git_config_sequence(opts, fn, data);
2068
+ if (inc.remote_urls) {
2069
+ string_list_clear(inc.remote_urls, 0);
2070
+ FREE_AND_NULL(inc.remote_urls);
2071
+ }
2072
+ return ret;
2073
}
2074
2075
static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)