From 849001bf870dd0d054099e8fde58f2d79dec2c76 Mon Sep 17 00:00:00 2001 From: jeparlefrancais Date: Mon, 16 Mar 2020 23:40:48 -0400 Subject: [PATCH 01/15] add install command --- Cargo.lock | 97 +++++++++++++++++++++++++++++++++++++ Cargo.toml | 7 +++ build.rs | 79 ++++++++++++++++++++++++++++++ memofs/Cargo.toml | 1 + memofs/src/snapshot.rs | 35 +++++++++++++- src/bin.rs | 1 + src/cli/mod.rs | 5 ++ src/cli/plugin.rs | 107 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 build.rs create mode 100644 src/cli/plugin.rs diff --git a/Cargo.lock b/Cargo.lock index cc0879134..a65570d36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,16 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "atty" version = "0.2.14" @@ -74,11 +84,30 @@ name = "base64" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bincode" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blake2b_simd" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "block-buffer" version = "0.7.3" @@ -231,6 +260,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cookie" version = "0.12.0" @@ -406,6 +440,26 @@ dependencies = [ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dirs-sys" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "doc-comment" version = "0.3.1" @@ -922,6 +976,7 @@ dependencies = [ "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "fs-err 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1564,6 +1619,16 @@ name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "redox_users" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex" version = "1.3.4" @@ -1663,11 +1728,21 @@ dependencies = [ "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "roblox_install" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rojo" version = "0.6.0-alpha.3" dependencies = [ "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1694,6 +1769,7 @@ dependencies = [ "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "roblox_install 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rojo-insta-ext 0.1.0", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1735,6 +1811,17 @@ dependencies = [ "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rust-argon2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.16" @@ -2531,6 +2618,8 @@ dependencies = [ "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" @@ -2538,7 +2627,9 @@ dependencies = [ "checksum backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" "checksum bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" @@ -2556,6 +2647,7 @@ dependencies = [ "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum console 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "45e0f3986890b3acbc782009e2629dfe2baa430ac091519ce3be26164a2ae6c0" +"checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" @@ -2573,6 +2665,8 @@ dependencies = [ "checksum ctor 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "47c5e5ac752e18207b12e16b10631ae5f7f68f8805f335f9b817ead83d9ffce1" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" "checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" @@ -2703,6 +2797,7 @@ dependencies = [ "checksum rbx_xml 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6431f38b84582ec4e4f40b525cdcc713d4a984dcc2e3eecd1a67ae4da1172fbd" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" "checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum regex-syntax 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" @@ -2711,6 +2806,8 @@ dependencies = [ "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25fa5b2c667bae0b6218361e96d365e414fe4a0fa80f476b9631aa2dea2c6881" +"checksum roblox_install 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f80edbbbcd67bce7ddaf754d94276b30ae0a72eedfdf034c0c987f4a535e4a54" +"checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" diff --git a/Cargo.toml b/Cargo.toml index 501e3b8bc..6d2adb7fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ harness = false memofs = { version = "0.1.0", path = "memofs" } backtrace = "0.3" +bincode = "1.2.1" crossbeam-channel = "0.4.0" csv = "1.1.1" env_logger = "0.7.1" @@ -85,6 +86,7 @@ regex = "1.3.1" reqwest = "0.9.20" ritz = "0.1.0" rlua = "0.17.0" +roblox_install = "0.2.2" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" snafu = "0.6.0" @@ -96,6 +98,11 @@ uuid = { version = "0.8.1", features = ["v4", "serde"] } [target.'cfg(windows)'.dependencies] winreg = "0.6.2" +[build-dependencies] +bincode = "1.2.1" +maplit = "1.0.1" +memofs = { version = "0.1.0", path = "memofs" } + [dev-dependencies] rojo-insta-ext = { path = "rojo-insta-ext" } diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..9a0ef617b --- /dev/null +++ b/build.rs @@ -0,0 +1,79 @@ +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; + +use maplit::hashmap; +use memofs::VfsSnapshot; + +fn snapshot_from_fs_path(path: &PathBuf) -> Result { + if path.is_dir() { + let entries: Result, PathBuf> = fs::read_dir(path) + .map_err(|_| path.to_owned())? + .map(|entry| entry.map_err(|_| path.to_owned())) + .into_iter() + .collect(); + + let vfs_entries: Result, PathBuf> = entries? + .iter() + .filter(|entry| !entry.path().ends_with(".spec.lua")) + .map(|entry| { + let path = entry.path(); + + path.file_name() + .and_then(|file_name| file_name.to_str()) + .ok_or(path.to_owned()) + .and_then(|file_name| { + snapshot_from_fs_path(&path).map(|snapshot| (file_name.to_owned(), snapshot)) + }) + }) + .into_iter() + .collect(); + + Ok(VfsSnapshot::dir(vfs_entries?)) + } else { + println!("cargo:rerun-if-changed={}", path.to_string_lossy()); + fs::read_to_string(path) + .ok() + .map(|content| VfsSnapshot::file(content)) + .ok_or(path.to_owned()) + } +} + +fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let plugin_root = PathBuf::from("plugin"); + + let plugin_modules = plugin_root.join("modules"); + + let snapshot = VfsSnapshot::dir(hashmap! { + "default.project.json" => snapshot_from_fs_path(&plugin_root.join("default.project.json")).unwrap(), + "fmt" => snapshot_from_fs_path(&plugin_root.join("fmt")).unwrap(), + "http" => snapshot_from_fs_path(&plugin_root.join("http")).unwrap(), + "log" => snapshot_from_fs_path(&plugin_root.join("log")).unwrap(), + "src" => snapshot_from_fs_path(&plugin_root.join("src")).unwrap(), + "modules" => VfsSnapshot::dir(hashmap! { + "roact" => VfsSnapshot::dir(hashmap! { + "src" => snapshot_from_fs_path(&plugin_modules.join("roact").join("src")).unwrap() + }), + "promise" => VfsSnapshot::dir(hashmap! { + "lib" => snapshot_from_fs_path(&plugin_modules.join("promise").join("lib")).unwrap() + }), + "t" => VfsSnapshot::dir(hashmap! { + "lib" => snapshot_from_fs_path(&plugin_modules.join("t").join("lib")).unwrap() + }), + "rbx-dom" => VfsSnapshot::dir(hashmap! { + "rbx_dom_lua" => VfsSnapshot::dir(hashmap! { + "src" => snapshot_from_fs_path(&plugin_modules.join("rbx-dom").join("rbx_dom_lua").join("src")).unwrap() + }) + }), + }), + }); + + println!("cargo:rerun-if-changed=build.rs"); + + let out_path = Path::new(&out_dir).join("plugin.bincode"); + let out_file = fs::File::create(&out_path).unwrap(); + + bincode::serialize_into(out_file, &snapshot).unwrap(); +} diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index 07fbec102..5b612fd50 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -14,3 +14,4 @@ homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" crossbeam-channel = "0.4.0" fs-err = "2.2.0" notify = "4.0.15" +serde = { version = "1.0", features = ["derive"] } diff --git a/memofs/src/snapshot.rs b/memofs/src/snapshot.rs index e6596bb27..227b12a5f 100644 --- a/memofs/src/snapshot.rs +++ b/memofs/src/snapshot.rs @@ -1,8 +1,12 @@ +use serde::{Serialize, Deserialize}; use std::collections::BTreeMap; +use std::fs; +use std::fs::DirEntry; +use std::path::PathBuf; /// A slice of a tree of files. Can be loaded into an /// [`InMemoryFs`](struct.InMemoryFs.html). -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] #[non_exhaustive] pub enum VfsSnapshot { File { @@ -41,4 +45,33 @@ impl VfsSnapshot { children: BTreeMap::new(), } } + + pub fn from_fs_path(path: &PathBuf) -> Result { + if path.is_file() { + fs::read_to_string(path).ok() + .map(|content| Self::file(content)) + .ok_or(path.to_owned()) + } else { + let entries: Result, PathBuf> = fs::read_dir(path) + .map_err(|_| path.to_owned())? + .map(|entry| entry.map_err(|_| path.to_owned())) + .into_iter() + .collect(); + + let vfs_entries: Result, PathBuf> = entries?.iter() + .map(|entry| { + let path = entry.path(); + + path.file_name() + .and_then(|file_name| file_name.to_str()) + .ok_or(path.to_owned()) + .and_then(|file_name| { + Self::from_fs_path(&path) + .map(|snapshot| (file_name.to_owned(), snapshot)) + }) + }).into_iter().collect(); + + Ok(Self::dir(vfs_entries?)) + } + } } diff --git a/src/bin.rs b/src/bin.rs index 5b7a846f9..4ea600449 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -12,6 +12,7 @@ fn run(subcommand: Subcommand) -> Result<(), Box> { Subcommand::Build(build_options) => cli::build(build_options)?, Subcommand::Upload(upload_options) => cli::upload(upload_options)?, Subcommand::Doc => cli::doc()?, + Subcommand::Plugin(plugin_options) => cli::plugin(plugin_options)?, } Ok(()) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 40179a325..bebd78fb9 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -3,6 +3,7 @@ mod build; mod doc; mod init; +mod plugin; mod serve; mod upload; @@ -20,6 +21,7 @@ use structopt::StructOpt; pub use self::build::*; pub use self::doc::*; pub use self::init::*; +pub use self::plugin::*; pub use self::serve::*; pub use self::upload::*; @@ -53,6 +55,9 @@ pub enum Subcommand { /// Open Rojo's documentation in your browser. Doc, + + /// Manages rojo's Roblox plugin. + Plugin(PluginCommand), } /// Initializes a new Rojo project. diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs new file mode 100644 index 000000000..3ef71ebd1 --- /dev/null +++ b/src/cli/plugin.rs @@ -0,0 +1,107 @@ +use crate::serve_session::ServeSession; + +use memofs::{Vfs, VfsSnapshot}; +use memofs::InMemoryFs; +use roblox_install::RobloxStudio; +use snafu::{ResultExt, Snafu}; +use std::{ + fs::{self, File}, + io::{self, BufWriter}, +}; +use structopt::StructOpt; + +static PLUGIN_FILE_NAME: &str = concat!("rojo-", env!("CARGO_PKG_VERSION"), ".rbxmx"); + +#[derive(Debug, StructOpt)] +enum PluginSubcommand { + /// Install the plugin in Roblox plugins folder. If the plugin is already installed, installing + /// it again will overwrite the current plugin file. + Install, + /// Removes the plugin if installed. + Uninstall, +} + +/// Install rojo's plugin. +#[derive(Debug, StructOpt)] +pub struct PluginCommand { + #[structopt(subcommand)] + subcommand: PluginSubcommand, +} + +#[derive(Debug, Snafu)] +pub struct PluginError(Error); + +#[derive(Debug, Snafu)] +enum Error { + #[snafu(display("Could not locate Roblox Studio: {}", source.to_string()))] + CannotLocateRobloxStudio { source: roblox_install::Error }, + + #[snafu(display("{}", source))] + Io { source: io::Error }, +} + +fn xml_encode_config() -> rbx_xml::EncodeOptions { + rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) +} + +pub fn plugin(options: PluginCommand) -> Result<(), PluginError> { + match options.subcommand { + PluginSubcommand::Install => install_plugin()?, + PluginSubcommand::Uninstall => uninstall_plugin()?, + } + Ok(()) +} + + +pub fn install_plugin() -> Result<(), PluginError> { + static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode")); + + let plugin_snapshot: VfsSnapshot = bincode::deserialize(PLUGIN_BINCODE) + .expect("rojo's plugin was not properly packed into rojo's binary"); + + let studio = RobloxStudio::locate() + .context(CannotLocateRobloxStudio)?; + + let plugins_folder_path = studio.plugins_path(); + + if !plugins_folder_path.exists() { + fs::create_dir(plugins_folder_path).context(Io)?; + log::trace!("Plugins folder did not exist so it was created"); + } + + let mut in_memory_fs = InMemoryFs::new(); + in_memory_fs.load_snapshot("plugin", plugin_snapshot).context(Io)?; + + let vfs = Vfs::new(in_memory_fs); + + let session = ServeSession::new(vfs, "plugin"); + + let tree = session.tree(); + + log::trace!("Writing plugin {} in {}", PLUGIN_FILE_NAME, plugins_folder_path.to_string_lossy()); + let file = File::create(plugins_folder_path.join(PLUGIN_FILE_NAME)).context(Io)?; + + let mut file = BufWriter::new(file); + + let root_id = tree.get_root_id(); + + rbx_xml::to_writer(&mut file, tree.inner(), &[root_id], xml_encode_config()).unwrap(); + + Ok(()) +} + +fn uninstall_plugin() -> Result<(), PluginError> { + let studio = RobloxStudio::locate() + .context(CannotLocateRobloxStudio)?; + + let rojo_plugin_path = studio.plugins_path().join(PLUGIN_FILE_NAME); + + if rojo_plugin_path.exists() { + log::trace!("Removing existing plugin {}", rojo_plugin_path.to_string_lossy()); + fs::remove_file(rojo_plugin_path).context(Io)?; + } else { + log::trace!("Plugin not installed {}", rojo_plugin_path.to_string_lossy()); + } + + Ok(()) +} From 3e1c98d71cdc9a6d31193a80d601f4d38f578fee Mon Sep 17 00:00:00 2001 From: jeparlefrancais Date: Mon, 16 Mar 2020 23:46:33 -0400 Subject: [PATCH 02/15] cargo fmt --- build.rs | 3 ++- memofs/src/snapshot.rs | 34 +--------------------------------- src/cli/plugin.rs | 29 +++++++++++++++++++---------- 3 files changed, 22 insertions(+), 44 deletions(-) diff --git a/build.rs b/build.rs index 9a0ef617b..5c7d14a78 100644 --- a/build.rs +++ b/build.rs @@ -23,7 +23,8 @@ fn snapshot_from_fs_path(path: &PathBuf) -> Result { .and_then(|file_name| file_name.to_str()) .ok_or(path.to_owned()) .and_then(|file_name| { - snapshot_from_fs_path(&path).map(|snapshot| (file_name.to_owned(), snapshot)) + snapshot_from_fs_path(&path) + .map(|snapshot| (file_name.to_owned(), snapshot)) }) }) .into_iter() diff --git a/memofs/src/snapshot.rs b/memofs/src/snapshot.rs index 227b12a5f..0df3d4734 100644 --- a/memofs/src/snapshot.rs +++ b/memofs/src/snapshot.rs @@ -1,8 +1,5 @@ -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -use std::fs; -use std::fs::DirEntry; -use std::path::PathBuf; /// A slice of a tree of files. Can be loaded into an /// [`InMemoryFs`](struct.InMemoryFs.html). @@ -45,33 +42,4 @@ impl VfsSnapshot { children: BTreeMap::new(), } } - - pub fn from_fs_path(path: &PathBuf) -> Result { - if path.is_file() { - fs::read_to_string(path).ok() - .map(|content| Self::file(content)) - .ok_or(path.to_owned()) - } else { - let entries: Result, PathBuf> = fs::read_dir(path) - .map_err(|_| path.to_owned())? - .map(|entry| entry.map_err(|_| path.to_owned())) - .into_iter() - .collect(); - - let vfs_entries: Result, PathBuf> = entries?.iter() - .map(|entry| { - let path = entry.path(); - - path.file_name() - .and_then(|file_name| file_name.to_str()) - .ok_or(path.to_owned()) - .and_then(|file_name| { - Self::from_fs_path(&path) - .map(|snapshot| (file_name.to_owned(), snapshot)) - }) - }).into_iter().collect(); - - Ok(Self::dir(vfs_entries?)) - } - } } diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index 3ef71ebd1..99b6cd636 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -1,7 +1,7 @@ use crate::serve_session::ServeSession; -use memofs::{Vfs, VfsSnapshot}; use memofs::InMemoryFs; +use memofs::{Vfs, VfsSnapshot}; use roblox_install::RobloxStudio; use snafu::{ResultExt, Snafu}; use std::{ @@ -52,15 +52,13 @@ pub fn plugin(options: PluginCommand) -> Result<(), PluginError> { Ok(()) } - pub fn install_plugin() -> Result<(), PluginError> { static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode")); let plugin_snapshot: VfsSnapshot = bincode::deserialize(PLUGIN_BINCODE) .expect("rojo's plugin was not properly packed into rojo's binary"); - let studio = RobloxStudio::locate() - .context(CannotLocateRobloxStudio)?; + let studio = RobloxStudio::locate().context(CannotLocateRobloxStudio)?; let plugins_folder_path = studio.plugins_path(); @@ -70,7 +68,9 @@ pub fn install_plugin() -> Result<(), PluginError> { } let mut in_memory_fs = InMemoryFs::new(); - in_memory_fs.load_snapshot("plugin", plugin_snapshot).context(Io)?; + in_memory_fs + .load_snapshot("plugin", plugin_snapshot) + .context(Io)?; let vfs = Vfs::new(in_memory_fs); @@ -78,7 +78,11 @@ pub fn install_plugin() -> Result<(), PluginError> { let tree = session.tree(); - log::trace!("Writing plugin {} in {}", PLUGIN_FILE_NAME, plugins_folder_path.to_string_lossy()); + log::trace!( + "Writing plugin {} in {}", + PLUGIN_FILE_NAME, + plugins_folder_path.to_string_lossy() + ); let file = File::create(plugins_folder_path.join(PLUGIN_FILE_NAME)).context(Io)?; let mut file = BufWriter::new(file); @@ -91,16 +95,21 @@ pub fn install_plugin() -> Result<(), PluginError> { } fn uninstall_plugin() -> Result<(), PluginError> { - let studio = RobloxStudio::locate() - .context(CannotLocateRobloxStudio)?; + let studio = RobloxStudio::locate().context(CannotLocateRobloxStudio)?; let rojo_plugin_path = studio.plugins_path().join(PLUGIN_FILE_NAME); if rojo_plugin_path.exists() { - log::trace!("Removing existing plugin {}", rojo_plugin_path.to_string_lossy()); + log::trace!( + "Removing existing plugin {}", + rojo_plugin_path.to_string_lossy() + ); fs::remove_file(rojo_plugin_path).context(Io)?; } else { - log::trace!("Plugin not installed {}", rojo_plugin_path.to_string_lossy()); + log::trace!( + "Plugin not installed {}", + rojo_plugin_path.to_string_lossy() + ); } Ok(()) From 1fd0f0c730085316183e4e07e9afe7ec55a75453 Mon Sep 17 00:00:00 2001 From: jeparlefrancais Date: Tue, 17 Mar 2020 00:12:39 -0400 Subject: [PATCH 03/15] filter spec files --- build.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/build.rs b/build.rs index 5c7d14a78..dd8add38f 100644 --- a/build.rs +++ b/build.rs @@ -15,12 +15,16 @@ fn snapshot_from_fs_path(path: &PathBuf) -> Result { let vfs_entries: Result, PathBuf> = entries? .iter() - .filter(|entry| !entry.path().ends_with(".spec.lua")) + .filter(|entry| { + let file_name = entry.file_name(); + !file_name.to_string_lossy().ends_with(".spec.lua") + }) .map(|entry| { let path = entry.path(); - path.file_name() - .and_then(|file_name| file_name.to_str()) + entry + .file_name() + .to_str() .ok_or(path.to_owned()) .and_then(|file_name| { snapshot_from_fs_path(&path) @@ -43,7 +47,8 @@ fn snapshot_from_fs_path(path: &PathBuf) -> Result { fn main() { let out_dir = env::var_os("OUT_DIR").unwrap(); - let plugin_root = PathBuf::from("plugin"); + let root_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap(); + let plugin_root = PathBuf::from(root_dir).join("plugin"); let plugin_modules = plugin_root.join("modules"); From 44c9513a3ac2003c885ea8c728c26de3defe0ef7 Mon Sep 17 00:00:00 2001 From: jeparlefrancais <35781636+jeparlefrancais@users.noreply.github.com> Date: Fri, 20 Mar 2020 17:03:33 -0400 Subject: [PATCH 04/15] Update src/cli/plugin.rs Co-Authored-By: Lucien Greathouse --- src/cli/plugin.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index 99b6cd636..df6da09dd 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -1,7 +1,6 @@ use crate::serve_session::ServeSession; -use memofs::InMemoryFs; -use memofs::{Vfs, VfsSnapshot}; +use memofs::{InMemoryFs, Vfs, VfsSnapshot}; use roblox_install::RobloxStudio; use snafu::{ResultExt, Snafu}; use std::{ From 81ea5a6d8678c118053a9871eda64a65478825fc Mon Sep 17 00:00:00 2001 From: jeparlefrancais <35781636+jeparlefrancais@users.noreply.github.com> Date: Fri, 20 Mar 2020 17:05:14 -0400 Subject: [PATCH 05/15] Update src/cli/plugin.rs Co-Authored-By: Lucien Greathouse --- src/cli/plugin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index df6da09dd..2e392ae16 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -20,7 +20,7 @@ enum PluginSubcommand { Uninstall, } -/// Install rojo's plugin. +/// Install Rojo's plugin. #[derive(Debug, StructOpt)] pub struct PluginCommand { #[structopt(subcommand)] From 466f0528c5239250bcff610063dadd66dafe0780 Mon Sep 17 00:00:00 2001 From: jeparlefrancais Date: Fri, 20 Mar 2020 17:24:37 -0400 Subject: [PATCH 06/15] fix comments --- build.rs | 6 ++++-- src/cli/mod.rs | 16 ++++++++++++++++ src/cli/plugin.rs | 39 +++++++++++---------------------------- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/build.rs b/build.rs index dd8add38f..a0d0e7dfc 100644 --- a/build.rs +++ b/build.rs @@ -17,7 +17,9 @@ fn snapshot_from_fs_path(path: &PathBuf) -> Result { .iter() .filter(|entry| { let file_name = entry.file_name(); - !file_name.to_string_lossy().ends_with(".spec.lua") + !file_name.to_str() + .map(|name| name.ends_with(".spec.lua")) + .unwrap_or(false) }) .map(|entry| { let path = entry.path(); @@ -36,7 +38,7 @@ fn snapshot_from_fs_path(path: &PathBuf) -> Result { Ok(VfsSnapshot::dir(vfs_entries?)) } else { - println!("cargo:rerun-if-changed={}", path.to_string_lossy()); + println!("cargo:rerun-if-changed={}", path.display()); fs::read_to_string(path) .ok() .map(|content| VfsSnapshot::file(content)) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index bebd78fb9..878c0c979 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -234,3 +234,19 @@ fn resolve_path(path: &Path) -> Cow<'_, Path> { Cow::Owned(env::current_dir().unwrap().join(path)) } } + +#[derive(Debug, StructOpt)] +pub enum PluginSubcommand { + /// Install the plugin in Roblox plugins folder. If the plugin is already installed, installing + /// it again will overwrite the current plugin file. + Install, + /// Removes the plugin if installed. + Uninstall, +} + +/// Install Rojo's plugin. +#[derive(Debug, StructOpt)] +pub struct PluginCommand { + #[structopt(subcommand)] + subcommand: PluginSubcommand, +} diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index 2e392ae16..c6da40ba2 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -1,31 +1,15 @@ -use crate::serve_session::ServeSession; - -use memofs::{InMemoryFs, Vfs, VfsSnapshot}; -use roblox_install::RobloxStudio; -use snafu::{ResultExt, Snafu}; use std::{ fs::{self, File}, io::{self, BufWriter}, }; -use structopt::StructOpt; -static PLUGIN_FILE_NAME: &str = concat!("rojo-", env!("CARGO_PKG_VERSION"), ".rbxmx"); +use memofs::{InMemoryFs, Vfs, VfsSnapshot}; +use roblox_install::RobloxStudio; +use snafu::{ResultExt, Snafu}; -#[derive(Debug, StructOpt)] -enum PluginSubcommand { - /// Install the plugin in Roblox plugins folder. If the plugin is already installed, installing - /// it again will overwrite the current plugin file. - Install, - /// Removes the plugin if installed. - Uninstall, -} +use crate::{cli::{PluginCommand, PluginSubcommand}, serve_session::ServeSession}; -/// Install Rojo's plugin. -#[derive(Debug, StructOpt)] -pub struct PluginCommand { - #[structopt(subcommand)] - subcommand: PluginSubcommand, -} +static PLUGIN_FILE_NAME: &str = "RojoManagedPlugin.rbxmx"; #[derive(Debug, Snafu)] pub struct PluginError(Error); @@ -45,17 +29,16 @@ fn xml_encode_config() -> rbx_xml::EncodeOptions { pub fn plugin(options: PluginCommand) -> Result<(), PluginError> { match options.subcommand { - PluginSubcommand::Install => install_plugin()?, - PluginSubcommand::Uninstall => uninstall_plugin()?, + PluginSubcommand::Install => install_plugin(), + PluginSubcommand::Uninstall => uninstall_plugin(), } - Ok(()) } pub fn install_plugin() -> Result<(), PluginError> { static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode")); let plugin_snapshot: VfsSnapshot = bincode::deserialize(PLUGIN_BINCODE) - .expect("rojo's plugin was not properly packed into rojo's binary"); + .expect("Rojo's plugin was not properly packed into Rojo's binary"); let studio = RobloxStudio::locate().context(CannotLocateRobloxStudio)?; @@ -80,7 +63,7 @@ pub fn install_plugin() -> Result<(), PluginError> { log::trace!( "Writing plugin {} in {}", PLUGIN_FILE_NAME, - plugins_folder_path.to_string_lossy() + plugins_folder_path.display() ); let file = File::create(plugins_folder_path.join(PLUGIN_FILE_NAME)).context(Io)?; @@ -101,13 +84,13 @@ fn uninstall_plugin() -> Result<(), PluginError> { if rojo_plugin_path.exists() { log::trace!( "Removing existing plugin {}", - rojo_plugin_path.to_string_lossy() + rojo_plugin_path.display() ); fs::remove_file(rojo_plugin_path).context(Io)?; } else { log::trace!( "Plugin not installed {}", - rojo_plugin_path.to_string_lossy() + rojo_plugin_path.display() ); } From 7aa752a2a7725c6b63f48d5b794eb51bb291d4c6 Mon Sep 17 00:00:00 2001 From: jeparlefrancais Date: Fri, 20 Mar 2020 17:31:37 -0400 Subject: [PATCH 07/15] encode plugin with rbx_binary --- src/cli/plugin.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index c6da40ba2..bc85b8676 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -23,10 +23,6 @@ enum Error { Io { source: io::Error }, } -fn xml_encode_config() -> rbx_xml::EncodeOptions { - rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) -} - pub fn plugin(options: PluginCommand) -> Result<(), PluginError> { match options.subcommand { PluginSubcommand::Install => install_plugin(), @@ -71,7 +67,8 @@ pub fn install_plugin() -> Result<(), PluginError> { let root_id = tree.get_root_id(); - rbx_xml::to_writer(&mut file, tree.inner(), &[root_id], xml_encode_config()).unwrap(); + rbx_binary::encode(tree.inner(), &[root_id], &mut file) + .expect("Unable to encode Rojo's plugin"); Ok(()) } From a37a8ba3d4a8a42660314905939b35b56d486ce6 Mon Sep 17 00:00:00 2001 From: jeparlefrancais Date: Fri, 20 Mar 2020 17:43:37 -0400 Subject: [PATCH 08/15] update build script --- build.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build.rs b/build.rs index a0d0e7dfc..738a7e038 100644 --- a/build.rs +++ b/build.rs @@ -10,7 +10,6 @@ fn snapshot_from_fs_path(path: &PathBuf) -> Result { let entries: Result, PathBuf> = fs::read_dir(path) .map_err(|_| path.to_owned())? .map(|entry| entry.map_err(|_| path.to_owned())) - .into_iter() .collect(); let vfs_entries: Result, PathBuf> = entries? @@ -33,7 +32,6 @@ fn snapshot_from_fs_path(path: &PathBuf) -> Result { .map(|snapshot| (file_name.to_owned(), snapshot)) }) }) - .into_iter() .collect(); Ok(VfsSnapshot::dir(vfs_entries?)) @@ -78,8 +76,6 @@ fn main() { }), }); - println!("cargo:rerun-if-changed=build.rs"); - let out_path = Path::new(&out_dir).join("plugin.bincode"); let out_file = fs::File::create(&out_path).unwrap(); From ef4731959ad2fca17a95cf25caee41d3230c26ff Mon Sep 17 00:00:00 2001 From: jeparlefrancais Date: Fri, 20 Mar 2020 18:36:40 -0400 Subject: [PATCH 09/15] refactor pathbuf error into io error --- build.rs | 51 +++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/build.rs b/build.rs index 738a7e038..ec694f950 100644 --- a/build.rs +++ b/build.rs @@ -1,46 +1,37 @@ use std::env; -use std::fs; -use std::path::{Path, PathBuf}; +use std::{fs, io, path::{Path, PathBuf}}; use maplit::hashmap; use memofs::VfsSnapshot; -fn snapshot_from_fs_path(path: &PathBuf) -> Result { +fn snapshot_from_fs_path(path: &PathBuf) -> io::Result { if path.is_dir() { - let entries: Result, PathBuf> = fs::read_dir(path) - .map_err(|_| path.to_owned())? - .map(|entry| entry.map_err(|_| path.to_owned())) - .collect(); + let vfs_entries = fs::read_dir(path)? + .filter_map(|entry| { + let entry = match entry { + Ok(entry) => entry, + Err(error) => return Some(Err(error)), + }; - let vfs_entries: Result, PathBuf> = entries? - .iter() - .filter(|entry| { - let file_name = entry.file_name(); - !file_name.to_str() - .map(|name| name.ends_with(".spec.lua")) - .unwrap_or(false) - }) - .map(|entry| { - let path = entry.path(); + let file_name = entry.file_name().to_str() + .map(str::to_owned) + .expect(&format!("Could not get file name from {}", entry.path().display())); - entry - .file_name() - .to_str() - .ok_or(path.to_owned()) - .and_then(|file_name| { - snapshot_from_fs_path(&path) - .map(|snapshot| (file_name.to_owned(), snapshot)) - }) - }) - .collect(); + if file_name.ends_with(".spec.lua") { + None + } else { + Some(snapshot_from_fs_path(&entry.path()) + .map(|snapshot| (file_name, snapshot))) + } + }); - Ok(VfsSnapshot::dir(vfs_entries?)) + let entries: io::Result> = vfs_entries.collect(); + + Ok(VfsSnapshot::dir(entries?)) } else { println!("cargo:rerun-if-changed={}", path.display()); fs::read_to_string(path) - .ok() .map(|content| VfsSnapshot::file(content)) - .ok_or(path.to_owned()) } } From 6d1f7da3c050f9236caa00adb87c94095e14fb78 Mon Sep 17 00:00:00 2001 From: jeparlefrancais Date: Fri, 20 Mar 2020 22:56:21 -0400 Subject: [PATCH 10/15] fix rojo typo --- src/cli/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 878c0c979..22454ca2a 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -56,7 +56,7 @@ pub enum Subcommand { /// Open Rojo's documentation in your browser. Doc, - /// Manages rojo's Roblox plugin. + /// Manages Rojo's Roblox plugin. Plugin(PluginCommand), } From c790972b1f0ccd35e48b7d96f3472e038685b445 Mon Sep 17 00:00:00 2001 From: jeparlefrancais Date: Fri, 20 Mar 2020 23:13:47 -0400 Subject: [PATCH 11/15] remove snafu --- Cargo.lock | 12 ++++++++++++ src/cli/plugin.rs | 35 +++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51e802762..600033219 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,16 @@ name = "anyhow" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "atty" version = "0.2.14" @@ -2634,6 +2644,8 @@ dependencies = [ "checksum aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum anyhow 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785" +"checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index bc85b8676..adb6c5ad4 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -3,52 +3,52 @@ use std::{ io::{self, BufWriter}, }; +use anyhow::Result; use memofs::{InMemoryFs, Vfs, VfsSnapshot}; use roblox_install::RobloxStudio; -use snafu::{ResultExt, Snafu}; +use thiserror::Error; use crate::{cli::{PluginCommand, PluginSubcommand}, serve_session::ServeSession}; static PLUGIN_FILE_NAME: &str = "RojoManagedPlugin.rbxmx"; -#[derive(Debug, Snafu)] -pub struct PluginError(Error); - -#[derive(Debug, Snafu)] +#[derive(Debug, Error)] enum Error { - #[snafu(display("Could not locate Roblox Studio: {}", source.to_string()))] + #[error("Could not locate Roblox Studio: {source}")] CannotLocateRobloxStudio { source: roblox_install::Error }, - #[snafu(display("{}", source))] + #[error("{source}")] Io { source: io::Error }, } -pub fn plugin(options: PluginCommand) -> Result<(), PluginError> { +pub fn plugin(options: PluginCommand) -> Result<()> { match options.subcommand { PluginSubcommand::Install => install_plugin(), PluginSubcommand::Uninstall => uninstall_plugin(), } } -pub fn install_plugin() -> Result<(), PluginError> { +pub fn install_plugin() -> Result<()> { static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode")); let plugin_snapshot: VfsSnapshot = bincode::deserialize(PLUGIN_BINCODE) .expect("Rojo's plugin was not properly packed into Rojo's binary"); - let studio = RobloxStudio::locate().context(CannotLocateRobloxStudio)?; + let studio = RobloxStudio::locate() + .map_err(|source| Error::CannotLocateRobloxStudio { source })?; let plugins_folder_path = studio.plugins_path(); if !plugins_folder_path.exists() { - fs::create_dir(plugins_folder_path).context(Io)?; + fs::create_dir(plugins_folder_path) + .map_err(|source| Error::Io { source })?; log::trace!("Plugins folder did not exist so it was created"); } let mut in_memory_fs = InMemoryFs::new(); in_memory_fs .load_snapshot("plugin", plugin_snapshot) - .context(Io)?; + .map_err(|source| Error::Io { source })?; let vfs = Vfs::new(in_memory_fs); @@ -61,7 +61,8 @@ pub fn install_plugin() -> Result<(), PluginError> { PLUGIN_FILE_NAME, plugins_folder_path.display() ); - let file = File::create(plugins_folder_path.join(PLUGIN_FILE_NAME)).context(Io)?; + let file = File::create(plugins_folder_path.join(PLUGIN_FILE_NAME)) + .map_err(|source| Error::Io { source })?; let mut file = BufWriter::new(file); @@ -73,8 +74,9 @@ pub fn install_plugin() -> Result<(), PluginError> { Ok(()) } -fn uninstall_plugin() -> Result<(), PluginError> { - let studio = RobloxStudio::locate().context(CannotLocateRobloxStudio)?; +fn uninstall_plugin() -> Result<()> { + let studio = RobloxStudio::locate() + .map_err(|source| Error::CannotLocateRobloxStudio { source })?; let rojo_plugin_path = studio.plugins_path().join(PLUGIN_FILE_NAME); @@ -83,7 +85,8 @@ fn uninstall_plugin() -> Result<(), PluginError> { "Removing existing plugin {}", rojo_plugin_path.display() ); - fs::remove_file(rojo_plugin_path).context(Io)?; + fs::remove_file(rojo_plugin_path) + .map_err(|source| Error::Io { source })?; } else { log::trace!( "Plugin not installed {}", From c30bb33ed4d9b56ff7f6cbfd766534c647d6ebf5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 12:47:46 -0700 Subject: [PATCH 12/15] Update `snapshot_from_fs_path` * Print `rerun-if-changed` even for directories, in order to run the build.rs script when files are added. * Switch `filter_map` loop to a regular for loop. I like the FP-style iterator stuff in Rust, but I think Result handling is easier in a normal loop. Also, I don't believe the result of read_dir implements `ExactSizedIterator`, so some of the wins of map+collect aren't there. --- build.rs | 56 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/build.rs b/build.rs index ec694f950..ef7b39b0e 100644 --- a/build.rs +++ b/build.rs @@ -1,37 +1,39 @@ use std::env; -use std::{fs, io, path::{Path, PathBuf}}; +use std::{ + fs, io, + path::{Path, PathBuf}, +}; use maplit::hashmap; use memofs::VfsSnapshot; -fn snapshot_from_fs_path(path: &PathBuf) -> io::Result { +fn snapshot_from_fs_path(path: &Path) -> io::Result { + println!("cargo:rerun-if-changed={}", path.display()); + if path.is_dir() { - let vfs_entries = fs::read_dir(path)? - .filter_map(|entry| { - let entry = match entry { - Ok(entry) => entry, - Err(error) => return Some(Err(error)), - }; - - let file_name = entry.file_name().to_str() - .map(str::to_owned) - .expect(&format!("Could not get file name from {}", entry.path().display())); - - if file_name.ends_with(".spec.lua") { - None - } else { - Some(snapshot_from_fs_path(&entry.path()) - .map(|snapshot| (file_name, snapshot))) - } - }); - - let entries: io::Result> = vfs_entries.collect(); - - Ok(VfsSnapshot::dir(entries?)) + let mut children = Vec::new(); + + for entry in fs::read_dir(path)? { + let entry = entry?; + + let file_name = entry.file_name().to_str().unwrap().to_owned(); + + // We can skip any TestEZ test files since they aren't necessary for + // the plugin to run. + if file_name.ends_with(".spec.lua") { + continue; + } + + let child_snapshot = snapshot_from_fs_path(&entry.path())?; + + children.push((file_name, child_snapshot)); + } + + Ok(VfsSnapshot::dir(children)) } else { - println!("cargo:rerun-if-changed={}", path.display()); - fs::read_to_string(path) - .map(|content| VfsSnapshot::file(content)) + let content = fs::read_to_string(path)?; + + Ok(VfsSnapshot::file(content)) } } From 9c9bcf96424d37f740c4dab9c33eb80d5e844b89 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 12:56:25 -0700 Subject: [PATCH 13/15] Replace Result::unwrap with ? in build.rs --- Cargo.toml | 4 +++- build.rs | 32 +++++++++++++++++--------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 28a2ccc19..875663bf1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -98,9 +98,11 @@ uuid = { version = "0.8.1", features = ["v4", "serde"] } winreg = "0.6.2" [build-dependencies] +memofs = { version = "0.1.0", path = "memofs" } + +anyhow = "1.0.27" bincode = "1.2.1" maplit = "1.0.1" -memofs = { version = "0.1.0", path = "memofs" } [dev-dependencies] rojo-insta-ext = { path = "rojo-insta-ext" } diff --git a/build.rs b/build.rs index ef7b39b0e..71f8d1fd9 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,7 @@ -use std::env; use std::{ - fs, io, + env, + fs::{self, File}, + io, path::{Path, PathBuf}, }; @@ -25,7 +26,6 @@ fn snapshot_from_fs_path(path: &Path) -> io::Result { } let child_snapshot = snapshot_from_fs_path(&entry.path())?; - children.push((file_name, child_snapshot)); } @@ -37,7 +37,7 @@ fn snapshot_from_fs_path(path: &Path) -> io::Result { } } -fn main() { +fn main() -> Result<(), anyhow::Error> { let out_dir = env::var_os("OUT_DIR").unwrap(); let root_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap(); @@ -46,31 +46,33 @@ fn main() { let plugin_modules = plugin_root.join("modules"); let snapshot = VfsSnapshot::dir(hashmap! { - "default.project.json" => snapshot_from_fs_path(&plugin_root.join("default.project.json")).unwrap(), - "fmt" => snapshot_from_fs_path(&plugin_root.join("fmt")).unwrap(), - "http" => snapshot_from_fs_path(&plugin_root.join("http")).unwrap(), - "log" => snapshot_from_fs_path(&plugin_root.join("log")).unwrap(), - "src" => snapshot_from_fs_path(&plugin_root.join("src")).unwrap(), + "default.project.json" => snapshot_from_fs_path(&plugin_root.join("default.project.json"))?, + "fmt" => snapshot_from_fs_path(&plugin_root.join("fmt"))?, + "http" => snapshot_from_fs_path(&plugin_root.join("http"))?, + "log" => snapshot_from_fs_path(&plugin_root.join("log"))?, + "src" => snapshot_from_fs_path(&plugin_root.join("src"))?, "modules" => VfsSnapshot::dir(hashmap! { "roact" => VfsSnapshot::dir(hashmap! { - "src" => snapshot_from_fs_path(&plugin_modules.join("roact").join("src")).unwrap() + "src" => snapshot_from_fs_path(&plugin_modules.join("roact").join("src"))? }), "promise" => VfsSnapshot::dir(hashmap! { - "lib" => snapshot_from_fs_path(&plugin_modules.join("promise").join("lib")).unwrap() + "lib" => snapshot_from_fs_path(&plugin_modules.join("promise").join("lib"))? }), "t" => VfsSnapshot::dir(hashmap! { - "lib" => snapshot_from_fs_path(&plugin_modules.join("t").join("lib")).unwrap() + "lib" => snapshot_from_fs_path(&plugin_modules.join("t").join("lib"))? }), "rbx-dom" => VfsSnapshot::dir(hashmap! { "rbx_dom_lua" => VfsSnapshot::dir(hashmap! { - "src" => snapshot_from_fs_path(&plugin_modules.join("rbx-dom").join("rbx_dom_lua").join("src")).unwrap() + "src" => snapshot_from_fs_path(&plugin_modules.join("rbx-dom").join("rbx_dom_lua").join("src"))? }) }), }), }); let out_path = Path::new(&out_dir).join("plugin.bincode"); - let out_file = fs::File::create(&out_path).unwrap(); + let out_file = File::create(&out_path)?; + + bincode::serialize_into(out_file, &snapshot)?; - bincode::serialize_into(out_file, &snapshot).unwrap(); + Ok(()) } From 20d4dd0b7ac839de6ba66a38a5e0b6779ef2c544 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 13:07:08 -0700 Subject: [PATCH 14/15] Simplify error handling code in runtime --- src/cli/mod.rs | 10 ++++--- src/cli/plugin.rs | 76 +++++++++++++++-------------------------------- 2 files changed, 30 insertions(+), 56 deletions(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 7a3b9354e..5bd69a1db 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -114,7 +114,7 @@ pub enum Subcommand { /// Open Rojo's documentation in your browser. Doc, - /// Manages Rojo's Roblox plugin. + /// Manages Rojo's Roblox Studio plugin. Plugin(PluginCommand), } @@ -295,10 +295,12 @@ fn resolve_path(path: &Path) -> Cow<'_, Path> { #[derive(Debug, StructOpt)] pub enum PluginSubcommand { - /// Install the plugin in Roblox plugins folder. If the plugin is already installed, installing - /// it again will overwrite the current plugin file. + /// 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 installed. + + /// Removes the plugin if it is installed. Uninstall, } diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index adb6c5ad4..a39fa2845 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -1,25 +1,19 @@ use std::{ fs::{self, File}, - io::{self, BufWriter}, + io::BufWriter, }; use anyhow::Result; use memofs::{InMemoryFs, Vfs, VfsSnapshot}; use roblox_install::RobloxStudio; -use thiserror::Error; -use crate::{cli::{PluginCommand, PluginSubcommand}, serve_session::ServeSession}; - -static PLUGIN_FILE_NAME: &str = "RojoManagedPlugin.rbxmx"; - -#[derive(Debug, Error)] -enum Error { - #[error("Could not locate Roblox Studio: {source}")] - CannotLocateRobloxStudio { source: roblox_install::Error }, +use crate::{ + cli::{PluginCommand, PluginSubcommand}, + serve_session::ServeSession, +}; - #[error("{source}")] - Io { source: io::Error }, -} +static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode")); +static PLUGIN_FILE_NAME: &str = "RojoManagedPlugin.rbxm"; pub fn plugin(options: PluginCommand) -> Result<()> { match options.subcommand { @@ -29,69 +23,47 @@ pub fn plugin(options: PluginCommand) -> Result<()> { } pub fn install_plugin() -> Result<()> { - static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode")); - let plugin_snapshot: VfsSnapshot = bincode::deserialize(PLUGIN_BINCODE) .expect("Rojo's plugin was not properly packed into Rojo's binary"); - let studio = RobloxStudio::locate() - .map_err(|source| Error::CannotLocateRobloxStudio { source })?; + let studio = RobloxStudio::locate()?; let plugins_folder_path = studio.plugins_path(); if !plugins_folder_path.exists() { - fs::create_dir(plugins_folder_path) - .map_err(|source| Error::Io { source })?; - log::trace!("Plugins folder did not exist so it was created"); + log::debug!("Creating Roblox Studio plugins folder"); + fs::create_dir(plugins_folder_path)?; } let mut in_memory_fs = InMemoryFs::new(); - in_memory_fs - .load_snapshot("plugin", plugin_snapshot) - .map_err(|source| Error::Io { source })?; + in_memory_fs.load_snapshot("plugin", plugin_snapshot)?; let vfs = Vfs::new(in_memory_fs); - let session = ServeSession::new(vfs, "plugin"); - let tree = session.tree(); - - log::trace!( - "Writing plugin {} in {}", - PLUGIN_FILE_NAME, - plugins_folder_path.display() - ); - let file = File::create(plugins_folder_path.join(PLUGIN_FILE_NAME)) - .map_err(|source| Error::Io { source })?; + let plugin_path = plugins_folder_path.join(PLUGIN_FILE_NAME); + log::debug!("Writing plugin to {}", plugin_path.display()); - let mut file = BufWriter::new(file); + let mut file = BufWriter::new(File::create(plugin_path)?); + let tree = session.tree(); let root_id = tree.get_root_id(); - rbx_binary::encode(tree.inner(), &[root_id], &mut file) - .expect("Unable to encode Rojo's plugin"); + rbx_binary::encode(tree.inner(), &[root_id], &mut file)?; Ok(()) } fn uninstall_plugin() -> Result<()> { - let studio = RobloxStudio::locate() - .map_err(|source| Error::CannotLocateRobloxStudio { source })?; - - let rojo_plugin_path = studio.plugins_path().join(PLUGIN_FILE_NAME); - - if rojo_plugin_path.exists() { - log::trace!( - "Removing existing plugin {}", - rojo_plugin_path.display() - ); - fs::remove_file(rojo_plugin_path) - .map_err(|source| Error::Io { source })?; + 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::trace!( - "Plugin not installed {}", - rojo_plugin_path.display() - ); + log::debug!("Plugin not installed at {}", plugin_path.display()); } Ok(()) From 4d5b13f288846657f23ad96d6be43f50d93add5f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 13:26:36 -0700 Subject: [PATCH 15/15] Checkout with submodules --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 536a7d9d7..ffe614eaf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,8 @@ jobs: steps: - uses: actions/checkout@v1 + with: + submodules: true - name: Setup Rust toolchain run: rustup default ${{ matrix.rust_version }}