blob: 53e4a58476319ad9a6bb5931b40b119d38d176b5 [file] [log] [blame] [edit]
// 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.
use std::path::{Path, PathBuf};
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
pub struct Opt {
#[structopt(short = "s", long = "stamp", parse(from_os_str))]
/// Stamp this file on success
pub stamp: Option<PathBuf>,
#[structopt(subcommand)]
pub cmd: Commands,
}
#[derive(StructOpt, Debug)]
pub enum Commands {
#[structopt(name = "validate")]
/// validate that one or more cmx files are valid
Validate {
#[structopt(name = "FILE", parse(from_os_str))]
/// files to process
files: Vec<PathBuf>,
#[structopt(long = "extra_schema", parse(from_str = "parse_extra_schema_arg"))]
/// extra JSON schema files to additionally validate against. A custom error message - to
/// be displayed if the schema fails to validate - can be specified by adding a ':'
/// separator and the message after the path.
extra_schemas: Vec<(PathBuf, Option<String>)>,
},
#[structopt(name = "merge")]
/// merge the listed cmx files
Merge {
#[structopt(name = "FILE", parse(from_os_str))]
/// files to process
///
/// If any file contains an array at its root, every object in the array
/// will be merged into the final object.
files: Vec<PathBuf>,
#[structopt(short = "o", long = "output", parse(from_os_str))]
/// file to write the merged results to, will print to stdout if not provided
output: Option<PathBuf>,
#[structopt(short = "f", long = "fromfile", parse(from_os_str))]
/// response file for files to process
///
/// If specified, additional files to merge will be read from the path provided.
/// The input format is delimited by newlines.
fromfile: Option<PathBuf>,
},
#[structopt(name = "include")]
/// add contents from includes if any
Include {
#[structopt(name = "FILE", parse(from_os_str))]
/// file to process
file: PathBuf,
#[structopt(short = "o", long = "output", parse(from_os_str))]
/// file to write the merged results to, will print to stdout if not provided
output: Option<PathBuf>,
#[structopt(short = "d", long = "depfile", parse(from_os_str))]
/// depfile for includes
///
/// If specified, include paths will be listed here, delimited by newlines.
depfile: Option<PathBuf>,
#[structopt(short = "i", long = "includepath", parse(from_os_str))]
/// base path for resolving includes
includepath: PathBuf,
},
#[structopt(name = "check-includes")]
/// check if given includes are present in a given component manifest
CheckIncludes {
#[structopt(name = "FILE", parse(from_os_str))]
/// file to process
file: PathBuf,
#[structopt(name = "expect")]
expected_includes: Vec<String>,
#[structopt(short = "f", long = "fromfile", parse(from_os_str))]
/// response file for includes to expect
///
/// If specified, additional includes to expect will be read from the path provided.
/// The input format is delimited by newlines.
fromfile: Option<PathBuf>,
#[structopt(short = "i", long = "includepath", parse(from_os_str))]
/// base path for resolving includes
includepath: PathBuf,
},
#[structopt(name = "format")]
/// format a json file
Format {
#[structopt(name = "FILE", parse(from_os_str))]
/// file to format
file: PathBuf,
#[structopt(short = "p", long = "pretty")]
/// whether to pretty-print the results (otherwise minify JSON documents; ignored for JSON5)
pretty: bool,
#[structopt(long = "cml")]
/// interpret input file as JSON5 CML, and output in the preferred style, preserving all
/// comments (this is the default for `.cml` files; implies `--pretty`)
cml: bool,
#[structopt(short = "i", long = "in-place")]
/// replace the input file with the formatted output (implies `--output <inputfile>`)
inplace: bool,
#[structopt(short = "o", long = "output", parse(from_os_str))]
/// file to write the formatted results to, will print to stdout if not provided
output: Option<PathBuf>,
},
#[structopt(name = "compile")]
/// compile a CML file
Compile {
#[structopt(name = "FILE", parse(from_os_str))]
/// file to format
file: PathBuf,
#[structopt(short = "o", long = "output", parse(from_os_str))]
/// file to write the formatted results to, will print to stdout if not provided
output: Option<PathBuf>,
#[structopt(short = "d", long = "depfile", parse(from_os_str))]
/// depfile for includes
///
/// If specified, include paths will be listed here, delimited by newlines.
depfile: Option<PathBuf>,
#[structopt(short = "i", long = "includepath", parse(from_os_str))]
/// base path for resolving includes
includepath: PathBuf,
},
}
fn parse_extra_schema_arg(src: &str) -> (PathBuf, Option<String>) {
let v: Vec<&str> = src.splitn(2, ':').collect();
(Path::new(v[0]).to_path_buf(), v.get(1).map(|s| s.to_string()))
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! test_parse_extra_schema_arg {
(
$(
$test_name:ident => {
input = $input:expr,
result = $result:expr,
},
)+
) => {
$(
#[test]
fn $test_name() {
assert_eq!(parse_extra_schema_arg($input), $result)
}
)+
}
}
test_parse_extra_schema_arg! {
test_parse_extra_schema_arg_schema_only => {
input = "/some/path",
result = (Path::new("/some/path").to_path_buf(), None),
},
test_parse_extra_schema_arg_schema_and_msg => {
input = "/some/path:my error message",
result = (Path::new("/some/path").to_path_buf(), Some("my error message".to_string())),
},
test_parse_extra_schema_arg_msg_with_sep => {
input = "/some/path:my:error:message",
result = (Path::new("/some/path").to_path_buf(), Some("my:error:message".to_string())),
},
}
}