MCPcopy Create free account
hub / github.com/bootc-dev/bootc / upgrade

Function upgrade

crates/lib/src/cli.rs:1154–1366  ·  view source on GitHub ↗
(
    opts: UpgradeOpts,
    storage: &Storage,
    booted_ostree: &BootedOstree<'_>,
)

Source from the content-addressed store, hash-verified

1152/// Implementation of the `bootc upgrade` CLI command.
1153#[context("Upgrading")]
1154async 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

Callers 1

run_from_optFunction · 0.85

Calls 15

get_statusFunction · 0.85
new_importerFunction · 0.85
check_bootc_labelFunction · 0.85
pull_unifiedFunction · 0.85
pullFunction · 0.85
stageFunction · 0.85
with_tagMethod · 0.80
query_imageMethod · 0.80
get_ostreeMethod · 0.80
change_finalizationMethod · 0.80

Tested by

no test coverage detected