diff --git a/Cargo.lock b/Cargo.lock index 16629f3..2cbac99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -425,6 +425,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "filetime" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.2.16", + "windows-sys 0.48.0", +] + [[package]] name = "fnv" version = "1.0.7" @@ -659,6 +671,26 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -697,6 +729,26 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +[[package]] +name = "kqueue" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -768,6 +820,7 @@ dependencies = [ "askama", "askama_rocket", "log", + "notify", "rocket", "rust-embed", "serde", @@ -814,6 +867,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] @@ -848,6 +902,22 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "notify" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5738a2795d57ea20abec2d6d76c6081186709c0024187cd5977265eda6598b51" +dependencies = [ + "bitflags 1.3.2", + "filetime", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -915,7 +985,7 @@ dependencies = [ "libc", "redox_syscall 0.3.5", "smallvec", - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -1787,7 +1857,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -1805,13 +1875,37 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 40bebfb..5d883a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = ["cli", "shared"] name = "meowy-webring" version = "0.1.0" edition = "2021" +rust-version = "1.70" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -45,3 +46,7 @@ path = "./shared" [dependencies.simple_logger] version = "4" default-features = false + +[dependencies.notify] +version = "6" +default-features = false diff --git a/shared/src/directories.rs b/shared/src/directories.rs index 8f56795..a746fa6 100644 --- a/shared/src/directories.rs +++ b/shared/src/directories.rs @@ -26,6 +26,11 @@ pub fn get_names_path() -> Result { return get_file_from_directory(directory.data_dir(), "names.json"); } +pub fn get_names_project_path() -> Result { + let directory = get_project_dir()?; + return Ok(directory.data_dir().to_path_buf()); +} + fn create_directory(path: &Path) -> Result<(), Error> { match std::fs::create_dir_all(path) { Ok(_) => { diff --git a/shared/src/errors.rs b/shared/src/errors.rs index aa744fe..a8647ce 100644 --- a/shared/src/errors.rs +++ b/shared/src/errors.rs @@ -5,7 +5,8 @@ pub enum ErrorStatus { DirectoriesError, LoggerInitializationError, NotFoundError, - AlreadyExistsError + AlreadyExistsError, + GenericError } pub struct Error { diff --git a/src/main.rs b/src/main.rs index 505df51..cbbd994 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ -use shared::{directories, names}; +use crate::watcher::hot_reloading; +use rocket::tokio; +use sites::init_names; #[macro_use] extern crate rocket; @@ -6,16 +8,15 @@ extern crate rocket; mod assets; mod links; mod routes; +mod sites; +mod watcher; #[launch] -fn rocket() -> _ { - let names_path = directories::get_names_path().unwrap(); - println!("names.json path: {}", names_path.display()); - let names_file = names::read_names_file(&names_path).unwrap(); - let names = names::load_names(names_file).unwrap(); +async fn rocket() -> _ { + init_names().unwrap(); + tokio::task::spawn_blocking(hot_reloading); rocket::build() - .manage(names) .mount( "/", routes![routes::index, routes::previous, routes::next, routes::name], diff --git a/src/routes.rs b/src/routes.rs index 576669b..28292f1 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -1,12 +1,14 @@ -use crate::{links::{next_url, previous_url}, assets::ErrorTemplate}; +use crate::{ + assets::ErrorTemplate, + links::{next_url, previous_url}, + sites::{ Names}, +}; use rocket::{ http::Status, response::Redirect, serde::{json::Json, Serialize}, - State, }; -use shared::names::Site; const NOT_FOUND_ERROR: ErrorTemplate = ErrorTemplate { error: "Not Found", @@ -26,27 +28,25 @@ pub fn index() -> &'static str { } #[get("/previous?")] -pub fn previous(source_url: String, names: &State>) -> Result { - let names = names.inner(); - match previous_url(&source_url, names) { +pub fn previous(source_url: String) -> Result { + match previous_url(&source_url, &Names::global()) { Some(url) => Ok(Redirect::to(format!("https://{}", url))), None => Err(Status::NotFound), } } #[get("/next?")] -pub fn next(source_url: String, names: &State>) -> Result { - let names = names.inner(); - match next_url(&source_url, names) { +pub fn next(source_url: String) -> Result { + match next_url(&source_url, &Names::global()) { Some(url) => Ok(Redirect::to(format!("https://{}", url))), None => Err(Status::NotFound), } } #[get("/name?")] -pub fn name(source_url: String, names: &State>) -> Result, Status> { - let previous_site_name = previous_url(&source_url, names); - let next_site_name = next_url(&source_url, names); +pub fn name(source_url: String) -> Result, Status> { + let previous_site_name = previous_url(&source_url, &Names::global()); + let next_site_name = next_url(&source_url, &Names::global()); if previous_site_name.is_none() && next_site_name.is_none() { return Err(Status::NotFound); diff --git a/src/sites.rs b/src/sites.rs new file mode 100644 index 0000000..6509ea8 --- /dev/null +++ b/src/sites.rs @@ -0,0 +1,39 @@ +use shared::{ + directories, + errors::{Error, ErrorStatus}, + names::{self, Site}, +}; +use std::sync::{Mutex, OnceLock}; + +pub struct Names {} + +impl Names { + pub fn global() -> Vec { + NAMES.get().unwrap().lock().unwrap().clone() + } + pub fn set() { + *NAMES.get().unwrap().lock().unwrap() = get_names(); + } +} + +static NAMES: OnceLock>> = OnceLock::new(); + +pub fn init_names() -> Result<(), Error> { + println!( + "names.json path: {}", + directories::get_names_path().unwrap().display() + ); + match NAMES.set(Mutex::new(get_names())) { + Ok(_) => Ok(()), + Err(_) => Err(Error { + status: ErrorStatus::GenericError, + data: "an error has occured while trying to get the names.json file".into(), + }), + } +} + +fn get_names() -> Vec { + let names_path = directories::get_names_path().unwrap(); + let names_file = names::read_names_file(&names_path).unwrap(); + names::load_names(names_file).unwrap() +} diff --git a/src/watcher.rs b/src/watcher.rs new file mode 100644 index 0000000..b908de7 --- /dev/null +++ b/src/watcher.rs @@ -0,0 +1,29 @@ +use notify::{Result, Watcher}; +use shared::directories; + +use crate::sites::Names; + +pub(crate) fn hot_reloading() { + let (tx, rx) = std::sync::mpsc::channel(); + let names_path = directories::get_names_project_path().unwrap(); + let mut watcher = notify::recommended_watcher(tx).unwrap(); + + watcher + .watch(&names_path, notify::RecursiveMode::NonRecursive) + .unwrap(); + + for res in rx { + watch(res); + } +} + +fn watch(res: Result) { + match res { + Ok(event) => { + if event.kind.is_modify() { + Names::set(); + } + } + Err(err) => println!("Error: {}", err), + } +}