use std::path::{Path, PathBuf};
use crate::config::Config;
use crate::error::*;
use crate::repo::Repo;
use crate::repo_info::RepoInfo;
use crate::workspace_config::{RepoEntry, WorkspaceConfig};
pub struct Workspace {
dir: PathBuf,
config: WorkspaceConfig,
}
impl Workspace {
pub fn discover(dir: PathBuf) -> Option<Result<Workspace>> {
if WorkspaceConfig::exists(&dir) {
Some(Self::from_dir(dir))
} else {
None
}
}
pub fn current(dir: PathBuf) -> Result<Workspace> {
Self::discover(dir).unwrap_or_else(|| Self::default())
}
pub fn default() -> Result<Workspace> {
Self::from_dir(dirs::home_dir().unwrap().join(".codealong"))
}
pub fn from_dir(dir: PathBuf) -> Result<Workspace> {
let config = match WorkspaceConfig::from_dir(&dir) {
Ok(config) => config,
Err(_) => WorkspaceConfig::default(),
};
Ok(Self::new(dir, config))
}
pub fn new(dir: PathBuf, config: WorkspaceConfig) -> Workspace {
Workspace { dir, config }
}
pub fn repos_dir(&self) -> &Path {
&self.dir
}
pub fn repo_dir(&self, repo_entry: &RepoEntry) -> PathBuf {
self.repos_dir().join(&repo_entry.path())
}
pub fn repos(&self) -> Vec<Repo> {
self.config
.repos
.iter()
.filter(|entry| !entry.ignore)
.map(|entry| self.repo(&entry))
.collect()
}
pub fn repo(&self, entry: &RepoEntry) -> Repo {
let path = self.repo_dir(&entry);
Repo::new(self.config.config.clone(), path, entry.repo_info.clone())
}
pub fn add(&mut self, repo_info: RepoInfo, path: Option<String>) -> Result<()> {
Ok(self.config.add(repo_info, path))
}
pub fn get_repo(self, name: &str) -> Option<Repo> {
self.config.get_entry(name).map(|entry| self.repo(entry))
}
pub fn add_config(&mut self, config: Config) {
self.config.config.merge(config);
}
pub fn dir(&self) -> &Path {
&self.dir
}
pub fn path(&self) -> &Path {
&self.dir
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_discover() -> Result<()> {
assert!(!Workspace::discover(Path::new(".").to_owned()).is_some());
assert!(
Workspace::discover(Path::new("./fixtures/workspaces/serde-rs").to_owned()).is_some()
);
Ok(())
}
}