From 6719be02c34202fb16b7a8903154264da5c492d9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 29 Jan 2019 18:10:14 -0800 Subject: [PATCH] Fall back to showing GraphViz source when GraphViz is not installed --- CHANGELOG.md | 1 + Cargo.lock | 6 +++--- server/Cargo.toml | 2 +- server/src/bin.rs | 11 ++++++++--- server/src/visualize.rs | 19 ++++++++++++++----- server/src/web.rs | 12 ++++++++++-- 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d4e05f1..587bee13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] * Added new (empty) diagnostic page served from the server * Added better error messages for when a file is missing that's referenced by a Rojo project +* Added support for visualization endpoints returning GraphViz source when Dot is not available ## [0.5.0 Alpha 2](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) * Added support for `.model.json` files, compatible with 0.4.x diff --git a/Cargo.lock b/Cargo.lock index 194e45af..d0f41761 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,7 +345,7 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.5.13" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1252,7 +1252,7 @@ version = "0.5.0-alpha.2" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1929,7 +1929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" -"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" diff --git a/server/Cargo.toml b/server/Cargo.toml index 881dafe9..df5be7f6 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -22,7 +22,7 @@ bundle-plugin = [] [dependencies] clap = "2.27" csv = "1.0" -env_logger = "0.5" +env_logger = "0.6" failure = "0.1.3" log = "0.4" maplit = "1.0.1" diff --git a/server/src/bin.rs b/server/src/bin.rs index 61ef05f0..7f5b80e7 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -20,9 +20,14 @@ fn make_path_absolute(value: &Path) -> PathBuf { } fn main() { - env_logger::Builder::from_default_env() - .default_format_timestamp(false) - .init(); + { + let log_env = env_logger::Env::default() + .default_filter_or("warn"); + + env_logger::Builder::from_env(log_env) + .default_format_timestamp(false) + .init(); + } let app = clap_app!(Rojo => (version: env!("CARGO_PKG_VERSION")) diff --git a/server/src/visualize.rs b/server/src/visualize.rs index 75b51b19..a09326e8 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -5,6 +5,7 @@ use std::{ process::{Command, Stdio}, }; +use log::warn; use rbx_tree::RbxId; use crate::{ @@ -27,13 +28,21 @@ digraph RojoTree { "#; /// Compiles DOT source to SVG by invoking dot on the command line. -pub fn graphviz_to_svg(source: &str) -> String { - let mut child = Command::new("dot") +pub fn graphviz_to_svg(source: &str) -> Option { + let command = Command::new("dot") .arg("-Tsvg") .stdin(Stdio::piped()) .stdout(Stdio::piped()) - .spawn() - .expect("Failed to spawn GraphViz process -- make sure it's installed in order to use /api/visualize"); + .spawn(); + + let mut child = match command { + Ok(child) => child, + Err(_) => { + warn!("Failed to spawn GraphViz process to visualize current state."); + warn!("If you want pretty graphs, install GraphViz and make sure 'dot' is on your PATH!"); + return None; + }, + }; { let stdin = child.stdin.as_mut().expect("Failed to open stdin"); @@ -41,7 +50,7 @@ pub fn graphviz_to_svg(source: &str) -> String { } let output = child.wait_with_output().expect("Failed to read stdout"); - String::from_utf8(output.stdout).expect("Failed to parse stdout as UTF-8") + Some(String::from_utf8(output.stdout).expect("Failed to parse stdout as UTF-8")) } /// A Display wrapper struct to visualize an RbxSession as SVG. diff --git a/server/src/web.rs b/server/src/web.rs index 0822f1cb..5c78bdfa 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -238,13 +238,21 @@ impl Server { fn handle_visualize_rbx(&self) -> Response { let rbx_session = self.live_session.rbx_session.lock().unwrap(); let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); - Response::svg(graphviz_to_svg(&dot_source)) + + match graphviz_to_svg(&dot_source) { + Some(svg) => Response::svg(svg), + None => Response::text(dot_source), + } } fn handle_visualize_imfs(&self) -> Response { let imfs = self.live_session.imfs.lock().unwrap(); let dot_source = format!("{}", VisualizeImfs(&imfs)); - Response::svg(graphviz_to_svg(&dot_source)) + + match graphviz_to_svg(&dot_source) { + Some(svg) => Response::svg(svg), + None => Response::text(dot_source), + } } fn handle_visualize_path_metadata(&self) -> Response {