make the cli more portable, and add logging

the cli now uses a new module in the shared crate, called directories
which is a module that has functions for directory stuff, mainly, it
uses the directories crate to have a portable way to have directories
for the application like data directories and config directories.

i also added logging to the shared and cli crates, so you can see debug
stuff with the RUST_LOG environment variable.
This commit is contained in:
Fries 2023-07-01 18:27:03 -07:00
parent 16c5c771bb
commit 8206cc6105
11 changed files with 319 additions and 53 deletions

24
.vscode/launch.json vendored
View file

@ -4,13 +4,17 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug",
"program": "${workspaceFolder}/<executable file>",
"args": [],
"cwd": "${workspaceFolder}"
}
]
}
{
"type": "lldb",
"request": "launch",
"name": "run meowy-cli",
"program": "${workspaceFolder}/target/debug/meowy-cli",
"args": ["print"],
"cwd": "${workspaceFolder}",
"sourceMap": {},
"sourceLanguages": [
"rust"
],
}
]
}

174
Cargo.lock generated
View file

@ -53,7 +53,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -63,7 +63,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
dependencies = [
"anstyle",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -253,9 +253,11 @@ name = "cli"
version = "0.1.0"
dependencies = [
"clap",
"log",
"serde",
"serde_json",
"shared",
"simple_logger",
]
[[package]]
@ -337,6 +339,27 @@ dependencies = [
"crypto-common",
]
[[package]]
name = "directories"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.48.0",
]
[[package]]
name = "either"
version = "1.8.1"
@ -366,7 +389,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -653,7 +676,7 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi 0.3.1",
"libc",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -665,7 +688,7 @@ dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -790,7 +813,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
"wasi",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -858,6 +881,12 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "overload"
version = "0.1.1"
@ -882,7 +911,7 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"redox_syscall 0.3.5",
"smallvec",
"windows-targets",
]
@ -995,6 +1024,15 @@ dependencies = [
"getrandom",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_syscall"
version = "0.3.5"
@ -1004,6 +1042,17 @@ dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"redox_syscall 0.2.16",
"thiserror",
]
[[package]]
name = "ref-cast"
version = "1.0.16"
@ -1187,7 +1236,7 @@ dependencies = [
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1287,6 +1336,8 @@ dependencies = [
name = "shared"
version = "0.1.0"
dependencies = [
"directories",
"log",
"serde",
"serde_json",
]
@ -1300,6 +1351,16 @@ dependencies = [
"libc",
]
[[package]]
name = "simple_logger"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2230cd5c29b815c9b699fb610b49a5ed65588f3509d9f0108be3a885da629333"
dependencies = [
"log",
"windows-sys 0.42.0",
]
[[package]]
name = "slab"
version = "0.4.8"
@ -1375,9 +1436,29 @@ dependencies = [
"autocfg",
"cfg-if",
"fastrand",
"redox_syscall",
"redox_syscall 0.3.5",
"rustix",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
name = "thiserror"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
@ -1432,7 +1513,7 @@ dependencies = [
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1707,6 +1788,21 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
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]]
name = "windows-sys"
version = "0.48.0"
@ -1722,51 +1818,93 @@ version = "0.48.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
"windows_i686_gnu 0.48.0",
"windows_i686_msvc 0.48.0",
"windows_x86_64_gnu 0.48.0",
"windows_x86_64_gnullvm 0.48.0",
"windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"

View file

@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
serde = "1.0"
serde_json = "1.0"
log = "0.4"
[dependencies.clap]
version = "4"
@ -14,6 +15,10 @@ features = ["derive"]
[dependencies.shared]
path = "../shared"
[dependencies.simple_logger]
version = "4"
default-features = false
[[bin]]
name = "meowy-cli"
path = "src/main.rs"

View file

@ -3,8 +3,8 @@ use clap::{arg, command, Args, Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub(crate) struct Arguments {
#[arg(help = "the path to the names.json file")]
pub(crate) path: String,
#[arg(help = "the path to the names.json file", long, short)]
pub(crate) path: Option<String>,
#[command(subcommand)]
pub(crate) command: Commands,
}

View file

@ -1,3 +1,5 @@
use std::path::Path;
use shared::{
errors::{Error, ErrorStatus},
names::Site,
@ -5,50 +7,58 @@ use shared::{
use crate::arguments::PrintGroup;
fn read_names(path: &String) -> Result<Vec<Site>, Error> {
match std::fs::read_to_string(path) {
fn read_names(path: &Path) -> Result<Vec<Site>, Error> {
match shared::names::read_names_file(path) {
Ok(names) => {
return shared::names::load_names(names);
}
Err(err) => Err(Error {
status: ErrorStatus::IOError,
data: err.to_string(),
data: err.data,
}),
}
}
pub(crate) fn print(path: &String, group: &PrintGroup) -> Result<(), Error> {
pub(crate) fn print(path: &Path, group: &PrintGroup) -> Result<(), Error> {
let names = read_names(path)?;
Ok(for site in names {
if group.name {
println!("{}", site.name.unwrap_or_default());
log::info!("{}", site.name.unwrap_or_default());
continue;
}
if group.url {
println!("{}", site.url);
log::info!("{}", site.url);
continue;
}
println!("{:?}", site);
log::info!("{:?}", site);
})
}
pub(crate) fn add(path: &String, url: &String, name: &Option<String>) -> Result<(), Error> {
pub(crate) fn add(path: &Path, url: &String, name: &Option<String>) -> Result<(), Error> {
let mut names = read_names(path)?;
let site = Site {
url: url.to_string(),
name: name.to_owned(),
};
names.push(site);
log::debug!("adding {:?} to {}", site, path.display());
names.push(site.clone());
let json = serde_json::to_string(&names).unwrap();
std::fs::write(path, json).unwrap();
log::info!("added {:?} to names.json", site);
Ok(())
}
pub(crate) fn remove(path: &String, url: &String) -> Result<(), Error> {
pub(crate) fn remove(path: &Path, url: &String) -> Result<(), Error> {
let mut names = read_names(path)?;
names.retain(|site| &site.url != url);
names.retain(|site| {
if &site.url == url {
log::info!("removing {:?} from names.json", site);
}
&site.url != url
});
let json = serde_json::to_string(&names).unwrap();
std::fs::write(path, json).unwrap();
Ok(())
}

View file

@ -1,18 +1,39 @@
use std::path::Path;
use arguments::{Arguments, Commands};
use clap::Parser;
use commands::{add, print, remove};
use shared::errors::Error;
use log::LevelFilter;
use shared::{
directories,
errors::{Error, ErrorStatus},
};
use simple_logger::SimpleLogger;
mod arguments;
mod commands;
fn main() -> Result<(), Error> {
fn main() -> Result<(), Error> {
if let Err(err) = SimpleLogger::new().with_level(LevelFilter::Info).env().init() {
return Err(Error {
status: ErrorStatus::LoggerInitializationError,
data: err.to_string(),
});
}
let directory = directories::get_project_dir()?;
let args = Arguments::parse();
let default_path = directories::get_file_from_directory(directory.data_dir(), "names.json")?;
let path = match &args.path {
Some(path) => Path::new(path),
None => &default_path,
};
match &args.command {
Commands::Print { group } => print(&args.path, &group)?,
Commands::Add { url, name } => add(&args.path, url, name)?,
Commands::Remove { url } => remove(&args.path, url)?,
Commands::Print { group } => print(path, &group)?,
Commands::Add { url, name } => add(path, url, name)?,
Commands::Remove { url } => remove(path, url)?,
};
Ok(())

View file

@ -5,6 +5,8 @@ edition = "2021"
[dependencies]
serde_json = "1.0"
directories = "5.0"
log = "0.4"
[dependencies.serde]
version = "1.0"

35
shared/src/directories.rs Normal file
View file

@ -0,0 +1,35 @@
use std::path::{Path, PathBuf};
use directories::ProjectDirs;
use crate::errors::{Error, ErrorStatus, DIRECTORIES_ERROR_MESSAGE};
pub fn get_project_dir() -> Result<ProjectDirs, Error> {
match ProjectDirs::from("moe", "solarpunk", "meowy-webring") {
Some(project) => Ok(project),
None => Err(Error {
status: ErrorStatus::DirectoriesError,
data: DIRECTORIES_ERROR_MESSAGE.into(),
}),
}
}
pub fn get_file_from_directory(path: &Path, filename: &str) -> Result<PathBuf, Error> {
if !path.exists() {
create_directory(path)?;
}
Ok(path.join(filename))
}
fn create_directory(path: &Path) -> Result<(), Error> {
match std::fs::create_dir_all(path) {
Ok(_) => {
log::debug!("created the directory {}", path.display());
Ok(())
}
Err(err) => Err(Error {
status: ErrorStatus::IOError,
data: err.to_string(),
}),
}
}

View file

@ -1,16 +1,24 @@
#[derive(Debug)]
pub enum ErrorStatus {
IOError,
ParsingError
ParsingError,
DirectoriesError,
LoggerInitializationError
}
pub struct Error {
pub status: ErrorStatus,
pub data: String
pub data: String,
}
pub(crate) static DIRECTORIES_ERROR_MESSAGE: &str = "could not retreive a valid home path from the operating system. maybe try to define the HOME enviroment variable if you\'re on a unix or unix like operating system.";
impl core::fmt::Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "A {:?} error has occured.\nDetails: {}", self.status, self.data)
}
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"A {:?} error has occured.\nDetails: {}",
self.status, self.data
)
}
}

View file

@ -1,2 +1,3 @@
pub mod names;
pub mod errors;
pub mod directories;

View file

@ -1,8 +1,10 @@
use std::path::Path;
use serde::{Deserialize, Serialize};
use crate::errors::{Error, ErrorStatus};
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Site {
pub url: String,
pub name: Option<String>,
@ -10,10 +12,50 @@ pub struct Site {
pub fn load_names(names: String) -> Result<Vec<Site>, Error> {
match serde_json::from_str::<Vec<Site>>(&names) {
Ok(content) => Ok(content),
Ok(content) => {
log::debug!("successfully parsed names.json.");
Ok(content)
}
Err(err) => Err(Error {
status: ErrorStatus::ParsingError,
data: err.to_string(),
}),
}
}
pub fn read_names_file(path: &Path) -> Result<String, Error> {
if !path.exists() {
log::debug!(
"the names.json file does not exist at {}. creating names.json",
path.display()
);
create_names_file(path)?
}
match std::fs::read_to_string(path) {
Ok(data) => {
log::debug!(
"successfully read the names.json file at {}",
path.display()
);
Ok(data)
}
Err(err) => Err(Error {
status: ErrorStatus::IOError,
data: err.to_string(),
}),
}
}
fn create_names_file(path: &Path) -> Result<(), Error> {
match std::fs::write(path, "[]") {
Ok(_) => {
log::debug!("created a names.json file at {}", path.display());
Ok(())
}
Err(err) => Err(Error {
status: ErrorStatus::IOError,
data: err.to_string(),
}),
}
}