Skip to content

[WIP] feat: unstable SHA256 support#1206

Draft
weihanglo wants to merge 10 commits intorust-lang:masterfrom
weihanglo:sha256-git2
Draft

[WIP] feat: unstable SHA256 support#1206
weihanglo wants to merge 10 commits intorust-lang:masterfrom
weihanglo:sha256-git2

Conversation

@weihanglo
Copy link
Member

@weihanglo weihanglo commented Jan 12, 2026

This adds an unstable-sha256 Cargo feature, as a follow-up of #1201.
Also adds some smoke tests for affected operations/types.

Part of #1090

Insta-stable

  • NEW Index::with_object_format to create with different format

Behind unstable-sha256

  • NEW ObjectFormat::Sha256 enum variant
  • NEW RepositoryInitOptions::object_format() method to set hash algo
  • NEW Remote::object_format method to get hash algo on a remote
  • NEW Oid::raw_bytes to return the full underlying bytes
  • CHANGED Diff::from_buffer to accept an extra object format argument
  • CHANGED Index::open to accept an extra object format argument
  • CHANGED Indexer::new to accept an extra object format argument
  • CHANGED Oid::from_str to accept an extra object format argument
  • CHANGED Oid::hash_{object,file} to accept an extra object format argument
  • CHANGED Oid::as_bytes to return the logic bytes (SHA1 -> 20 bytes; SHA256 -> 32 bytes)
  • CHANGED impl Hash for Oid to hash git_oid->kind
  • REMOVED Index::new to avoid misuse.
  • REMOVED impl std::FromStr for Oid to avoid misuse

libgit2 1.9 compatibility changes

This PR also includes fixes for libgit2 1.9 breaking changes:

  • Renamed build macros (GIT_SHA1_COLLISIONDETECT -> GIT_SHA1_BUILTIN, HTTPS backend macros)
  • Added refdb_type field to git_repository_init_options
  • Updating sha256 bindings accordingly

See libgit2/libgit2#6994 and libgit2/libgit2#7102 for upstream changes.

These changes can be split out if needed.

src/oid.rs Outdated
Comment on lines 183 to 189
/// View this OID as a byte-slice.
///
/// * 20 bytes in length if the feature `unstable-sha256` is not enabled.
/// * 32 bytes in length if the feature `unstable-sha256` is enabled.
pub fn as_bytes(&self) -> &[u8] {
&self.raw.id
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should return 20 bytes if unstable-sha256 is enabled but the object format is SHA-1.

One reason for this is that crate features should be additive; turning on the feature shouldn't unnecessarily affect how the crate behaves with already-supported repositories.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for calling this out. That's a fair point, but I'm not sure "feature additivity" is the core issue here.

I think the real question is what Oid::as_bytes() is supposed to mean in this crate: the logical object ID bytes, or the raw backing storage from libgit2.

I'm leaning toward the logical interpretation. That seems like the less surprising API for callers, as you mentioned.

The reason I wasn’t fully convinced yet is that this type has historically been a fairly thin wrapper over libgit2, so I wanted to check whether anyone might rely on the raw representation or the backing buffer. Or maybe we should just mark this with a big ‼️ in the changelog, so we can transit to your proposal. Do you know any use of this functions in the wild?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is the option to have Oid::as_bytes() give you the logical representation and introduce a new Oid::raw_bytes() for the (probably few) users that actually want the entire buffer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed the as_bytes part and also added the raw_bytes method. Thanks for the feedback, folks!

* GIT_SHA1_COLLISIONDETECT -> GIT_SHA1_BUILTIN
* GIT_WINHTTP -> GIT_HTTPS_WINHTTP
* GIT_SECURE_TRANSPORT -> GIT_HTTPS_SECURETRANSPORT
* GIT_OPENSSL -> GIT_HTTPS_OPENSSL

See <libgit2/libgit2#6994>
* Add `GIT_REPOSITORY_INIT_RELATIVE_GITLINK`
  at libgit2/libgit2@bc737620d
* Remove `GIT_REPOSITORY_INIT_NO_DOTGIT_DIR`
  at libgit2/libgit2@ca2a241e4
* Remove `GIT_OBJECT_OFS_DELTA`
* Remove `GIT_OBJECT_REF_DELTA`

See libgit2/libgit2@23da3a8f3
libgit2 simplified SHA256 API to use `_ext` suffixes instead of
changing base function signatures. This avoids breaking changes
for users who don't need SHA256 support.

Updated bindings:

- git_oid_from_raw
- git_oid_from_prefix
- git_oid_from_string
- git_diff_from_buffer_ext
- git_index_new_ext
- git_index_open_ext
- git_odb_new_ext
- git_odb_open_ext
- git_repository_new_ext

See libgit2/libgit2@56e2a85643f (libgit2/libgit2#6975)
@weihanglo weihanglo mentioned this pull request Mar 16, 2026
This adds an `unstable-sha256` Cargo feature,
as a follow-up of rust-lang#1201

Also adds some smoke tests for affected operations/types.

## Insta-stable

* **NEW** `Index::with_object_format` to create with different format

## Behind `unstable-sha256

* **NEW** `ObjectFormat::Sha256` enum variant
* **NEW** `RepositoryInitOptions::object_format()` method to set hash algo
* **NEW** `Remote::object_format` method to get hash algo on a remote
* **CHANGED** `Diff::from_buffer` to accept a extra object format argument
* **CHANGED** `Index::open` to accept a extra object format argument
* **CHANGED** `Indexer::new` to accept a extra object format argument
* **CHANGED** `Oid::from_str` to accept a extra object format argument
* **CHANGED** `Oid::hash_{object,file}` to accept a extra object format argument
* **REMOVED** `Index::new` to avoid misuse.
* **REMOVED** `impl std::FromStr for Oid` to avoid misuse
This also run systest first,
so we can dicover bindding mismatch before
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants