Automatically run dot to generate PDFs or PNGs (#6912)
This commit is contained in:
parent
24cb4798bc
commit
4405e8a15b
|
@ -16,10 +16,11 @@ use solana_sdk::{
|
||||||
use solana_vote_api::vote_state::VoteState;
|
use solana_vote_api::vote_state::VoteState;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap, HashSet},
|
collections::{BTreeMap, HashMap, HashSet},
|
||||||
|
ffi::OsStr,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{stdout, Write},
|
io::{self, stdout, Write},
|
||||||
path::PathBuf,
|
path::{Path, PathBuf},
|
||||||
process::exit,
|
process::{exit, Command, Stdio},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,6 +142,30 @@ fn output_ledger(blocktree: Blocktree, starting_slot: Slot, method: LedgerOutput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_dot(dot: String, output_file: &str, output_format: &str) -> io::Result<()> {
|
||||||
|
let mut child = Command::new("dot")
|
||||||
|
.arg(format!("-T{}", output_format))
|
||||||
|
.arg(format!("-o{}", output_file))
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.map_err(|err| {
|
||||||
|
eprintln!("Failed to spawn dot: {:?}", err);
|
||||||
|
err
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let stdin = child.stdin.as_mut().unwrap();
|
||||||
|
stdin.write_all(&dot.into_bytes())?;
|
||||||
|
|
||||||
|
let status = child.wait_with_output()?.status;
|
||||||
|
if !status.success() {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("dot failed with error {}", status.code().unwrap_or(-1)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
fn graph_forks(
|
fn graph_forks(
|
||||||
bank_forks: BankForks,
|
bank_forks: BankForks,
|
||||||
|
@ -450,7 +475,7 @@ fn main() {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("graph_forks")
|
Arg::with_name("graph_forks")
|
||||||
.long("graph-forks")
|
.long("graph-forks")
|
||||||
.value_name("FILENAME.GV")
|
.value_name("FILENAME")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Create a Graphviz DOT file representing the active forks once the ledger is verified"),
|
.help("Create a Graphviz DOT file representing the active forks once the ledger is verified"),
|
||||||
)
|
)
|
||||||
|
@ -577,19 +602,27 @@ fn main() {
|
||||||
Ok((bank_forks, bank_forks_info, _leader_schedule_cache)) => {
|
Ok((bank_forks, bank_forks_info, _leader_schedule_cache)) => {
|
||||||
println!("Ok");
|
println!("Ok");
|
||||||
|
|
||||||
if let Some(dot_file) = arg_matches.value_of("graph_forks") {
|
if let Some(output_file) = arg_matches.value_of("graph_forks") {
|
||||||
let dot = graph_forks(
|
let dot = graph_forks(
|
||||||
bank_forks,
|
bank_forks,
|
||||||
bank_forks_info,
|
bank_forks_info,
|
||||||
arg_matches.is_present("graph_forks_include_all_votes"),
|
arg_matches.is_present("graph_forks_include_all_votes"),
|
||||||
);
|
);
|
||||||
|
|
||||||
match File::create(dot_file)
|
let extension = Path::new(output_file).extension();
|
||||||
|
let result = if extension == Some(OsStr::new("pdf")) {
|
||||||
|
render_dot(dot, output_file, "pdf")
|
||||||
|
} else if extension == Some(OsStr::new("png")) {
|
||||||
|
render_dot(dot, output_file, "png")
|
||||||
|
} else {
|
||||||
|
File::create(output_file)
|
||||||
.and_then(|mut file| file.write_all(&dot.into_bytes()))
|
.and_then(|mut file| file.write_all(&dot.into_bytes()))
|
||||||
{
|
|
||||||
Ok(_) => println!("Wrote {}", dot_file),
|
|
||||||
Err(err) => eprintln!("Unable to write {}: {}", dot_file, err),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(_) => println!("Wrote {}", output_file),
|
||||||
|
Err(err) => eprintln!("Unable to write {}: {}", output_file, err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
Loading…
Reference in New Issue