rojo/src/cli/plugin.rs
Joe 484b190464 Refactor ServeSession to support oneshot sessions
- Updated the ServeSession struct to allow for optional ChangeProcessor and related fields, enabling lightweight oneshot sessions that do not require live filesystem monitoring.
- Modified the new and new_oneshot methods to initialize sessions accordingly, improving flexibility for commands that only need a snapshot of the tree.
- Adjusted related CLI commands to utilize the new oneshot session functionality, enhancing performance for operations like plugin installation and syncback.

These changes streamline session management and improve the efficiency of operations that do not require continuous updates.
2026-02-15 14:43:19 -06:00

103 lines
2.8 KiB
Rust

use std::{
fs::{self, File},
io::BufWriter,
};
use clap::Parser;
use memofs::{InMemoryFs, Vfs, VfsSnapshot};
use roblox_install::RobloxStudio;
use crate::serve_session::ServeSession;
static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode"));
static PLUGIN_FILE_NAME: &str = "AtlasManagedPlugin.rbxm";
/// Install Rojo's plugin.
#[derive(Debug, Parser)]
pub struct PluginCommand {
#[clap(subcommand)]
subcommand: PluginSubcommand,
}
/// Manages Rojo's Roblox Studio plugin.
#[derive(Debug, Parser)]
pub enum PluginSubcommand {
/// Install the plugin in Roblox Studio's plugins folder. If the plugin is
/// already installed, installing it again will overwrite the current plugin
/// file.
Install,
/// Removes the plugin if it is installed.
Uninstall,
}
impl PluginCommand {
pub fn run(self) -> anyhow::Result<()> {
self.subcommand.run()
}
}
impl PluginSubcommand {
pub fn run(self) -> anyhow::Result<()> {
match self {
PluginSubcommand::Install => install_plugin(),
PluginSubcommand::Uninstall => uninstall_plugin(),
}
}
}
fn initialize_plugin() -> anyhow::Result<ServeSession> {
let (plugin_snapshot, _): (VfsSnapshot, usize) =
bincode::serde::decode_from_slice(PLUGIN_BINCODE, bincode::config::standard())
.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_oneshot(vfs, "/plugin")?)
}
fn install_plugin() -> anyhow::Result<()> {
let studio = RobloxStudio::locate()?;
let plugins_folder_path = studio.plugins_path();
if !plugins_folder_path.exists() {
log::debug!("Creating Roblox Studio plugins folder");
fs::create_dir(plugins_folder_path)?;
}
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();
rbx_binary::to_writer(&mut file, tree.inner(), &[root_id])?;
Ok(())
}
fn uninstall_plugin() -> anyhow::Result<()> {
let studio = RobloxStudio::locate()?;
let plugin_path = studio.plugins_path().join(PLUGIN_FILE_NAME);
if plugin_path.exists() {
log::debug!("Removing existing plugin from {}", plugin_path.display());
fs::remove_file(plugin_path)?;
} else {
log::debug!("Plugin not installed at {}", plugin_path.display());
}
Ok(())
}
#[test]
fn plugin_initialize() {
assert!(initialize_plugin().is_ok())
}