use crate::config::Scope;
use std::path::PathBuf;
fn _application() -> String {
std::env::current_exe()
.map(|path| path.display().to_string())
.unwrap_or(crate::config::APP_NAME.to_string())
}
fn _application_option() -> Option<String> {
Some(_application())
}
fn _artifacts() -> String {
crate::config::DEFAULT_DIR_ARTIFACTS.to_string()
}
fn _default_scope() -> Scope {
Scope::from_workdir(crate::config::DEFAULT_WORKDIR)
}
fn _default_context() -> Option<String> {
Some(".".to_string())
}
fn _default_workdir() -> PathBuf {
std::env::current_dir().unwrap_or(crate::config::DEFAULT_WORKDIR.into())
}
#[derive(
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
)]
#[serde(default)]
pub struct WorkspaceConfig {
#[serde(default = "_application")]
pub(crate) application: String,
#[serde(default = "_artifacts")]
pub(crate) artifacts: String,
pub(crate) build: Option<String>,
#[serde(default = "_default_workdir")]
pub(crate) workdir: PathBuf,
}
impl WorkspaceConfig {
pub fn new<T>(workdir: T) -> Self
where
PathBuf: From<T>,
{
Self {
application: _application(),
artifacts: _artifacts(),
build: None,
workdir: workdir.into(),
}
}
pub fn artifacts(&self) -> &str {
&self.artifacts
}
pub fn application(&self) -> &str {
&self.application
}
pub fn build(&self) -> Option<&str> {
self.build.as_deref()
}
pub const fn workdir(&self) -> &PathBuf {
&self.workdir
}
pub fn with_artifacts<T>(self, artifacts: T) -> Self
where
T: ToString,
{
Self {
artifacts: artifacts.to_string(),
..self
}
}
pub fn with_application<T>(self, application: T) -> Self
where
T: ToString,
{
Self {
application: application.to_string(),
..self
}
}
pub fn with_build<T>(self, build: T) -> Self
where
T: ToString,
{
Self {
build: Some(build.to_string()),
..self
}
}
pub fn with_workdir(self, workdir: PathBuf) -> Self {
Self { workdir, ..self }
}
pub fn set_artifacts<T>(&mut self, artifacts: T)
where
T: ToString,
{
self.artifacts = artifacts.to_string()
}
pub fn set_application<T>(&mut self, application: T)
where
T: ToString,
{
self.application = application.to_string()
}
pub fn set_build<T>(&mut self, build: T)
where
T: ToString,
{
self.build = Some(build.to_string())
}
pub fn set_current_dir(&self) {
let path = self.workdir();
debug_assert!(self.is_workdir_valid());
tracing::info!("setting current directory to: {p}", p = path.display());
std::env::set_current_dir(path).unwrap();
}
pub fn set_workdir<T>(&mut self, workdir: T)
where
PathBuf: From<T>,
{
self.workdir = workdir.into();
}
pub fn set_workdir_option<T>(&mut self, workdir: Option<T>)
where
PathBuf: From<T>,
{
workdir.map(|w| self.set_workdir(w));
}
pub fn is_workdir_valid(&self) -> bool {
self.workdir().is_dir()
}
pub fn path_to_application(&self) -> PathBuf {
let path = if self.application().is_empty() {
std::env::current_exe().expect("unable to determine the location of the executable")
} else {
self.workdir().join(self.application())
};
debug_assert!(path.is_file());
path
}
pub fn path_to_artifacts(&self) -> PathBuf {
self.workdir().join(self.artifacts())
}
}
impl Default for WorkspaceConfig {
fn default() -> Self {
Self::new(crate::config::DEFAULT_WORKDIR)
}
}
impl core::fmt::Display for WorkspaceConfig {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(serde_json::to_string(self).unwrap().as_str())
}
}