use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use super::output::StringOrVec;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct PublishConfig {
pub core_crate: Option<String>,
#[serde(default)]
pub languages: HashMap<String, PublishLanguageConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct PublishLanguageConfig {
pub precondition: Option<String>,
pub before: Option<StringOrVec>,
pub vendor_mode: Option<VendorMode>,
pub nif_versions: Option<Vec<String>>,
pub build_command: Option<StringOrVec>,
pub package_command: Option<StringOrVec>,
pub archive_format: Option<String>,
pub pkg_config: Option<bool>,
pub cmake_config: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
#[derive(Default)]
pub enum VendorMode {
CoreOnly,
Full,
#[default]
None,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn publish_config_deserializes_empty() {
let toml_str = "";
let cfg: PublishConfig = toml::from_str(toml_str).unwrap();
assert!(cfg.core_crate.is_none());
assert!(cfg.languages.is_empty());
}
#[test]
fn publish_config_deserializes_with_languages() {
let toml_str = r#"
core_crate = "crates/my-lib"
[languages.ruby]
vendor_mode = "core-only"
[languages.r]
vendor_mode = "full"
[languages.elixir]
vendor_mode = "core-only"
nif_versions = ["2.16", "2.17"]
[languages.c_ffi]
pkg_config = true
cmake_config = true
"#;
let cfg: PublishConfig = toml::from_str(toml_str).unwrap();
assert_eq!(cfg.core_crate.as_deref(), Some("crates/my-lib"));
let ruby = cfg.languages.get("ruby").unwrap();
assert_eq!(ruby.vendor_mode, Some(VendorMode::CoreOnly));
let r = cfg.languages.get("r").unwrap();
assert_eq!(r.vendor_mode, Some(VendorMode::Full));
let elixir = cfg.languages.get("elixir").unwrap();
assert_eq!(
elixir.nif_versions.as_deref(),
Some(&["2.16".to_string(), "2.17".to_string()][..])
);
let c_ffi = cfg.languages.get("c_ffi").unwrap();
assert_eq!(c_ffi.pkg_config, Some(true));
assert_eq!(c_ffi.cmake_config, Some(true));
}
#[test]
fn publish_language_config_with_commands() {
let toml_str = r#"
precondition = "which cargo"
before = ["step1", "step2"]
build_command = "cross build --release"
package_command = "custom-packager"
archive_format = "zip"
"#;
let cfg: PublishLanguageConfig = toml::from_str(toml_str).unwrap();
assert_eq!(cfg.precondition.as_deref(), Some("which cargo"));
assert_eq!(cfg.before.unwrap().commands(), vec!["step1", "step2"]);
assert_eq!(cfg.build_command.unwrap().commands(), vec!["cross build --release"]);
assert_eq!(cfg.package_command.unwrap().commands(), vec!["custom-packager"]);
assert_eq!(cfg.archive_format.as_deref(), Some("zip"));
}
#[test]
fn vendor_mode_kebab_case() {
assert_eq!(
serde_json::from_str::<VendorMode>(r#""core-only""#).unwrap(),
VendorMode::CoreOnly
);
assert_eq!(
serde_json::from_str::<VendorMode>(r#""full""#).unwrap(),
VendorMode::Full
);
assert_eq!(
serde_json::from_str::<VendorMode>(r#""none""#).unwrap(),
VendorMode::None
);
}
#[test]
fn publish_config_in_alef_config() {
let toml_str = r#"
languages = ["python", "ruby"]
[crate]
name = "test-lib"
sources = ["src/lib.rs"]
[publish]
core_crate = "crates/test-lib"
[publish.languages.ruby]
vendor_mode = "core-only"
"#;
let cfg: super::super::AlefConfig = toml::from_str(toml_str).unwrap();
let publish = cfg.publish.unwrap();
assert_eq!(publish.core_crate.as_deref(), Some("crates/test-lib"));
let ruby = publish.languages.get("ruby").unwrap();
assert_eq!(ruby.vendor_mode, Some(VendorMode::CoreOnly));
}
}