use std::path::PathBuf;
use anyhow::Result;
use crate::parsers::parse_sbom;
use crate::pipeline::exit_codes;
use crate::serialization::emit::{self, EmitError, EmitTarget};
pub fn run_convert(
file: &PathBuf,
target: &str,
output_file: Option<&PathBuf>,
preserve: bool,
quiet: bool,
) -> Result<i32> {
let Some(emit_target) = EmitTarget::parse(target) else {
eprintln!("error: unknown conversion target '{target}'. Supported: cyclonedx, spdx.");
return Ok(exit_codes::ERROR);
};
let raw_json = std::fs::read_to_string(file)?;
let mut sbom = parse_sbom(file)?;
if preserve {
emit::preserve_source_json(&raw_json, &mut sbom);
}
let (output, report) = match emit::emit(&sbom, emit_target) {
Ok(result) => result,
Err(EmitError::Unsupported(fmt)) => {
eprintln!("error: emitting to {fmt} is not yet implemented.");
return Ok(exit_codes::ERROR);
}
Err(e) => return Err(e.into()),
};
if !quiet {
eprint!("{}", report.render());
if report.is_lossy() {
eprintln!(
" Note: conversion is lossy ({} field type(s) dropped). Re-run with --preserve to retain format-specific blocks where possible.",
report.dropped_count()
);
}
}
match output_file {
Some(path) => {
std::fs::write(path, &output)?;
if !quiet {
eprintln!("Converted SBOM written to {}", path.display());
}
}
None => {
println!("{output}");
}
}
Ok(exit_codes::SUCCESS)
}