use std::path::PathBuf;
fn _default_context() -> Option<String> {
Some(".".to_string())
}
fn _default_workdir() -> String {
std::env::current_dir()
.map(|path| path.display().to_string())
.unwrap_or_else(|_| ".".to_string())
}
#[derive(
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
)]
#[serde(default, deny_unknown_fields, rename_all = "snake_case")]
#[repr(C)]
pub struct Scope {
pub(crate) context: Option<String>,
#[serde(default = "_default_workdir")]
pub(crate) workdir: String,
}
impl Scope {
pub fn from_workdir<T>(workdir: T) -> Self
where
T: ToString,
{
Self {
context: None,
workdir: workdir.to_string(),
}
}
pub fn context(&self) -> Option<&str> {
self.context.as_deref()
}
pub fn context_mut(&mut self) -> Option<&mut String> {
self.context.as_mut()
}
pub fn workdir(&self) -> &str {
&self.workdir
}
pub fn as_path(&self) -> PathBuf {
let mut path = PathBuf::new();
self.context().clone().map(|context| path.push(context));
path.push(self.workdir());
debug_assert!(path.is_dir());
path
}
pub fn as_path_str(&self) -> String {
self.as_path().display().to_string()
}
pub fn contextless(self) -> Self {
Self {
context: None,
..self
}
}
pub fn set_cwd(&self) {
std::env::set_current_dir(self.as_path()).unwrap();
}
pub fn set_context<T>(&mut self, context: T)
where
T: ToString,
{
self.context = Some(context.to_string())
}
pub fn set_workdir<T>(&mut self, workdir: T)
where
T: ToString,
{
self.workdir = workdir.to_string()
}
pub fn display(&self) -> String {
self.as_path().display().to_string()
}
}
impl Default for Scope {
fn default() -> Self {
Self {
context: None,
workdir: ".".into(),
}
}
}
impl core::fmt::Display for Scope {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{path}", path = self.display())
}
}
impl core::str::FromStr for Scope {
type Err = std::io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::from_workdir(s))
}
}