Skip to content

Commit

Permalink
feat(daemon): build configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
kkharji committed May 8, 2022
1 parent 9b888d9 commit 8798b62
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 38 deletions.
6 changes: 1 addition & 5 deletions src/daemon/bin.rs
Expand Up @@ -40,11 +40,7 @@ async fn main() -> anyhow::Result<()> {
}
Ok(req) => {
if let Err(e) = req.message.handle(state.clone()).await {
return tracing::error!(
"[Failure]: Cause: ({:?}), Message: {:?}",
e,
req
);
return tracing::error!("[Failure]: Cause: ({:?})", e);
};
}
};
Expand Down
8 changes: 4 additions & 4 deletions src/daemon/message.rs
Expand Up @@ -25,7 +25,7 @@ pub enum Message {

#[cfg(feature = "daemon")]
impl Message {
pub async fn handle(&self, state: super::DaemonState) -> anyhow::Result<()> {
pub async fn handle(self, state: super::DaemonState) -> anyhow::Result<()> {
match self {
Self::Build(c) => Handler::handle(c, state).await,
Self::Run(c) => Handler::handle(c, state).await,
Expand All @@ -40,16 +40,16 @@ impl Message {
/// Requirement for daemon handling request
#[cfg(feature = "daemon")]
#[async_trait::async_trait]
pub trait Handler: std::fmt::Debug {
async fn handle(&self, _state: super::DaemonState) -> anyhow::Result<()> {
pub trait Handler: std::fmt::Debug + Sized {
async fn handle(self, _state: super::DaemonState) -> anyhow::Result<()> {
tracing::error!("Not Implemented! {:#?}", self);
Ok(())
}
}

/// Requirement for daemon sending request
#[cfg(feature = "lua")]
pub trait Requestor<'a, M: Into<Request> + std::fmt::Debug + FromLua<'a>> {
pub trait Requester<'a, M: Into<Request> + std::fmt::Debug + FromLua<'a>> {
fn request(lua: &Lua, msg: M) -> LuaResult<()> {
Self::pre(lua, &msg)?;
Daemon::execute(lua, msg)
Expand Down
2 changes: 1 addition & 1 deletion src/daemon/requests.rs
Expand Up @@ -21,7 +21,7 @@ use crate::util::mlua::LuaExtension;
use mlua::prelude::*;

#[cfg(feature = "mlua")]
use super::Requestor;
use super::Requester;

#[cfg(feature = "daemon")]
use async_stream::stream;
Expand Down
31 changes: 15 additions & 16 deletions src/daemon/requests/build.rs
@@ -1,29 +1,31 @@
use super::*;
use crate::types::BuildConfiguration;
use std::fmt::Debug;

/// Build a project.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Build {
pub pid: i32,
pub root: String,
pub target: Option<String>,
pub configuration: Option<String>,
pub scheme: Option<String>,
pub client: Client,
pub config: BuildConfiguration,
}

#[cfg(feature = "lua")]
impl<'a> Requestor<'a, Build> for Build {}
impl<'a> Requester<'a, Build> for Build {
fn pre(lua: &Lua, msg: &Build) -> LuaResult<()> {
lua.trace(&format!("{:?}", msg.config))
}
}

#[cfg(feature = "daemon")]
#[async_trait]
impl Handler for Build {
async fn handle(&self, state: DaemonState) -> Result<()> {
async fn handle(self, state: DaemonState) -> Result<()> {
tracing::debug!("Handling build request..");

let state = state.lock().await;
let ws = state.get_workspace(&self.root)?;
let nvim = ws.get_client(&self.pid)?;
let mut logs = ws.project.xcodebuild(&["build"]).await?;
let ws = state.get_workspace(&self.client.root)?;
let nvim = ws.get_client(&self.client.pid)?;
let mut logs = ws.project.xcodebuild(&["build"], self.config).await?;
let stream = Box::pin(stream! {
while let Some(step) = logs.next().await {
let line = match step {
Expand All @@ -50,11 +52,8 @@ impl<'a> FromLua<'a> for Build {
fn from_lua(lua_value: LuaValue<'a>, _lua: &'a Lua) -> LuaResult<Self> {
if let LuaValue::Table(table) = lua_value {
Ok(Self {
pid: table.get("pid")?,
root: table.get("root")?,
target: table.get("target")?,
configuration: table.get("configuration")?,
scheme: table.get("scheme")?,
client: table.get("client")?,
config: table.get("config")?,
})
} else {
Err(LuaError::external("Fail to deserialize Build"))
Expand Down
4 changes: 2 additions & 2 deletions src/daemon/requests/drop.rs
Expand Up @@ -9,7 +9,7 @@ pub struct Drop {
#[cfg(feature = "daemon")]
#[async_trait]
impl Handler for Drop {
async fn handle(&self, state: DaemonState) -> Result<()> {
async fn handle(self, state: DaemonState) -> Result<()> {
tracing::trace!("{:?}", self);
let (root, pid) = (&self.client.root, self.client.pid);
let mut state = state.lock().await;
Expand All @@ -18,7 +18,7 @@ impl Handler for Drop {
}

#[cfg(feature = "lua")]
impl<'a> Requestor<'a, Drop> for Drop {
impl<'a> Requester<'a, Drop> for Drop {
fn pre(_lua: &Lua, _msg: &Drop) -> LuaResult<()> {
Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions src/daemon/requests/project_info.rs
Expand Up @@ -7,12 +7,12 @@ pub struct ProjectInfo {
}

#[cfg(feature = "lua")]
impl<'a> Requestor<'a, ProjectInfo> for ProjectInfo {}
impl<'a> Requester<'a, ProjectInfo> for ProjectInfo {}

#[cfg(feature = "daemon")]
#[async_trait]
impl Handler for ProjectInfo {
async fn handle(&self, state: DaemonState) -> Result<()> {
async fn handle(self, state: DaemonState) -> Result<()> {
let (root, pid) = (&self.client.root, self.client.pid);
tracing::info!("Getting info for {}", root);

Expand Down
4 changes: 2 additions & 2 deletions src/daemon/requests/register.rs
Expand Up @@ -8,7 +8,7 @@ pub struct Register {
}

#[cfg(feature = "lua")]
impl<'a> Requestor<'a, Register> for Register {
impl<'a> Requester<'a, Register> for Register {
fn pre(lua: &Lua, msg: &Register) -> LuaResult<()> {
lua.trace(&format!("Registered client ({})", msg.client.pid))
}
Expand All @@ -17,7 +17,7 @@ impl<'a> Requestor<'a, Register> for Register {
#[cfg(feature = "daemon")]
#[async_trait]
impl Handler for Register {
async fn handle(&self, state: DaemonState) -> anyhow::Result<()> {
async fn handle(self, state: DaemonState) -> anyhow::Result<()> {
tracing::trace!("{:?}", self);
let mut state = state.lock().await;
let client = &self.client;
Expand Down
4 changes: 2 additions & 2 deletions src/daemon/requests/rename_file.rs
Expand Up @@ -7,13 +7,13 @@ pub struct RenameFile {
}

#[cfg(feature = "lua")]
impl<'a> Requestor<'a, RenameFile> for RenameFile {}
impl<'a> Requester<'a, RenameFile> for RenameFile {}

// TODO: Implement file rename along with it's main class if any.
#[cfg(feature = "daemon")]
#[async_trait]
impl Handler for RenameFile {
async fn handle(&self, _state: DaemonState) -> Result<()> {
async fn handle(self, _state: DaemonState) -> Result<()> {
tracing::info!("Reanmed command");
Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions src/daemon/requests/run.rs
Expand Up @@ -8,7 +8,7 @@ pub struct Run {
}

#[cfg(feature = "lua")]
impl<'a> Requestor<'a, Run> for Run {}
impl<'a> Requester<'a, Run> for Run {}

// TODO: Implement run command
//
Expand All @@ -18,7 +18,7 @@ impl<'a> Requestor<'a, Run> for Run {}
#[cfg(feature = "daemon")]
#[async_trait::async_trait]
impl Handler for Run {
async fn handle(&self, _state: DaemonState) -> Result<()> {
async fn handle(self, _state: DaemonState) -> Result<()> {
tracing::info!("Run command");
Ok(())
}
Expand Down
6 changes: 4 additions & 2 deletions src/daemon/state/project.rs
@@ -1,6 +1,6 @@
use crate::types::BuildConfiguration;
#[cfg(feature = "serial")]
use serde::{Deserialize, Serialize};

use std::collections::HashMap;
use std::path::PathBuf;

Expand Down Expand Up @@ -86,18 +86,20 @@ impl Project {
```
*/

self.xcodebuild(&["build"]).await
self.xcodebuild(&["build"], Default::default()).await
}

#[cfg(feature = "daemon")]
pub async fn xcodebuild<'a, I: 'a, S: 'a>(
&'a self,
args: I,
_config: BuildConfiguration,
) -> anyhow::Result<impl tokio_stream::Stream<Item = xcodebuild::parser::Step> + 'a>
where
I: IntoIterator<Item = S>,
S: AsRef<std::ffi::OsStr>,
{
// TOOD: Process configuration
xcodebuild::runner::spawn(&self.root, args).await
}

Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Expand Up @@ -10,4 +10,7 @@ pub mod xcodegen;
#[cfg(any(feature = "daemon", feature = "mlua"))]
pub mod daemon;

#[cfg(feature = "serial")]
pub mod types;

pub mod util;
72 changes: 72 additions & 0 deletions src/types.rs
@@ -0,0 +1,72 @@
#[cfg(feature = "lua")]
use mlua::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(untagged)]
pub enum XConfiguration {
#[default]
Debug,
Release,
Custom(String),
}

#[cfg(feature = "lua")]
impl<'a> FromLua<'a> for XConfiguration {
fn from_lua(lua_value: LuaValue<'a>, _lua: &'a Lua) -> LuaResult<Self> {
if let LuaValue::String(config) = lua_value {
let value = config.to_str()?;
Ok(match value {
"debug" | "Debug" => Self::Debug,
"release" | "Release" => Self::Release,
_ => Self::Custom(value.to_string()),
})
} else if matches!(lua_value, LuaValue::Nil) {
Ok(Self::Debug)
} else {
Err(LuaError::external("Expected a table got XConfiguration"))
}
}
}

/// Xcode Scheme
///
/// An Xcode scheme defines a collection of targets to build, a configuration to use when building,
/// and a collection of tests to execute.
pub type XScheme = String;

/// Xcode Target
///
/// A target specifies a product to build and contains the instructions for building the product
/// from a set of files in a project or workspace.
pub type XTarget = String;

/// Fields required to build a project
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct BuildConfiguration {
/// TODO(nvim): make build config sysroot default to tmp in auto-build
pub sysroot: Option<String>,
/// Target to build
pub target: Option<XTarget>,
/// Configuration to build with, default Debug
#[serde(default)]
pub configuration: XConfiguration,
/// Scheme to build with
pub scheme: Option<XScheme>,
}

#[cfg(feature = "lua")]
impl<'a> FromLua<'a> for BuildConfiguration {
fn from_lua(lua_value: LuaValue<'a>, _lua: &'a Lua) -> LuaResult<Self> {
if let LuaValue::Table(table) = lua_value {
Ok(Self {
sysroot: table.get("sysroot")?,
target: table.get("target")?,
configuration: table.get("configuration")?,
scheme: table.get("scheme")?,
})
} else {
Ok(BuildConfiguration::default())
}
}
}

0 comments on commit 8798b62

Please sign in to comment.