Commit 8351abc7822c38f597bf0ee07f0f293a4f62b1f3

Edward Thomson 2015-06-23T23:17:18

Merge pull request #3249 from libgit2/cmn/repo-version-check Check the repository version

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;