diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libgit2.c | 23 | ||||
-rw-r--r-- | src/repository.c | 115 | ||||
-rw-r--r-- | src/repository.h | 4 |
3 files changed, 139 insertions, 3 deletions
diff --git a/src/libgit2.c b/src/libgit2.c index 09f7ab533..cc793b458 100644 --- a/src/libgit2.c +++ b/src/libgit2.c @@ -52,6 +52,7 @@ static void libgit2_settings_global_shutdown(void) { git__free(git__user_agent); git__free(git__ssl_ciphers); + git_repository__free_extensions(); } static int git_libgit2_settings_global_init(void) @@ -367,6 +368,28 @@ int git_libgit2_opts(int key, ...) git_odb__loose_priority = va_arg(ap, int); break; + case GIT_OPT_SET_EXTENSIONS: + { + const char **extensions = va_arg(ap, const char **); + size_t len = va_arg(ap, size_t); + error = git_repository__set_extensions(extensions, len); + } + break; + + case GIT_OPT_GET_EXTENSIONS: + { + git_strarray *out = va_arg(ap, git_strarray *); + char **extensions; + size_t len; + + if ((error = git_repository__extensions(&extensions, &len)) < 0) + break; + + out->strings = extensions; + out->count = len; + } + break; + default: git_error_set(GIT_ERROR_INVALID, "invalid option key"); error = -1; diff --git a/src/repository.c b/src/repository.c index aae0c910b..d32111379 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1427,15 +1427,60 @@ static int check_repositoryformatversion(int *version, git_config *config) return 0; } +static const char *builtin_extensions[] = { + "noop" +}; + +static git_vector user_extensions = GIT_VECTOR_INIT; + static int check_valid_extension(const git_config_entry *entry, void *payload) { + git_buf cfg = GIT_BUF_INIT; + bool reject; + const char *extension; + size_t i; + int error = 0; + GIT_UNUSED(payload); - if (!strcmp(entry->name, "extensions.noop")) - return 0; + git_vector_foreach (&user_extensions, i, extension) { + git_buf_clear(&cfg); + + /* + * Users can specify that they don't want to support an + * extension with a '!' prefix. + */ + if ((reject = (extension[0] == '!')) == true) + extension = &extension[1]; + + if ((error = git_buf_printf(&cfg, "extensions.%s", extension)) < 0) + goto done; + if (strcmp(entry->name, cfg.ptr) == 0) { + if (reject) + goto fail; + + goto done; + } + } + + for (i = 0; i < ARRAY_SIZE(builtin_extensions); i++) { + extension = builtin_extensions[i]; + + if ((error = git_buf_printf(&cfg, "extensions.%s", extension)) < 0) + goto done; + + if (strcmp(entry->name, cfg.ptr) == 0) + goto done; + } + +fail: git_error_set(GIT_ERROR_REPOSITORY, "unsupported extension name %s", entry->name); - return -1; + error = -1; + +done: + git_buf_dispose(&cfg); + return error; } static int check_extensions(git_config *config, int version) @@ -1446,6 +1491,70 @@ static int check_extensions(git_config *config, int version) return git_config_foreach_match(config, "^extensions\\.", check_valid_extension, NULL); } +int git_repository__extensions(char ***out, size_t *out_len) +{ + git_vector extensions; + const char *builtin, *user; + char *extension; + size_t i, j; + + if (git_vector_init(&extensions, 8, NULL) < 0) + return -1; + + for (i = 0; i < ARRAY_SIZE(builtin_extensions); i++) { + bool match = false; + + builtin = builtin_extensions[i]; + + git_vector_foreach (&user_extensions, j, user) { + if (user[0] == '!' && strcmp(builtin, &user[1]) == 0) { + match = true; + break; + } + } + + if (match) + continue; + + if ((extension = git__strdup(builtin)) == NULL || + git_vector_insert(&extensions, extension) < 0) + return -1; + } + + git_vector_foreach (&user_extensions, i, user) { + if (user[0] == '!') + continue; + + if ((extension = git__strdup(user)) == NULL || + git_vector_insert(&extensions, extension) < 0) + return -1; + } + + *out = (char **)git_vector_detach(out_len, NULL, &extensions); + return 0; +} + +int git_repository__set_extensions(const char **extensions, size_t len) +{ + char *extension; + size_t i; + + git_repository__free_extensions(); + + for (i = 0; i < len; i++) { + if ((extension = git__strdup(extensions[i])) == NULL || + git_vector_insert(&user_extensions, extension) < 0) + return -1; + } + + return 0; +} + +void git_repository__free_extensions(void) +{ + git_vector_free_deep(&user_extensions); +} + int git_repository_create_head(const char *git_dir, const char *ref_name) { git_buf ref_path = GIT_BUF_INIT; diff --git a/src/repository.h b/src/repository.h index f48dd9edf..cbc160140 100644 --- a/src/repository.h +++ b/src/repository.h @@ -249,4 +249,8 @@ int git_repository_initialbranch(git_buf *out, git_repository *repo); */ int git_repository_workdir_path(git_buf *out, git_repository *repo, const char *path); +int git_repository__extensions(char ***out, size_t *out_len); +int git_repository__set_extensions(const char **extensions, size_t len); +void git_repository__free_extensions(void); + #endif |