diff --git a/src/commands/build.rs b/src/commands/build.rs index 903c6e10..4b1b8591 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -1,18 +1,15 @@ use std::{ - collections::HashMap, fs::File, io::{self, BufWriter, Write}, path::PathBuf, }; use failure::Fail; -use rbx_dom_weak::RbxInstanceProperties; use crate::{ + common_setup, imfs::{FsError, Imfs, RealFetcher, WatchMode}, - project::{Project, ProjectLoadError}, - snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext, SnapshotPluginContext}, + project::ProjectLoadError, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -83,52 +80,11 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { log::debug!("Hoping to generate file of type {:?}", output_kind); - let maybe_project = match Project::load_fuzzy(&options.fuzzy_project_path) { - Ok(project) => Some(project), - Err(ProjectLoadError::NotFound) => None, - Err(other) => return Err(other.into()), - }; - log::trace!("Using project file {:#?}", maybe_project); - - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }, - metadata: Default::default(), - }); - let root_id = tree.get_root_id(); - log::trace!("Constructing in-memory filesystem"); let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled)); - log::trace!("Reading project root"); - let entry = imfs - .get(&options.fuzzy_project_path) - .expect("could not get project path"); - - let mut snapshot_context = InstanceSnapshotContext::default(); - - if let Some(project) = maybe_project { - // If the project file defines no plugins, then there's no need to - // initialize the snapshot plugin context. - if !project.plugins.is_empty() { - snapshot_context.plugin_context = - Some(SnapshotPluginContext::new(project.plugins.clone())); - } - } - - log::trace!("Generating snapshot of instances from IMFS"); - let snapshot = snapshot_from_imfs(&mut snapshot_context, &mut imfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - log::trace!("Computing patch set"); - let patch_set = compute_patch_set(&snapshot, &tree, root_id); - - log::trace!("Applying patch set"); - apply_patch_set(&mut tree, patch_set); + let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut imfs); + let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); let mut file = BufWriter::new(File::create(&options.output_file)?); diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 22c4a485..4aaef7df 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -9,7 +9,7 @@ use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{ imfs::{Imfs, RealFetcher, WatchMode}, - project::{Project, ProjectLoadError}, + project::ProjectLoadError, serve_session::ServeSession, web::LiveServer, }; @@ -33,33 +33,18 @@ impl_from!(ServeError { }); pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { - let maybe_project = match Project::load_fuzzy(&options.fuzzy_project_path) { - Ok(project) => Some(project), - Err(ProjectLoadError::NotFound) => None, - Err(other) => return Err(other.into()), - }; + let imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled)); + + let session = Arc::new(ServeSession::new(imfs, &options.fuzzy_project_path)); let port = options .port - .or_else(|| { - maybe_project - .as_ref() - .and_then(|project| project.serve_port) - }) + .or_else(|| session.project_port()) .unwrap_or(DEFAULT_PORT); - let _ = show_start_message(port); - - let imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled)); - - let session = Arc::new(ServeSession::new( - imfs, - &options.fuzzy_project_path, - maybe_project, - )); - let server = LiveServer::new(session); + let _ = show_start_message(port); server.start(port); Ok(()) diff --git a/src/commands/upload.rs b/src/commands/upload.rs index ded0446a..08bb7fd9 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -1,14 +1,12 @@ -use std::{collections::HashMap, path::PathBuf}; +use std::path::PathBuf; use failure::Fail; -use rbx_dom_weak::RbxInstanceProperties; use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; use crate::{ auth_cookie::get_auth_cookie, + common_setup, imfs::{Imfs, RealFetcher, WatchMode}, - snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, }; #[derive(Debug, Fail)] @@ -45,40 +43,15 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { .or_else(get_auth_cookie) .ok_or(UploadError::NeedAuthCookie)?; - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }, - metadata: Default::default(), - }); - let root_id = tree.get_root_id(); - log::trace!("Constructing in-memory filesystem"); let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled)); - log::trace!("Reading project root"); - let entry = imfs - .get(&options.fuzzy_project_path) - .expect("could not get project path"); - - // TODO: Compute snapshot context from project. - log::trace!("Generating snapshot of instances from IMFS"); - let snapshot = snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - log::trace!("Computing patch set"); - let patch_set = compute_patch_set(&snapshot, &tree, root_id); - - log::trace!("Applying patch set"); - apply_patch_set(&mut tree, patch_set); - + let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut imfs); let root_id = tree.get_root_id(); let mut buffer = Vec::new(); + log::trace!("Encoding XML model"); let config = rbx_xml::EncodeOptions::new() .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown); rbx_xml::to_writer(&mut buffer, tree.inner(), &[root_id], config)?; @@ -88,6 +61,7 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { options.asset_id ); + log::trace!("POSTing to {}", url); let client = reqwest::Client::new(); let mut response = client .post(&url) diff --git a/src/common_setup.rs b/src/common_setup.rs new file mode 100644 index 00000000..ee94ed65 --- /dev/null +++ b/src/common_setup.rs @@ -0,0 +1,66 @@ +//! Initialization routines that are used by more than one Rojo command or +//! utility. + +use std::path::Path; + +use rbx_dom_weak::RbxInstanceProperties; + +use crate::{ + imfs::{Imfs, ImfsFetcher}, + project::{Project, ProjectLoadError}, + snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, + snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext, SnapshotPluginContext}, +}; + +pub fn start( + fuzzy_project_path: &Path, + imfs: &mut Imfs, +) -> (Option, RojoTree) { + log::trace!("Loading project file from {}", fuzzy_project_path.display()); + let maybe_project = match Project::load_fuzzy(fuzzy_project_path) { + Ok(project) => Some(project), + Err(ProjectLoadError::NotFound) => None, + Err(other) => panic!("{}", other), // TODO: return error upward + }; + + log::trace!("Constructing initial tree"); + let mut tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: Default::default(), + }, + metadata: Default::default(), + }); + + let root_id = tree.get_root_id(); + + log::trace!("Constructing snapshot context"); + let mut snapshot_context = InstanceSnapshotContext::default(); + if let Some(project) = &maybe_project { + // If the project file defines no plugins, then there's no need to + // initialize the snapshot plugin context. + if !project.plugins.is_empty() { + snapshot_context.plugin_context = + Some(SnapshotPluginContext::new(project.plugins.clone())); + } + } + + log::trace!("Reading project root"); + let entry = imfs + .get(fuzzy_project_path) + .expect("could not get project path"); + + log::trace!("Generating snapshot of instances from IMFS"); + let snapshot = snapshot_from_imfs(&mut snapshot_context, imfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + log::trace!("Computing patch set"); + let patch_set = compute_patch_set(&snapshot, &tree, root_id); + + log::trace!("Applying patch set"); + apply_patch_set(&mut tree, patch_set); + + (maybe_project, tree) +} diff --git a/src/lib.rs b/src/lib.rs index 0ae30678..6384b989 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ mod tree_view; mod auth_cookie; mod change_processor; +mod common_setup; mod imfs; mod message_queue; mod multimap; diff --git a/src/serve_session.rs b/src/serve_session.rs index ebac8567..76486407 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -5,18 +5,14 @@ use std::{ time::Instant, }; -use rbx_dom_weak::RbxInstanceProperties; - use crate::{ change_processor::ChangeProcessor, + common_setup, imfs::{Imfs, ImfsFetcher}, message_queue::MessageQueue, project::Project, session_id::SessionId, - snapshot::{ - apply_patch_set, compute_patch_set, AppliedPatchSet, InstancePropertiesWithMeta, RojoTree, - }, - snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, + snapshot::{AppliedPatchSet, RojoTree}, }; /// Contains all of the state for a Rojo serve session. @@ -82,47 +78,14 @@ impl ServeSession { /// The project file is expected to be loaded out-of-band since it's /// currently loaded from the filesystem directly instead of through the /// in-memory filesystem layer. - pub fn new>( - mut imfs: Imfs, - start_path: P, - root_project: Option, - ) -> Self { + pub fn new>(mut imfs: Imfs, start_path: P) -> Self { let start_path = start_path.as_ref(); - log::trace!( - "Starting new ServeSession at path {} with project {:#?}", - start_path.display(), - root_project - ); + log::trace!("Starting new ServeSession at path {}", start_path.display(),); let start_time = Instant::now(); - log::trace!("Constructing initial tree"); - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: Default::default(), - }, - metadata: Default::default(), - }); - let root_id = tree.get_root_id(); - - log::trace!("Loading start path: {}", start_path.display()); - let entry = imfs.get(start_path).expect("could not get project path"); - - // TODO: Compute snapshot context from project. - log::trace!("Snapshotting start path"); - let snapshot = - snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - log::trace!("Computing initial patch set"); - let patch_set = compute_patch_set(&snapshot, &tree, root_id); - - log::trace!("Applying initial patch set"); - apply_patch_set(&mut tree, patch_set); + let (root_project, tree) = common_setup::start(start_path, &mut imfs); let session_id = SessionId::new(); let message_queue = MessageQueue::new(); @@ -177,6 +140,12 @@ impl ServeSession { .map(|project| project.name.as_str()) } + pub fn project_port(&self) -> Option { + self.root_project + .as_ref() + .and_then(|project| project.serve_port) + } + pub fn start_time(&self) -> Instant { self.start_time } @@ -214,7 +183,7 @@ mod serve_session { imfs.debug_load_snapshot("/foo", ImfsSnapshot::empty_dir()); - let session = ServeSession::new(imfs, "/foo", None); + let session = ServeSession::new(imfs, "/foo"); let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); @@ -241,7 +210,7 @@ mod serve_session { }), ); - let session = ServeSession::new(imfs, "/foo", None); + let session = ServeSession::new(imfs, "/foo"); let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); @@ -259,7 +228,7 @@ mod serve_session { }), ); - let session = ServeSession::new(imfs, "/root", None); + let session = ServeSession::new(imfs, "/root"); let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); @@ -278,7 +247,7 @@ mod serve_session { ); let imfs = Imfs::new(fetcher); - let session = ServeSession::new(imfs, "/root", None); + let session = ServeSession::new(imfs, "/root"); let mut redactions = RedactionMap::new(); assert_yaml_snapshot!( @@ -317,7 +286,7 @@ mod serve_session { state.load_snapshot("/foo.txt", ImfsSnapshot::file("Hello!")); let imfs = Imfs::new(fetcher); - let session = ServeSession::new(imfs, "/foo.txt", None); + let session = ServeSession::new(imfs, "/foo.txt"); let mut redactions = RedactionMap::new(); assert_yaml_snapshot!(