mirror of
https://github.com/git/git.git
synced 2024-06-02 00:06:11 +02:00
Merge branch 'ma/clear-repository-format'
The setup code has been cleaned up to avoid leaks around the repository_format structure. * ma/clear-repository-format: setup: fix memory leaks with `struct repository_format` setup: free old value before setting `work_tree`
This commit is contained in:
commit
6b5688b760
|
@ -96,7 +96,7 @@ static void copy_templates(const char *template_dir)
|
||||||
struct strbuf path = STRBUF_INIT;
|
struct strbuf path = STRBUF_INIT;
|
||||||
struct strbuf template_path = STRBUF_INIT;
|
struct strbuf template_path = STRBUF_INIT;
|
||||||
size_t template_len;
|
size_t template_len;
|
||||||
struct repository_format template_format;
|
struct repository_format template_format = REPOSITORY_FORMAT_INIT;
|
||||||
struct strbuf err = STRBUF_INIT;
|
struct strbuf err = STRBUF_INIT;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
char *to_free = NULL;
|
char *to_free = NULL;
|
||||||
|
@ -148,6 +148,7 @@ static void copy_templates(const char *template_dir)
|
||||||
free(to_free);
|
free(to_free);
|
||||||
strbuf_release(&path);
|
strbuf_release(&path);
|
||||||
strbuf_release(&template_path);
|
strbuf_release(&template_path);
|
||||||
|
clear_repository_format(&template_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int git_init_db_config(const char *k, const char *v, void *cb)
|
static int git_init_db_config(const char *k, const char *v, void *cb)
|
||||||
|
|
31
cache.h
31
cache.h
|
@ -962,6 +962,10 @@ extern char *repository_format_partial_clone;
|
||||||
extern const char *core_partial_clone_filter_default;
|
extern const char *core_partial_clone_filter_default;
|
||||||
extern int repository_format_worktree_config;
|
extern int repository_format_worktree_config;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You _have_ to initialize a `struct repository_format` using
|
||||||
|
* `= REPOSITORY_FORMAT_INIT` before calling `read_repository_format()`.
|
||||||
|
*/
|
||||||
struct repository_format {
|
struct repository_format {
|
||||||
int version;
|
int version;
|
||||||
int precious_objects;
|
int precious_objects;
|
||||||
|
@ -973,14 +977,35 @@ struct repository_format {
|
||||||
struct string_list unknown_extensions;
|
struct string_list unknown_extensions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always use this to initialize a `struct repository_format`
|
||||||
|
* to a well-defined, default state before calling
|
||||||
|
* `read_repository()`.
|
||||||
|
*/
|
||||||
|
#define REPOSITORY_FORMAT_INIT \
|
||||||
|
{ \
|
||||||
|
.version = -1, \
|
||||||
|
.is_bare = -1, \
|
||||||
|
.hash_algo = GIT_HASH_SHA1, \
|
||||||
|
.unknown_extensions = STRING_LIST_INIT_DUP, \
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the repository format characteristics from the config file "path" into
|
* Read the repository format characteristics from the config file "path" into
|
||||||
* "format" struct. Returns the numeric version. On error, -1 is returned,
|
* "format" struct. Returns the numeric version. On error, or if no version is
|
||||||
* format->version is set to -1, and all other fields in the struct are
|
* found in the configuration, -1 is returned, format->version is set to -1,
|
||||||
* undefined.
|
* and all other fields in the struct are set to the default configuration
|
||||||
|
* (REPOSITORY_FORMAT_INIT). Always initialize the struct using
|
||||||
|
* REPOSITORY_FORMAT_INIT before calling this function.
|
||||||
*/
|
*/
|
||||||
int read_repository_format(struct repository_format *format, const char *path);
|
int read_repository_format(struct repository_format *format, const char *path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the memory held onto by `format`, but not the struct itself.
|
||||||
|
* (No need to use this after `read_repository_format()` fails.)
|
||||||
|
*/
|
||||||
|
void clear_repository_format(struct repository_format *format);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify that the repository described by repository_format is something we
|
* Verify that the repository described by repository_format is something we
|
||||||
* can read. If it is, return 0. Otherwise, return -1, and "err" will describe
|
* can read. If it is, return 0. Otherwise, return -1, and "err" will describe
|
||||||
|
|
|
@ -157,7 +157,7 @@ int repo_init(struct repository *repo,
|
||||||
const char *gitdir,
|
const char *gitdir,
|
||||||
const char *worktree)
|
const char *worktree)
|
||||||
{
|
{
|
||||||
struct repository_format format;
|
struct repository_format format = REPOSITORY_FORMAT_INIT;
|
||||||
memset(repo, 0, sizeof(*repo));
|
memset(repo, 0, sizeof(*repo));
|
||||||
|
|
||||||
repo->objects = raw_object_store_new();
|
repo->objects = raw_object_store_new();
|
||||||
|
@ -174,6 +174,7 @@ int repo_init(struct repository *repo,
|
||||||
if (worktree)
|
if (worktree)
|
||||||
repo_set_worktree(repo, worktree);
|
repo_set_worktree(repo, worktree);
|
||||||
|
|
||||||
|
clear_repository_format(&format);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
40
setup.c
40
setup.c
|
@ -411,6 +411,7 @@ static int read_worktree_config(const char *var, const char *value, void *vdata)
|
||||||
} else if (strcmp(var, "core.worktree") == 0) {
|
} else if (strcmp(var, "core.worktree") == 0) {
|
||||||
if (!value)
|
if (!value)
|
||||||
return config_error_nonbool(var);
|
return config_error_nonbool(var);
|
||||||
|
free(data->work_tree);
|
||||||
data->work_tree = xstrdup(value);
|
data->work_tree = xstrdup(value);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -476,7 +477,7 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
|
||||||
}
|
}
|
||||||
|
|
||||||
repository_format_precious_objects = candidate->precious_objects;
|
repository_format_precious_objects = candidate->precious_objects;
|
||||||
repository_format_partial_clone = candidate->partial_clone;
|
repository_format_partial_clone = xstrdup_or_null(candidate->partial_clone);
|
||||||
repository_format_worktree_config = candidate->worktree_config;
|
repository_format_worktree_config = candidate->worktree_config;
|
||||||
string_list_clear(&candidate->unknown_extensions, 0);
|
string_list_clear(&candidate->unknown_extensions, 0);
|
||||||
|
|
||||||
|
@ -499,27 +500,38 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
|
||||||
}
|
}
|
||||||
if (candidate->work_tree) {
|
if (candidate->work_tree) {
|
||||||
free(git_work_tree_cfg);
|
free(git_work_tree_cfg);
|
||||||
git_work_tree_cfg = candidate->work_tree;
|
git_work_tree_cfg = xstrdup(candidate->work_tree);
|
||||||
inside_work_tree = -1;
|
inside_work_tree = -1;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
free(candidate->work_tree);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_repository_format(struct repository_format *format)
|
||||||
|
{
|
||||||
|
const struct repository_format fresh = REPOSITORY_FORMAT_INIT;
|
||||||
|
|
||||||
|
memcpy(format, &fresh, sizeof(fresh));
|
||||||
|
}
|
||||||
|
|
||||||
int read_repository_format(struct repository_format *format, const char *path)
|
int read_repository_format(struct repository_format *format, const char *path)
|
||||||
{
|
{
|
||||||
memset(format, 0, sizeof(*format));
|
clear_repository_format(format);
|
||||||
format->version = -1;
|
|
||||||
format->is_bare = -1;
|
|
||||||
format->hash_algo = GIT_HASH_SHA1;
|
|
||||||
string_list_init(&format->unknown_extensions, 1);
|
|
||||||
git_config_from_file(check_repo_format, path, format);
|
git_config_from_file(check_repo_format, path, format);
|
||||||
|
if (format->version == -1)
|
||||||
|
clear_repository_format(format);
|
||||||
return format->version;
|
return format->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear_repository_format(struct repository_format *format)
|
||||||
|
{
|
||||||
|
string_list_clear(&format->unknown_extensions, 0);
|
||||||
|
free(format->work_tree);
|
||||||
|
free(format->partial_clone);
|
||||||
|
init_repository_format(format);
|
||||||
|
}
|
||||||
|
|
||||||
int verify_repository_format(const struct repository_format *format,
|
int verify_repository_format(const struct repository_format *format,
|
||||||
struct strbuf *err)
|
struct strbuf *err)
|
||||||
{
|
{
|
||||||
|
@ -997,7 +1009,7 @@ int discover_git_directory(struct strbuf *commondir,
|
||||||
struct strbuf dir = STRBUF_INIT, err = STRBUF_INIT;
|
struct strbuf dir = STRBUF_INIT, err = STRBUF_INIT;
|
||||||
size_t gitdir_offset = gitdir->len, cwd_len;
|
size_t gitdir_offset = gitdir->len, cwd_len;
|
||||||
size_t commondir_offset = commondir->len;
|
size_t commondir_offset = commondir->len;
|
||||||
struct repository_format candidate;
|
struct repository_format candidate = REPOSITORY_FORMAT_INIT;
|
||||||
|
|
||||||
if (strbuf_getcwd(&dir))
|
if (strbuf_getcwd(&dir))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1034,9 +1046,11 @@ int discover_git_directory(struct strbuf *commondir,
|
||||||
strbuf_release(&err);
|
strbuf_release(&err);
|
||||||
strbuf_setlen(commondir, commondir_offset);
|
strbuf_setlen(commondir, commondir_offset);
|
||||||
strbuf_setlen(gitdir, gitdir_offset);
|
strbuf_setlen(gitdir, gitdir_offset);
|
||||||
|
clear_repository_format(&candidate);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_repository_format(&candidate);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1045,7 +1059,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||||
static struct strbuf cwd = STRBUF_INIT;
|
static struct strbuf cwd = STRBUF_INIT;
|
||||||
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
|
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
|
||||||
const char *prefix = NULL;
|
const char *prefix = NULL;
|
||||||
struct repository_format repo_fmt;
|
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We may have read an incomplete configuration before
|
* We may have read an incomplete configuration before
|
||||||
|
@ -1157,6 +1171,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||||
|
|
||||||
strbuf_release(&dir);
|
strbuf_release(&dir);
|
||||||
strbuf_release(&gitdir);
|
strbuf_release(&gitdir);
|
||||||
|
clear_repository_format(&repo_fmt);
|
||||||
|
|
||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
@ -1214,9 +1229,10 @@ int git_config_perm(const char *var, const char *value)
|
||||||
|
|
||||||
void check_repository_format(void)
|
void check_repository_format(void)
|
||||||
{
|
{
|
||||||
struct repository_format repo_fmt;
|
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
|
||||||
check_repository_format_gently(get_git_dir(), &repo_fmt, NULL);
|
check_repository_format_gently(get_git_dir(), &repo_fmt, NULL);
|
||||||
startup_info->have_repository = 1;
|
startup_info->have_repository = 1;
|
||||||
|
clear_repository_format(&repo_fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -444,7 +444,7 @@ int submodule_uses_worktrees(const char *path)
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct repository_format format;
|
struct repository_format format = REPOSITORY_FORMAT_INIT;
|
||||||
|
|
||||||
submodule_gitdir = git_pathdup_submodule(path, "%s", "");
|
submodule_gitdir = git_pathdup_submodule(path, "%s", "");
|
||||||
if (!submodule_gitdir)
|
if (!submodule_gitdir)
|
||||||
|
@ -462,8 +462,10 @@ int submodule_uses_worktrees(const char *path)
|
||||||
read_repository_format(&format, sb.buf);
|
read_repository_format(&format, sb.buf);
|
||||||
if (format.version != 0) {
|
if (format.version != 0) {
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
|
clear_repository_format(&format);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
clear_repository_format(&format);
|
||||||
|
|
||||||
/* Replace config by worktrees. */
|
/* Replace config by worktrees. */
|
||||||
strbuf_setlen(&sb, sb.len - strlen("config"));
|
strbuf_setlen(&sb, sb.len - strlen("config"));
|
||||||
|
|
Loading…
Reference in New Issue