From bc0897872d51e4d770d96ea4f18692b6415d2ac6 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 7 Aug 2026 15:55:08 +0200 Subject: [PATCH] setup: extract path_allowlist_apply() In a following commit we are going to check whether a repository is part of an allowlist specified in a config variable. To prepare for that let's extract existing code from safe_directory_cb() into a new path_allowlist_apply() helper that will help with such checks. While at it let's make the helper's code simpler and more generic. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- setup.c | 107 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 48 deletions(-) diff --git a/setup.c b/setup.c index b4652651df..734875c146 100644 --- a/setup.c +++ b/setup.c @@ -1329,6 +1329,64 @@ static int canonicalize_ceiling_entry(struct string_list_item *item, } } +static void path_allowlist_apply(const char *key, const char *value, + const char *target_path, int *is_match) +{ + char *allowed = NULL; + char *normalized = NULL; + + if (!value || !*value) { + *is_match = 0; + return; + } + + if (!strcmp(value, "*")) { + *is_match = 1; + return; + } + + if (git_config_pathname(&allowed, key, value) || !allowed) + return; + + /* + * Setting the config variable to a non-absolute path makes + * little sense---it won't be relative to the configuration + * file the item is defined in. Except for ".", which means + * "if we are at the top level of a repository, then it is + * OK", which is slightly tighter than "*" that allows + * discovery. + */ + if (!is_absolute_path(allowed) && strcmp(allowed, ".")) { + warning(_("%s '%s' not absolute"), key, allowed); + goto end; + } + + /* + * A .gitconfig in $HOME may be shared across different + * machines and the config variable entries may or may not + * exist as paths on all of these machines. In other words, + * it is not a warning worthy event when there is no such path + * on this machine---the entry may be useful elsewhere. + */ + normalized = real_pathdup(allowed, 0); + if (!normalized) + goto end; + + if (ends_with(normalized, "/*")) { + size_t len = strlen(normalized); + if (!fspathncmp(normalized, target_path, len - 1)) + *is_match = 1; + goto end; + } + + if (!fspathcmp(target_path, normalized)) + *is_match = 1; + +end: + free(normalized); + free(allowed); +} + struct safe_directory_data { char *path; int is_safe; @@ -1342,54 +1400,7 @@ static int safe_directory_cb(const char *key, const char *value, if (strcmp(key, "safe.directory")) return 0; - if (!value || !*value) { - data->is_safe = 0; - } else if (!strcmp(value, "*")) { - data->is_safe = 1; - } else { - char *allowed = NULL; - - if (!git_config_pathname(&allowed, key, value) && allowed) { - char *normalized = NULL; - - /* - * Setting safe.directory to a non-absolute path - * makes little sense---it won't be relative to - * the configuration file the item is defined in. - * Except for ".", which means "if we are at the top - * level of a repository, then it is OK", which is - * slightly tighter than "*" that allows discovery. - */ - if (!is_absolute_path(allowed) && strcmp(allowed, ".")) { - warning(_("safe.directory '%s' not absolute"), - allowed); - goto next; - } - - /* - * A .gitconfig in $HOME may be shared across - * different machines and safe.directory entries - * may or may not exist as paths on all of these - * machines. In other words, it is not a warning - * worthy event when there is no such path on this - * machine---the entry may be useful elsewhere. - */ - normalized = real_pathdup(allowed, 0); - if (!normalized) - goto next; - - if (ends_with(normalized, "/*")) { - size_t len = strlen(normalized); - if (!fspathncmp(normalized, data->path, len - 1)) - data->is_safe = 1; - } else if (!fspathcmp(data->path, normalized)) { - data->is_safe = 1; - } - next: - free(normalized); - free(allowed); - } - } + path_allowlist_apply(key, value, data->path, &data->is_safe); return 0; }