blob: 24a734b6f9608294ed798efa3419576b63016529 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::subpackage_blobs_package::construct_subpackage_blobs_package;
use anyhow::{Context, Result};
use assembly_manifest::{AssemblyManifest, PackagesMetadata};
use assembly_partitions_config::PartitionsConfig;
use assembly_tool::SdkToolProvider;
use assembly_update_package::{Slot, UpdatePackageBuilder};
use assembly_update_packages_manifest::UpdatePackagesManifest;
use epoch::EpochFile;
use ffx_assembly_args::CreateUpdateArgs;
use fuchsia_pkg::PackageManifest;
use fuchsia_url::RepositoryUrl;
use std::collections::BTreeSet;
use std::fs::File;
pub fn create_update(args: CreateUpdateArgs) -> Result<()> {
let mut file = File::open(&args.partitions)
.with_context(|| format!("Failed to open: {}", args.partitions))?;
let partitions = PartitionsConfig::from_reader(&mut file)
.context("Failed to parse the partitions config")?;
let epoch: EpochFile = EpochFile::Version1 { epoch: args.epoch };
let system_a_manifest =
args.system_a.as_ref().map(AssemblyManifest::try_load_from).transpose()?;
let subpackage_blobs_package = if let Some(manifest) = &system_a_manifest {
Some(construct_subpackage_blobs_package(
manifest,
&args.outdir,
if let Some(gendir) = &args.gendir { gendir } else { &args.outdir },
&args.subpackage_blobs_package_name,
)?)
} else {
None
};
let mut builder = UpdatePackageBuilder::new(
partitions,
args.board_name,
args.version_file,
epoch,
&args.outdir,
);
// Set the package name.
// Typically used for OTA tests.
if let Some(name) = args.update_package_name {
builder.set_name(name);
}
// Use the provided repo for the update images packages if necessary.
if let Some(default_repo) = &args.rewrite_default_repo {
let default_repo = RepositoryUrl::parse_host(default_repo.clone())?;
builder.set_repository(default_repo);
}
// Add the packages to update.
if let Some(manifest) = &system_a_manifest {
let mut packages = create_update_packages_manifest(manifest)?;
// Inject the subpackage blobs package into the update package.
if let Some(subpackage_blobs_package) = &subpackage_blobs_package {
packages.add_by_manifest(&subpackage_blobs_package.manifest)?;
};
// Rewrite all the package URLs to use this repo as the repository.
if let Some(default_repo) = &args.rewrite_default_repo {
let default_repo = RepositoryUrl::parse_host(default_repo.clone())?;
packages.set_repository(default_repo);
}
builder.add_packages(packages);
}
// Set the gendir separate from the outdir.
if let Some(gendir) = args.gendir {
builder.set_gendir(gendir);
}
// Set the images to update in the primary slot.
if let Some(manifest) = system_a_manifest {
builder.add_slot_images(Slot::Primary(manifest));
}
// Set the images to update in the recovery slot.
if let Some(manifest) =
args.system_r.as_ref().map(AssemblyManifest::try_load_from).transpose()?
{
builder.add_slot_images(Slot::Recovery(manifest));
}
let tools = SdkToolProvider::try_new()?;
builder.build(Box::new(tools))?;
Ok(())
}
fn create_update_packages_manifest(
assembly_manifest: &AssemblyManifest,
) -> Result<UpdatePackagesManifest> {
let mut packages_manifest = UpdatePackagesManifest::V1(BTreeSet::new());
for image in &assembly_manifest.images {
if let Some(contents) = image.get_blobfs_contents() {
let PackagesMetadata { base, cache } = &contents.packages;
for package in base.0.iter().chain(cache.0.iter()) {
let manifest = PackageManifest::try_load_from(&package.manifest)?;
packages_manifest.add_by_manifest(&manifest)?;
}
}
}
Ok(packages_manifest)
}