librojo/cli/
plugin.rs

1use std::{
2    fs::{self, File},
3    io::BufWriter,
4};
5
6use clap::Parser;
7use memofs::{InMemoryFs, Vfs, VfsSnapshot};
8use roblox_install::RobloxStudio;
9
10use crate::serve_session::ServeSession;
11
12static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode"));
13static PLUGIN_FILE_NAME: &str = "RojoManagedPlugin.rbxm";
14
15/// Install Rojo's plugin.
16#[derive(Debug, Parser)]
17pub struct PluginCommand {
18    #[clap(subcommand)]
19    subcommand: PluginSubcommand,
20}
21
22/// Manages Rojo's Roblox Studio plugin.
23#[derive(Debug, Parser)]
24pub enum PluginSubcommand {
25    /// Install the plugin in Roblox Studio's plugins folder. If the plugin is
26    /// already installed, installing it again will overwrite the current plugin
27    /// file.
28    Install,
29
30    /// Removes the plugin if it is installed.
31    Uninstall,
32}
33
34impl PluginCommand {
35    pub fn run(self) -> anyhow::Result<()> {
36        self.subcommand.run()
37    }
38}
39
40impl PluginSubcommand {
41    pub fn run(self) -> anyhow::Result<()> {
42        match self {
43            PluginSubcommand::Install => install_plugin(),
44            PluginSubcommand::Uninstall => uninstall_plugin(),
45        }
46    }
47}
48
49fn install_plugin() -> anyhow::Result<()> {
50    let plugin_snapshot: VfsSnapshot = bincode::deserialize(PLUGIN_BINCODE)
51        .expect("Rojo's plugin was not properly packed into Rojo's binary");
52
53    let studio = RobloxStudio::locate()?;
54
55    let plugins_folder_path = studio.plugins_path();
56
57    if !plugins_folder_path.exists() {
58        log::debug!("Creating Roblox Studio plugins folder");
59        fs::create_dir(plugins_folder_path)?;
60    }
61
62    let mut in_memory_fs = InMemoryFs::new();
63    in_memory_fs.load_snapshot("/plugin", plugin_snapshot)?;
64
65    let vfs = Vfs::new(in_memory_fs);
66    let session = ServeSession::new(vfs, "/plugin")?;
67
68    let plugin_path = plugins_folder_path.join(PLUGIN_FILE_NAME);
69    log::debug!("Writing plugin to {}", plugin_path.display());
70
71    let mut file = BufWriter::new(File::create(plugin_path)?);
72
73    let tree = session.tree();
74    let root_id = tree.get_root_id();
75
76    rbx_binary::to_writer(&mut file, tree.inner(), &[root_id])?;
77
78    Ok(())
79}
80
81fn uninstall_plugin() -> anyhow::Result<()> {
82    let studio = RobloxStudio::locate()?;
83
84    let plugin_path = studio.plugins_path().join(PLUGIN_FILE_NAME);
85
86    if plugin_path.exists() {
87        log::debug!("Removing existing plugin from {}", plugin_path.display());
88        fs::remove_file(plugin_path)?;
89    } else {
90        log::debug!("Plugin not installed at {}", plugin_path.display());
91    }
92
93    Ok(())
94}