(
opts: UpgradeOpts,
storage: &Storage,
booted_ostree: &BootedOstree<'_>,
)
| 1152 | /// Implementation of the `bootc upgrade` CLI command. |
| 1153 | #[context("Upgrading")] |
| 1154 | async fn upgrade( |
| 1155 | opts: UpgradeOpts, |
| 1156 | storage: &Storage, |
| 1157 | booted_ostree: &BootedOstree<'_>, |
| 1158 | ) -> Result<()> { |
| 1159 | let repo = &booted_ostree.repo(); |
| 1160 | |
| 1161 | let host = crate::status::get_status(booted_ostree)?.1; |
| 1162 | let current_image = host.spec.image.as_ref(); |
| 1163 | |
| 1164 | // Handle --tag: derive target from current image + new tag |
| 1165 | let derived_image = if let Some(ref tag) = opts.tag { |
| 1166 | let image = current_image.ok_or_else(|| { |
| 1167 | anyhow::anyhow!("--tag requires a booted image with a specified source") |
| 1168 | })?; |
| 1169 | Some(image.with_tag(tag)?) |
| 1170 | } else { |
| 1171 | None |
| 1172 | }; |
| 1173 | |
| 1174 | let imgref = derived_image.as_ref().or(current_image); |
| 1175 | let prog: ProgressWriter = opts.progress.try_into()?; |
| 1176 | |
| 1177 | // If there's no specified image, let's be nice and check if the booted system is using rpm-ostree |
| 1178 | if imgref.is_none() { |
| 1179 | let booted_incompatible = host.status.booted.as_ref().is_some_and(|b| b.incompatible); |
| 1180 | |
| 1181 | let staged_incompatible = host.status.staged.as_ref().is_some_and(|b| b.incompatible); |
| 1182 | |
| 1183 | if booted_incompatible || staged_incompatible { |
| 1184 | return Err(anyhow::anyhow!( |
| 1185 | "Deployment contains local rpm-ostree modifications; cannot upgrade via bootc. You can run `rpm-ostree reset` to undo the modifications." |
| 1186 | )); |
| 1187 | } |
| 1188 | } |
| 1189 | |
| 1190 | let imgref = imgref.ok_or_else(|| anyhow::anyhow!("No image source specified"))?; |
| 1191 | // Use the derived image reference (if --tag was specified) instead of the spec's image |
| 1192 | let spec = RequiredHostSpec { image: imgref }; |
| 1193 | let booted_image = host |
| 1194 | .status |
| 1195 | .booted |
| 1196 | .as_ref() |
| 1197 | .map(|b| b.query_image(repo)) |
| 1198 | .transpose()? |
| 1199 | .flatten(); |
| 1200 | // Find the currently queued digest, if any before we pull |
| 1201 | let staged = host.status.staged.as_ref(); |
| 1202 | let staged_image = staged.as_ref().and_then(|s| s.image.as_ref()); |
| 1203 | let mut changed = false; |
| 1204 | |
| 1205 | // Handle --from-downloaded: unlock existing staged deployment without fetching from image source |
| 1206 | if opts.from_downloaded { |
| 1207 | let ostree = storage.get_ostree()?; |
| 1208 | let staged_deployment = ostree |
| 1209 | .staged_deployment() |
| 1210 | .ok_or_else(|| anyhow::anyhow!("No staged deployment found"))?; |
| 1211 |
no test coverage detected