Compare commits

...

4 Commits

Author SHA1 Message Date
Fries 93bd3540e8 use async mutex
looks like the best way to do the state thing after all is global so i
should use async mutexes so stuff doesn't block.
2023-07-03 22:14:10 -07:00
Fries a672135793 add cursed hot reloading support
im sorry if you have to look at the sites.rs file.
2023-07-03 16:23:14 -07:00
Fries ac93e8e0eb Merge pull request 'make printing less complicated and refactor cli' (#5) from improvements into main
Reviewed-on: #5
2023-07-03 23:20:53 +00:00
Fries d6a763a90b change spelling of seperator to separator
looks like i spelt that wrong..
2023-07-03 16:19:45 -07:00
14 changed files with 226 additions and 42 deletions

110
Cargo.lock generated
View File

@ -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]]

View File

@ -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"]

View File

@ -8,9 +8,9 @@ pub(crate) struct Arguments {
#[arg( #[arg(
long, long,
short, short,
help = "a seperator string to seperate the url from the name. defaults to : with a space after that." help = "a separator string to seperate the url from the name. defaults to : with a space after that."
)] )]
pub(crate) seperator: Option<String>, pub(crate) separator: Option<String>,
#[command(subcommand)] #[command(subcommand)]
pub(crate) command: Commands, pub(crate) command: Commands,
} }

View File

@ -10,7 +10,7 @@ pub(crate) fn add(
path: &Path, path: &Path,
url: &String, url: &String,
name: &Option<String>, name: &Option<String>,
seperator: &String, separator: &String,
) -> Result<(), Error> { ) -> Result<(), Error> {
let names_file = names::read_names_file(path)?; let names_file = names::read_names_file(path)?;
let mut names = names::load_names(names_file)?; let mut names = names::load_names(names_file)?;
@ -36,7 +36,7 @@ pub(crate) fn add(
std::fs::write(path, json).unwrap(); std::fs::write(path, json).unwrap();
println!( println!(
"added {} to names.json", "added {} to names.json",
site_string(&site, PrintOptions::All, seperator) site_string(&site, PrintOptions::All, separator)
); );
Ok(()) Ok(())

View File

@ -11,7 +11,7 @@ pub(crate) fn print(
path: &Path, path: &Path,
filter: &Option<String>, filter: &Option<String>,
group: &PrintGroup, group: &PrintGroup,
seperator: &String, separator: &String,
json: bool, json: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let names_file = names::read_names_file(path)?; let names_file = names::read_names_file(path)?;
@ -25,7 +25,7 @@ pub(crate) fn print(
data: "this url was not found in names.json".into(), data: "this url was not found in names.json".into(),
}); });
} }
return filter_site(&names[0], json, seperator, group); return filter_site(&names[0], json, separator, group);
} }
for site in names { for site in names {
@ -34,7 +34,7 @@ pub(crate) fn print(
continue; continue;
} }
printing(seperator, &site, group); printing(separator, &site, group);
} }
Ok(()) Ok(())
@ -43,7 +43,7 @@ pub(crate) fn print(
fn filter_site( fn filter_site(
site: &Site, site: &Site,
json: bool, json: bool,
seperator: &String, separator: &String,
group: &PrintGroup, group: &PrintGroup,
) -> Result<(), Error> { ) -> Result<(), Error> {
if json { if json {
@ -51,7 +51,7 @@ fn filter_site(
return Ok(()); return Ok(());
} }
return Ok(printing(seperator, site, group)); return Ok(printing(separator, site, group));
} }
fn json_printing(site: &Site) -> Result<(), Error> { fn json_printing(site: &Site) -> Result<(), Error> {
@ -67,8 +67,8 @@ fn json_printing(site: &Site) -> Result<(), Error> {
} }
} }
fn printing(seperator: &String, site: &Site, group: &PrintGroup) { fn printing(separator: &String, site: &Site, group: &PrintGroup) {
let string = site_string(site, print_group_to_options(group), seperator); let string = site_string(site, print_group_to_options(group), separator);
println!("{}", string); println!("{}", string);
} }

View File

@ -3,7 +3,7 @@ use std::path::Path;
use crate::commands::utils::{site_string, PrintOptions}; use crate::commands::utils::{site_string, PrintOptions};
pub(crate) fn remove(path: &Path, url: &String, seperator: &String) -> Result<(), Error> { pub(crate) fn remove(path: &Path, url: &String, separator: &String) -> Result<(), Error> {
let names_file = names::read_names_file(path)?; let names_file = names::read_names_file(path)?;
let mut names = names::load_names(names_file)?; let mut names = names::load_names(names_file)?;
@ -11,7 +11,7 @@ pub(crate) fn remove(path: &Path, url: &String, seperator: &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, seperator) site_string(&site, PrintOptions::All, separator)
); );
} }
&site.url != url &site.url != url

View File

@ -6,7 +6,7 @@ pub(super) enum PrintOptions {
All, All,
} }
pub(super) fn site_string(site: &Site, options: PrintOptions, seperator: &String) -> String { pub(super) fn site_string(site: &Site, options: PrintOptions, separator: &String) -> String {
let mut string = String::new(); let mut string = String::new();
if matches!(options, PrintOptions::Url) || matches!(options, PrintOptions::All) { if matches!(options, PrintOptions::Url) || matches!(options, PrintOptions::All) {
@ -18,7 +18,7 @@ pub(super) fn site_string(site: &Site, options: PrintOptions, seperator: &String
return string; return string;
} }
if !string.is_empty() { if !string.is_empty() {
string += &format!("{}{}", seperator, name) string += &format!("{}{}", separator, name)
} else { } else {
string += name; string += name;
} }

View File

@ -13,7 +13,7 @@ fn main() -> Result<(), Error> {
let default_path = directories::get_names_path()?; let default_path = directories::get_names_path()?;
let args = Arguments::parse(); let args = Arguments::parse();
let seperator = args.seperator.unwrap_or(": ".into()); let separator = args.separator.unwrap_or(": ".into());
let path = match &args.path { let path = match &args.path {
Some(path) => Path::new(path), Some(path) => Path::new(path),
@ -25,9 +25,9 @@ fn main() -> Result<(), Error> {
filter, filter,
group, group,
json, json,
} => print(path, filter, group, &seperator, *json)?, } => print(path, filter, group, &separator, *json)?,
Commands::Add { url, name } => add(path, url, name, &seperator)?, Commands::Add { url, name } => add(path, url, name, &separator)?,
Commands::Remove { url } => remove(path, url, &seperator)?, Commands::Remove { url } => remove(path, url, &separator)?,
}; };
Ok(()) Ok(())

View File

@ -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(_) => {

View File

@ -5,7 +5,8 @@ pub enum ErrorStatus {
DirectoriesError, DirectoriesError,
LoggerInitializationError, LoggerInitializationError,
NotFoundError, NotFoundError,
AlreadyExistsError AlreadyExistsError,
GenericError
} }
pub struct Error { pub struct Error {

View File

@ -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],

View File

@ -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);

37
src/sites.rs Normal file
View File

@ -0,0 +1,37 @@
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() {
*NAMES.get().unwrap().blocking_lock() = get_names();
}
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())) {
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<Site> {
let names_path = directories::get_names_path().unwrap();
let names_file = names::read_names_file(&names_path).unwrap();
names::load_names(names_file).unwrap()
}

30
src/watcher.rs Normal file
View File

@ -0,0 +1,30 @@
use notify::{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.is_modify() {
sites::set_names();
}
}
Err(err) => println!("Error: {}", err),
}
}