-
-
Notifications
You must be signed in to change notification settings - Fork 497
gix: allow sha256-only builds #2627
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
62de1ec
ce43061
57a1280
1b3ca28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,15 +45,12 @@ impl StageOne { | |
| .map(|version| Core::REPOSITORY_FORMAT_VERSION.try_into_usize(version)) | ||
| .transpose()? | ||
| .unwrap_or_default(); | ||
| let object_hash = (repo_format_version != 1) | ||
| .then_some(Ok(gix_hash::Kind::Sha1)) | ||
| .or_else(|| { | ||
| config | ||
| .string(Extensions::OBJECT_FORMAT) | ||
| .map(|format| Extensions::OBJECT_FORMAT.try_into_object_format(format)) | ||
| }) | ||
| .transpose()? | ||
| .unwrap_or(gix_hash::Kind::Sha1); | ||
| let object_hash = match config.string(Extensions::OBJECT_FORMAT) { | ||
| // objectFormat is honored from repository format version 1 onwards. | ||
| Some(format) if repo_format_version >= 1 => Extensions::OBJECT_FORMAT.try_into_object_format(format)?, | ||
| Some(_) => return Err(Error::ObjectFormatRequiresV1), | ||
| None => legacy_object_hash()?, | ||
| }; | ||
|
|
||
| let extension_worktree = util::config_bool( | ||
| &config, | ||
|
|
@@ -104,6 +101,22 @@ impl StageOne { | |
| } | ||
| } | ||
|
|
||
| /// Return the object hash for a repository that does not set `extensions.objectFormat`. | ||
| /// | ||
| /// Git interprets a missing objectFormat as the original Sha1 layout, so we return | ||
| /// gix_hash::Kind::Sha1 whenever this build can handle it. | ||
| /// In Sha256-only builds we cannot open such a repository, so return an error instead. | ||
| fn legacy_object_hash() -> Result<gix_hash::Kind, Error> { | ||
| #[cfg(feature = "sha1")] | ||
| { | ||
| Ok(gix_hash::Kind::Sha1) | ||
| } | ||
| #[cfg(not(feature = "sha1"))] | ||
| { | ||
| Err(Error::UnsupportedObjectFormat { name: "sha1".into() }) | ||
| } | ||
|
Comment on lines
+114
to
+117
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was a bit stuck here and decided to go with something else. Initially, instead of saying this isn't possible, I asked myself what would Git do if it would allow to not compile SHA-1 in. Then I think it should just be like SHA-1 never happened, hence SHA-256 is returned. However, Git doesn't do that and it An interesting journey, leading to nothing but this comment 😁. |
||
| } | ||
|
10ne1 marked this conversation as resolved.
|
||
|
|
||
| fn load_config( | ||
| config_path: std::path::PathBuf, | ||
| buf: &mut Vec<u8>, | ||
|
|
@@ -157,3 +170,24 @@ fn load_config( | |
|
|
||
| Ok(config) | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test felt redundant in the light of compile-time safety and docs of |
||
| /// `legacy_object_hash` has a feature-gated split: Sha1 when this build supports it, an error | ||
| /// otherwise. Assert the branch matching the current build so the sha256-only path is covered | ||
| /// when the lib tests run under `--no-default-features --features sha256`. | ||
| #[test] | ||
| fn legacy_object_hash_reflects_build_features() { | ||
| let actual = super::legacy_object_hash(); | ||
| #[cfg(feature = "sha1")] | ||
| assert!( | ||
| matches!(actual, Ok(gix_hash::Kind::Sha1)), | ||
| "with sha1 support a missing objectFormat resolves to the legacy Sha1 layout, got {actual:?}" | ||
| ); | ||
| #[cfg(not(feature = "sha1"))] | ||
| assert!( | ||
| matches!(actual, Err(super::Error::UnsupportedObjectFormat { .. })), | ||
| "without sha1 support a missing objectFormat cannot be opened, got {actual:?}" | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -86,6 +86,11 @@ pub enum Error { | |
| RefsNamespace(#[from] refs_namespace::Error), | ||
| #[error("Cannot handle objects formatted as {:?}", .name)] | ||
| UnsupportedObjectFormat { name: BString }, | ||
| #[error( | ||
| "extensions.objectFormat is a v1-only extension, but the repository format version is 0; \ | ||
| set core.repositoryFormatVersion=1 to use it, or remove extensions.objectFormat to fall back to the default Sha1 format (if supported by this build)" | ||
| )] | ||
| ObjectFormatRequiresV1, | ||
|
10ne1 marked this conversation as resolved.
Comment on lines
+89
to
+93
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A wonderful error message! |
||
| #[error(transparent)] | ||
| CoreAbbrev(#[from] abbrev::Error), | ||
| #[error("Could not read configuration file at \"{}\"", path.display())] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -165,6 +165,19 @@ mkdir not-a-repo-with-files; | |
| touch this that | ||
| ) | ||
|
|
||
| # objectFormat is a v1-only extension; a version-0 repo that sets it is invalid (even for sha1). | ||
| # Reach that state with git config independently of the fixture's default hash: first make a valid | ||
| # v1+objectFormat repo, then flip the version to 0 as the last write. The flip must come last because | ||
| # git config refuses to run once the repo is already invalid (v0 with a v1-only extension). | ||
| for format in sha1 sha256; do | ||
| git init "objectformat-$format-with-repository-format-v0" | ||
| (cd "objectformat-$format-with-repository-format-v0" | ||
| git config core.repositoryFormatVersion 1 | ||
| git config extensions.objectFormat "$format" | ||
| git config core.repositoryFormatVersion 0 | ||
| ) | ||
| done | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed the 'dance' in favor of something more direct, for better or worse. |
||
|
|
||
| git init ssl-verify-disabled | ||
| (cd ssl-verify-disabled | ||
| git config http.sslVerify false | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -354,6 +354,32 @@ mod not_a_repository { | |
| } | ||
| } | ||
|
|
||
| mod object_format_extension { | ||
| use crate::util::named_subrepo_opts; | ||
|
|
||
| #[test] | ||
| fn rejects_object_format_on_v0_repo() -> crate::Result { | ||
| // objectFormat is a "v1-only" extension: git refuses to operate on a version-0 repo that | ||
| // sets it, even for sha1 (unlike grandfathered extensions like preciousObjects, which v0 | ||
| // still honours). This rejection was introduced in git 2.29.0 (2020). We match it. | ||
|
Comment on lines
+362
to
+364
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the research that went into this. |
||
| for name in [ | ||
| "objectformat-sha256-with-repository-format-v0", | ||
| "objectformat-sha1-with-repository-format-v0", | ||
| ] { | ||
| let err = named_subrepo_opts("make_config_repos.sh", name, gix::open::Options::isolated()) | ||
| .expect_err("a v0 repository setting extensions.objectFormat must be rejected"); | ||
| assert!( | ||
| matches!( | ||
| err, | ||
| gix::open::Error::Config(gix::config::Error::ObjectFormatRequiresV1) | ||
| ), | ||
| "objectFormat on a v0 repository must be rejected, got {err:?} for {name}" | ||
| ); | ||
| } | ||
| Ok(()) | ||
| } | ||
| } | ||
|
|
||
| mod open_path_as_is { | ||
|
|
||
| use crate::util::{named_subrepo_opts, repo_opts}; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.