use std::path::Path;
use super::cli::Request as UpgradeRequest;
use super::plan::{self, UpgradeError};
use super::report::Report as UpgradeReport;
use crate::command::Command;
use crate::config::Config;
use crate::domain::action::upgrade::Action;
use crate::infra::github::Registry;
use crate::infra::lock::Error as LockFileError;
use crate::infra::manifest::Error as ManifestError;
use crate::infra::workflow_update::WorkflowWriter;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum RunError {
#[error(transparent)]
Github(#[from] crate::infra::github::Error),
#[error(transparent)]
Manifest(#[from] ManifestError),
#[error(transparent)]
Lock(#[from] LockFileError),
#[error(transparent)]
Upgrade(#[from] UpgradeError),
}
pub struct Upgrade {
pub request: UpgradeRequest,
}
impl Command for Upgrade {
type Report = UpgradeReport;
type Error = RunError;
fn run(
&self,
repo_root: &Path,
config: Config,
on_progress: &mut dyn FnMut(&str),
) -> Result<UpgradeReport, RunError> {
let has_manifest = config.manifest_path.exists();
let registry = Registry::new(config.settings.github_token)?;
let updater = WorkflowWriter::new(repo_root);
let upgrade_plan = plan::plan(
&config.manifest,
&config.lock,
®istry,
&self.request,
&mut *on_progress,
)?;
if upgrade_plan.is_empty() {
return Ok(UpgradeReport {
up_to_date: true,
..Default::default()
});
}
if has_manifest {
crate::infra::manifest::patch::apply_manifest_diff(
&config.manifest_path,
&upgrade_plan.manifest,
)?;
let lock_store = crate::infra::lock::Store::new(&config.lock_path);
lock_store.save(&upgrade_plan.lock)?;
}
let workflows_updated = plan::apply_upgrade_workflows(
&updater,
&upgrade_plan.lock_changes,
&upgrade_plan.upgrades,
)?;
if config.manifest_migrated {
on_progress("migrated gx.toml → semver specifiers");
}
let upgrades = upgrade_plan
.upgrades
.iter()
.map(|u| {
let from = u.current.to_string();
let to = match &u.action {
Action::InRange { candidate } => candidate.to_string(),
Action::CrossRange { new_specifier, .. } => new_specifier.to_string(),
};
(u.id.to_string(), from, to)
})
.collect();
let report = UpgradeReport {
upgrades,
workflows_updated,
up_to_date: false,
..Default::default()
};
Ok(report)
}
}