diff --git a/eden/scm/lib/gitstore/src/gitstore.rs b/eden/scm/lib/gitstore/src/gitstore.rs index 26b9971846f9a..2165c14bf9b48 100644 --- a/eden/scm/lib/gitstore/src/gitstore.rs +++ b/eden/scm/lib/gitstore/src/gitstore.rs @@ -97,6 +97,12 @@ impl GitStore { /// `open` a Git bare repo at `git_dir`. Gain access to its odb (object database). pub fn open(git_dir: &Path, config: &dyn Config) -> Result { let mut git = BareGit::from_git_dir_and_config(git_dir.to_owned(), config); + // libgit2 < 2.0 rejects reftable repos ("unsupported extension name + // extensions.refstorage"). GitStore only uses libgit2 for the odb. References + // are read by gitcompat, which supports reftable. So tolerating the extension + // is enough. + // SAFETY: This sets a libgit2 global. Every caller sets the same value. + unsafe { git2::opts::set_extensions(&["refstorage"])? }; let git_repo = match git2::Repository::open(git_dir) { Ok(repo) => repo, Err(err) if err.message() == "unsupported extension name extensions.partialclone" => { @@ -135,6 +141,15 @@ impl GitStore { } Err(err) => return Err(err.into()), }; + // "://" stores references at a custom path. gitcompat cannot + // read those, so keep rejecting them, like libgit2 did. + if let Ok(value) = git_repo.config()?.get_string("extensions.refstorage") { + if value.contains("://") { + anyhow::bail!( + "Git references stored at a custom path are not supported (extensions.refstorage = {value:?})" + ); + } + } let odb = git_repo.odb()?; // Git's negotiation algorithm works on commit reference level and can add significant diff --git a/eden/scm/tests/test-dotgit-reftable.t b/eden/scm/tests/test-dotgit-reftable.t new file mode 100644 index 0000000000000..debf7e2140d73 --- /dev/null +++ b/eden/scm/tests/test-dotgit-reftable.t @@ -0,0 +1,21 @@ +#require git no-eden no-windows + + $ . $TESTDIR/git.sh + $ git init -q -b main --ref-format=reftable repo + $ cd repo + $ echo first > a + $ git add a + $ git commit -q -m first + +Read a repo that stores references in the reftable format. + + $ sl log -T '{desc}\n' + first + +Write a commit that Git can read. + + $ echo second > a + $ sl commit -q -m second + $ git log --format=%s + second + first