From 199a39208c6fee1b135047ac92e14dca2cbf09d3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 8 Mar 2020 17:48:14 -0700 Subject: [PATCH] Implement 'rojo build --watch' (#284) * Refactor build command to reproduce model more easily * Spawn ServeSession for building --- Cargo.toml | 2 +- src/cli/build.rs | 47 ++++++++++++++++++++++++++++++++++++++--------- src/cli/mod.rs | 4 ++++ 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 20fe9229..a85b486d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,7 @@ serde_json = "1.0" snafu = "0.6.0" structopt = "0.3.5" termcolor = "1.0.5" +tokio = "0.1.22" uuid = { version = "0.8.1", features = ["v4", "serde"] } [target.'cfg(windows)'.dependencies] @@ -95,5 +96,4 @@ paste = "0.1" pretty_assertions = "0.6.1" serde_yaml = "0.8.9" tempfile = "3.0" -tokio = "0.1.22" walkdir = "2.1" diff --git a/src/cli/build.rs b/src/cli/build.rs index fff73fa4..d3d3f07c 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -4,11 +4,13 @@ use std::{ }; use snafu::{ResultExt, Snafu}; +use tokio::runtime::Runtime; use crate::{ cli::BuildCommand, - common_setup, project::ProjectError, + serve_session::ServeSession, + snapshot::RojoTree, vfs::{RealFetcher, Vfs, WatchMode}, }; @@ -71,18 +73,47 @@ pub fn build(options: BuildCommand) -> Result<(), BuildError> { } fn build_inner(options: BuildCommand) -> Result<(), Error> { - let output_kind = detect_output_kind(&options).ok_or(Error::UnknownOutputKind)?; + log::trace!("Constructing in-memory filesystem"); + let watch_mode = if options.watch { + WatchMode::Enabled + } else { + WatchMode::Disabled + }; + + let vfs = Vfs::new(RealFetcher::new(watch_mode)); + + let session = ServeSession::new(vfs, &options.absolute_project()); + let mut cursor = session.message_queue().cursor(); + + { + let tree = session.tree(); + write_model(&tree, &options)?; + } + + if options.watch { + let mut rt = Runtime::new().unwrap(); + + loop { + let receiver = session.message_queue().subscribe(cursor); + let (new_cursor, _patch_set) = rt.block_on(receiver).unwrap(); + cursor = new_cursor; + + let tree = session.tree(); + write_model(&tree, &options)?; + } + } + + Ok(()) +} + +fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), Error> { + let output_kind = detect_output_kind(&options).ok_or(Error::UnknownOutputKind)?; log::debug!("Hoping to generate file of type {:?}", output_kind); - log::trace!("Constructing in-memory filesystem"); - let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - - let (_maybe_project, tree) = common_setup::start(&options.absolute_project(), &vfs); let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); - let file = File::create(&options.output).context(Io)?; let mut file = BufWriter::new(file); @@ -121,7 +152,5 @@ fn build_inner(options: BuildCommand) -> Result<(), Error> { file.flush().context(Io)?; - log::trace!("Done!"); - Ok(()) } diff --git a/src/cli/mod.rs b/src/cli/mod.rs index a10039da..d0048116 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -140,6 +140,10 @@ pub struct BuildCommand { /// Where to output the result. #[structopt(long, short)] pub output: PathBuf, + + /// Whether to automatically rebuild when any input files change. + #[structopt(long)] + pub watch: bool, } impl BuildCommand {