use std::{collections::HashMap, path::Path};
use crate::{
config::{
package::{DEFAULT_TAG_PREFIX, PackageConfig, SubPackage},
prerelease::PrereleaseConfig,
},
error::Result,
orchestrator::config::{GlobalOverrides, PackageOverrides},
};
pub fn resolve_package_name(
package: &PackageConfig,
repo_name: &str,
) -> String {
if !package.name.is_empty() {
return package.name.clone();
}
Path::new(&package.workspace_root)
.join(&package.path)
.file_name()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or_else(|| repo_name.to_string())
}
pub fn resolve_sub_package_name(
package: &SubPackage,
workspace_root: &str,
repo_name: &str,
) -> String {
if !package.name.is_empty() {
return package.name.clone();
}
Path::new(workspace_root)
.join(&package.path)
.file_name()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or_else(|| repo_name.to_string())
}
pub fn resolve_tag_prefix(
resolved_name: &str,
package: &PackageConfig,
package_overrides: &HashMap<String, PackageOverrides>,
global_overrides: &GlobalOverrides,
) -> String {
if let Some(overrides) = package_overrides.get(resolved_name)
&& let Some(prefix) = overrides.tag_prefix.as_ref()
{
return prefix.clone();
}
if let Some(prefix) = global_overrides.tag_prefix.as_ref() {
return prefix.clone();
}
if let Some(prefix) = package.tag_prefix.as_ref() {
return prefix.clone();
}
if package.workspace_root != "." || package.path != "." {
format!("{}-v", resolved_name)
} else {
DEFAULT_TAG_PREFIX.to_string()
}
}
pub fn resolve_auto_start_next(
package: &PackageConfig,
global_auto_start_next: Option<bool>,
) -> bool {
package
.auto_start_next
.or(global_auto_start_next)
.unwrap_or_default()
}
pub fn resolve_prerelease(
package: &PackageConfig,
global_prerelease: &PrereleaseConfig,
global_overrides: &GlobalOverrides,
package_overrides: &HashMap<String, PackageOverrides>,
) -> Result<Option<PrereleaseConfig>> {
let mut prerelease = global_prerelease.clone();
if let Some(pkg_prerelease) = package.prerelease.clone() {
prerelease = pkg_prerelease;
}
if let Some(ref suffix) = global_overrides.prerelease_suffix {
prerelease.suffix = Some(suffix.clone());
}
if let Some(strategy) = global_overrides.prerelease_strategy {
prerelease.strategy = strategy;
}
if let Some(overrides) = package_overrides.get(&package.name) {
if let Some(ref suffix) = overrides.prerelease_suffix {
prerelease.suffix = Some(suffix.clone());
}
if let Some(strategy) = overrides.prerelease_strategy {
prerelease.strategy = strategy;
}
}
prerelease.suffix = prerelease
.suffix
.as_ref()
.map(|value| value.trim().to_string())
.filter(|value| !value.is_empty());
if prerelease.suffix.is_some() {
Ok(Some(prerelease))
} else {
Ok(None)
}
}
pub fn resolve_version_increment_flags(
package: &PackageConfig,
global_breaking: bool,
global_features: bool,
) -> (bool, bool) {
let breaking = package
.breaking_always_increment_major
.unwrap_or(global_breaking);
let features = package
.features_always_increment_minor
.unwrap_or(global_features);
(breaking, features)
}
pub fn resolve_custom_increment_regexes(
package: &PackageConfig,
global_custom_major: &Option<String>,
global_custom_minor: &Option<String>,
) -> (Option<String>, Option<String>) {
let major = package
.custom_major_increment_regex
.clone()
.or_else(|| global_custom_major.clone());
let minor = package
.custom_minor_increment_regex
.clone()
.or_else(|| global_custom_minor.clone());
(major, minor)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::prerelease::PrereleaseStrategy;
fn create_test_package(name: &str) -> PackageConfig {
PackageConfig {
name: name.to_string(),
workspace_root: ".".to_string(),
path: ".".to_string(),
..Default::default()
}
}
#[test]
fn resolve_package_name_uses_config_when_set() {
let pkg = create_test_package("my-package");
let name = resolve_package_name(&pkg, "repo");
assert_eq!(name, "my-package");
}
#[test]
fn resolve_package_name_derives_from_path() {
let mut pkg = create_test_package("");
pkg.path = "packages/api".to_string();
let name = resolve_package_name(&pkg, "repo");
assert_eq!(name, "api");
}
#[test]
fn resolve_package_name_fallback_to_repo() {
let pkg = create_test_package("");
let name = resolve_package_name(&pkg, "fallback-repo");
assert_eq!(name, "fallback-repo");
}
#[test]
fn resolve_tag_prefix_uses_explicit_config() {
let mut pkg = create_test_package("test");
pkg.tag_prefix = Some("custom-v".to_string());
let resolved_name = pkg.name.clone();
let package_overrides = HashMap::new();
let global_overrides = GlobalOverrides::default();
assert_eq!(
resolve_tag_prefix(
&resolved_name,
&pkg,
&package_overrides,
&global_overrides
),
"custom-v"
);
}
#[test]
fn resolve_tag_prefix_uses_package_name_when_not_root() {
let mut pkg = create_test_package("api");
pkg.path = "packages/api".to_string();
let resolved_name = pkg.name.clone();
let package_overrides = HashMap::new();
let global_overrides = GlobalOverrides::default();
assert_eq!(
resolve_tag_prefix(
&resolved_name,
&pkg,
&package_overrides,
&global_overrides
),
"api-v"
);
}
#[test]
fn resolve_tag_prefix_uses_default_at_root() {
let pkg = create_test_package("test");
let resolved_name = pkg.name.clone();
let package_overrides = HashMap::new();
let global_overrides = GlobalOverrides::default();
assert_eq!(
resolve_tag_prefix(
&resolved_name,
&pkg,
&package_overrides,
&global_overrides
),
"v"
);
}
#[test]
fn resolve_tag_prefix_package_override_takes_precedence() {
let mut pkg = create_test_package("my-pkg");
pkg.tag_prefix = Some("config-v".to_string());
let mut package_overrides = HashMap::new();
package_overrides.insert(
"my-pkg".to_string(),
PackageOverrides {
tag_prefix: Some("cli-v".to_string()),
prerelease_suffix: None,
prerelease_strategy: None,
},
);
let global_overrides = GlobalOverrides {
tag_prefix: Some("global-v".to_string()),
..GlobalOverrides::default()
};
assert_eq!(
resolve_tag_prefix(
"my-pkg",
&pkg,
&package_overrides,
&global_overrides
),
"cli-v"
);
}
#[test]
fn resolve_tag_prefix_global_override_over_config() {
let mut pkg = create_test_package("my-pkg");
pkg.tag_prefix = Some("config-v".to_string());
let package_overrides = HashMap::new();
let global_overrides = GlobalOverrides {
tag_prefix: Some("global-v".to_string()),
..GlobalOverrides::default()
};
assert_eq!(
resolve_tag_prefix(
"my-pkg",
&pkg,
&package_overrides,
&global_overrides
),
"global-v"
);
}
#[test]
fn resolve_auto_start_next_precedence() {
let mut pkg = create_test_package("test");
pkg.auto_start_next = Some(true);
assert!(resolve_auto_start_next(&pkg, Some(false)));
pkg.auto_start_next = None;
assert!(resolve_auto_start_next(&pkg, Some(true)));
assert!(!resolve_auto_start_next(&pkg, None));
}
#[test]
fn resolve_prerelease_returns_none_without_suffix() {
let pkg = create_test_package("test");
let global = PrereleaseConfig::default();
let global_overrides = GlobalOverrides::default();
let package_overrides = HashMap::new();
let result = resolve_prerelease(
&pkg,
&global,
&global_overrides,
&package_overrides,
)
.unwrap();
assert!(result.is_none());
}
#[test]
fn resolve_prerelease_with_global_suffix() {
let pkg = create_test_package("test");
let global = PrereleaseConfig {
suffix: Some("beta".to_string()),
strategy: PrereleaseStrategy::Versioned,
};
let global_overrides = GlobalOverrides::default();
let package_overrides = HashMap::new();
let result = resolve_prerelease(
&pkg,
&global,
&global_overrides,
&package_overrides,
)
.unwrap()
.unwrap();
assert_eq!(result.suffix, Some("beta".to_string()));
}
#[test]
fn resolve_version_increment_flags_uses_package_config() {
let mut pkg = create_test_package("test");
pkg.breaking_always_increment_major = Some(false);
pkg.features_always_increment_minor = Some(false);
let (breaking, features) =
resolve_version_increment_flags(&pkg, true, true);
assert!(!breaking);
assert!(!features);
}
#[test]
fn resolve_version_increment_flags_uses_global_defaults() {
let pkg = create_test_package("test");
let (breaking, features) =
resolve_version_increment_flags(&pkg, true, false);
assert!(breaking);
assert!(!features);
}
}