summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cache.h24
-rw-r--r--setup.c118
2 files changed, 103 insertions, 39 deletions
diff --git a/cache.h b/cache.h
index 867e73eb54..4fc42b5ec7 100644
--- a/cache.h
+++ b/cache.h
@@ -750,6 +750,30 @@ extern int grafts_replace_parents;
extern int repository_format_version;
extern int repository_format_precious_objects;
+struct repository_format {
+ int version;
+ int precious_objects;
+ int is_bare;
+ char *work_tree;
+ struct string_list unknown_extensions;
+};
+
+/*
+ * Read the repository format characteristics from the config file "path" into
+ * "format" struct. Returns the numeric version. On error, -1 is returned,
+ * format->version is set to -1, and all other fields in the struct are
+ * undefined.
+ */
+int read_repository_format(struct repository_format *format, const char *path);
+
+/*
+ * 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
+ * any errors encountered.
+ */
+int verify_repository_format(const struct repository_format *format,
+ struct strbuf *err);
+
/*
* Check the repository format version in the path found in get_git_dir(),
* and die if it is a version we don't understand. Generally one would
diff --git a/setup.c b/setup.c
index a6013e6dd3..8aa49a9570 100644
--- a/setup.c
+++ b/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;
/*
* The input parameter must contain an absolute path, and it must already be
@@ -370,12 +369,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);
+ data->version = git_config_int(var, value);
else if (skip_prefix(var, "extensions.", &ext)) {
/*
* record any known extensions here; otherwise,
@@ -385,61 +385,104 @@ 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);
}
return 0;
}
+static int read_repository_format_1(struct repository_format *, config_fn_t,
+ const char *);
+
static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
{
struct strbuf sb = STRBUF_INIT;
- const char *repo_config;
+ struct strbuf err = STRBUF_INIT;
+ struct repository_format candidate;
config_fn_t fn;
- int ret = 0;
-
- string_list_clear(&unknown_extensions, 0);
if (get_common_dir(&sb, gitdir))
fn = check_repo_format;
else
fn = check_repository_format_version;
+
strbuf_addstr(&sb, "/config");
- repo_config = sb.buf;
+ read_repository_format_1(&candidate, fn, sb.buf);
+ strbuf_release(&sb);
/*
- * Ignore return value; for historical reasons, we must treat a missing
- * config file as a noop (git-init relies on this).
+ * 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_from_file(fn, repo_config, NULL);
- 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_version = candidate.version;
+ repository_format_precious_objects = candidate.precious_objects;
+ string_list_clear(&candidate.unknown_extensions, 0);
+ 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;
+ }
+
+ return 0;
+}
+
+static int read_repository_format_1(struct repository_format *format,
+ config_fn_t fn, 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(fn, path, format);
+ return format->version;
+}
+
+int read_repository_format(struct repository_format *format, const char *path)
+{
+ return read_repository_format_1(format, check_repository_format_version, path);
+}
+
+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;
}
/*
@@ -958,19 +1001,16 @@ int git_config_perm(const char *var, const char *value)
int check_repository_format_version(const char *var, const char *value, void *cb)
{
+ struct repository_format *data = 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;
+ data->is_bare = git_config_bool(var, value);
} 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;
+ data->work_tree = xstrdup(value);
}
return 0;
}