diff --git a/Cargo.lock b/Cargo.lock index fe90702..c0e34eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,6 +304,7 @@ dependencies = [ "ar", "async-compression", "bon", + "buildpacks-deb-packages", "bullet_stream", "debversion", "edit-distance", diff --git a/Cargo.toml b/Cargo.toml index 1e53b51..e6b1c7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ libcnb-test = "=0.26.0" regex = "1" strip-ansi-escapes = "0.2" tempfile = "3" +buildpacks-deb-packages = { path = "." } [lints.rust] unreachable_pub = "warn" diff --git a/project.toml b/project.toml new file mode 100644 index 0000000..90eb617 --- /dev/null +++ b/project.toml @@ -0,0 +1,7 @@ +[_] +schema-version = "0.2" + +[com.heroku.buildpacks.deb-packages] +install = [ + "git" +] \ No newline at end of file diff --git a/src/debian/multiarch_name.rs b/src/debian/multiarch_name.rs index b52244c..7143daf 100644 --- a/src/debian/multiarch_name.rs +++ b/src/debian/multiarch_name.rs @@ -1,6 +1,8 @@ use std::fmt::{Display, Formatter}; use crate::debian::ArchitectureName; +use std::str::FromStr; +// use std::fmt::{Display, Formatter}; #[derive(Debug, PartialEq, Clone)] #[allow(non_camel_case_types)] @@ -28,9 +30,32 @@ impl Display for MultiarchName { } } +impl FromStr for MultiarchName { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "x86_64-linux-gnu" => Ok(MultiarchName::X86_64_LINUX_GNU), + "aarch64-linux-gnu" => Ok(MultiarchName::AARCH_64_LINUX_GNU), + _ => Err(()), + } + } +} + #[cfg(test)] mod tests { use super::*; + use std::str::FromStr; + + #[test] + fn test_multiarch_name_from_str() { + // Test valid strings + assert_eq!(MultiarchName::from_str("x86_64-linux-gnu").unwrap(), MultiarchName::X86_64_LINUX_GNU); + assert_eq!(MultiarchName::from_str("aarch64-linux-gnu").unwrap(), MultiarchName::AARCH_64_LINUX_GNU); + + // Test invalid string + assert!(MultiarchName::from_str("invalid-arch").is_err()); + } #[test] fn converting_architecture_name_to_multiarch_name() { diff --git a/src/install_packages.rs b/src/install_packages.rs index 70c4b0d..c268369 100644 --- a/src/install_packages.rs +++ b/src/install_packages.rs @@ -134,6 +134,7 @@ pub(crate) async fn install_packages( } } + // Configure the environment variables for the installed layer let layer_env = configure_layer_environment( &install_layer.path(), &MultiarchName::from(&distro.architecture), @@ -313,6 +314,7 @@ async fn extract(download_path: PathBuf, output_dir: PathBuf) -> BuildpackResult Ok(()) } +// Modified function to include setting GIT_EXEC_PATH fn configure_layer_environment(install_path: &Path, multiarch_name: &MultiarchName) -> LayerEnv { let mut layer_env = LayerEnv::new(); @@ -323,8 +325,16 @@ fn configure_layer_environment(install_path: &Path, multiarch_name: &MultiarchNa ]; prepend_to_env_var(&mut layer_env, "PATH", &bin_paths); + // Set GIT_EXEC_PATH + let git_exec_path = install_path.join("usr/lib/git-core"); + layer_env.insert( + Scope::All, + ModificationBehavior::Override, + "GIT_EXEC_PATH", + git_exec_path.to_string_lossy().to_string(), + ); + // support multi-arch and legacy filesystem layouts for debian packages - // https://wiki.ubuntu.com/MultiarchSpec let library_paths = [ install_path.join(format!("usr/lib/{multiarch_name}")), install_path.join("usr/lib"), @@ -602,3 +612,25 @@ mod test { .unwrap_or_default() } } + +#[cfg(test)] +mod unit_tests { + use std::path::PathBuf; + use libcnb::layer_env::Scope; + use crate::install_packages::configure_layer_environment; + use crate::debian::MultiarchName; + use std::str::FromStr; + + #[test] + fn test_configure_layer_environment_sets_git_exec_path() { + let install_path = PathBuf::from("/mock/install/path"); + let multiarch_name = MultiarchName::from_str("x86_64-linux-gnu").unwrap(); + let layer_env = configure_layer_environment(&install_path, &multiarch_name); + + assert_eq!( + layer_env.apply_to_empty(Scope::All).get("GIT_EXEC_PATH").map(|s| s.to_string_lossy().into_owned()), + // layer_env.apply_to_empty(Scope::All).get("GIT_EXEC_PATH"), + Some("/mock/install/path/usr/lib/git-core".to_string()) + ); + } +} \ No newline at end of file diff --git a/tests/integration_test.rs b/tests/integration_test.rs index e16e345..e9e0f21 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -620,3 +620,47 @@ fn update_project_toml(app_dir: &Path, update_fn: impl FnOnce(&mut DocumentMut)) update_fn(&mut doc); std::fs::write(&project_toml, doc.to_string()).unwrap(); } + +#[test] +fn test_get_integration_test_builder() { + // Set environment variable + std::env::set_var("INTEGRATION_TEST_CNB_BUILDER", "heroku/builder:24"); + assert_eq!(get_integration_test_builder(), "heroku/builder:24"); + + // Unset environment variable + std::env::remove_var("INTEGRATION_TEST_CNB_BUILDER"); + assert_eq!(get_integration_test_builder(), DEFAULT_BUILDER); +} + +#[test] +fn test_get_integration_test_arch() { + // Set environment variable + std::env::set_var("INTEGRATION_TEST_CNB_ARCH", "arm64"); + assert_eq!(get_integration_test_arch(), "arm64"); + + // Unset environment variable + std::env::remove_var("INTEGRATION_TEST_CNB_ARCH"); + assert_eq!(get_integration_test_arch(), DEFAULT_ARCH); +} + +#[test] +fn test_panic_unsupported_test_configuration() { + // This test should panic + let result = std::panic::catch_unwind(|| { + panic_unsupported_test_configuration(); + }); + assert!(result.is_err()); +} + +#[test] +fn test_set_install_config() { + let temp_dir = tempfile::tempdir().unwrap(); + let app_dir = temp_dir.path(); + std::fs::write(app_dir.join("project.toml"), "[com.heroku.buildpacks.deb-packages]").unwrap(); + + set_install_config(app_dir, [requested_package_config("ffmpeg", true)]); + + let contents = std::fs::read_to_string(app_dir.join("project.toml")).unwrap(); + assert!(contents.contains("ffmpeg")); + assert!(contents.contains("skip_dependencies = true")); +} \ No newline at end of file