aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <yvchraiqi@protonmail.com>2022-06-10 17:48:32 +0200
committermetamuffin <yvchraiqi@protonmail.com>2022-06-10 17:48:32 +0200
commit45f2d1651f17d7e155748cfd1e1cd9a96f3e530e (patch)
tree6847a4552db06b56a5e0a55aa56354eccb7c41b1
parentd65b915f3dfda28aad6f2806df38c8ad77135d8b (diff)
downloadkarlender-45f2d1651f17d7e155748cfd1e1cd9a96f3e530e.tar
karlender-45f2d1651f17d7e155748cfd1e1cd9a96f3e530e.tar.bz2
karlender-45f2d1651f17d7e155748cfd1e1cd9a96f3e530e.tar.zst
better cli
-rw-r--r--Cargo.lock48
-rw-r--r--karlc/Cargo.toml2
-rw-r--r--karlc/src/client.rs20
-rw-r--r--karlc/src/main.rs77
-rw-r--r--karlcommon/src/protocol.rs13
-rw-r--r--karld/src/interface.rs7
-rw-r--r--karld/src/main.rs18
7 files changed, 159 insertions, 26 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 13acdf5..e233ef1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -133,6 +133,17 @@ dependencies = [
]
[[package]]
+name = "getrandom"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -185,6 +196,7 @@ dependencies = [
"env_logger",
"karlcommon",
"log",
+ "rand",
"serde",
"serde_json",
]
@@ -264,6 +276,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa"
[[package]]
+name = "ppv-lite86"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -306,6 +324,36 @@ dependencies = [
]
[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
name = "regex"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/karlc/Cargo.toml b/karlc/Cargo.toml
index f95dee0..653933a 100644
--- a/karlc/Cargo.toml
+++ b/karlc/Cargo.toml
@@ -13,3 +13,5 @@ env_logger = "0.9.0"
log = "0.4.17"
crossbeam-channel = "0.5.4"
chrono = { version = "0.4.19", features = ["serde"] }
+rand = "0.8.5"
+
diff --git a/karlc/src/client.rs b/karlc/src/client.rs
index 6420da0..e7ca44d 100644
--- a/karlc/src/client.rs
+++ b/karlc/src/client.rs
@@ -5,8 +5,8 @@ use std::{
};
use crossbeam_channel::Receiver;
-use karlcommon::{ClientboundPacket, ServerboundPacket};
-use log::debug;
+use karlcommon::{version, ClientboundPacket, ServerboundPacket};
+use log::{debug, error};
pub struct Client {
socket: UnixStream,
@@ -17,18 +17,20 @@ impl Client {
pub fn new(socket: UnixStream) -> Self {
let (sender, receiver) = crossbeam_channel::unbounded();
let mut reader = BufReader::new(socket.try_clone().unwrap());
- thread::spawn(move || {
- loop {
- let mut buf = String::new();
- reader.read_line(&mut buf).unwrap();
- let p: ClientboundPacket = serde_json::from_str(buf.as_str()).unwrap();
- debug!("<- {:?}", p);
+ thread::spawn(move || loop {
+ let mut buf = String::new();
+ reader.read_line(&mut buf).unwrap();
+ let p: ClientboundPacket = serde_json::from_str(buf.as_str()).unwrap();
+ debug!("<- {:?}", p);
+ if let ClientboundPacket::Error(e) = p {
+ error!("daemon reported error: {:?}", e);
+ } else {
sender.send(p).unwrap();
}
});
let mut c = Self { receiver, socket };
c.send(ServerboundPacket::Handshake {
- version: env!("CARGO_PKG_VERSION").to_owned(),
+ version: version!(),
});
return c;
}
diff --git a/karlc/src/main.rs b/karlc/src/main.rs
index 9a89de9..ef56fd9 100644
--- a/karlc/src/main.rs
+++ b/karlc/src/main.rs
@@ -1,16 +1,19 @@
pub mod client;
use chrono::{NaiveDateTime, Utc};
-use clap::{Parser, Subcommand};
+use clap::{Args, Parser, Subcommand};
use client::Client;
-use karlcommon::{socket_path, version, ClientboundPacket, ServerboundPacket};
+use karlcommon::{socket_path, version, ClientboundPacket, ServerboundPacket, Task};
use log::{error, info};
-use std::{os::unix::net::UnixStream, process::exit};
+use std::{os::unix::net::UnixStream, path::PathBuf, process::exit};
/// CLI interface for karld
#[derive(Parser)]
#[clap(about, author, version)]
-struct Args {
+struct Arguments {
+ /// Custom path to the daemon socket
+ #[clap(long)]
+ socket_path: Option<PathBuf>,
#[clap(subcommand)]
action: Action,
}
@@ -21,13 +24,36 @@ pub enum Action {
Version,
/// List all tasks
List,
+ /// Remove a task by id
+ Remove { id: u64 },
+ /// Update a task by id
+ Update {
+ id: u64,
+ #[clap(flatten)]
+ task: TaskSpec,
+ },
+ /// Create a task
+ Create {
+ #[clap(flatten)]
+ task: TaskSpec,
+ },
+}
+
+#[derive(Args)]
+pub struct TaskSpec {
+ #[clap(short, long)]
+ name: String,
+ #[clap(short, long)]
+ description: Option<String>,
+ #[clap(short, long)]
+ tags: Vec<String>,
}
fn main() {
env_logger::init();
- let args = Args::parse();
+ let args = Arguments::parse();
- let socket = match UnixStream::connect(socket_path()) {
+ let socket = match UnixStream::connect(args.socket_path.unwrap_or(socket_path())) {
Ok(s) => s,
Err(e) => {
error!("failed to connect to socket: {}", e);
@@ -62,7 +88,11 @@ fn main() {
\x1b[38;2;100;255;100mDescription:\x1b[0m {}
\x1b[38;2;100;255;100mOccurence:\x1b[0m {:?}
\x1b[38;2;100;255;100mNext instances: \x1b[0m",
- t.id, t.name, t.description, t.occurence
+ t.id,
+ t.name,
+ t.description
+ .unwrap_or("\x1b[3m\x1b[2m(no description)\x1b[0m".to_string()),
+ t.occurence
);
client.send(ServerboundPacket::ListInstances {
task: t.id,
@@ -94,5 +124,38 @@ fn main() {
}
}
}
+ Action::Remove { id } => {
+ client.send(ServerboundPacket::RemoveTask(id));
+ }
+ Action::Update { id, task } => {
+ let mut t = task.build();
+ t.id = id;
+ client.send(ServerboundPacket::UpdateTask(t))
+ }
+ Action::Create { task } => client.send(ServerboundPacket::UpdateTask(task.build())),
+ }
+
+ // sync
+ client.send(ServerboundPacket::Sync);
+ for p in client.receiver.iter() {
+ if let ClientboundPacket::Sync = p {
+ break;
+ }
+ }
+}
+
+impl TaskSpec {
+ pub fn build(self) -> Task {
+ Task {
+ id: rand::random(),
+ name: self.name,
+ description: self.description,
+ tags: self.tags,
+ priority: 0.0,
+ completed: None,
+ scheduled: None,
+ occurence: None,
+ deadline: None,
+ }
}
}
diff --git a/karlcommon/src/protocol.rs b/karlcommon/src/protocol.rs
index e5bb9f0..a86ca3d 100644
--- a/karlcommon/src/protocol.rs
+++ b/karlcommon/src/protocol.rs
@@ -6,14 +6,23 @@ use serde::{Deserialize, Serialize};
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
pub enum ClientboundPacket {
Handshake { version: String },
- Error(String),
+ Error(ProtoError),
TaskList(Vec<Task>),
InstanceList(Vec<Instance>),
+ Sync,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(tag = "type", content = "data", rename_all = "snake_case")]
+pub enum ProtoError {
+ UnknownTask,
+ FormatError(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
pub enum ServerboundPacket {
+ Sync,
Handshake {
version: String,
},
@@ -31,7 +40,7 @@ pub enum ServerboundPacket {
pub struct Task {
pub id: u64,
pub name: String,
- pub description: String,
+ pub description: Option<String>,
pub tags: Vec<String>,
pub priority: f64,
diff --git a/karld/src/interface.rs b/karld/src/interface.rs
index 127c0db..750f307 100644
--- a/karld/src/interface.rs
+++ b/karld/src/interface.rs
@@ -1,5 +1,5 @@
use crate::handle_packet;
-use karlcommon::{socket_path, version, ClientboundPacket, ServerboundPacket};
+use karlcommon::{socket_path, version, ClientboundPacket, ProtoError, ServerboundPacket};
use log::{debug, error, info, warn};
use std::io;
use std::io::{BufRead, BufReader, ErrorKind, Write};
@@ -61,7 +61,10 @@ fn handle_connection(id: u32, mut stream: UnixStream) -> io::Result<()> {
Err(err) => {
warn!("client error: {:?}", &err);
responder
- .send(ClientboundPacket::Error(format!("{}", &err)))
+ .send(ClientboundPacket::Error(ProtoError::FormatError(format!(
+ "{}",
+ &err
+ ))))
.map_err(|_| io::Error::from(ErrorKind::InvalidInput))?
}
}
diff --git a/karld/src/main.rs b/karld/src/main.rs
index 1bc5798..0983554 100644
--- a/karld/src/main.rs
+++ b/karld/src/main.rs
@@ -5,7 +5,9 @@ use chrono::NaiveDateTime;
use condition::ConditionFind;
use crossbeam_channel::Sender;
use interface::network_loop;
-use karlcommon::{ClientboundPacket, Condition, Instance, Property, ServerboundPacket, Task};
+use karlcommon::{
+ ClientboundPacket, Condition, Instance, Property, ProtoError, ServerboundPacket, Task,
+};
use log::{debug, info};
use std::{collections::HashMap, sync::RwLock};
@@ -16,8 +18,8 @@ fn main() {
0,
Task {
id: 0,
- name: "blub".to_string(),
- description: "blob".to_string(),
+ name: "Mittagessen im Februar".to_string(),
+ description: None,
tags: vec![],
priority: 69.0,
completed: None,
@@ -46,6 +48,9 @@ lazy_static::lazy_static! {
pub fn handle_packet(client: u32, packet: ServerboundPacket, responder: Sender<ClientboundPacket>) {
match packet {
+ ServerboundPacket::Sync => {
+ let _ = responder.send(ClientboundPacket::Sync);
+ }
ServerboundPacket::ListTasks => {
let _ = responder.send(ClientboundPacket::TaskList(
TASKS.read().unwrap().values().map(|e| e.clone()).collect(),
@@ -55,7 +60,9 @@ pub fn handle_packet(client: u32, packet: ServerboundPacket, responder: Sender<C
TASKS.write().unwrap().insert(t.id, t);
}
ServerboundPacket::RemoveTask(i) => {
- TASKS.write().unwrap().remove(&i);
+ if TASKS.write().unwrap().remove(&i).is_none() {
+ let _ = responder.send(ClientboundPacket::Error(ProtoError::UnknownTask));
+ }
}
ServerboundPacket::Handshake { version } => {
debug!("{client}: version {version}");
@@ -64,8 +71,7 @@ pub fn handle_packet(client: u32, packet: ServerboundPacket, responder: Sender<C
let t = match TASKS.read().unwrap().get(&task).cloned() {
Some(t) => t,
None => {
- let _ =
- responder.send(ClientboundPacket::Error("task does not exist".to_string()));
+ let _ = responder.send(ClientboundPacket::Error(ProtoError::UnknownTask));
return;
}
};