Skip to content

Commit 47ac970

Browse files
bk2204gitster
authored andcommitted
builtin/clone: avoid failure with GIT_DEFAULT_HASH
If a user is cloning a SHA-1 repository with GIT_DEFAULT_HASH set to "sha256", then we can end up with a repository where the repository format version is 0 but the extensions.objectformat key is set to "sha256". This is both wrong (the user has a SHA-1 repository) and nonfunctional (because the extension cannot be used in a v0 repository). This happens because in a clone, we initially set up the repository, and then change its algorithm based on what the remote side tells us it's using. We've initially set up the repository as SHA-256 in this case, and then later on reset the repository version without clearing the extension. We could just always set the extension in this case, but that would mean that our SHA-1 repositories weren't compatible with older Git versions, even though there's no reason why they shouldn't be. And we also don't want to initialize the repository as SHA-1 initially, since that means if we're cloning an empty repository, we'll have failed to honor the GIT_DEFAULT_HASH variable and will end up with a SHA-1 repository, not a SHA-256 repository. Neither of those are appealing, so let's tell the repository initialization code if we're doing a reinit like this, and if so, to clear the extension if we're using SHA-1. This makes sure we produce a valid and functional repository and doesn't break any of our other use cases. Reported-by: Matheus Tavares <[email protected]> Signed-off-by: brian m. carlson <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 385c171 commit 47ac970

File tree

4 files changed

+20
-4
lines changed

4 files changed

+20
-4
lines changed

builtin/clone.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
12331233
* Now that we know what algorithm the remote side is using,
12341234
* let's set ours to the same thing.
12351235
*/
1236-
initialize_repository_version(hash_algo);
1236+
initialize_repository_version(hash_algo, 1);
12371237
repo_set_hash_algo(the_repository, hash_algo);
12381238

12391239
mapped_refs = wanted_peer_refs(refs, &remote->fetch);

builtin/init-db.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree)
179179
return 1;
180180
}
181181

182-
void initialize_repository_version(int hash_algo)
182+
void initialize_repository_version(int hash_algo, int reinit)
183183
{
184184
char repo_version_string[10];
185185
int repo_version = GIT_REPO_VERSION;
@@ -195,6 +195,8 @@ void initialize_repository_version(int hash_algo)
195195
if (hash_algo != GIT_HASH_SHA1)
196196
git_config_set("extensions.objectformat",
197197
hash_algos[hash_algo].name);
198+
else if (reinit)
199+
git_config_set_gently("extensions.objectformat", NULL);
198200
}
199201

200202
static int create_default_files(const char *template_path,
@@ -277,7 +279,7 @@ static int create_default_files(const char *template_path,
277279
free(ref);
278280
}
279281

280-
initialize_repository_version(fmt->hash_algo);
282+
initialize_repository_version(fmt->hash_algo, 0);
281283

282284
/* Check filemode trustability */
283285
path = git_path_buf(&buf, "config");

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ int path_inside_repo(const char *prefix, const char *path);
629629
int init_db(const char *git_dir, const char *real_git_dir,
630630
const char *template_dir, int hash_algo,
631631
const char *initial_branch, unsigned int flags);
632-
void initialize_repository_version(int hash_algo);
632+
void initialize_repository_version(int hash_algo, int reinit);
633633

634634
void sanitize_stdfds(void);
635635
int daemonize(void);

t/t5601-clone.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,20 @@ test_expect_success CASE_INSENSITIVE_FS 'colliding file detection' '
631631
test_i18ngrep "the following paths have collided" icasefs/warning
632632
'
633633

634+
test_expect_success 'clone with GIT_DEFAULT_HASH' '
635+
(
636+
sane_unset GIT_DEFAULT_HASH &&
637+
git init --object-format=sha1 test-sha1 &&
638+
git init --object-format=sha256 test-sha256
639+
) &&
640+
test_commit -C test-sha1 foo &&
641+
test_commit -C test-sha256 foo &&
642+
GIT_DEFAULT_HASH=sha1 git clone test-sha256 test-clone-sha256 &&
643+
GIT_DEFAULT_HASH=sha256 git clone test-sha1 test-clone-sha1 &&
644+
git -C test-clone-sha1 status &&
645+
git -C test-clone-sha256 status
646+
'
647+
634648
partial_clone_server () {
635649
SERVER="$1" &&
636650

0 commit comments

Comments
 (0)