diff --git a/Cargo.lock b/Cargo.lock index b9e6d869..04dec5b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -531,6 +531,7 @@ dependencies = [ "cargo_metadata", "clap", "futures", + "git2", "heck 0.5.0", "indexmap 2.7.0", "libc", @@ -642,6 +643,8 @@ version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -1445,6 +1448,21 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "git2" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5220b8ba44c68a9a7f7a7659e864dd73692e417ef0211bea133c7b74e031eeb9" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + [[package]] name = "group" version = "0.13.0" @@ -1953,6 +1971,15 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.76" @@ -2045,6 +2072,20 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libgit2-sys" +version = "0.18.1+1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1dcb20f84ffcdd825c7a311ae347cce604a6f084a767dec4a4929829645290e" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + [[package]] name = "libredox" version = "0.1.3" @@ -2055,6 +2096,32 @@ dependencies = [ "libc", ] +[[package]] +name = "libssh2-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-keyutils" version = "0.2.4" @@ -2439,6 +2506,24 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -4254,6 +4339,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.5" diff --git a/Cargo.toml b/Cargo.toml index 211fd5a5..1536c0ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ bytes = { workspace = true } cargo_metadata = { workspace = true } cargo-component-core = { workspace = true } cargo-config2 = { workspace = true } +git2 = { workspace = true } clap = { workspace = true } futures = { workspace = true } heck = { workspace = true } @@ -74,6 +75,7 @@ bytes = "1.6.0" cargo_metadata = "0.19.1" cargo-component-core = { path = "crates/core", version = "0.21.1" } cargo-config2 = "0.1.24" +git2 = "0.20.1" clap = { version = "4.5.4", features = ["derive", "env"] } dirs = "5" futures = "0.3.30" diff --git a/src/git.rs b/src/git.rs new file mode 100644 index 00000000..105e2670 --- /dev/null +++ b/src/git.rs @@ -0,0 +1,51 @@ +use anyhow::Result; +use cargo_metadata::Package; +use git2::{ErrorClass, ErrorCode, Repository}; + +#[derive(Debug)] +pub struct GitMetadata { + commit: String, +} + +impl GitMetadata { + /// Creates a new Git metadata for the given cargo package. + pub fn from_package(package: &Package) -> Result> { + log::debug!( + "searching for git metadata from manifest `{path}`", + path = package.manifest_path + ); + + let repository = match Repository::discover(package.manifest_path.clone()) { + Ok(repository) => Ok(repository), + Err(ref e) + if e.class() == ErrorClass::Repository && e.code() == ErrorCode::NotFound => + { + return Ok(None) + } + Err(e) => Err(e), + }?; + + let head = match repository.head() { + Ok(head) => Ok(head), + Err(ref e) + if e.class() == ErrorClass::Reference && e.code() == ErrorCode::UnbornBranch => + { + return Ok(None) + } + Err(error) => Err(error), + }?; + + let commit = head.peel_to_commit()?; + let commit_id = commit.id(); + + let metadata = Self { + commit: commit_id.to_string(), + }; + + Ok(Some(metadata)) + } + + pub fn commit(&self) -> &str { + &self.commit + } +} diff --git a/src/lib.rs b/src/lib.rs index c81a2406..fba400c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,6 +36,7 @@ use wit_component::ComponentEncoder; use crate::target::install_wasm32_wasip1; use config::{CargoArguments, CargoPackageSpec, Config}; +use git::GitMetadata; use lock::{acquire_lock_file_ro, acquire_lock_file_rw}; use metadata::ComponentMetadata; use registry::{PackageDependencyResolution, PackageResolutionMap}; @@ -44,6 +45,7 @@ mod bindings; pub mod commands; pub mod config; mod generator; +mod git; mod lock; mod metadata; mod registry; @@ -971,12 +973,14 @@ fn componentize( .validate(true); let package = &cargo_metadata[&artifact.package_id]; - let component = add_component_metadata(&package, &encoder.encode()?).with_context(|| { - format!( - "failed to add metadata to output component `{path}`", - path = path.display() - ) - })?; + let git = GitMetadata::from_package(package)?; + let component = add_component_metadata(package, git.as_ref(), &encoder.encode()?) + .with_context(|| { + format!( + "failed to add metadata to output component `{path}`", + path = path.display() + ) + })?; // To make the write atomic, first write to a temp file and then rename the file let temp_dir = cargo_metadata.target_directory.join("tmp"); @@ -1021,7 +1025,11 @@ pub struct PublishOptions<'a> { } /// Read metadata from `Cargo.toml` and add it to the component -fn add_component_metadata(package: &Package, wasm: &[u8]) -> Result> { +fn add_component_metadata( + package: &Package, + git: Option<&GitMetadata>, + wasm: &[u8], +) -> Result> { let metadata = wasm_metadata::AddMetadata { name: Some(package.name.clone()), language: vec![("Rust".to_string(), "".to_string())], @@ -1055,8 +1063,7 @@ fn add_component_metadata(package: &Package, wasm: &[u8]) -> Result> { .as_ref() .map(|s| wasm_metadata::Homepage::new(s.to_string().as_str())) .transpose()?, - // TODO: get the git commit hash - revision: None, + revision: git.map(|git| wasm_metadata::Revision::new(git.commit().to_string())), version: Some(wasm_metadata::Version::new(package.version.to_string())), }; metadata.to_wasm(wasm)