(
targets: &[Box<dyn MigrationTarget>],
resolver: &mut dyn AmbiguityResolver,
)
| 83 | |
| 84 | #[expect(clippy::result_large_err)] |
| 85 | pub fn migrate_targets( |
| 86 | targets: &[Box<dyn MigrationTarget>], |
| 87 | resolver: &mut dyn AmbiguityResolver, |
| 88 | ) -> Result<MigrationReport, MigrationOrchestratorError> { |
| 89 | let to_version = ConfigVersion::current(); |
| 90 | let mut pending = Vec::new(); |
| 91 | |
| 92 | for target in targets { |
| 93 | let path = target.path().to_path_buf(); |
| 94 | let target_name = target.name().to_string(); |
| 95 | let original = |
| 96 | fs::read_to_string(&path).map_err(|source| MigrationOrchestratorError::ReadFile { |
| 97 | path: path.clone(), |
| 98 | source, |
| 99 | })?; |
| 100 | let detected = target.detect_version(&original).map_err(|source| { |
| 101 | MigrationOrchestratorError::DetectVersion { |
| 102 | target: target_name.clone(), |
| 103 | source, |
| 104 | } |
| 105 | })?; |
| 106 | let from_version = detected.unwrap_or_else(ConfigVersion::legacy_baseline); |
| 107 | let output = target |
| 108 | .migrate(&original, &from_version, &to_version, resolver) |
| 109 | .map_err(|source| MigrationOrchestratorError::MigrateTarget { |
| 110 | target: target_name.clone(), |
| 111 | source, |
| 112 | })?; |
| 113 | |
| 114 | target.validate(&output.content).map_err(|source| { |
| 115 | MigrationOrchestratorError::ValidateTarget { |
| 116 | target: target_name.clone(), |
| 117 | source, |
| 118 | } |
| 119 | })?; |
| 120 | |
| 121 | pending.push(PendingMigration { |
| 122 | target_name, |
| 123 | path, |
| 124 | from_version, |
| 125 | to_version: to_version.clone(), |
| 126 | changed: output.content != original, |
| 127 | output, |
| 128 | backup_path: None, |
| 129 | }); |
| 130 | } |
| 131 | |
| 132 | let mut written = Vec::<(PathBuf, PathBuf)>::new(); |
| 133 | |
| 134 | for entry in &mut pending { |
| 135 | if !entry.changed { |
| 136 | continue; |
| 137 | } |
| 138 | |
| 139 | let backup_path = next_backup_path(&entry.path); |
| 140 | fs::copy(&entry.path, &backup_path).map_err(|source| { |
| 141 | MigrationOrchestratorError::BackupFile { |
| 142 | path: entry.path.clone(), |
no test coverage detected