From 9a97f49e3aa15edc479fc590f4b28fc44c155c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 21 Dec 2014 15:31:03 +0000 Subject: config: borrow refcounted references This changes the get_entry() method to return a refcounted version of the config entry, which you have to free when you're done. This allows us to avoid freeing the memory in which the entry is stored on a refresh, which may happen at any time for a live config. For this reason, get_string() has been forbidden on live configs and a new function get_string_buf() has been added, which stores the string in a git_buf which the user then owns. The functions which parse the string value takea advantage of the borrowing to parse safely and then release the entry. --- CHANGELOG.md | 12 ++++ include/git2/config.h | 40 ++++++++++--- include/git2/sys/config.h | 4 +- src/attrcache.c | 3 +- src/branch.c | 39 ++++++------- src/checkout.c | 10 ++-- src/config.c | 119 +++++++++++++++++++++++++++++++------- src/config.h | 4 +- src/config_cache.c | 3 +- src/config_file.c | 24 +++++--- src/config_file.h | 2 +- src/diff.c | 3 +- src/diff_driver.c | 3 +- src/remote.c | 9 ++- src/repository.c | 14 +++-- tests/clone/nonetwork.c | 2 +- tests/config/config_helpers.c | 13 +++-- tests/config/configlevel.c | 14 +++-- tests/config/global.c | 8 ++- tests/config/include.c | 50 +++++++++------- tests/config/new.c | 12 ++-- tests/config/read.c | 78 +++++++++++++------------ tests/config/rename.c | 8 ++- tests/config/stress.c | 58 ++++++++----------- tests/config/validkeyname.c | 5 +- tests/config/write.c | 63 ++++++++++++-------- tests/network/remote/remotes.c | 16 ++--- tests/refs/branches/move.c | 48 ++++++++------- tests/refs/branches/upstream.c | 25 +++----- tests/repo/init.c | 15 +---- tests/repo/setters.c | 8 ++- tests/submodule/add.c | 15 +---- tests/submodule/init.c | 12 ++-- tests/submodule/modify.c | 17 ++---- tests/submodule/repository_init.c | 8 +-- 35 files changed, 446 insertions(+), 318 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b88488e61..6f9e1f1cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,11 @@ v0.22 + 1 set and query which identity will be used when writing to the reflog. +* `git_config_entry_free()` frees a config entry. + +* `git_config_get_string_buf()` provides a way to safely retrieve a + string from a non-snapshot configuration. + ### API removals ### Breaking API changes @@ -53,6 +58,13 @@ v0.22 + 1 `git_repository_detach_head()` * `git_reset()` +* `git_config_get_entry()` now gives back a ref-counted + `git_config_entry`. You must free it when you no longer need it. + +* `git_config_get_string()` will return an error if used on a + non-snapshot configuration, as there can be no guarantee that the + returned pointer is valid. + v0.22 ------ diff --git a/include/git2/config.h b/include/git2/config.h index 70c8beade..6d3fdb0c2 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -58,12 +58,19 @@ typedef enum { /** * An entry in a configuration file */ -typedef struct { +typedef struct git_config_entry { const char *name; /**< Name of the entry (normalised) */ const char *value; /**< String value of the entry */ git_config_level_t level; /**< Which config file this was found in */ + void (*free)(struct git_config_entry *entry); /**< Free function for this entry */ + void *payload; /**< Opaque value for the free function. Do not read or write */ } git_config_entry; +/** + * Free a config entry + */ +GIT_EXTERN(void) git_config_entry_free(git_config_entry *); + typedef int (*git_config_foreach_cb)(const git_config_entry *, void *); typedef struct git_config_iterator git_config_iterator; @@ -261,16 +268,15 @@ GIT_EXTERN(void) git_config_free(git_config *cfg); /** * Get the git_config_entry of a config variable. * - * The git_config_entry is owned by the config and should not be freed by the - * user. - + * Free the git_config_entry after use with `git_config_entry_free()`. + * * @param out pointer to the variable git_config_entry * @param cfg where to look for the variable * @param name the variable's name * @return 0 or an error code */ GIT_EXTERN(int) git_config_get_entry( - const git_config_entry **out, + git_config_entry **out, const git_config *cfg, const char *name); @@ -340,21 +346,37 @@ GIT_EXTERN(int) git_config_get_path(git_buf *out, const git_config *cfg, const c /** * Get the value of a string config variable. * - * The string is owned by the variable and should not be freed by the - * user. The pointer will be valid until the next operation on this - * config object. + * This function can only be used on snapshot config objects. The + * string is owned by the config and should not be freed by the + * user. The pointer will be valid until the config is freed. * * All config files will be looked into, in the order of their * defined level. A higher level means a higher priority. The * first occurrence of the variable will be returned here. * - * @param out pointer to the variable's value + * @param out pointer to the string * @param cfg where to look for the variable * @param name the variable's name * @return 0 or an error code */ GIT_EXTERN(int) git_config_get_string(const char **out, const git_config *cfg, const char *name); +/** + * Get the value of a string config variable. + * + * The value of the config will be copied into the buffer. + * + * All config files will be looked into, in the order of their + * defined level. A higher level means a higher priority. The + * first occurrence of the variable will be returned here. + * + * @param out buffer in which to store the string + * @param cfg where to look for the variable + * @param name the variable's name + * @return 0 or an error code + */ +GIT_EXTERN(int) git_config_get_string_buf(git_buf *out, const git_config *cfg, const char *name); + /** * Get each value of a multivar in a foreach callback * diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 9136635ef..b5b7df15f 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -53,11 +53,13 @@ struct git_config_iterator { */ struct git_config_backend { unsigned int version; + /** True if this backend is for a snapshot */ + int readonly; struct git_config *cfg; /* Open means open the file/database and parse if necessary */ int (*open)(struct git_config_backend *, git_config_level_t level); - int (*get)(struct git_config_backend *, const char *key, const git_config_entry **entry); + int (*get)(struct git_config_backend *, const char *key, git_config_entry **entry); int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); diff --git a/src/attrcache.c b/src/attrcache.c index 018fa4874..5bc260460 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -276,7 +276,7 @@ static int attr_cache__lookup_path( { git_buf buf = GIT_BUF_INIT; int error; - const git_config_entry *entry = NULL; + git_config_entry *entry = NULL; *out = NULL; @@ -296,6 +296,7 @@ static int attr_cache__lookup_path( else if (!git_sysdir_find_xdg_file(&buf, fallback)) *out = git_buf_detach(&buf); + git_config_entry_free(entry); git_buf_free(&buf); return error; diff --git a/src/branch.c b/src/branch.c index 4e9460f36..06602c525 100644 --- a/src/branch.c +++ b/src/branch.c @@ -301,7 +301,7 @@ int git_branch_name( } static int retrieve_upstream_configuration( - const char **out, + git_buf *out, const git_config *config, const char *canonical_branch_name, const char *format) @@ -313,7 +313,7 @@ static int retrieve_upstream_configuration( canonical_branch_name + strlen(GIT_REFS_HEADS_DIR)) < 0) return -1; - error = git_config_get_string(out, config, git_buf_cstr(&buf)); + error = git_config_get_string_buf(out, config, git_buf_cstr(&buf)); git_buf_free(&buf); return error; } @@ -323,7 +323,8 @@ int git_branch_upstream_name( git_repository *repo, const char *refname) { - const char *remote_name, *merge_name; + git_buf remote_name = GIT_BUF_INIT; + git_buf merge_name = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT; int error = -1; git_remote *remote = NULL; @@ -348,27 +349,27 @@ int git_branch_upstream_name( &merge_name, config, refname, "branch.%s.merge")) < 0) goto cleanup; - if (!*remote_name || !*merge_name) { + if (git_buf_len(&remote_name) == 0 || git_buf_len(&merge_name) == 0) { giterr_set(GITERR_REFERENCE, "branch '%s' does not have an upstream", refname); error = GIT_ENOTFOUND; goto cleanup; } - if (strcmp(".", remote_name) != 0) { - if ((error = git_remote_lookup(&remote, repo, remote_name)) < 0) + if (strcmp(".", git_buf_cstr(&remote_name)) != 0) { + if ((error = git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name))) < 0) goto cleanup; - refspec = git_remote__matching_refspec(remote, merge_name); + refspec = git_remote__matching_refspec(remote, git_buf_cstr(&merge_name)); if (!refspec) { error = GIT_ENOTFOUND; goto cleanup; } - if (git_refspec_transform(&buf, refspec, merge_name) < 0) + if (git_refspec_transform(&buf, refspec, git_buf_cstr(&merge_name)) < 0) goto cleanup; } else - if (git_buf_sets(&buf, merge_name) < 0) + if (git_buf_set(&buf, git_buf_cstr(&merge_name), git_buf_len(&merge_name)) < 0) goto cleanup; error = git_buf_set(out, git_buf_cstr(&buf), git_buf_len(&buf)); @@ -376,6 +377,8 @@ int git_branch_upstream_name( cleanup: git_config_free(config); git_remote_free(remote); + git_buf_free(&remote_name); + git_buf_free(&merge_name); git_buf_free(&buf); return error; } @@ -383,29 +386,25 @@ cleanup: int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname) { int error; - const char *str; git_config *cfg; if (!git_reference__is_branch(refname)) return not_a_local_branch(refname); - git_buf_sanitize(buf); - if ((error = git_repository_config_snapshot(&cfg, repo)) < 0) + if ((error = git_repository_config__weakptr(&cfg, repo)) < 0) return error; - if ((error = retrieve_upstream_configuration(&str, cfg, refname, "branch.%s.remote")) < 0) - goto cleanup; + git_buf_sanitize(buf); - if (!*str) { + if ((error = retrieve_upstream_configuration(buf, cfg, refname, "branch.%s.remote")) < 0) + return error; + + if (git_buf_len(buf) == 0) { giterr_set(GITERR_REFERENCE, "branch '%s' does not have an upstream remote", refname); error = GIT_ENOTFOUND; - goto cleanup; + git_buf_clear(buf); } - error = git_buf_puts(buf, str); - -cleanup: - git_config_free(cfg); return error; } diff --git a/src/checkout.c b/src/checkout.c index c06928138..b106c110c 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -2390,25 +2390,27 @@ static int checkout_data_init( if ((data->opts.checkout_strategy & (GIT_CHECKOUT_CONFLICT_STYLE_MERGE | GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)) == 0) { - const char *conflict_style; + git_config_entry *conflict_style = NULL; git_config *cfg = NULL; if ((error = git_repository_config__weakptr(&cfg, repo)) < 0 || - (error = git_config_get_string(&conflict_style, cfg, "merge.conflictstyle")) < 0 || + (error = git_config_get_entry(&conflict_style, cfg, "merge.conflictstyle")) < 0 || error == GIT_ENOTFOUND) ; else if (error) goto cleanup; - else if (strcmp(conflict_style, "merge") == 0) + else if (strcmp(conflict_style->value, "merge") == 0) data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_MERGE; - else if (strcmp(conflict_style, "diff3") == 0) + else if (strcmp(conflict_style->value, "diff3") == 0) data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3; else { giterr_set(GITERR_CHECKOUT, "unknown style '%s' given for 'merge.conflictstyle'", conflict_style); error = -1; + git_config_entry_free(conflict_style); goto cleanup; } + git_config_entry_free(conflict_style); } if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 || diff --git a/src/config.c b/src/config.c index f80770138..d116a9d80 100644 --- a/src/config.c +++ b/src/config.c @@ -19,6 +19,14 @@ #include +void git_config_entry_free(git_config_entry *entry) +{ + if (!entry) + return; + + entry->free(entry); +} + typedef struct { git_refcount rc; @@ -638,7 +646,7 @@ int git_config__update_entry( bool only_if_existing) { int error = 0; - const git_config_entry *ce = NULL; + git_config_entry *ce = NULL; if ((error = git_config__lookup_entry(&ce, config, key, false)) < 0) return error; @@ -657,6 +665,7 @@ int git_config__update_entry( else error = git_config_set_string(config, key, value); + git_config_entry_free(ce); return error; } @@ -677,7 +686,7 @@ enum { }; static int get_entry( - const git_config_entry **out, + git_config_entry **out, const git_config *cfg, const char *name, bool normalize_name, @@ -721,13 +730,13 @@ cleanup: } int git_config_get_entry( - const git_config_entry **out, const git_config *cfg, const char *name) + git_config_entry **out, const git_config *cfg, const char *name) { return get_entry(out, cfg, name, true, GET_ALL_ERRORS); } int git_config__lookup_entry( - const git_config_entry **out, + git_config_entry **out, const git_config *cfg, const char *key, bool no_errors) @@ -743,87 +752,154 @@ int git_config_get_mapped( const git_cvar_map *maps, size_t map_n) { - const git_config_entry *entry; + git_config_entry *entry; int ret; if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0) return ret; - return git_config_lookup_map_value(out, maps, map_n, entry->value); + ret = git_config_lookup_map_value(out, maps, map_n, entry->value); + git_config_entry_free(entry); + + return ret; } int git_config_get_int64(int64_t *out, const git_config *cfg, const char *name) { - const git_config_entry *entry; + git_config_entry *entry; int ret; if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0) return ret; - return git_config_parse_int64(out, entry->value); + ret = git_config_parse_int64(out, entry->value); + git_config_entry_free(entry); + + return ret; } int git_config_get_int32(int32_t *out, const git_config *cfg, const char *name) { - const git_config_entry *entry; + git_config_entry *entry; int ret; if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0) return ret; - return git_config_parse_int32(out, entry->value); + ret = git_config_parse_int32(out, entry->value); + git_config_entry_free(entry); + + return ret; } int git_config_get_bool(int *out, const git_config *cfg, const char *name) { - const git_config_entry *entry; + git_config_entry *entry; int ret; if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0) return ret; - return git_config_parse_bool(out, entry->value); + ret = git_config_parse_bool(out, entry->value); + git_config_entry_free(entry); + + return ret; +} + +static int is_readonly(const git_config *cfg) +{ + size_t i; + file_internal *internal; + + git_vector_foreach(&cfg->files, i, internal) { + if (!internal || !internal->file) + continue; + + if (!internal->file->readonly) + return 0; + } + + return 1; } int git_config_get_path(git_buf *out, const git_config *cfg, const char *name) { - const git_config_entry *entry; + git_config_entry *entry; int error; if ((error = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0) return error; - return git_config_parse_path(out, entry->value); + error = git_config_parse_path(out, entry->value); + git_config_entry_free(entry); + + return error; } int git_config_get_string( const char **out, const git_config *cfg, const char *name) { - const git_config_entry *entry; - int ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS); + git_config_entry *entry; + int ret; + + if (!is_readonly(cfg)) { + giterr_set(GITERR_CONFIG, "get_string called on a live config object"); + return -1; + } + + ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS); *out = !ret ? (entry->value ? entry->value : "") : NULL; + + git_config_entry_free(entry); + return ret; } -const char *git_config__get_string_force( +int git_config_get_string_buf( + git_buf *out, const git_config *cfg, const char *name) +{ + git_config_entry *entry; + int ret; + const char *str; + + git_buf_sanitize(out); + + ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS); + str = !ret ? (entry->value ? entry->value : "") : NULL; + + if (str) + ret = git_buf_puts(out, str); + + git_config_entry_free(entry); + + return ret; +} + +char *git_config__get_string_force( const git_config *cfg, const char *key, const char *fallback_value) { - const git_config_entry *entry; + git_config_entry *entry; + char *ret; + get_entry(&entry, cfg, key, false, GET_NO_ERRORS); - return (entry && entry->value) ? entry->value : fallback_value; + ret = (entry && entry->value) ? git__strdup(entry->value) : fallback_value ? git__strdup(fallback_value) : NULL; + git_config_entry_free(entry); + + return ret; } int git_config__get_bool_force( const git_config *cfg, const char *key, int fallback_value) { int val = fallback_value; - const git_config_entry *entry; + git_config_entry *entry; get_entry(&entry, cfg, key, false, GET_NO_ERRORS); if (entry && git_config_parse_bool(&val, entry->value) < 0) giterr_clear(); + git_config_entry_free(entry); return val; } @@ -831,13 +907,14 @@ int git_config__get_int_force( const git_config *cfg, const char *key, int fallback_value) { int32_t val = (int32_t)fallback_value; - const git_config_entry *entry; + git_config_entry *entry; get_entry(&entry, cfg, key, false, GET_NO_ERRORS); if (entry && git_config_parse_int32(&val, entry->value) < 0) giterr_clear(); + git_config_entry_free(entry); return (int)val; } diff --git a/src/config.h b/src/config.h index b0dcb49ac..691868b1d 100644 --- a/src/config.h +++ b/src/config.h @@ -48,7 +48,7 @@ extern int git_config__normalize_name(const char *in, char **out); /* internal only: does not normalize key and sets out to NULL if not found */ extern int git_config__lookup_entry( - const git_config_entry **out, + git_config_entry **out, const git_config *cfg, const char *key, bool no_errors); @@ -67,7 +67,7 @@ extern int git_config__update_entry( * failures occur while trying to access the value. */ -extern const char *git_config__get_string_force( +extern char *git_config__get_string_force( const git_config *cfg, const char *key, const char *fallback_value); extern int git_config__get_bool_force( diff --git a/src/config_cache.c b/src/config_cache.c index d397a4bab..c859ec148 100644 --- a/src/config_cache.c +++ b/src/config_cache.c @@ -84,7 +84,7 @@ int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar) { int error = 0; struct map_data *data = &_cvar_maps[(int)cvar]; - const git_config_entry *entry; + git_config_entry *entry; git_config__lookup_entry(&entry, config, data->cvar_name, false); @@ -96,6 +96,7 @@ int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar) else error = git_config_parse_bool(out, entry->value); + git_config_entry_free(entry); return error; } diff --git a/src/config_file.c b/src/config_file.c index 168dd5483..732705687 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -96,7 +96,6 @@ typedef struct { /* mutex to coordinate accessing the values */ git_mutex values_mutex; refcounted_strmap *values; - int readonly; } diskfile_header; typedef struct { @@ -504,19 +503,26 @@ out: return ret; } +/* release the map containing the entry as an equivalent to freeing it */ +static void release_map(git_config_entry *entry) +{ + refcounted_strmap *map = (refcounted_strmap *) entry->payload; + refcounted_strmap_free(map); +} + /* * Internal function that actually gets the value in string form */ -static int config_get(git_config_backend *cfg, const char *key, const git_config_entry **out) +static int config_get(git_config_backend *cfg, const char *key, git_config_entry **out) { diskfile_header *h = (diskfile_header *)cfg; refcounted_strmap *map; git_strmap *values; khiter_t pos; cvar_t *var; - int error; + int error = 0; - if (!h->readonly && ((error = config_refresh(cfg)) < 0)) + if (!h->parent.readonly && ((error = config_refresh(cfg)) < 0)) return error; map = refcounted_strmap_take(h); @@ -534,9 +540,11 @@ static int config_get(git_config_backend *cfg, const char *key, const git_config while (var->next) var = var->next; - refcounted_strmap_free(map); *out = var->entry; - return 0; + (*out)->free = release_map; + (*out)->payload = map; + + return error; } static int config_set_multivar( @@ -763,7 +771,7 @@ static int config_readonly_open(git_config_backend *cfg, git_config_level_t leve refcounted_strmap *src_map; int error; - if (!src_header->readonly && (error = config_refresh(&src_header->parent)) < 0) + if (!src_header->parent.readonly && (error = config_refresh(&src_header->parent)) < 0) return error; /* We're just copying data, don't care about the level */ @@ -787,7 +795,7 @@ int git_config_file__snapshot(git_config_backend **out, diskfile_backend *in) backend->snapshot_from = in; - backend->header.readonly = 1; + backend->header.parent.readonly = 1; backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION; backend->header.parent.open = config_readonly_open; backend->header.parent.get = config_get; diff --git a/src/config_file.h b/src/config_file.h index fcccbd5cc..0d8bf740f 100644 --- a/src/config_file.h +++ b/src/config_file.h @@ -21,7 +21,7 @@ GIT_INLINE(void) git_config_file_free(git_config_backend *cfg) } GIT_INLINE(int) git_config_file_get_string( - const git_config_entry **out, git_config_backend *cfg, const char *name) + git_config_entry **out, git_config_backend *cfg, const char *name) { return cfg->get(cfg, name, out); } diff --git a/src/diff.c b/src/diff.c index 815351b21..9432b0467 100644 --- a/src/diff.c +++ b/src/diff.c @@ -461,12 +461,13 @@ static int diff_list_apply_options( /* if ignore_submodules not explicitly set, check diff config */ if (diff->opts.ignore_submodules <= 0) { - const git_config_entry *entry; + git_config_entry *entry; git_config__lookup_entry(&entry, cfg, "diff.ignoresubmodules", true); if (entry && git_submodule_parse_ignore( &diff->opts.ignore_submodules, entry->value) < 0) giterr_clear(); + git_config_entry_free(entry); } /* if either prefix is not set, figure out appropriate value */ diff --git a/src/diff_driver.c b/src/diff_driver.c index 049e6ef2a..69eef0f7a 100644 --- a/src/diff_driver.c +++ b/src/diff_driver.c @@ -242,7 +242,7 @@ static int git_diff_driver_load( khiter_t pos; git_config *cfg = NULL; git_buf name = GIT_BUF_INIT; - const git_config_entry *ce; + git_config_entry *ce = NULL; bool found_driver = false; if ((reg = git_repository_driver_registry(repo)) == NULL) @@ -341,6 +341,7 @@ static int git_diff_driver_load( *out = drv; done: + git_config_entry_free(ce); git_buf_free(&name); git_config_free(cfg); diff --git a/src/remote.c b/src/remote.c index bc6d8a2c4..4924bf83a 100644 --- a/src/remote.c +++ b/src/remote.c @@ -52,7 +52,7 @@ static int add_refspec(git_remote *remote, const char *string, bool is_fetch) static int download_tags_value(git_remote *remote, git_config *cfg) { - const git_config_entry *ce; + git_config_entry *ce; git_buf buf = GIT_BUF_INIT; int error; @@ -70,6 +70,7 @@ static int download_tags_value(git_remote *remote, git_config *cfg) remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; } + git_config_entry_free(ce); return error; } @@ -548,7 +549,7 @@ int git_remote_save(const git_remote *remote) git_config *cfg; const char *tagopt = NULL; git_buf buf = GIT_BUF_INIT; - const git_config_entry *existing; + git_config_entry *existing = NULL; assert(remote); @@ -618,6 +619,7 @@ int git_remote_save(const git_remote *remote) cfg, git_buf_cstr(&buf), tagopt, true, false); cleanup: + git_config_entry_free(existing); git_buf_free(&buf); return error; } @@ -753,7 +755,7 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url) { git_config *cfg; - const git_config_entry *ce; + git_config_entry *ce = NULL; const char *val = NULL; int error; @@ -805,6 +807,7 @@ found: *proxy_url = git__strdup(val); GITERR_CHECK_ALLOC(*proxy_url); } + git_config_entry_free(ce); return 0; } diff --git a/src/repository.c b/src/repository.c index 778cdefd7..43d3aeaea 100644 --- a/src/repository.c +++ b/src/repository.c @@ -191,7 +191,7 @@ static int load_config_data(git_repository *repo, const git_config *config) static int load_workdir(git_repository *repo, git_config *config, git_buf *parent_path) { int error; - const git_config_entry *ce; + git_config_entry *ce; git_buf worktree = GIT_BUF_INIT; if (repo->is_bare) @@ -204,7 +204,7 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren if (ce && ce->value) { if ((error = git_path_prettify_dir( &worktree, ce->value, repo->path_repository)) < 0) - return error; + goto cleanup; repo->workdir = git_buf_detach(&worktree); } @@ -212,14 +212,18 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren repo->workdir = git_buf_detach(parent_path); else { if (git_path_dirname_r(&worktree, repo->path_repository) < 0 || - git_path_to_dir(&worktree) < 0) - return -1; + git_path_to_dir(&worktree) < 0) { + error = -1; + goto cleanup; + } repo->workdir = git_buf_detach(&worktree); } GITERR_CHECK_ALLOC(repo->workdir); - return 0; +cleanup: + git_config_entry_free(ce); + return error; } /* diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c index 46b36ed92..2a3157739 100644 --- a/tests/clone/nonetwork.c +++ b/tests/clone/nonetwork.c @@ -291,7 +291,7 @@ void test_clone_nonetwork__clone_from_empty_sets_upstream(void) cl_set_cleanup(&cleanup_repository, "./repowithunborn"); cl_git_pass(git_clone(&repo, "./test1", "./repowithunborn", NULL)); - cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_repository_config_snapshot(&config, repo)); cl_git_pass(git_config_get_string(&str, config, "branch.master.remote")); cl_assert_equal_s("origin", str); diff --git a/tests/config/config_helpers.c b/tests/config/config_helpers.c index 35da720e0..025838ad7 100644 --- a/tests/config/config_helpers.c +++ b/tests/config/config_helpers.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "config_helpers.h" #include "repository.h" +#include "buffer.h" void assert_config_entry_existence( git_repository *repo, @@ -8,12 +9,13 @@ void assert_config_entry_existence( bool is_supposed_to_exist) { git_config *config; - const char *out; + git_config_entry *entry = NULL; int result; cl_git_pass(git_repository_config__weakptr(&config, repo)); - result = git_config_get_string(&out, config, name); + result = git_config_get_entry(&entry, config, name); + git_config_entry_free(entry); if (is_supposed_to_exist) cl_git_pass(result); @@ -27,13 +29,14 @@ void assert_config_entry_value( const char *expected_value) { git_config *config; - const char *out; + git_buf buf = GIT_BUF_INIT; cl_git_pass(git_repository_config__weakptr(&config, repo)); - cl_git_pass(git_config_get_string(&out, config, name)); + cl_git_pass(git_config_get_string_buf(&buf, config, name)); - cl_assert_equal_s(expected_value, out); + cl_assert_equal_s(expected_value, git_buf_cstr(&buf)); + git_buf_free(&buf); } static int count_config_entries_cb( diff --git a/tests/config/configlevel.c b/tests/config/configlevel.c index 1c22e8d9f..ca478b1a5 100644 --- a/tests/config/configlevel.c +++ b/tests/config/configlevel.c @@ -22,7 +22,7 @@ void test_config_configlevel__adding_the_same_level_twice_returns_EEXISTS(void) void test_config_configlevel__can_replace_a_config_file_at_an_existing_level(void) { git_config *cfg; - const char *s; + git_buf buf = {0}; cl_git_pass(git_config_new(&cfg)); cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"), @@ -30,9 +30,10 @@ void test_config_configlevel__can_replace_a_config_file_at_an_existing_level(voi cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"), GIT_CONFIG_LEVEL_LOCAL, 1)); - cl_git_pass(git_config_get_string(&s, cfg, "core.stringglobal")); - cl_assert_equal_s("don't find me!", s); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.stringglobal")); + cl_assert_equal_s("don't find me!", buf.ptr); + git_buf_free(&buf); git_config_free(cfg); } @@ -40,7 +41,7 @@ void test_config_configlevel__can_read_from_a_single_level_focused_file_after_pa { git_config *cfg; git_config *single_level_cfg; - const char *s; + git_buf buf = {0}; cl_git_pass(git_config_new(&cfg)); cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"), @@ -52,9 +53,10 @@ void test_config_configlevel__can_read_from_a_single_level_focused_file_after_pa git_config_free(cfg); - cl_git_pass(git_config_get_string(&s, single_level_cfg, "core.stringglobal")); - cl_assert_equal_s("don't find me!", s); + cl_git_pass(git_config_get_string_buf(&buf, single_level_cfg, "core.stringglobal")); + cl_assert_equal_s("don't find me!", buf.ptr); + git_buf_free(&buf); git_config_free(single_level_cfg); } diff --git a/tests/config/global.c b/tests/config/global.c index fc471f90d..4481308d6 100644 --- a/tests/config/global.c +++ b/tests/config/global.c @@ -46,8 +46,9 @@ void test_config_global__open_global(void) void test_config_global__open_xdg(void) { git_config *cfg, *xdg, *selected; - const char *val, *str = "teststring"; + const char *str = "teststring"; const char *key = "this.variable"; + git_buf buf = {0}; cl_git_mkfile("xdg/git/config", "# XDG config\n[core]\n test = 1\n"); @@ -56,9 +57,10 @@ void test_config_global__open_xdg(void) cl_git_pass(git_config_open_global(&selected, cfg)); cl_git_pass(git_config_set_string(xdg, key, str)); - cl_git_pass(git_config_get_string(&val, selected, key)); - cl_assert_equal_s(str, val); + cl_git_pass(git_config_get_string_buf(&buf, selected, key)); + cl_assert_equal_s(str, buf.ptr); + git_buf_free(&buf); git_config_free(selected); git_config_free(xdg); git_config_free(cfg); diff --git a/tests/config/include.c b/tests/config/include.c index 8232af489..e9f542afe 100644 --- a/tests/config/include.c +++ b/tests/config/include.c @@ -5,20 +5,20 @@ void test_config_include__relative(void) { git_config *cfg; - const char *str; + git_buf buf = GIT_BUF_INIT; cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config-include"))); - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "huzzah"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz")); + cl_assert_equal_s("huzzah", git_buf_cstr(&buf)); + git_buf_free(&buf); git_config_free(cfg); } void test_config_include__absolute(void) { git_config *cfg; - const char *str; git_buf buf = GIT_BUF_INIT; cl_git_pass(git_buf_printf(&buf, "[include]\npath = %s/config-included", cl_fixture("config"))); @@ -27,25 +27,27 @@ void test_config_include__absolute(void) git_buf_free(&buf); cl_git_pass(git_config_open_ondisk(&cfg, "config-include-absolute")); - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "huzzah"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz")); + cl_assert_equal_s("huzzah", git_buf_cstr(&buf)); + git_buf_free(&buf); git_config_free(cfg); } void test_config_include__homedir(void) { git_config *cfg; - const char *str; + git_buf buf = GIT_BUF_INIT; cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, cl_fixture("config"))); cl_git_mkfile("config-include-homedir", "[include]\npath = ~/config-included"); cl_git_pass(git_config_open_ondisk(&cfg, "config-include-homedir")); - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "huzzah"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz")); + cl_assert_equal_s("huzzah", git_buf_cstr(&buf)); + git_buf_free(&buf); git_config_free(cfg); cl_sandbox_set_search_path_defaults(); @@ -55,7 +57,7 @@ void test_config_include__homedir(void) void test_config_include__ordering(void) { git_config *cfg; - const char *str; + git_buf buf = GIT_BUF_INIT; cl_git_mkfile("included", "[foo \"bar\"]\nbaz = hurrah\nfrotz = hiya"); cl_git_mkfile("including", @@ -65,11 +67,13 @@ void test_config_include__ordering(void) cl_git_pass(git_config_open_ondisk(&cfg, "including")); - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.frotz")); - cl_assert_equal_s(str, "hiya"); - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "huzzah"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.frotz")); + cl_assert_equal_s("hiya", git_buf_cstr(&buf)); + git_buf_clear(&buf); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz")); + cl_assert_equal_s("huzzah", git_buf_cstr(&buf)); + git_buf_free(&buf); git_config_free(cfg); } @@ -90,16 +94,17 @@ void test_config_include__depth(void) void test_config_include__missing(void) { git_config *cfg; - const char *str; + git_buf buf = GIT_BUF_INIT; cl_git_mkfile("including", "[include]\npath = nonexistentfile\n[foo]\nbar = baz"); giterr_clear(); cl_git_pass(git_config_open_ondisk(&cfg, "including")); cl_assert(giterr_last() == NULL); - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar")); - cl_assert_equal_s(str, "baz"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar")); + cl_assert_equal_s("baz", git_buf_cstr(&buf)); + git_buf_free(&buf); git_config_free(cfg); } @@ -107,7 +112,7 @@ void test_config_include__missing(void) void test_config_include__depth2(void) { git_config *cfg; - const char *str; + git_buf buf = GIT_BUF_INIT; const char *content = "[include]\n" replicate10(replicate10("path=bottom\n")); cl_git_mkfile("top-level", "[include]\npath = middle\n[foo]\nbar = baz"); @@ -116,11 +121,12 @@ void test_config_include__depth2(void) cl_git_pass(git_config_open_ondisk(&cfg, "top-level")); - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar")); - cl_assert_equal_s(str, "baz"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar")); + cl_assert_equal_s("baz", git_buf_cstr(&buf)); - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar2")); - cl_assert_equal_s(str, "baz2"); + git_buf_clear(&buf); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar2")); + cl_assert_equal_s("baz2", git_buf_cstr(&buf)); git_config_free(cfg); } diff --git a/tests/config/new.c b/tests/config/new.c index dd6dbca9e..b39baa0a5 100644 --- a/tests/config/new.c +++ b/tests/config/new.c @@ -8,8 +8,8 @@ void test_config_new__write_new_config(void) { - const char *out; git_config *config; + git_buf buf = GIT_BUF_INIT; cl_git_mkfile(TEST_CONFIG, ""); cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); @@ -21,11 +21,13 @@ void test_config_new__write_new_config(void) cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - cl_git_pass(git_config_get_string(&out, config, "color.ui")); - cl_assert_equal_s(out, "auto"); - cl_git_pass(git_config_get_string(&out, config, "core.editor")); - cl_assert_equal_s(out, "ed"); + cl_git_pass(git_config_get_string_buf(&buf, config, "color.ui")); + cl_assert_equal_s("auto", git_buf_cstr(&buf)); + git_buf_clear(&buf); + cl_git_pass(git_config_get_string_buf(&buf, config, "core.editor")); + cl_assert_equal_s("ed", git_buf_cstr(&buf)); + git_buf_free(&buf); git_config_free(config); p_unlink(TEST_CONFIG); diff --git a/tests/config/read.c b/tests/config/read.c index 1799970fb..a7b77159e 100644 --- a/tests/config/read.c +++ b/tests/config/read.c @@ -2,6 +2,13 @@ #include "buffer.h" #include "path.h" +static git_buf buf = GIT_BUF_INIT; + +void test_config_read__cleanup(void) +{ + git_buf_free(&buf); +} + void test_config_read__simple_read(void) { git_config *cfg; @@ -25,14 +32,15 @@ void test_config_read__case_sensitive(void) { git_config *cfg; int i; - const char *str; cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config1"))); - cl_git_pass(git_config_get_string(&str, cfg, "this.that.other")); - cl_assert_equal_s(str, "true"); - cl_git_pass(git_config_get_string(&str, cfg, "this.That.other")); - cl_assert_equal_s(str, "yes"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "this.that.other")); + cl_assert_equal_s("true", git_buf_cstr(&buf)); + git_buf_clear(&buf); + + cl_git_pass(git_config_get_string_buf(&buf, cfg, "this.That.other")); + cl_assert_equal_s("yes", git_buf_cstr(&buf)); cl_git_pass(git_config_get_bool(&i, cfg, "this.that.other")); cl_assert(i == 1); @@ -52,12 +60,11 @@ void test_config_read__case_sensitive(void) void test_config_read__multiline_value(void) { git_config *cfg; - const char *str; cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config2"))); - cl_git_pass(git_config_get_string(&str, cfg, "this.That.and")); - cl_assert_equal_s(str, "one one one two two three three"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "this.That.and")); + cl_assert_equal_s("one one one two two three three", git_buf_cstr(&buf)); git_config_free(cfg); } @@ -68,15 +75,14 @@ void test_config_read__multiline_value(void) void test_config_read__subsection_header(void) { git_config *cfg; - const char *str; cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config3"))); - cl_git_pass(git_config_get_string(&str, cfg, "section.subsection.var")); - cl_assert_equal_s(str, "hello"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "section.subsection.var")); + cl_assert_equal_s("hello", git_buf_cstr(&buf)); /* The subsection is transformed to lower-case */ - cl_must_fail(git_config_get_string(&str, cfg, "section.subSectIon.var")); + cl_must_fail(git_config_get_string_buf(&buf, cfg, "section.subSectIon.var")); git_config_free(cfg); } @@ -84,21 +90,21 @@ void test_config_read__subsection_header(void) void test_config_read__lone_variable(void) { git_config *cfg; - const char *str; int i; cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config4"))); cl_git_fail(git_config_get_int32(&i, cfg, "some.section.variable")); - cl_git_pass(git_config_get_string(&str, cfg, "some.section.variable")); - cl_assert_equal_s(str, ""); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.section.variable")); + cl_assert_equal_s("", git_buf_cstr(&buf)); + git_buf_clear(&buf); cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variable")); cl_assert(i == 1); - cl_git_pass(git_config_get_string(&str, cfg, "some.section.variableeq")); - cl_assert_equal_s(str, ""); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.section.variableeq")); + cl_assert_equal_s("", git_buf_cstr(&buf)); cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variableeq")); cl_assert(i == 0); @@ -184,14 +190,14 @@ void test_config_read__header_in_last_line(void) void test_config_read__prefixes(void) { git_config *cfg; - const char *str; cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9"))); - cl_git_pass(git_config_get_string(&str, cfg, "remote.ab.url")); - cl_assert_equal_s(str, "http://example.com/git/ab"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "remote.ab.url")); + cl_assert_equal_s("http://example.com/git/ab", git_buf_cstr(&buf)); + git_buf_clear(&buf); - cl_git_pass(git_config_get_string(&str, cfg, "remote.abba.url")); - cl_assert_equal_s(str, "http://example.com/git/abba"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "remote.abba.url")); + cl_assert_equal_s("http://example.com/git/abba", git_buf_cstr(&buf)); git_config_free(cfg); } @@ -199,11 +205,10 @@ void test_config_read__prefixes(void) void test_config_read__escaping_quotes(void) { git_config *cfg; - const char *str; cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config13"))); - cl_git_pass(git_config_get_string(&str, cfg, "core.editor")); - cl_assert_equal_s("\"C:/Program Files/Nonsense/bah.exe\" \"--some option\"", str); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.editor")); + cl_assert_equal_s("\"C:/Program Files/Nonsense/bah.exe\" \"--some option\"", git_buf_cstr(&buf)); git_config_free(cfg); } @@ -363,15 +368,15 @@ void test_config_read__iterator_glob(void) void test_config_read__whitespace_not_required_around_assignment(void) { git_config *cfg; - const char *str; cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config14"))); - cl_git_pass(git_config_get_string(&str, cfg, "a.b")); - cl_assert_equal_s(str, "c"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "a.b")); + cl_assert_equal_s("c", git_buf_cstr(&buf)); + git_buf_clear(&buf); - cl_git_pass(git_config_get_string(&str, cfg, "d.e")); - cl_assert_equal_s(str, "f"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "d.e")); + cl_assert_equal_s("f", git_buf_cstr(&buf)); git_config_free(cfg); } @@ -379,7 +384,7 @@ void test_config_read__whitespace_not_required_around_assignment(void) void test_config_read__read_git_config_entry(void) { git_config *cfg; - const git_config_entry *entry; + git_config_entry *entry; cl_git_pass(git_config_new(&cfg)); cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), @@ -390,6 +395,7 @@ void test_config_read__read_git_config_entry(void) cl_assert_equal_s("42", entry->value); cl_assert_equal_i(GIT_CONFIG_LEVEL_SYSTEM, entry->level); + git_config_entry_free(entry); git_config_free(cfg); } @@ -480,7 +486,6 @@ void test_config_read__simple_read_from_specific_level(void) git_config *cfg, *cfg_specific; int i; int64_t l, expected = +9223372036854775803; - const char *s; cl_git_pass(git_config_new(&cfg)); cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"), @@ -496,8 +501,8 @@ void test_config_read__simple_read_from_specific_level(void) cl_assert(l == expected); cl_git_pass(git_config_get_bool(&i, cfg_specific, "core.boolglobal")); cl_assert_equal_b(true, i); - cl_git_pass(git_config_get_string(&s, cfg_specific, "core.stringglobal")); - cl_assert_equal_s("I'm a global config value!", s); + cl_git_pass(git_config_get_string_buf(&buf, cfg_specific, "core.stringglobal")); + cl_assert_equal_s("I'm a global config value!", git_buf_cstr(&buf)); git_config_free(cfg_specific); git_config_free(cfg); @@ -558,14 +563,13 @@ void test_config_read__corrupt_header3(void) void test_config_read__override_variable(void) { git_config *cfg; - const char *str; cl_set_cleanup(&clean_test_config, NULL); cl_git_mkfile("./testconfig", "[some] var = one\nvar = two"); cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig")); - cl_git_pass(git_config_get_string(&str, cfg, "some.var")); - cl_assert_equal_s(str, "two"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var")); + cl_assert_equal_s("two", git_buf_cstr(&buf)); git_config_free(cfg); } diff --git a/tests/config/rename.c b/tests/config/rename.c index db07c798f..a4614158a 100644 --- a/tests/config/rename.c +++ b/tests/config/rename.c @@ -21,11 +21,12 @@ void test_config_rename__cleanup(void) void test_config_rename__can_rename(void) { - const git_config_entry *ce; + git_config_entry *ce; cl_git_pass(git_config_get_entry( &ce, g_config, "branch.track-local.remote")); cl_assert_equal_s(".", ce->value); + git_config_entry_free(ce); cl_git_fail(git_config_get_entry( &ce, g_config, "branch.local-track.remote")); @@ -36,6 +37,7 @@ void test_config_rename__can_rename(void) cl_git_pass(git_config_get_entry( &ce, g_config, "branch.local-track.remote")); cl_assert_equal_s(".", ce->value); + git_config_entry_free(ce); cl_git_fail(git_config_get_entry( &ce, g_config, "branch.track-local.remote")); @@ -43,7 +45,7 @@ void test_config_rename__can_rename(void) void test_config_rename__prevent_overwrite(void) { - const git_config_entry *ce; + git_config_entry *ce; cl_git_pass(git_config_set_string( g_config, "branch.local-track.remote", "yellow")); @@ -51,6 +53,7 @@ void test_config_rename__prevent_overwrite(void) cl_git_pass(git_config_get_entry( &ce, g_config, "branch.local-track.remote")); cl_assert_equal_s("yellow", ce->value); + git_config_entry_free(ce); cl_git_pass(git_config_rename_section( g_repo, "branch.track-local", "branch.local-track")); @@ -58,6 +61,7 @@ void test_config_rename__prevent_overwrite(void) cl_git_pass(git_config_get_entry( &ce, g_config, "branch.local-track.remote")); cl_assert_equal_s(".", ce->value); + git_config_entry_free(ce); /* so, we don't currently prevent overwrite... */ /* { diff --git a/tests/config/stress.c b/tests/config/stress.c index e8e9d2b61..503f44f03 100644 --- a/tests/config/stress.c +++ b/tests/config/stress.c @@ -6,6 +6,8 @@ #define TEST_CONFIG "git-test-config" +static git_buf buf = GIT_BUF_INIT; + void test_config_stress__initialize(void) { git_filebuf file = GIT_FILEBUF_INIT; @@ -20,50 +22,43 @@ void test_config_stress__initialize(void) void test_config_stress__cleanup(void) { + git_buf_free(&buf); p_unlink(TEST_CONFIG); } void test_config_stress__dont_break_on_invalid_input(void) { - const char *editor, *color; git_config *config; cl_assert(git_path_exists(TEST_CONFIG)); cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - cl_git_pass(git_config_get_string(&color, config, "color.ui")); - cl_git_pass(git_config_get_string(&editor, config, "core.editor")); + cl_git_pass(git_config_get_string_buf(&buf, config, "color.ui")); + cl_git_pass(git_config_get_string_buf(&buf, config, "core.editor")); git_config_free(config); } +void assert_config_value(git_config *config, const char *key, const char *value) +{ + git_buf_clear(&buf); + cl_git_pass(git_config_get_string_buf(&buf, config, key)); + cl_assert_equal_s(value, git_buf_cstr(&buf)); +} + void test_config_stress__comments(void) { git_config *config; - const char *str; cl_git_pass(git_config_open_ondisk(&config, cl_fixture("config/config12"))); - cl_git_pass(git_config_get_string(&str, config, "some.section.test2")); - cl_assert_equal_s("hello", str); - - cl_git_pass(git_config_get_string(&str, config, "some.section.test3")); - cl_assert_equal_s("welcome", str); - - cl_git_pass(git_config_get_string(&str, config, "some.section.other")); - cl_assert_equal_s("hello! \" ; ; ; ", str); - - cl_git_pass(git_config_get_string(&str, config, "some.section.other2")); - cl_assert_equal_s("cool! \" # # # ", str); - - cl_git_pass(git_config_get_string(&str, config, "some.section.multi")); - cl_assert_equal_s("hi, this is a ; multiline comment # with ;\n special chars and other stuff !@#", str); - - cl_git_pass(git_config_get_string(&str, config, "some.section.multi2")); - cl_assert_equal_s("good, this is a ; multiline comment # with ;\n special chars and other stuff !@#", str); - - cl_git_pass(git_config_get_string(&str, config, "some.section.back")); - cl_assert_equal_s("this is \ba phrase", str); + assert_config_value(config, "some.section.test2", "hello"); + assert_config_value(config, "some.section.test3", "welcome"); + assert_config_value(config, "some.section.other", "hello! \" ; ; ; "); + assert_config_value(config, "some.section.other2", "cool! \" # # # "); + assert_config_value(config, "some.section.multi", "hi, this is a ; multiline comment # with ;\n special chars and other stuff !@#"); + assert_config_value(config, "some.section.multi2", "good, this is a ; multiline comment # with ;\n special chars and other stuff !@#"); + assert_config_value(config, "some.section.back", "this is \ba phrase"); git_config_free(config); } @@ -71,7 +66,6 @@ void test_config_stress__comments(void) void test_config_stress__escape_subsection_names(void) { git_config *config; - const char *str; cl_assert(git_path_exists("git-test-config")); cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); @@ -81,15 +75,14 @@ void test_config_stress__escape_subsection_names(void) cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - cl_git_pass(git_config_get_string(&str, config, "some.sec\\tion.other")); - cl_assert_equal_s("foo", str); + assert_config_value(config, "some.sec\\tion.other", "foo"); + git_config_free(config); } void test_config_stress__trailing_backslash(void) { git_config *config; - const char *str; const char *path = "C:\\iam\\some\\windows\\path\\"; cl_assert(git_path_exists("git-test-config")); @@ -98,20 +91,19 @@ void test_config_stress__trailing_backslash(void) git_config_free(config); cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - cl_git_pass(git_config_get_string(&str, config, "windows.path")); - cl_assert_equal_s(path, str); + assert_config_value(config, "windows.path", path); + git_config_free(config); } void test_config_stress__complex(void) { git_config *config; - const char *str; const char *path = "./config-immediate-multiline"; cl_git_mkfile(path, "[imm]\n multi = \"\\\nfoo\""); cl_git_pass(git_config_open_ondisk(&config, path)); - cl_git_pass(git_config_get_string(&str, config, "imm.multi")); - cl_assert_equal_s(str, "foo"); + assert_config_value(config, "imm.multi", "foo"); + git_config_free(config); } diff --git a/tests/config/validkeyname.c b/tests/config/validkeyname.c index 0ef4a9ae3..4b36509af 100644 --- a/tests/config/validkeyname.c +++ b/tests/config/validkeyname.c @@ -3,7 +3,6 @@ #include "config.h" static git_config *cfg; -static const char *value; void test_config_validkeyname__initialize(void) { @@ -22,7 +21,9 @@ void test_config_validkeyname__cleanup(void) static void assert_invalid_config_key_name(const char *name) { - cl_git_fail_with(git_config_get_string(&value, cfg, name), + git_buf buf = GIT_BUF_INIT; + + cl_git_fail_with(git_config_get_string_buf(&buf, cfg, name), GIT_EINVALIDSPEC); cl_git_fail_with(git_config_set_string(cfg, name, "42"), GIT_EINVALIDSPEC); diff --git a/tests/config/write.c b/tests/config/write.c index 067b7445b..32e6f27b4 100644 --- a/tests/config/write.c +++ b/tests/config/write.c @@ -1,4 +1,5 @@ #include "clar_libgit2.h" +#include "buffer.h" void test_config_write__initialize(void) { @@ -108,15 +109,17 @@ void test_config_write__delete_value_at_specific_level(void) void test_config_write__write_subsection(void) { git_config *cfg; - const char *str; + git_buf buf = GIT_BUF_INIT; cl_git_pass(git_config_open_ondisk(&cfg, "config9")); cl_git_pass(git_config_set_string(cfg, "my.own.var", "works")); git_config_free(cfg); cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_string(&str, cfg, "my.own.var")); - cl_assert_equal_s("works", str); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "my.own.var")); + cl_assert_equal_s("works", git_buf_cstr(&buf)); + + git_buf_free(&buf); git_config_free(cfg); } @@ -132,46 +135,52 @@ void test_config_write__delete_inexistent(void) void test_config_write__value_containing_quotes(void) { git_config *cfg; - const char* str; + git_buf buf = GIT_BUF_INIT; cl_git_pass(git_config_open_ondisk(&cfg, "config9")); cl_git_pass(git_config_set_string(cfg, "core.somevar", "this \"has\" quotes")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this \"has\" quotes"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar")); + cl_assert_equal_s("this \"has\" quotes", git_buf_cstr(&buf)); + git_buf_clear(&buf); git_config_free(cfg); cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this \"has\" quotes"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar")); + cl_assert_equal_s("this \"has\" quotes", git_buf_cstr(&buf)); + git_buf_clear(&buf); git_config_free(cfg); /* The code path for values that already exist is different, check that one as well */ cl_git_pass(git_config_open_ondisk(&cfg, "config9")); cl_git_pass(git_config_set_string(cfg, "core.somevar", "this also \"has\" quotes")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this also \"has\" quotes"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar")); + cl_assert_equal_s("this also \"has\" quotes", git_buf_cstr(&buf)); + git_buf_clear(&buf); git_config_free(cfg); cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this also \"has\" quotes"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar")); + cl_assert_equal_s("this also \"has\" quotes", git_buf_cstr(&buf)); + git_buf_free(&buf); git_config_free(cfg); } void test_config_write__escape_value(void) { git_config *cfg; - const char* str; + git_buf buf = GIT_BUF_INIT; cl_git_pass(git_config_open_ondisk(&cfg, "config9")); cl_git_pass(git_config_set_string(cfg, "core.somevar", "this \"has\" quotes and \t")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this \"has\" quotes and \t"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar")); + cl_assert_equal_s("this \"has\" quotes and \t", git_buf_cstr(&buf)); + git_buf_clear(&buf); git_config_free(cfg); cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this \"has\" quotes and \t"); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar")); + cl_assert_equal_s("this \"has\" quotes and \t", git_buf_cstr(&buf)); + git_buf_free(&buf); git_config_free(cfg); } @@ -180,7 +189,7 @@ void test_config_write__add_value_at_specific_level(void) git_config *cfg, *cfg_specific; int i; int64_t l, expected = +9223372036854775803; - const char *s; + git_buf buf = GIT_BUF_INIT; // open config15 as global level config file cl_git_pass(git_config_new(&cfg)); @@ -207,9 +216,10 @@ void test_config_write__add_value_at_specific_level(void) cl_assert(l == expected); cl_git_pass(git_config_get_bool(&i, cfg, "core.boolglobal")); cl_assert_equal_b(true, i); - cl_git_pass(git_config_get_string(&s, cfg, "core.stringglobal")); - cl_assert_equal_s("I'm a global config value!", s); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.stringglobal")); + cl_assert_equal_s("I'm a global config value!", git_buf_cstr(&buf)); + git_buf_free(&buf); git_config_free(cfg); } @@ -247,7 +257,7 @@ void test_config_write__add_section_at_file_with_no_clrf_at_the_end(void) void test_config_write__add_value_which_needs_quotes(void) { - git_config *cfg; + git_config *cfg, *base; const char* str1; const char* str2; const char* str3; @@ -262,7 +272,8 @@ void test_config_write__add_value_which_needs_quotes(void) cl_git_pass(git_config_set_string(cfg, "core.startwhithsapceandcontainsdoublequote", " some\"thing")); git_config_free(cfg); - cl_git_pass(git_config_open_ondisk(&cfg, "config17")); + cl_git_pass(git_config_open_ondisk(&base, "config17")); + cl_git_pass(git_config_snapshot(&cfg, base)); cl_git_pass(git_config_get_string(&str1, cfg, "core.startwithspace")); cl_assert_equal_s(" Something", str1); cl_git_pass(git_config_get_string(&str2, cfg, "core.endwithspace")); @@ -274,6 +285,7 @@ void test_config_write__add_value_which_needs_quotes(void) cl_git_pass(git_config_get_string(&str5, cfg, "core.startwhithsapceandcontainsdoublequote")); cl_assert_equal_s(" some\"thing", str5); git_config_free(cfg); + git_config_free(base); } void test_config_write__can_set_a_value_to_NULL(void) @@ -294,15 +306,16 @@ void test_config_write__can_set_an_empty_value(void) { git_repository *repository; git_config *config; - const char * str; + git_buf buf = {0}; repository = cl_git_sandbox_init("testrepo.git"); cl_git_pass(git_repository_config(&config, repository)); cl_git_pass(git_config_set_string(config, "core.somevar", "")); - cl_git_pass(git_config_get_string(&str, config, "core.somevar")); - cl_assert_equal_s(str, ""); + cl_git_pass(git_config_get_string_buf(&buf, config, "core.somevar")); + cl_assert_equal_s("", buf.ptr); + git_buf_free(&buf); git_config_free(config); cl_git_sandbox_cleanup(); } diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c index 2ae6886bd..e750f7b1e 100644 --- a/tests/network/remote/remotes.c +++ b/tests/network/remote/remotes.c @@ -1,4 +1,5 @@ #include "clar_libgit2.h" +#include "config/config_helpers.h" #include "buffer.h" #include "refspec.h" #include "remote.h" @@ -385,26 +386,17 @@ void test_network_remote_remotes__cannot_add_a_remote_with_an_invalid_name(void) void test_network_remote_remotes__tagopt(void) { - const char *opt; - git_config *cfg; - - cl_git_pass(git_repository_config(&cfg, _repo)); - git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); cl_git_pass(git_remote_save(_remote)); - cl_git_pass(git_config_get_string(&opt, cfg, "remote.test.tagopt")); - cl_assert_equal_s("--tags", opt); + assert_config_entry_value(_repo, "remote.test.tagopt", "--tags"); git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_NONE); cl_git_pass(git_remote_save(_remote)); - cl_git_pass(git_config_get_string(&opt, cfg, "remote.test.tagopt")); - cl_assert_equal_s("--no-tags", opt); + assert_config_entry_value(_repo, "remote.test.tagopt", "--no-tags"); git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); cl_git_pass(git_remote_save(_remote)); - cl_assert(git_config_get_string(&opt, cfg, "remote.test.tagopt") == GIT_ENOTFOUND); - - git_config_free(cfg); + assert_config_entry_existence(_repo, "remote.test.tagopt", false); } void test_network_remote_remotes__can_load_with_an_empty_url(void) diff --git a/tests/refs/branches/move.c b/tests/refs/branches/move.c index c1d1ae396..6e335d1fa 100644 --- a/tests/refs/branches/move.c +++ b/tests/refs/branches/move.c @@ -67,16 +67,17 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll { git_reference *original_ref, *new_ref; git_config *config; - const git_config_entry *ce; + git_buf buf = GIT_BUF_INIT; char *original_remote, *original_merge; + const char *str; - cl_git_pass(git_repository_config(&config, repo)); - - cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote")); - original_remote = strdup(ce->value); - cl_git_pass(git_config_get_entry(&ce, config, "branch.master.merge")); - original_merge = strdup(ce->value); + cl_git_pass(git_repository_config_snapshot(&config, repo)); + cl_git_pass(git_config_get_string_buf(&buf, config, "branch.master.remote")); + original_remote = git_buf_detach(&buf); + cl_git_pass(git_config_get_string_buf(&buf, config, "branch.master.merge")); + original_merge = git_buf_detach(&buf); + git_config_free(config); cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); @@ -84,20 +85,25 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll git_branch_move(&new_ref, original_ref, "master", 0)); cl_assert(giterr_last()->message != NULL); - cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote")); - cl_assert_equal_s(original_remote, ce->value); - cl_git_pass(git_config_get_entry(&ce, config, "branch.master.merge")); - cl_assert_equal_s(original_merge, ce->value); + cl_git_pass(git_repository_config_snapshot(&config, repo)); + cl_git_pass(git_config_get_string(&str, config, "branch.master.remote")); + cl_assert_equal_s(original_remote, str); + cl_git_pass(git_config_get_string(&str, config, "branch.master.merge")); + cl_assert_equal_s(original_merge, str); + git_config_free(config); cl_assert_equal_i(GIT_EEXISTS, git_branch_move(&new_ref, original_ref, "cannot-fetch", 0)); cl_assert(giterr_last()->message != NULL); - cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote")); - cl_assert_equal_s(original_remote, ce->value); - cl_git_pass(git_config_get_entry(&ce, config, "branch.master.merge")); - cl_assert_equal_s(original_merge, ce->value); + + cl_git_pass(git_repository_config_snapshot(&config, repo)); + cl_git_pass(git_config_get_string(&str, config, "branch.master.remote")); + cl_assert_equal_s(original_remote, str); + cl_git_pass(git_config_get_string(&str, config, "branch.master.merge")); + cl_assert_equal_s(original_merge, str); + git_config_free(config); git_reference_free(original_ref); cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/track-local")); @@ -106,12 +112,14 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll git_branch_move(&new_ref, original_ref, "master", 0)); cl_assert(giterr_last()->message != NULL); - cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote")); - cl_assert_equal_s(original_remote, ce->value); - cl_git_pass(git_config_get_entry(&ce, config, "branch.master.merge")); - cl_assert_equal_s(original_merge, ce->value); - free(original_remote); free(original_merge); + cl_git_pass(git_repository_config_snapshot(&config, repo)); + cl_git_pass(git_config_get_string(&str, config, "branch.master.remote")); + cl_assert_equal_s(original_remote, str); + cl_git_pass(git_config_get_string(&str, config, "branch.master.merge")); + cl_assert_equal_s(original_merge, str); + + git__free(original_remote); git__free(original_merge); git_reference_free(original_ref); git_config_free(config); } diff --git a/tests/refs/branches/upstream.c b/tests/refs/branches/upstream.c index f44f563a3..351449416 100644 --- a/tests/refs/branches/upstream.c +++ b/tests/refs/branches/upstream.c @@ -1,4 +1,5 @@ #include "clar_libgit2.h" +#include "config/config_helpers.h" #include "refs.h" static git_repository *repo; @@ -123,8 +124,6 @@ void test_refs_branches_upstream__set_unset_upstream(void) { git_reference *branch; git_repository *repository; - const char *value; - git_config *config; repository = cl_git_sandbox_init("testrepo.git"); @@ -132,11 +131,8 @@ void test_refs_branches_upstream__set_unset_upstream(void) cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/test")); cl_git_pass(git_branch_set_upstream(branch, "test/master")); - cl_git_pass(git_repository_config(&config, repository)); - cl_git_pass(git_config_get_string(&value, config, "branch.test.remote")); - cl_assert_equal_s(value, "test"); - cl_git_pass(git_config_get_string(&value, config, "branch.test.merge")); - cl_assert_equal_s(value, "refs/heads/master"); + assert_config_entry_value(repository, "branch.test.remote", "test"); + assert_config_entry_value(repository, "branch.test.merge", "refs/heads/master"); git_reference_free(branch); @@ -144,25 +140,22 @@ void test_refs_branches_upstream__set_unset_upstream(void) cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/test")); cl_git_pass(git_branch_set_upstream(branch, "master")); - cl_git_pass(git_config_get_string(&value, config, "branch.test.remote")); - cl_assert_equal_s(value, "."); - cl_git_pass(git_config_get_string(&value, config, "branch.test.merge")); - cl_assert_equal_s(value, "refs/heads/master"); + assert_config_entry_value(repository, "branch.test.remote", "."); + assert_config_entry_value(repository, "branch.test.merge", "refs/heads/master"); /* unset */ cl_git_pass(git_branch_set_upstream(branch, NULL)); - cl_git_fail_with(git_config_get_string(&value, config, "branch.test.merge"), GIT_ENOTFOUND); - cl_git_fail_with(git_config_get_string(&value, config, "branch.test.remote"), GIT_ENOTFOUND); + assert_config_entry_existence(repository, "branch.test.remote", false); + assert_config_entry_existence(repository, "branch.test.merge", false); git_reference_free(branch); cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/master")); cl_git_pass(git_branch_set_upstream(branch, NULL)); - cl_git_fail_with(git_config_get_string(&value, config, "branch.master.merge"), GIT_ENOTFOUND); - cl_git_fail_with(git_config_get_string(&value, config, "branch.master.remote"), GIT_ENOTFOUND); + assert_config_entry_existence(repository, "branch.test.remote", false); + assert_config_entry_existence(repository, "branch.test.merge", false); git_reference_free(branch); - git_config_free(config); cl_git_sandbox_cleanup(); } diff --git a/tests/repo/init.c b/tests/repo/init.c index 076156817..525020f5a 100644 --- a/tests/repo/init.c +++ b/tests/repo/init.c @@ -3,6 +3,7 @@ #include "repository.h" #include "config.h" #include "path.h" +#include "config/config_helpers.h" enum repo_mode { STANDARD_REPOSITORY = 0, @@ -370,8 +371,6 @@ void test_repo_init__extended_1(void) void test_repo_init__relative_gitdir(void) { git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - git_config *cfg; - const char *worktree_path; git_buf dot_git_content = GIT_BUF_INIT; opts.workdir_path = "../c_wd"; @@ -391,24 +390,19 @@ void test_repo_init__relative_gitdir(void) /* Verify that the gitlink and worktree entries are relative */ /* Verify worktree */ - cl_git_pass(git_repository_config(&cfg, _repo)); - cl_git_pass(git_config_get_string(&worktree_path, cfg, "core.worktree")); - cl_assert_equal_s("../c_wd/", worktree_path); + assert_config_entry_value(_repo, "core.worktree", "../c_wd/"); /* Verify gitlink */ cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git")); cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content.ptr); git_buf_free(&dot_git_content); - git_config_free(cfg); cleanup_repository("root"); } void test_repo_init__relative_gitdir_2(void) { git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - git_config *cfg; - const char *worktree_path; git_buf dot_git_content = GIT_BUF_INIT; git_buf full_path = GIT_BUF_INIT; @@ -433,16 +427,13 @@ void test_repo_init__relative_gitdir_2(void) /* Verify that the gitlink and worktree entries are relative */ /* Verify worktree */ - cl_git_pass(git_repository_config(&cfg, _repo)); - cl_git_pass(git_config_get_string(&worktree_path, cfg, "core.worktree")); - cl_assert_equal_s("../c_wd/", worktree_path); + assert_config_entry_value(_repo, "core.worktree", "../c_wd/"); /* Verify gitlink */ cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git")); cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content.ptr); git_buf_free(&dot_git_content); - git_config_free(cfg); cleanup_repository("root"); } diff --git a/tests/repo/setters.c b/tests/repo/setters.c index f34f1e471..5a83fdbee 100644 --- a/tests/repo/setters.c +++ b/tests/repo/setters.c @@ -46,7 +46,7 @@ void test_repo_setters__setting_a_workdir_prettifies_its_path(void) void test_repo_setters__setting_a_workdir_creates_a_gitlink(void) { git_config *cfg; - const char *val; + git_buf buf = GIT_BUF_INIT; git_buf content = GIT_BUF_INIT; cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", true)); @@ -59,8 +59,10 @@ void test_repo_setters__setting_a_workdir_creates_a_gitlink(void) git_buf_free(&content); cl_git_pass(git_repository_config(&cfg, repo)); - cl_git_pass(git_config_get_string(&val, cfg, "core.worktree")); - cl_assert(git__suffixcmp(val, "new_workdir/") == 0); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.worktree")); + cl_assert(git__suffixcmp(git_buf_cstr(&buf), "new_workdir/") == 0); + + git_buf_free(&buf); git_config_free(cfg); } diff --git a/tests/submodule/add.c b/tests/submodule/add.c index 05dbafd88..01625d3aa 100644 --- a/tests/submodule/add.c +++ b/tests/submodule/add.c @@ -2,6 +2,7 @@ #include "posix.h" #include "path.h" #include "submodule_helpers.h" +#include "config/config_helpers.h" #include "fileops.h" static git_repository *g_repo = NULL; @@ -13,26 +14,19 @@ void test_submodule_add__cleanup(void) static void assert_submodule_url(const char* name, const char *url) { - git_config *cfg; - const char *s; git_buf key = GIT_BUF_INIT; - cl_git_pass(git_repository_config(&cfg, g_repo)); cl_git_pass(git_buf_printf(&key, "submodule.%s.url", name)); - cl_git_pass(git_config_get_string(&s, cfg, git_buf_cstr(&key))); - cl_assert_equal_s(s, url); + assert_config_entry_value(g_repo, git_buf_cstr(&key), url); - git_config_free(cfg); git_buf_free(&key); } void test_submodule_add__url_absolute(void) { git_submodule *sm; - git_config *cfg; git_repository *repo; - const char *worktree_path; git_buf dot_git_content = GIT_BUF_INIT; g_repo = setup_fixture_submod2(); @@ -59,15 +53,12 @@ void test_submodule_add__url_absolute(void) cl_git_pass(git_repository_open(&repo, "submod2/" "sm_libgit2")); /* Verify worktree path is relative */ - cl_git_pass(git_repository_config(&cfg, repo)); - cl_git_pass(git_config_get_string(&worktree_path, cfg, "core.worktree")); - cl_assert_equal_s("../../../sm_libgit2/", worktree_path); + assert_config_entry_value(repo, "core.worktree", "../../../sm_libgit2/"); /* Verify gitdir path is relative */ cl_git_pass(git_futils_readbuffer(&dot_git_content, "submod2/" "sm_libgit2" "/.git")); cl_assert_equal_s("gitdir: ../.git/modules/sm_libgit2/", dot_git_content.ptr); - git_config_free(cfg); git_repository_free(repo); git_buf_free(&dot_git_content); diff --git a/tests/submodule/init.c b/tests/submodule/init.c index 3db6dae61..dbde0f284 100644 --- a/tests/submodule/init.c +++ b/tests/submodule/init.c @@ -34,9 +34,9 @@ void test_submodule_init__absolute_url(void) /* init and verify that absolute path is written to .git/config */ cl_git_pass(git_submodule_init(sm, false)); - cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_repository_config_snapshot(&cfg, g_repo)); - git_config_get_string(&config_url, cfg, "submodule.testrepo.url"); + cl_git_pass(git_config_get_string(&config_url, cfg, "submodule.testrepo.url")); cl_assert_equal_s(absolute_url.ptr, config_url); git_buf_free(&absolute_url); @@ -64,9 +64,9 @@ void test_submodule_init__relative_url(void) /* init and verify that absolute path is written to .git/config */ cl_git_pass(git_submodule_init(sm, false)); - cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_repository_config_snapshot(&cfg, g_repo)); - git_config_get_string(&config_url, cfg, "submodule.testrepo.url"); + cl_git_pass(git_config_get_string(&config_url, cfg, "submodule.testrepo.url")); cl_assert_equal_s(absolute_url.ptr, config_url); git_buf_free(&absolute_url); @@ -102,9 +102,9 @@ void test_submodule_init__relative_url_detached_head(void) /* init and verify that absolute path is written to .git/config */ cl_git_pass(git_submodule_init(sm, false)); - cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_repository_config_snapshot(&cfg, g_repo)); - git_config_get_string(&config_url, cfg, "submodule.testrepo.url"); + cl_git_pass(git_config_get_string(&config_url, cfg, "submodule.testrepo.url")); cl_assert_equal_s(absolute_url.ptr, config_url); git_buf_free(&absolute_url); diff --git a/tests/submodule/modify.c b/tests/submodule/modify.c index 9bb48bad2..3d7269bff 100644 --- a/tests/submodule/modify.c +++ b/tests/submodule/modify.c @@ -2,6 +2,7 @@ #include "posix.h" #include "path.h" #include "submodule_helpers.h" +#include "config/config_helpers.h" static git_repository *g_repo = NULL; @@ -51,7 +52,7 @@ void test_submodule_modify__init(void) git_submodule_reload_all(g_repo, 1); /* confirm submodule data in config */ - cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_repository_config_snapshot(&cfg, g_repo)); cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_unchanged.url")); cl_assert(git__suffixcmp(str, "/submod2_target") == 0); cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_changed_head.url")); @@ -72,20 +73,12 @@ static int sync_one_submodule( static void assert_submodule_url_is_synced( git_submodule *sm, const char *parent_key, const char *child_key) { - git_config *cfg; - const char *str; git_repository *smrepo; - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_get_string(&str, cfg, parent_key)); - cl_assert_equal_s(git_submodule_url(sm), str); - git_config_free(cfg); + assert_config_entry_value(g_repo, parent_key, git_submodule_url(sm)); cl_git_pass(git_submodule_open(&smrepo, sm)); - cl_git_pass(git_repository_config(&cfg, smrepo)); - cl_git_pass(git_config_get_string(&str, cfg, child_key)); - cl_assert_equal_s(git_submodule_url(sm), str); - git_config_free(cfg); + assert_config_entry_value(smrepo, child_key, git_submodule_url(sm)); git_repository_free(smrepo); } @@ -111,7 +104,7 @@ void test_submodule_modify__sync(void) */ /* check submodule info does not match before sync */ - cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_repository_config_snapshot(&cfg, g_repo)); cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM1".url")); cl_assert(strcmp(git_submodule_url(sm1), str) != 0); cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM2".url")); diff --git a/tests/submodule/repository_init.c b/tests/submodule/repository_init.c index bf1968d66..9be1e0b23 100644 --- a/tests/submodule/repository_init.c +++ b/tests/submodule/repository_init.c @@ -2,6 +2,7 @@ #include "posix.h" #include "path.h" #include "submodule_helpers.h" +#include "config/config_helpers.h" #include "fileops.h" static git_repository *g_repo = NULL; @@ -10,8 +11,6 @@ void test_submodule_repository_init__basic(void) { git_submodule *sm; git_repository *repo; - git_config *cfg; - const char *worktree_path; git_buf dot_git_content = GIT_BUF_INIT; g_repo = setup_fixture_submod2(); @@ -21,9 +20,7 @@ void test_submodule_repository_init__basic(void) cl_git_pass(git_submodule_repo_init(&repo, sm, 1)); /* Verify worktree */ - cl_git_pass(git_repository_config(&cfg, repo)); - cl_git_pass(git_config_get_string(&worktree_path, cfg, "core.worktree")); - cl_assert_equal_s("../../../sm_gitmodules_only/", worktree_path); + assert_config_entry_value(repo, "core.worktree", "../../../sm_gitmodules_only/"); /* Verify gitlink */ cl_git_pass(git_futils_readbuffer(&dot_git_content, "submod2/" "sm_gitmodules_only" "/.git")); @@ -35,7 +32,6 @@ void test_submodule_repository_init__basic(void) cl_assert(git_path_isdir("submod2/.git/modules/" "sm_gitmodules_only")); cl_assert(git_path_isfile("submod2/.git/modules/" "sm_gitmodules_only" "/HEAD")); - git_config_free(cfg); git_submodule_free(sm); git_repository_free(repo); git_buf_free(&dot_git_content); -- cgit v1.2.1