hot reloading support #6
11 changed files with 217 additions and 28 deletions
110
Cargo.lock
generated
110
Cargo.lock
generated
|
@ -425,12 +425,33 @@ dependencies = [
|
||||||
"version_check",
|
"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]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fsevent-sys"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.28"
|
version = "0.3.28"
|
||||||
|
@ -659,6 +680,26 @@ version = "0.1.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
|
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]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
|
@ -697,6 +738,26 @@ version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
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]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -768,6 +829,7 @@ dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"askama_rocket",
|
"askama_rocket",
|
||||||
"log",
|
"log",
|
||||||
|
"notify",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rust-embed",
|
"rust-embed",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -814,6 +876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
|
"log",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
@ -848,6 +911,23 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"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",
|
||||||
|
"fsevent-sys",
|
||||||
|
"inotify",
|
||||||
|
"kqueue",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"walkdir",
|
||||||
|
"windows-sys 0.45.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
|
@ -915,7 +995,7 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall 0.3.5",
|
"redox_syscall 0.3.5",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-targets",
|
"windows-targets 0.48.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1787,7 +1867,7 @@ version = "0.48.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets",
|
"windows-targets 0.48.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1805,13 +1885,37 @@ dependencies = [
|
||||||
"windows_x86_64_msvc 0.42.2",
|
"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]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
|
|
|
@ -5,6 +5,7 @@ members = ["cli", "shared"]
|
||||||
name = "meowy-webring"
|
name = "meowy-webring"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
rust-version = "1.70"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
@ -45,3 +46,8 @@ path = "./shared"
|
||||||
[dependencies.simple_logger]
|
[dependencies.simple_logger]
|
||||||
version = "4"
|
version = "4"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.notify]
|
||||||
|
version = "6"
|
||||||
|
default-features = false
|
||||||
|
features = ["macos_fsevent"]
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub(crate) fn print(
|
||||||
|
|
||||||
if let Some(filter) = filter {
|
if let Some(filter) = filter {
|
||||||
names.retain(|f| &f.url == filter);
|
names.retain(|f| &f.url == filter);
|
||||||
if names.len() == 0 {
|
if names.is_empty() {
|
||||||
return Err(Error {
|
return Err(Error {
|
||||||
status: ErrorStatus::NotFoundError,
|
status: ErrorStatus::NotFoundError,
|
||||||
data: "this url was not found in names.json".into(),
|
data: "this url was not found in names.json".into(),
|
||||||
|
@ -50,8 +50,8 @@ fn filter_site(
|
||||||
json_printing(site)?;
|
json_printing(site)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
printing(separator, site, group);
|
||||||
return Ok(printing(separator, site, group));
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_printing(site: &Site) -> Result<(), Error> {
|
fn json_printing(site: &Site) -> Result<(), Error> {
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub(crate) fn remove(path: &Path, url: &String, separator: &String) -> Result<()
|
||||||
if &site.url == url {
|
if &site.url == url {
|
||||||
println!(
|
println!(
|
||||||
"removing {} from names.json",
|
"removing {} from names.json",
|
||||||
site_string(&site, PrintOptions::All, separator)
|
site_string(site, PrintOptions::All, separator)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
&site.url != url
|
&site.url != url
|
||||||
|
|
|
@ -24,5 +24,5 @@ pub(super) fn site_string(site: &Site, options: PrintOptions, separator: &String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return string;
|
string
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,11 @@ pub fn get_names_path() -> Result<PathBuf, Error> {
|
||||||
return get_file_from_directory(directory.data_dir(), "names.json");
|
return get_file_from_directory(directory.data_dir(), "names.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_names_project_path() -> Result<PathBuf, Error> {
|
||||||
|
let directory = get_project_dir()?;
|
||||||
|
return Ok(directory.data_dir().to_path_buf());
|
||||||
|
}
|
||||||
|
|
||||||
fn create_directory(path: &Path) -> Result<(), Error> {
|
fn create_directory(path: &Path) -> Result<(), Error> {
|
||||||
match std::fs::create_dir_all(path) {
|
match std::fs::create_dir_all(path) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
|
|
@ -5,7 +5,8 @@ pub enum ErrorStatus {
|
||||||
DirectoriesError,
|
DirectoriesError,
|
||||||
LoggerInitializationError,
|
LoggerInitializationError,
|
||||||
NotFoundError,
|
NotFoundError,
|
||||||
AlreadyExistsError
|
AlreadyExistsError,
|
||||||
|
GenericError
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
|
|
15
src/main.rs
15
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]
|
#[macro_use]
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
@ -6,16 +8,15 @@ extern crate rocket;
|
||||||
mod assets;
|
mod assets;
|
||||||
mod links;
|
mod links;
|
||||||
mod routes;
|
mod routes;
|
||||||
|
mod sites;
|
||||||
|
mod watcher;
|
||||||
|
|
||||||
#[launch]
|
#[launch]
|
||||||
fn rocket() -> _ {
|
async fn rocket() -> _ {
|
||||||
let names_path = directories::get_names_path().unwrap();
|
init_names().unwrap();
|
||||||
println!("names.json path: {}", names_path.display());
|
tokio::task::spawn_blocking(hot_reloading);
|
||||||
let names_file = names::read_names_file(&names_path).unwrap();
|
|
||||||
let names = names::load_names(names_file).unwrap();
|
|
||||||
|
|
||||||
rocket::build()
|
rocket::build()
|
||||||
.manage(names)
|
|
||||||
.mount(
|
.mount(
|
||||||
"/",
|
"/",
|
||||||
routes![routes::index, routes::previous, routes::next, routes::name],
|
routes![routes::index, routes::previous, routes::next, routes::name],
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
use crate::{links::{next_url, previous_url}, assets::ErrorTemplate};
|
use crate::{
|
||||||
|
assets::ErrorTemplate,
|
||||||
|
links::{next_url, previous_url},
|
||||||
|
sites::get_global_names,
|
||||||
|
};
|
||||||
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
http::Status,
|
http::Status,
|
||||||
response::Redirect,
|
response::Redirect,
|
||||||
serde::{json::Json, Serialize},
|
serde::{json::Json, Serialize},
|
||||||
State,
|
|
||||||
};
|
};
|
||||||
use shared::names::Site;
|
|
||||||
|
|
||||||
const NOT_FOUND_ERROR: ErrorTemplate = ErrorTemplate {
|
const NOT_FOUND_ERROR: ErrorTemplate = ErrorTemplate {
|
||||||
error: "Not Found",
|
error: "Not Found",
|
||||||
|
@ -26,27 +28,25 @@ pub fn index() -> &'static str {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/previous?<source_url>")]
|
#[get("/previous?<source_url>")]
|
||||||
pub fn previous(source_url: String, names: &State<Vec<Site>>) -> Result<Redirect, Status> {
|
pub async fn previous(source_url: String) -> Result<Redirect, Status> {
|
||||||
let names = names.inner();
|
match previous_url(&source_url, &get_global_names().await) {
|
||||||
match previous_url(&source_url, names) {
|
|
||||||
Some(url) => Ok(Redirect::to(format!("https://{}", url))),
|
Some(url) => Ok(Redirect::to(format!("https://{}", url))),
|
||||||
None => Err(Status::NotFound),
|
None => Err(Status::NotFound),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/next?<source_url>")]
|
#[get("/next?<source_url>")]
|
||||||
pub fn next(source_url: String, names: &State<Vec<Site>>) -> Result<Redirect, Status> {
|
pub async fn next(source_url: String) -> Result<Redirect, Status> {
|
||||||
let names = names.inner();
|
match next_url(&source_url, &get_global_names().await) {
|
||||||
match next_url(&source_url, names) {
|
|
||||||
Some(url) => Ok(Redirect::to(format!("https://{}", url))),
|
Some(url) => Ok(Redirect::to(format!("https://{}", url))),
|
||||||
None => Err(Status::NotFound),
|
None => Err(Status::NotFound),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/name?<source_url>")]
|
#[get("/name?<source_url>")]
|
||||||
pub fn name(source_url: String, names: &State<Vec<Site>>) -> Result<Json<JsonResponse>, Status> {
|
pub async fn name(source_url: String) -> Result<Json<JsonResponse>, Status> {
|
||||||
let previous_site_name = previous_url(&source_url, names);
|
let previous_site_name = previous_url(&source_url, &get_global_names().await);
|
||||||
let next_site_name = next_url(&source_url, names);
|
let next_site_name = next_url(&source_url, &get_global_names().await);
|
||||||
|
|
||||||
if previous_site_name.is_none() && next_site_name.is_none() {
|
if previous_site_name.is_none() && next_site_name.is_none() {
|
||||||
return Err(Status::NotFound);
|
return Err(Status::NotFound);
|
||||||
|
|
40
src/sites.rs
Normal file
40
src/sites.rs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
use rocket::tokio::sync::Mutex;
|
||||||
|
use shared::{
|
||||||
|
directories,
|
||||||
|
errors::{Error, ErrorStatus},
|
||||||
|
names::{self, Site},
|
||||||
|
};
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
pub async fn get_global_names() -> Vec<Site> {
|
||||||
|
NAMES.get().unwrap().lock().await.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_names() {
|
||||||
|
match get_names() {
|
||||||
|
Ok(names) => *NAMES.get().unwrap().blocking_lock() = names,
|
||||||
|
Err(err) => println!("{:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NAMES: OnceLock<Mutex<Vec<Site>>> = 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().unwrap())) {
|
||||||
|
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() -> Result<Vec<Site>, Error> {
|
||||||
|
let names_path = directories::get_names_path()?;
|
||||||
|
let names_file = names::read_names_file(&names_path)?;
|
||||||
|
names::load_names(names_file)
|
||||||
|
}
|
32
src/watcher.rs
Normal file
32
src/watcher.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
use notify::{
|
||||||
|
event::{DataChange, ModifyKind},
|
||||||
|
EventKind, Result, Watcher,
|
||||||
|
};
|
||||||
|
use shared::directories;
|
||||||
|
|
||||||
|
use crate::sites;
|
||||||
|
|
||||||
|
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<notify::Event>) {
|
||||||
|
match res {
|
||||||
|
Ok(event) => {
|
||||||
|
if event.kind == EventKind::Modify(ModifyKind::Data(DataChange::Any)) {
|
||||||
|
sites::set_names();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => println!("Error: {}", err),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue