Skip to content

Commit

Permalink
Add an expandconfig utility to add default values
Browse files Browse the repository at this point in the history
This patch adds an `expandconfig` binary which is able to load a
configuration file, and write it back (in either TOML or YAML format)
with the default values expanded.  This is useful in a variety of
scenarios:

 - Check that a configuration file is valid with:

    expandconfig /path/to/config.toml

 - See default field values and structure with:

    expandconfig

 - See all available fields with (YAML displays fields with a default
   `None` value while TOML skips them):

    expandconfig -f yaml
  • Loading branch information
Elarnon committed Dec 1, 2018
1 parent 27cf90d commit 528a1fa
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ name = "bench-perf-model"
path = "tools/bench_perf_model/main.rs"
required-features = ["cuda"]

[[bin]]
name = "expandconfig"

[[bench]]
name = "descent"
harness = false
Expand Down Expand Up @@ -76,6 +79,7 @@ rpds = "0.5.0"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0.22"
serde_yaml = "0.8"
bincode = "1.0"
std-semaphore = "0.1.0"
tempfile = "3.0.1"
Expand Down
113 changes: 113 additions & 0 deletions src/bin/expandconfig.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
extern crate getopts;
extern crate serde_yaml;
extern crate toml;

extern crate telamon;

use std::env;
use std::io::{Read, Write};

use getopts::Options;

enum Format {
Toml,
Yaml,
}

/// Expand a configuration.
///
/// # Arguments
///
/// - input: Path to the input file to use. If `None`, the default configuration is loaded. If
/// "-", the configuration is read from the standard input.
///
/// - output: Path to the output file. If "-", the configuration is printed to the standard
/// output.
fn expand_config(input: Option<&str>, output: &str, format: Format) {
let input_str = input
.map(|input| {
let mut input_str = String::new();
match input {
"-" => {
let stdin = std::io::stdin();
stdin.lock().read_to_string(&mut input_str).unwrap();
}
_ => {
std::fs::File::open(input)
.unwrap()
.read_to_string(&mut input_str)
.unwrap();
}
};
input_str
}).unwrap_or_else(|| "".to_string());

let config: telamon::explorer::config::Config = toml::from_str(&input_str).unwrap();

let output_str = match format {
Format::Toml => toml::to_string(&config).unwrap(),
Format::Yaml => serde_yaml::to_string(&config).unwrap(),
};

match output {
"-" => print!("{}", output_str),
_ => {
write!(std::fs::File::create(output).unwrap(), "{}", output_str);
}
}
}

fn print_usage(program: &str, opts: Options) {
let brief = format!(
"Usage: {} PATH [options]
Loads an explorer configuration file and outputs it with the default values added. This can also
be used as a simple validator of an explorer configuration file by discarding the output.
",
program
);
print!("{}", opts.usage(&brief));
}

fn main() {
let args: Vec<String> = env::args().collect();
let program = args[0].clone();

let mut opts = Options::new();
opts.optflag("h", "help", "Prints help information");
opts.optopt("o", "output", "Path to the output file", "PATH");
opts.optopt("f", "format", "Output format", "[toml|yaml]");

let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(f) => panic!(f.to_string()),
};

if matches.opt_present("h") {
print_usage(&program, opts);
return;
}

let output = matches.opt_str("o").unwrap_or_else(|| "-".to_string());
let input = if !matches.free.is_empty() {
Some(&matches.free[0][..])
} else {
None
};

let format = match matches
.opt_str("f")
.unwrap_or_else(|| "toml".to_string())
.to_lowercase()
.as_ref()
{
"yaml" => Format::Yaml,
"toml" => Format::Toml,
_ => {
print_usage(&program, opts);
return;
}
};

expand_config(input, &output, format);
}

0 comments on commit 528a1fa

Please sign in to comment.