diff --git a/crates/memofs/CHANGELOG.md b/crates/memofs/CHANGELOG.md index 16d578c3..85b51523 100644 --- a/crates/memofs/CHANGELOG.md +++ b/crates/memofs/CHANGELOG.md @@ -1,11 +1,15 @@ # memofs Changelog ## Unreleased Changes +* Added `Vfs::exists`. [#1169] +* Added `create_dir` and `create_dir_all` to allow creating directories. [#937] + +[#1169]: https://github.com/rojo-rbx/rojo/pull/1169 +[#937]: https://github.com/rojo-rbx/rojo/pull/937 ## 0.3.0 (2024-03-15) * Changed `StdBackend` file watching component to use minimal recursive watches. [#830] * Added `Vfs::read_to_string` and `Vfs::read_to_string_lf_normalized` [#854] -* Added `create_dir` and `create_dir_all` to allow creating directories. [#830]: https://github.com/rojo-rbx/rojo/pull/830 [#854]: https://github.com/rojo-rbx/rojo/pull/854 diff --git a/crates/memofs/src/in_memory_fs.rs b/crates/memofs/src/in_memory_fs.rs index acca08c4..3c825575 100644 --- a/crates/memofs/src/in_memory_fs.rs +++ b/crates/memofs/src/in_memory_fs.rs @@ -157,6 +157,11 @@ impl VfsBackend for InMemoryFs { ) } + fn exists(&mut self, path: &Path) -> io::Result { + let inner = self.inner.lock().unwrap(); + Ok(inner.entries.contains_key(path)) + } + fn read_dir(&mut self, path: &Path) -> io::Result { let inner = self.inner.lock().unwrap(); diff --git a/crates/memofs/src/lib.rs b/crates/memofs/src/lib.rs index 028a413b..bc7e329e 100644 --- a/crates/memofs/src/lib.rs +++ b/crates/memofs/src/lib.rs @@ -70,6 +70,7 @@ impl IoResultExt for io::Result { pub trait VfsBackend: sealed::Sealed + Send + 'static { fn read(&mut self, path: &Path) -> io::Result>; fn write(&mut self, path: &Path, data: &[u8]) -> io::Result<()>; + fn exists(&mut self, path: &Path) -> io::Result; fn read_dir(&mut self, path: &Path) -> io::Result; fn create_dir(&mut self, path: &Path) -> io::Result<()>; fn create_dir_all(&mut self, path: &Path) -> io::Result<()>; @@ -175,6 +176,11 @@ impl VfsInner { Ok(Arc::new(contents_str.into())) } + fn exists>(&mut self, path: P) -> io::Result { + let path = path.as_ref(); + self.backend.exists(path) + } + fn write, C: AsRef<[u8]>>(&mut self, path: P, contents: C) -> io::Result<()> { let path = path.as_ref(); let contents = contents.as_ref(); @@ -338,6 +344,17 @@ impl Vfs { self.inner.lock().unwrap().read_dir(path) } + /// Return whether the given path exists. + /// + /// Roughly equivalent to [`std::fs::exists`][std::fs::exists]. + /// + /// [std::fs::exists]: https://doc.rust-lang.org/stable/std/fs/fn.exists.html + #[inline] + pub fn exists>(&self, path: P) -> io::Result { + let path = path.as_ref(); + self.inner.lock().unwrap().exists(path) + } + /// Creates a directory at the provided location. /// /// Roughly equivalent to [`std::fs::create_dir`][std::fs::create_dir]. diff --git a/crates/memofs/src/noop_backend.rs b/crates/memofs/src/noop_backend.rs index 18f6f809..dd10d452 100644 --- a/crates/memofs/src/noop_backend.rs +++ b/crates/memofs/src/noop_backend.rs @@ -22,6 +22,10 @@ impl VfsBackend for NoopBackend { Err(io::Error::other("NoopBackend doesn't do anything")) } + fn exists(&mut self, _path: &Path) -> io::Result { + Err(io::Error::other("NoopBackend doesn't do anything")) + } + fn read_dir(&mut self, _path: &Path) -> io::Result { Err(io::Error::other("NoopBackend doesn't do anything")) } diff --git a/crates/memofs/src/std_backend.rs b/crates/memofs/src/std_backend.rs index d39fb179..f354d806 100644 --- a/crates/memofs/src/std_backend.rs +++ b/crates/memofs/src/std_backend.rs @@ -63,6 +63,10 @@ impl VfsBackend for StdBackend { fs_err::write(path, data) } + fn exists(&mut self, path: &Path) -> io::Result { + std::fs::exists(path) + } + fn read_dir(&mut self, path: &Path) -> io::Result { let entries: Result, _> = fs_err::read_dir(path)?.collect(); let mut entries = entries?; diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index aa8773b3..03177654 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -46,10 +46,18 @@ impl PluginSubcommand { } } -fn install_plugin() -> anyhow::Result<()> { +fn initialize_plugin() -> anyhow::Result { let plugin_snapshot: VfsSnapshot = bincode::deserialize(PLUGIN_BINCODE) .expect("Rojo's plugin was not properly packed into Rojo's binary"); + let mut in_memory_fs = InMemoryFs::new(); + in_memory_fs.load_snapshot("/plugin", plugin_snapshot)?; + + let vfs = Vfs::new(in_memory_fs); + Ok(ServeSession::new(vfs, "/plugin")?) +} + +fn install_plugin() -> anyhow::Result<()> { let studio = RobloxStudio::locate()?; let plugins_folder_path = studio.plugins_path(); @@ -59,17 +67,12 @@ fn install_plugin() -> anyhow::Result<()> { fs::create_dir(plugins_folder_path)?; } - let mut in_memory_fs = InMemoryFs::new(); - in_memory_fs.load_snapshot("/plugin", plugin_snapshot)?; - - let vfs = Vfs::new(in_memory_fs); - let session = ServeSession::new(vfs, "/plugin")?; - let plugin_path = plugins_folder_path.join(PLUGIN_FILE_NAME); log::debug!("Writing plugin to {}", plugin_path.display()); let mut file = BufWriter::new(File::create(plugin_path)?); + let session = initialize_plugin()?; let tree = session.tree(); let root_id = tree.get_root_id(); @@ -92,3 +95,8 @@ fn uninstall_plugin() -> anyhow::Result<()> { Ok(()) } + +#[test] +fn plugin_initialize() { + assert!(initialize_plugin().is_ok()) +} diff --git a/src/project.rs b/src/project.rs index 20c2dc9c..5cc8278e 100644 --- a/src/project.rs +++ b/src/project.rs @@ -295,7 +295,7 @@ impl Project { // Check for default projects. for default_project_name in DEFAULT_PROJECT_NAMES { let project_path = path.join(default_project_name); - if project_path.exists() { + if let Ok(true) = vfs.exists(&project_path) { return Self::load_exact(vfs, &project_path, None); } }