Skip to content

Commit

Permalink
refactor(project): Refactored project list into more extensible struc…
Browse files Browse the repository at this point in the history
…ture
  • Loading branch information
acovaci committed May 20, 2024
1 parent ea6f703 commit 8f451db
Show file tree
Hide file tree
Showing 22 changed files with 510 additions and 1,565 deletions.
1,439 changes: 36 additions & 1,403 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,3 @@ git2 = "0.18.3"
home = "0.5.9"
serde = { version = "1.0.202", features = ["serde_derive"] }
thiserror = "1.0.61"

[dev-dependencies]
cargo-about = "0.6.1"
2 changes: 2 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod project;
pub mod version;
36 changes: 36 additions & 0 deletions src/cli/project.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use plumb::{core::config::PlumbConfig, error::Error, types::Project};

pub fn list(config: PlumbConfig) -> Result<(), Error> {
for project in get_projects(config) {
println!(
"{} @ {}",
project.name(),
project.location().path().display()
);
}
Ok(())
}

fn get_projects(config: PlumbConfig) -> Vec<Project> {
config.projects().to_vec()
}

#[cfg(test)]
mod tests {
use super::*;

use plumb::types::Location;

#[test]
fn test_get_projects() {
let config = PlumbConfig::load(None).unwrap();
let projects = get_projects(config);
assert_eq!(
projects,
vec![
Project::new("plumb", Location::new("~/projects/plumb".into(), None)),
Project::new("monad", Location::new("~/projects/monad".into(), None))
]
);
}
}
23 changes: 23 additions & 0 deletions src/cli/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use plumb::{error::Error, types::SemanticVersion};

pub fn version() -> Result<(), Error> {
println!("plumb {}", get_version()?);
Ok(())
}

fn get_version() -> Result<SemanticVersion, Error> {
SemanticVersion::from_env()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_version() {
assert_eq!(
get_version().unwrap(),
SemanticVersion::try_from("0.1.0").unwrap()
);
}
}
94 changes: 0 additions & 94 deletions src/config.rs

This file was deleted.

97 changes: 97 additions & 0 deletions src/core/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use std::{collections::HashMap, path::Path};

use crate::{
error::Error,
filesystem::config::ConfigFile,
types::{location::LocationKey, DefaultLocation, Location, Project},
};

use super::{project::ProjectBuilder, settings::SettingsBuilder};

pub struct PlumbConfig {
locations: HashMap<LocationKey, Location>,
settings: PlumbSettings,
projects: Vec<Project>,
}

#[derive(Debug, Clone, Default)]
pub struct PlumbSettings {
pub(self) default_project_location: Option<Location>,
}

impl PlumbSettings {
pub fn new(default_locations: HashMap<DefaultLocation, Location>) -> Self {
Self {
default_project_location: default_locations.get(&DefaultLocation::Projects).cloned(),
}
}
}

impl PlumbConfig {
pub fn new(locations: Vec<Location>) -> Self {
Self {
locations: locations
.into_iter()
.map(|l| (l.key().clone(), l))
.collect(),
projects: vec![],
settings: PlumbSettings::default(),
}
}

pub fn load(path: Option<&Path>) -> Result<Self, Error> {
let config = ConfigFile::load(path)?;
let locations = config.parse_locations();
let mut plumb_config = Self::new(locations);

let mut settings_builder = plumb_config.settings_builder();

let settings = config.parse_settings(&mut settings_builder)?;

plumb_config.settings = settings;
let project_builder = plumb_config
.project_builder()
.unwrap_or_else(|| panic!("No project builder found"));

let projects = config.parse_projects(project_builder);

for project in projects {
plumb_config.add_project(project);
}

Ok(plumb_config)
}

pub fn add_project(&mut self, project: Project) {
self.projects.push(project);
}

pub fn project_builder(&self) -> Option<ProjectBuilder> {
Some(ProjectBuilder::new(
self.default_location_for(DefaultLocation::Projects)?
.clone(),
))
}

fn settings_builder(&self) -> SettingsBuilder {
SettingsBuilder::new(self)
}

pub fn list_locations(&self) -> Vec<&Location> {
self.locations.values().collect()
}

pub fn get_location(&self, key: LocationKey) -> Option<&Location> {
self.locations.get(&key)
}

pub fn default_location_for(&self, kind: DefaultLocation) -> Option<&Location> {
match kind {
DefaultLocation::Projects => self.settings.default_project_location.as_ref(),
}
}

pub fn projects(&self) -> &Vec<Project> {
&self.projects
}
}
3 changes: 3 additions & 0 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod config;
pub mod project;
pub mod settings;
23 changes: 23 additions & 0 deletions src/core/project.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::types::{Location, Project};

pub struct ProjectBuilder {
location: Location,
}

impl ProjectBuilder {
pub fn new(default_location: Location) -> Self {
Self {
location: default_location,
}
}

pub fn build(&self, name: &str, location: Option<Location>) -> Project {
Project::new(
name,
location.unwrap_or({
let path = self.location.path().join(name);
Location::new(path, None)
}),
)
}
}
37 changes: 37 additions & 0 deletions src/core/settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::collections::HashMap;

use crate::error::Error;
use crate::types::DefaultLocation;

use super::config::{PlumbConfig, PlumbSettings};

pub struct SettingsBuilder<'a> {
config: &'a PlumbConfig,
default_locations: HashMap<DefaultLocation, String>,
}

impl SettingsBuilder<'_> {
pub fn new(config: &PlumbConfig) -> SettingsBuilder {
SettingsBuilder {
config,
default_locations: HashMap::new(),
}
}

pub fn add_default_location(&mut self, kind: DefaultLocation, location: String) {
self.default_locations.insert(kind, location);
}

pub fn build(&self) -> Result<PlumbSettings, Error> {
let default_locations = self
.default_locations
.iter()
.filter_map(|(k, v)| {
let location = self.config.get_location(v.to_string());
location.map(|l| (k.clone(), l.clone()))
})
.collect();

Ok(PlumbSettings::new(default_locations))
}
}
12 changes: 9 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ pub type Error = PlumbError;

#[derive(Debug, Error)]
pub enum PlumbError {
#[error("Could not find home directory.")]
#[error("Could not find home directory")]
HomeDirNotFound,

#[error("Could not load configuration file.")]
#[error("Could not parse version string: {0}")]
VersionParseError(String),

#[error("Could not load configuration file: {0}")]
ConfigError(#[from] config::ConfigError),

#[error("IO error")]
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),

#[error("Invalid arguments. Please see `plumb help` for more information.")]
InvalidArguments,
}
Loading

0 comments on commit 8f451db

Please sign in to comment.