Merge pull request #3249 from libgit2/cmn/repo-version-check Check the repository version
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
diff --git a/src/repository.c b/src/repository.c
index c608fa0..b7c99ea 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -32,6 +32,8 @@
# include "win32/w32_util.h"
#endif
+static int check_repositoryformatversion(git_config *config);
+
#define GIT_FILE_CONTENT_PREFIX "gitdir:"
#define GIT_BRANCH_MASTER "master"
@@ -489,6 +491,7 @@ int git_repository_open_ext(
git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT,
link_path = GIT_BUF_INIT;
git_repository *repo;
+ git_config *config = NULL;
if (repo_ptr)
*repo_ptr = NULL;
@@ -510,22 +513,36 @@ int git_repository_open_ext(
GITERR_CHECK_ALLOC(repo->path_gitlink);
}
+ /*
+ * We'd like to have the config, but git doesn't particularly
+ * care if it's not there, so we need to deal with that.
+ */
+
+ error = git_repository_config_snapshot(&config, repo);
+ if (error < 0 && error != GIT_ENOTFOUND)
+ goto cleanup;
+
+ if (config && (error = check_repositoryformatversion(config)) < 0)
+ goto cleanup;
+
if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
repo->is_bare = 1;
else {
- git_config *config = NULL;
- if ((error = git_repository_config_snapshot(&config, repo)) < 0 ||
- (error = load_config_data(repo, config)) < 0 ||
- (error = load_workdir(repo, config, &parent)) < 0)
- git_repository_free(repo);
-
- git_config_free(config);
+ if (config &&
+ ((error = load_config_data(repo, config)) < 0 ||
+ (error = load_workdir(repo, config, &parent))) < 0)
+ goto cleanup;
}
- if (!error)
- *repo_ptr = repo;
+cleanup:
git_buf_free(&parent);
+ git_config_free(config);
+
+ if (error < 0)
+ git_repository_free(repo);
+ else
+ *repo_ptr = repo;
return error;
}
@@ -931,9 +948,14 @@ bool git_repository__reserved_names(
static int check_repositoryformatversion(git_config *config)
{
- int version;
+ int version, error;
- if (git_config_get_int32(&version, config, "core.repositoryformatversion") < 0)
+ error = git_config_get_int32(&version, config, "core.repositoryformatversion");
+ /* git ignores this if the config variable isn't there */
+ if (error == GIT_ENOTFOUND)
+ return 0;
+
+ if (error < 0)
return -1;
if (GIT_REPO_VERSION < version) {
diff --git a/tests/repo/open.c b/tests/repo/open.c
index 637c785..6a5ab24 100644
--- a/tests/repo/open.c
+++ b/tests/repo/open.c
@@ -20,6 +20,23 @@ void test_repo_open__bare_empty_repo(void)
cl_assert(git_repository_workdir(repo) == NULL);
}
+void test_repo_open__format_version_1(void)
+{
+ git_buf path = GIT_BUF_INIT;
+ git_repository *repo;
+ git_config *config;
+
+ repo = cl_git_sandbox_init("empty_bare.git");
+
+ cl_git_pass(git_repository_open(&repo, "empty_bare.git"));
+ cl_git_pass(git_repository_config__weakptr(&config, repo));
+
+ cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 1));
+
+ git_repository_free(repo);
+ cl_git_fail(git_repository_open(&repo, "empty_bare.git"));
+}
+
void test_repo_open__standard_empty_repo_through_gitdir(void)
{
git_repository *repo;