use crate::changeset::ChangesetManager;
use crate::error::{UpgradeError, UpgradeResult};
use crate::types::VersionBump;
use std::collections::HashSet;
use std::path::Path;
use sublime_git_tools::Repo;
pub async fn create_changeset_for_upgrades<S>(
changeset_manager: &ChangesetManager<S>,
affected_packages: HashSet<String>,
workspace_root: &Path,
bump_type_str: &str,
) -> UpgradeResult<Option<String>>
where
S: crate::changeset::ChangesetStorage + Send + Sync,
{
if affected_packages.is_empty() {
return Ok(None);
}
let bump =
VersionBump::parse(bump_type_str).map_err(|e| UpgradeError::ChangesetCreationFailed {
reason: format!("Invalid bump type '{}': {}", bump_type_str, e),
})?;
let branch_name = match get_current_branch(workspace_root) {
Ok(branch) => branch,
Err(e) => {
eprintln!("Warning: Could not determine current git branch: {}", e);
return Ok(None);
}
};
let package_list: Vec<String> = affected_packages.into_iter().collect();
let changeset_exists = changeset_manager
.storage()
.exists(&branch_name)
.await
.map_err(|e| UpgradeError::ChangesetCreationFailed { reason: e.to_string() })?;
if changeset_exists {
update_existing_changeset(changeset_manager, &branch_name, package_list).await?;
} else {
create_new_changeset(changeset_manager, &branch_name, bump, package_list).await?;
}
Ok(Some(branch_name))
}
async fn create_new_changeset<S>(
changeset_manager: &ChangesetManager<S>,
branch_name: &str,
bump: VersionBump,
packages: Vec<String>,
) -> UpgradeResult<()>
where
S: crate::changeset::ChangesetStorage + Send + Sync,
{
let mut changeset = changeset_manager
.create(branch_name, bump, vec![])
.await
.map_err(|e| UpgradeError::ChangesetCreationFailed { reason: e.to_string() })?;
let mut sorted_packages = packages;
sorted_packages.sort();
changeset.packages = sorted_packages;
changeset_manager
.storage()
.save(&changeset)
.await
.map_err(|e| UpgradeError::ChangesetCreationFailed { reason: e.to_string() })?;
Ok(())
}
async fn update_existing_changeset<S>(
changeset_manager: &ChangesetManager<S>,
branch_name: &str,
new_packages: Vec<String>,
) -> UpgradeResult<()>
where
S: crate::changeset::ChangesetStorage + Send + Sync,
{
let mut changeset = changeset_manager
.load(branch_name)
.await
.map_err(|e| UpgradeError::ChangesetCreationFailed { reason: e.to_string() })?;
let mut existing_packages: HashSet<String> = changeset.packages.into_iter().collect();
for package in new_packages {
existing_packages.insert(package);
}
changeset.packages = existing_packages.into_iter().collect();
changeset.packages.sort();
changeset.updated_at = chrono::Utc::now();
changeset_manager
.storage()
.save(&changeset)
.await
.map_err(|e| UpgradeError::ChangesetCreationFailed { reason: e.to_string() })?;
Ok(())
}
fn get_current_branch(workspace_root: &Path) -> UpgradeResult<String> {
let workspace_str = workspace_root.to_str().ok_or_else(|| {
UpgradeError::ChangesetCreationFailed { reason: "Invalid workspace path".to_string() }
})?;
let repo = Repo::open(workspace_str).map_err(|e| UpgradeError::ChangesetCreationFailed {
reason: format!("Failed to open git repository: {}", e),
})?;
let branch = repo.get_current_branch().map_err(|e| UpgradeError::ChangesetCreationFailed {
reason: format!("Failed to get current branch: {}", e),
})?;
Ok(branch)
}