| // Copyright 2018 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. |
| |
| #![warn(missing_docs)] |
| // TODO(fxb/87635): Fix this. |
| // This crate doesn't comply with all 2018 idioms |
| #![allow(elided_lifetimes_in_paths)] |
| |
| //! `cmc` is the Component Manifest Compiler. |
| |
| use anyhow::{ensure, Error}; |
| pub use cml::{self, error, one_or_many, translate, Document}; |
| use reference_doc::MarkdownReferenceDocGenerator; |
| use std::fs; |
| use std::path::{Path, PathBuf}; |
| use structopt::StructOpt; |
| |
| #[allow(unused)] // A test-only macro is defined on all builds. |
| mod compile; |
| mod features; |
| mod format; |
| mod include; |
| mod merge; |
| mod opts; |
| mod reference; |
| mod util; |
| mod validate; |
| |
| fn main() -> Result<(), Error> { |
| run_cmc() |
| } |
| |
| fn path_exists(path: &Path) -> Result<(), Error> { |
| ensure!(path.exists(), "{:?} does not exist", path); |
| Ok(()) |
| } |
| |
| fn optional_path_exists(optional_path: Option<&PathBuf>) -> Result<(), Error> { |
| if let Some(path) = optional_path.as_ref() { |
| ensure!(path.exists(), "{:?} does not exist", path); |
| } |
| Ok(()) |
| } |
| |
| fn run_cmc() -> Result<(), Error> { |
| let opt = opts::Opt::from_args(); |
| match opt.cmd { |
| opts::Commands::Validate { files, extra_schemas } => { |
| validate::validate(&files, &extra_schemas, &features::FeatureSet::empty())? |
| } |
| opts::Commands::ValidateReferences { component_manifest, package_manifest, gn_label } => { |
| reference::validate(&component_manifest, &package_manifest, gn_label.as_ref())? |
| } |
| opts::Commands::Merge { files, output, fromfile, depfile } => { |
| merge::merge(files, output, fromfile, depfile)? |
| } |
| opts::Commands::Include { file, output, depfile, includepath, includeroot } => { |
| path_exists(&file)?; |
| include::merge_includes( |
| &file, |
| output.as_ref(), |
| depfile.as_ref(), |
| &includepath, |
| &includeroot, |
| )? |
| } |
| opts::Commands::CheckIncludes { |
| file, |
| expected_includes, |
| fromfile, |
| depfile, |
| includepath, |
| includeroot, |
| } => { |
| path_exists(&file)?; |
| optional_path_exists(fromfile.as_ref())?; |
| include::check_includes( |
| &file, |
| expected_includes, |
| fromfile.as_ref(), |
| depfile.as_ref(), |
| opt.stamp.as_ref(), |
| &includepath, |
| &includeroot, |
| )? |
| } |
| opts::Commands::Format { file, pretty, cml, inplace, mut output } => { |
| path_exists(&file)?; |
| if inplace { |
| output = Some(file.clone()); |
| } |
| format::format(&file, pretty, cml, output)?; |
| } |
| opts::Commands::Compile { |
| file, |
| output, |
| depfile, |
| includepath, |
| includeroot, |
| config_package_path, |
| features, |
| experimental_force_runner, |
| } => { |
| path_exists(&file)?; |
| compile::compile( |
| &file, |
| &output.unwrap(), |
| depfile, |
| &includepath, |
| &includeroot, |
| config_package_path.as_ref().map(String::as_str), |
| &features.into(), |
| &experimental_force_runner, |
| )? |
| } |
| opts::Commands::PrintReferenceDocs { output } => { |
| let docs = Document::get_reference_doc_markdown(); |
| match &output { |
| None => println!("{}", docs), |
| Some(path) => fs::write(path, docs)?, |
| } |
| } |
| } |
| if let Some(stamp_path) = opt.stamp { |
| stamp(stamp_path)?; |
| } |
| Ok(()) |
| } |
| |
| fn stamp(stamp_path: PathBuf) -> Result<(), Error> { |
| fs::File::create(stamp_path)?; |
| Ok(()) |
| } |