Skip to content

Commit e3ebb0d

Browse files
committed
feat(sys): support system libgit2-experimental.so
1 parent e76bce6 commit e3ebb0d

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

libgit2-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@ zlib-ng-compat = ["libz-sys/zlib-ng", "libssh2-sys?/zlib-ng-compat"]
4949
# DO NOT enable this feature by default in your dependencies.
5050
# Due to Cargo's additive features,
5151
# downstream users cannot deactivate it once enabled.
52-
unstable-sha256 = ["vendored"]
52+
unstable-sha256 = []

libgit2-sys/build.rs

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,66 @@ use std::path::{Path, PathBuf};
55
use std::process::Command;
66

77
/// Tries to use system libgit2 and emits necessary build script instructions.
8-
fn try_system_libgit2() -> Result<pkg_config::Library, pkg_config::Error> {
8+
fn try_system_libgit2(
9+
experimental_sha256: bool,
10+
) -> Result<pkg_config::Library, Box<dyn std::error::Error>> {
911
let mut cfg = pkg_config::Config::new();
1012
let range_version = "1.9.2".."1.10.0";
1113

12-
let lib = match cfg.range_version(range_version).probe("libgit2") {
13-
Ok(lib) => lib,
14-
Err(e) => {
15-
println!("cargo:warning=failed to probe system libgit2: {e}");
16-
return Err(e);
14+
let lib = if experimental_sha256 {
15+
// Determine whether experimental SHA256 object support is enabled.
16+
//
17+
// Given the SHA256 support is ABI-incompatible,
18+
// we take a conservative approach here:
19+
//
20+
// 1. Only accept if the library name has the `-experimental` suffix
21+
// 2. The experimental library must have an `experimental.h` header file
22+
// containing an enabled `GIT_EXPERIMENTAL_SHA256` constant.
23+
//
24+
// See how libgit2 handles experimental features:
25+
// https://github.com/libgit2/libgit2/blob/3ac4c0adb1064bad16a7f980d87e7261753fd07e/cmake/ExperimentalFeatures.cmake
26+
match cfg
27+
.range_version(range_version.clone())
28+
.probe("libgit2-experimental")
29+
{
30+
Ok(lib) => {
31+
let sha256_constant_in_header = lib.include_paths.iter().any(|path| {
32+
let header = path.join("git2/experimental.h");
33+
let contents = match std::fs::read_to_string(header) {
34+
Ok(s) => s,
35+
Err(_) => return false,
36+
};
37+
if contents.contains("#cmakedefine") {
38+
// still template
39+
return false;
40+
}
41+
contents
42+
.lines()
43+
.any(|l| l.starts_with("#define GIT_EXPERIMENTAL_SHA256 1"))
44+
});
45+
if sha256_constant_in_header {
46+
println!("cargo:rustc-cfg=libgit2_experimental_sha256");
47+
lib
48+
} else {
49+
println!("cargo:warning=no GIT_EXPERIMENTAL_SHA256 constant in headers");
50+
return Err(
51+
"GIT_EXPERIMENTAL_SHA256 wasn't enabled for libgit2-experimental library"
52+
.into(),
53+
);
54+
}
55+
}
56+
Err(e) => {
57+
println!("cargo:warning=failed to probe system libgit2-experimental: {e}");
58+
return Err(e.into());
59+
}
60+
}
61+
} else {
62+
match cfg.range_version(range_version).probe("libgit2") {
63+
Ok(lib) => lib,
64+
Err(e) => {
65+
println!("cargo:warning=failed to probe system libgit2: {e}");
66+
return Err(e.into());
67+
}
1768
}
1869
};
1970

@@ -45,7 +96,7 @@ fn main() {
4596
let forced_no_vendor = env::var_os("LIBGIT2_NO_VENDOR").map_or(false, |s| s != "0");
4697

4798
if forced_no_vendor {
48-
if try_system_libgit2().is_err() {
99+
if try_system_libgit2(unstable_sha256).is_err() {
49100
panic!(
50101
"\
51102
The environment variable `LIBGIT2_NO_VENDOR` has been set but no compatible system libgit2 could be found.
@@ -60,7 +111,7 @@ The build is now aborting. To disable, unset the variable or use `LIBGIT2_NO_VEN
60111

61112
// To use zlib-ng in zlib-compat mode, we have to build libgit2 ourselves.
62113
let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat;
63-
if try_to_use_system_libgit2 && try_system_libgit2().is_ok() {
114+
if try_to_use_system_libgit2 && try_system_libgit2(unstable_sha256).is_ok() {
64115
// using system libgit2 has worked
65116
return;
66117
}

0 commit comments

Comments
 (0)