Merge branch 'jk/check-repository-format' into maint
The repository set-up sequence has been streamlined (the biggest change is that there is no longer git_config_early()), so that we do not attempt to look into refs/* when we know we do not have a Git repository. * jk/check-repository-format: verify_repository_format: mark messages for translation setup: drop repository_format_version global setup: unify repository version callbacks init: use setup.c's repo version verification setup: refactor repo format reading and verification config: drop git_config_early check_repository_format_gently: stop using git_config_early lazily load core.sharedrepository wrap shared_repository global in get/set accessors setup: document check_repository_format()
This commit is contained in:
144
setup.c
144
setup.c
@ -5,7 +5,6 @@
|
||||
static int inside_git_dir = -1;
|
||||
static int inside_work_tree = -1;
|
||||
static int work_tree_config_is_bogus;
|
||||
static struct string_list unknown_extensions = STRING_LIST_INIT_DUP;
|
||||
|
||||
static struct startup_info the_startup_info;
|
||||
struct startup_info *startup_info = &the_startup_info;
|
||||
@ -373,14 +372,13 @@ void setup_work_tree(void)
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
static int check_repo_format(const char *var, const char *value, void *cb)
|
||||
static int check_repo_format(const char *var, const char *value, void *vdata)
|
||||
{
|
||||
struct repository_format *data = vdata;
|
||||
const char *ext;
|
||||
|
||||
if (strcmp(var, "core.repositoryformatversion") == 0)
|
||||
repository_format_version = git_config_int(var, value);
|
||||
else if (strcmp(var, "core.sharedrepository") == 0)
|
||||
shared_repository = git_config_perm(var, value);
|
||||
data->version = git_config_int(var, value);
|
||||
else if (skip_prefix(var, "extensions.", &ext)) {
|
||||
/*
|
||||
* record any known extensions here; otherwise,
|
||||
@ -390,9 +388,15 @@ static int check_repo_format(const char *var, const char *value, void *cb)
|
||||
if (!strcmp(ext, "noop"))
|
||||
;
|
||||
else if (!strcmp(ext, "preciousobjects"))
|
||||
repository_format_precious_objects = git_config_bool(var, value);
|
||||
data->precious_objects = git_config_bool(var, value);
|
||||
else
|
||||
string_list_append(&unknown_extensions, ext);
|
||||
string_list_append(&data->unknown_extensions, ext);
|
||||
} else if (strcmp(var, "core.bare") == 0) {
|
||||
data->is_bare = git_config_bool(var, value);
|
||||
} else if (strcmp(var, "core.worktree") == 0) {
|
||||
if (!value)
|
||||
return config_error_nonbool(var);
|
||||
data->work_tree = xstrdup(value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -400,56 +404,84 @@ static int check_repo_format(const char *var, const char *value, void *cb)
|
||||
static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
const char *repo_config;
|
||||
config_fn_t fn;
|
||||
int ret = 0;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
struct repository_format candidate;
|
||||
int has_common;
|
||||
|
||||
string_list_clear(&unknown_extensions, 0);
|
||||
|
||||
if (get_common_dir(&sb, gitdir))
|
||||
fn = check_repo_format;
|
||||
else
|
||||
fn = check_repository_format_version;
|
||||
has_common = get_common_dir(&sb, gitdir);
|
||||
strbuf_addstr(&sb, "/config");
|
||||
repo_config = sb.buf;
|
||||
read_repository_format(&candidate, sb.buf);
|
||||
strbuf_release(&sb);
|
||||
|
||||
/*
|
||||
* git_config() can't be used here because it calls git_pathdup()
|
||||
* to get $GIT_CONFIG/config. That call will make setup_git_env()
|
||||
* set git_dir to ".git".
|
||||
*
|
||||
* We are in gitdir setup, no git dir has been found useable yet.
|
||||
* Use a gentler version of git_config() to check if this repo
|
||||
* is a good one.
|
||||
* For historical use of check_repository_format() in git-init,
|
||||
* we treat a missing config as a silent "ok", even when nongit_ok
|
||||
* is unset.
|
||||
*/
|
||||
git_config_early(fn, NULL, repo_config);
|
||||
if (GIT_REPO_VERSION_READ < repository_format_version) {
|
||||
if (!nongit_ok)
|
||||
die ("Expected git repo version <= %d, found %d",
|
||||
GIT_REPO_VERSION_READ, repository_format_version);
|
||||
warning("Expected git repo version <= %d, found %d",
|
||||
GIT_REPO_VERSION_READ, repository_format_version);
|
||||
warning("Please upgrade Git");
|
||||
*nongit_ok = -1;
|
||||
ret = -1;
|
||||
if (candidate.version < 0)
|
||||
return 0;
|
||||
|
||||
if (verify_repository_format(&candidate, &err) < 0) {
|
||||
if (nongit_ok) {
|
||||
warning("%s", err.buf);
|
||||
strbuf_release(&err);
|
||||
*nongit_ok = -1;
|
||||
return -1;
|
||||
}
|
||||
die("%s", err.buf);
|
||||
}
|
||||
|
||||
if (repository_format_version >= 1 && unknown_extensions.nr) {
|
||||
repository_format_precious_objects = candidate.precious_objects;
|
||||
string_list_clear(&candidate.unknown_extensions, 0);
|
||||
if (!has_common) {
|
||||
if (candidate.is_bare != -1) {
|
||||
is_bare_repository_cfg = candidate.is_bare;
|
||||
if (is_bare_repository_cfg == 1)
|
||||
inside_work_tree = -1;
|
||||
}
|
||||
if (candidate.work_tree) {
|
||||
free(git_work_tree_cfg);
|
||||
git_work_tree_cfg = candidate.work_tree;
|
||||
inside_work_tree = -1;
|
||||
}
|
||||
} else {
|
||||
free(candidate.work_tree);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_repository_format(struct repository_format *format, const char *path)
|
||||
{
|
||||
memset(format, 0, sizeof(*format));
|
||||
format->version = -1;
|
||||
format->is_bare = -1;
|
||||
string_list_init(&format->unknown_extensions, 1);
|
||||
git_config_from_file(check_repo_format, path, format);
|
||||
return format->version;
|
||||
}
|
||||
|
||||
int verify_repository_format(const struct repository_format *format,
|
||||
struct strbuf *err)
|
||||
{
|
||||
if (GIT_REPO_VERSION_READ < format->version) {
|
||||
strbuf_addf(err, _("Expected git repo version <= %d, found %d"),
|
||||
GIT_REPO_VERSION_READ, format->version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (format->version >= 1 && format->unknown_extensions.nr) {
|
||||
int i;
|
||||
|
||||
if (!nongit_ok)
|
||||
die("unknown repository extension: %s",
|
||||
unknown_extensions.items[0].string);
|
||||
strbuf_addstr(err, _("unknown repository extensions found:"));
|
||||
|
||||
for (i = 0; i < unknown_extensions.nr; i++)
|
||||
warning("unknown repository extension: %s",
|
||||
unknown_extensions.items[i].string);
|
||||
*nongit_ok = -1;
|
||||
ret = -1;
|
||||
for (i = 0; i < format->unknown_extensions.nr; i++)
|
||||
strbuf_addf(err, "\n\t%s",
|
||||
format->unknown_extensions.items[i].string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strbuf_release(&sb);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -965,30 +997,10 @@ int git_config_perm(const char *var, const char *value)
|
||||
return -(i & 0666);
|
||||
}
|
||||
|
||||
int check_repository_format_version(const char *var, const char *value, void *cb)
|
||||
{
|
||||
int ret = check_repo_format(var, value, cb);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (strcmp(var, "core.bare") == 0) {
|
||||
is_bare_repository_cfg = git_config_bool(var, value);
|
||||
if (is_bare_repository_cfg == 1)
|
||||
inside_work_tree = -1;
|
||||
} else if (strcmp(var, "core.worktree") == 0) {
|
||||
if (!value)
|
||||
return config_error_nonbool(var);
|
||||
free(git_work_tree_cfg);
|
||||
git_work_tree_cfg = xstrdup(value);
|
||||
inside_work_tree = -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_repository_format(void)
|
||||
void check_repository_format(void)
|
||||
{
|
||||
check_repository_format_gently(get_git_dir(), NULL);
|
||||
startup_info->have_repository = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user