diff --git a/Cargo.toml b/Cargo.toml index a7f086bf0..0a78715d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,6 +74,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] @@ -89,5 +90,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 fff73fa49..d3d3f07cf 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"); - log::debug!("Hoping to generate file of type {:?}", output_kind); + let watch_mode = if options.watch { + WatchMode::Enabled + } else { + WatchMode::Disabled + }; - log::trace!("Constructing in-memory filesystem"); - let vfs = Vfs::new(RealFetcher::new(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); - 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 208100021..c96135496 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 {