Skip to content

Commit

Permalink
feat(core): abstract everything in core
Browse files Browse the repository at this point in the history
Feels right todo it this way. more feature guard needs to be added
though.
  • Loading branch information
kkharji committed Apr 18, 2022
1 parent 4543d31 commit b0362ee
Show file tree
Hide file tree
Showing 16 changed files with 175 additions and 171 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Expand Up @@ -32,12 +32,16 @@ wax = "0.4.0"
regex = "1.5"
lazy_static = "1.4.0"
shell-words = "1.1.0"
mlua = { version = "0.7.4", optional = true }
# TODO: make libxcodebase lightweight
# Use features to exclude stuff likce tracing and async-trait as well tokio
# WARN: api totally changed on later versions.
# It would make sense to create custom function
# Breaks
# gitignore = "1.0.7"
[features]
default = [ ]
lua = [ "mlua" ]

[lib]
name = "xcodebase"
Expand Down
11 changes: 5 additions & 6 deletions core/command.rs
Expand Up @@ -3,30 +3,29 @@ use anyhow::{bail, Result};
use async_trait::async_trait;

mod build;
mod drop;
mod register;
mod rename_file;
mod run;
mod unregister;

pub use build::Build;
pub use drop::Drop;
pub use register::Register;
pub use rename_file::RenameFile;
pub use run::Run;
pub use unregister::UnRegister;

#[async_trait]
pub trait DaemonCommand {
async fn handle(&self, state: SharedState) -> anyhow::Result<()>;
}

/// Rename file + class
#[derive(Debug)]
pub enum Command {
Build(Build),
Run(Run),
RenameFile(RenameFile),
Register(Register),
UnRegister(UnRegister),
Drop(Drop),
}

impl Command {
Expand All @@ -36,7 +35,7 @@ impl Command {
Command::Run(c) => c.handle(state).await,
Command::RenameFile(c) => c.handle(state).await,
Command::Register(c) => c.handle(state).await,
Command::UnRegister(c) => c.handle(state).await,
Command::Drop(c) => c.handle(state).await,
}
}

Expand All @@ -48,7 +47,7 @@ impl Command {
"run" => Ok(Self::Run(Run::new(args)?)),
"rename_file" => Ok(Self::RenameFile(RenameFile::new(args)?)),
"register" => Ok(Self::Register(Register::new(args)?)),
"unregister" => Ok(Self::UnRegister(UnRegister::new(args)?)),
"drop" => Ok(Self::Drop(Drop::new(args)?)),
_ => bail!("Unknown command messsage: {cmd}"),
}
}
Expand Down
17 changes: 12 additions & 5 deletions core/command/unregister.rs → core/command/drop.rs
@@ -1,17 +1,17 @@
use crate::state::SharedState;
use crate::{daemon, DaemonCommand};
use crate::{Daemon, DaemonCommand};
use anyhow::{bail, Result};
use async_trait::async_trait;
use tracing::trace;

/// Register new client with workspace
#[derive(Debug)]
pub struct UnRegister {
pub struct Drop {
pub pid: i32,
pub root: String,
}

impl UnRegister {
impl Drop {
pub fn new(args: Vec<&str>) -> Result<Self> {
let pid = args.get(0);
let root = args.get(1);
Expand All @@ -27,12 +27,19 @@ impl UnRegister {
}

pub fn request(pid: i32, root: String) -> Result<()> {
daemon::execute(&["unregister", pid.to_string().as_str(), root.as_str()])
Daemon::execute(&["drop", pid.to_string().as_str(), root.as_str()])
}

#[cfg(feature = "lua")]
pub fn lua(lua: &mlua::Lua, (pid, root): (i32, String)) -> mlua::Result<()> {
use crate::mlua::LuaExtension;
lua.trace(&format!("Added (pid: {pid} cwd: {root})"))?;
Self::request(pid, root).map_err(mlua::Error::external)
}
}

#[async_trait]
impl DaemonCommand for UnRegister {
impl DaemonCommand for Drop {
async fn handle(&self, state: SharedState) -> Result<()> {
trace!("{:?}", self);
state
Expand Down
11 changes: 9 additions & 2 deletions core/command/register.rs
@@ -1,5 +1,5 @@
use crate::state::SharedState;
use crate::{daemon, DaemonCommand};
use crate::{Daemon, DaemonCommand};
use anyhow::{bail, Result};
use async_trait::async_trait;
use tracing::trace;
Expand Down Expand Up @@ -27,7 +27,14 @@ impl Register {
}

pub fn request(pid: i32, root: String) -> Result<()> {
daemon::execute(&["register", pid.to_string().as_str(), root.as_str()])
Daemon::execute(&["register", pid.to_string().as_str(), root.as_str()])
}

#[cfg(feature = "lua")]
pub fn lua(lua: &mlua::Lua, (pid, root): (i32, String)) -> mlua::Result<()> {
use crate::mlua::LuaExtension;
lua.trace(&format!("Removed (pid: {pid} cwd: {root})"))?;
Self::request(pid, root).map_err(mlua::Error::external)
}
}

Expand Down
4 changes: 2 additions & 2 deletions core/command/rename_file.rs
@@ -1,5 +1,5 @@
use crate::state::SharedState;
use crate::{daemon, DaemonCommand};
use crate::{Daemon, DaemonCommand};
use anyhow::{bail, Result};
use async_trait::async_trait;

Expand Down Expand Up @@ -33,7 +33,7 @@ impl RenameFile {
}

pub fn request(path: &str, name: &str, new_name: &str) -> Result<()> {
daemon::execute(&["rename_file", path, name, new_name])
Daemon::execute(&["rename_file", path, name, new_name])
}
}

Expand Down
4 changes: 2 additions & 2 deletions core/command/run.rs
@@ -1,5 +1,5 @@
use crate::state::SharedState;
use crate::{daemon, DaemonCommand};
use crate::{Daemon, DaemonCommand};
use anyhow::Result;
use async_trait::async_trait;

Expand All @@ -16,7 +16,7 @@ impl Run {
}

pub fn request(path: &str, name: &str, new_name: &str) -> Result<()> {
daemon::execute(&["run", path, name, new_name])
Daemon::execute(&["run", path, name, new_name])
}
}

Expand Down
135 changes: 114 additions & 21 deletions core/daemon.rs
@@ -1,28 +1,121 @@
use crate::constants::{DAEMON_BINARY, DAEMON_SOCKET_PATH};
use anyhow::Result;
use std::io::Write;
use std::net::Shutdown;
use std::os::unix::net::UnixStream;
use std::process::Command;

/// Check if Unix socket is running
pub fn is_running() -> bool {
match UnixStream::connect(DAEMON_SOCKET_PATH) {
Ok(s) => s.shutdown(Shutdown::Both).ok().is_some(),
Err(_) => false,
use anyhow::{bail, Context, Result};

pub struct Daemon {
state: std::sync::Arc<tokio::sync::Mutex<crate::state::State>>,
listener: tokio::net::UnixListener,
}

impl Daemon {
pub fn default() -> Self {
if std::fs::metadata(DAEMON_SOCKET_PATH).is_ok() {
std::fs::remove_file(DAEMON_SOCKET_PATH).ok();
}

tracing::info!("Started");

Self {
state: Default::default(),
listener: tokio::net::UnixListener::bind(DAEMON_SOCKET_PATH).unwrap(),
}
}

/// Run Main daemon server loop
pub async fn run(&mut self) -> ! {
use tokio::io::AsyncReadExt;

loop {
let state = self.state.clone();
let (mut s, _) = self.listener.accept().await.unwrap();
tokio::spawn(async move {
// let mut current_state = state.lock().await;
// current_state.update_clients();

// trace!("Current State: {:?}", state.lock().await)
let mut string = String::default();

if let Err(e) = s.read_to_string(&mut string).await {
tracing::error!("[Read Error]: {:?}", e);
return;
};

if string.len() == 0 {
return;
}

let msg = crate::Command::parse(string.as_str().trim());

if let Err(e) = msg {
tracing::error!("[Parse Error]: {:?}", e);
return;
};

let msg = msg.unwrap();
if let Err(e) = msg.handle(state.clone()).await {
tracing::error!("[Handling Error]: {:?}", e);
return;
};

crate::watch::update(state, msg).await;
});
}
}
}

/// Spawn new instance of the server via running binaray is a child process
pub fn spawn() -> Result<()> {
Command::new(DAEMON_BINARY).spawn()?;
Ok(())
impl Daemon {
/// Spawn new instance of the server via running binaray is a child process
pub fn spawn() -> Result<()> {
std::process::Command::new(DAEMON_BINARY)
.spawn()
.context("Unable to start background instance using daemon binaray")
.map(|_| ())
}

/// Pass args to running daemon
pub fn execute(args: &[&str]) -> Result<()> {
use std::io::Write;
match std::os::unix::net::UnixStream::connect(DAEMON_SOCKET_PATH) {
Ok(mut stream) => {
stream.write_all(args.join(" ").as_str().as_ref())?;
stream.flush().context("Fail to flush stream!")
}
Err(e) => bail!("Fail to execute {:#?}: {e}", args),
}
}
}

/// Execute argument in the runtime
pub fn execute(args: &[&str]) -> Result<()> {
let mut stream = UnixStream::connect(DAEMON_SOCKET_PATH)?;
stream.write_all(args.join(" ").as_str().as_ref())?;
stream.flush()?;
Ok(())
#[cfg(feature = "lua")]
use crate::mlua::LuaExtension;

#[cfg(feature = "lua")]
impl Daemon {
/// Representation of daemon table in lua
pub fn lua(lua: &mlua::Lua) -> mlua::Result<mlua::Table> {
let table = lua.create_table()?;
table.set("is_running", lua.create_function(Self::is_running)?)?;
table.set("ensure", lua.create_function(Self::ensure)?)?;
table.set("register", lua.create_function(crate::Register::lua)?)?;
table.set("drop", lua.create_function(crate::Drop::lua)?)?;
Ok(table)
}

/// Check if Daemon is running
pub fn is_running(_: &mlua::Lua, _: ()) -> mlua::Result<bool> {
match std::os::unix::net::UnixStream::connect(DAEMON_SOCKET_PATH) {
Ok(stream) => Ok(stream.shutdown(std::net::Shutdown::Both).ok().is_some()),
Err(_) => Ok(false),
}
}

/// Ensure that daemon is currently running in background
pub fn ensure(lua: &mlua::Lua, _: ()) -> mlua::Result<bool> {
if Self::is_running(lua, ()).unwrap() {
Ok(false)
} else if Self::spawn().is_ok() {
lua.info("Spawned Background Server")?;
Ok(true)
} else {
panic!("Unable to spawn background server");
}
}
}
7 changes: 7 additions & 0 deletions core/lib.rs
Expand Up @@ -2,10 +2,17 @@ pub mod constants;
pub mod daemon;
pub mod state;

#[cfg(feature = "lua")]
mod mlua;

#[cfg(feature = "lua")]
pub use crate::mlua::LuaExtension;

mod command;
mod project;
mod xcode;
pub use command::*;
pub use daemon::*;
pub mod util;
pub mod watch;

Expand Down
4 changes: 2 additions & 2 deletions nvim/src/extensions.rs → core/mlua.rs
@@ -1,6 +1,6 @@
use mlua::prelude::*;

pub trait LuaExt {
pub trait LuaExtension {
fn print(&self, msg: &str);
fn trace(&self, msg: &str) -> LuaResult<()>;
fn error(&self, msg: &str) -> LuaResult<()>;
Expand All @@ -18,7 +18,7 @@ fn log(lua: &Lua, level: &str, msg: &str) -> LuaResult<()> {
.call::<_, ()>(msg.to_lua(lua))
}

impl LuaExt for Lua {
impl LuaExtension for Lua {
fn print(&self, msg: &str) {
self.globals()
.get::<_, LuaFunction>("print")
Expand Down
11 changes: 1 addition & 10 deletions core/state.rs
Expand Up @@ -8,7 +8,7 @@ use tokio::task::JoinHandle;
use tracing::trace;

/// Main state
#[derive(Debug)]
#[derive(Debug, Default)]
pub struct State {
/// Manged workspaces
pub workspaces: HashMap<String, Workspace>,
Expand All @@ -21,15 +21,6 @@ pub struct State {
pub type SharedState = Arc<Mutex<State>>;

impl State {
pub fn new() -> Result<SharedState> {
let state = State {
workspaces: HashMap::new(),
watchers: HashMap::new(),
clients: vec![],
};
Ok(Arc::new(Mutex::new(state)))
}

pub fn update_clients(&mut self) {
self.clients.retain(|&pid| {
if proc_pid::name(pid).is_err() {
Expand Down

0 comments on commit b0362ee

Please sign in to comment.