From e17db098597d186603903197e7d3a87e9c16e912 Mon Sep 17 00:00:00 2001 From: kjuulh Date: Sun, 22 Jan 2023 21:27:24 +0100 Subject: [PATCH] add install --- src/cli.rs | 8 ++-- src/context/mod.rs | 29 ++++++++++++ src/deps.rs | 15 +++--- src/main.rs | 2 + src/models.rs | 6 +-- src/parser.rs | 22 +++++++-- src/resolvers/install.rs | 5 +- src/services/downloader.rs | 96 ++++++++++++++++++++++++++++++++++++++ src/services/mod.rs | 1 + 9 files changed, 163 insertions(+), 21 deletions(-) create mode 100644 src/context/mod.rs create mode 100644 src/services/downloader.rs create mode 100644 src/services/mod.rs diff --git a/src/cli.rs b/src/cli.rs index 6e1094b..0b8dc70 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf}; +use std::path::PathBuf; use crate::{ deps, @@ -27,11 +27,11 @@ impl Cli { let path = matches.get_one::("path"); if let Some(p) = path { - let validated_path = PathBuf::from(p); - if !validated_path.exists() { + let path = PathBuf::from(p); + if !path.exists() { eyre::bail!("no char.toml exists at --path") } - self.deps.parser.set_path(validated_path); + self.deps.parser.set_path(path); } match matches.subcommand() { diff --git a/src/context/mod.rs b/src/context/mod.rs new file mode 100644 index 0000000..d057c6d --- /dev/null +++ b/src/context/mod.rs @@ -0,0 +1,29 @@ +use crate::models::Char; + +pub struct Context {} + +impl Context { + pub fn new(chars: Vec) -> Self { + Self {} + } +} + +pub struct ContextBuilder { + chars: Vec, +} + +impl ContextBuilder { + pub fn new() -> Self { + Self { chars: vec![] } + } + + pub fn add_char(mut self, char: &Char) -> Self { + self.chars.push(char.clone()); + + self + } + + pub fn build(self) -> Context { + Context::new(self.chars) + } +} diff --git a/src/deps.rs b/src/deps.rs index fa52bde..2633d27 100644 --- a/src/deps.rs +++ b/src/deps.rs @@ -1,9 +1,6 @@ -use std::{ - ops::{Deref}, - sync::Arc, -}; +use std::{ops::Deref, sync::Arc}; -use crate::parser::Parser; +use crate::{parser::Parser, services::downloader::Downloader}; #[derive(Debug, Clone)] pub struct Deps { @@ -13,14 +10,16 @@ pub struct Deps { #[derive(Debug, Clone)] pub struct InnerDeps { pub parser: Parser, + pub downloader: Downloader, } impl Default for Deps { fn default() -> Self { + let parser = Parser::default(); + let downloader = Downloader::new(parser.clone()); + Self { - inner: Arc::new(InnerDeps { - parser: Parser::default(), - }), + inner: Arc::new(InnerDeps { parser, downloader }), } } } diff --git a/src/main.rs b/src/main.rs index 04b3602..96f24c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,8 @@ mod deps; mod models; mod parser; mod resolvers; +mod services; +mod context; fn main() -> eyre::Result<()> { color_eyre::install()?; diff --git a/src/models.rs b/src/models.rs index 1352066..bb2b041 100644 --- a/src/models.rs +++ b/src/models.rs @@ -7,9 +7,9 @@ type Dependencies = Vec; #[derive(Serialize, Deserialize, Clone, Debug)] pub struct Conf { - plan: String, - dependencies: Option, - overrides: Option, + pub plan: String, + pub dependencies: Option, + pub overrides: Option, } #[derive(Serialize, Deserialize, Clone, Debug)] diff --git a/src/parser.rs b/src/parser.rs index a207970..e5c2799 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -19,22 +19,38 @@ impl Parser { } } - pub fn set_path(&self, _path: PathBuf) { - let _writer = self.path.write().unwrap(); + pub fn set_path(&self, path: PathBuf) { + let mut writer = self.path.write().unwrap(); + *writer = Some(path); } - pub fn parse(&self) -> eyre::Result { + pub fn get_path(&self) -> eyre::Result { let read_path = self.path.read().unwrap(); let path = match read_path.clone() { Some(p) => p, None => todo!(), // find using git later on }; + Ok(path) + } + + pub fn parse(&self) -> eyre::Result { + let mut path = self.get_path()?; + if !path.ends_with("char.toml") { + path.push("char.toml") + } let contents = std::fs::read_to_string(&path).context("char.toml doesn't exist at that path")?; contents.parse::() } + + pub fn parse_from(&self, path: &PathBuf) -> eyre::Result { + let contents = + std::fs::read_to_string(path).context("char.toml doesn't exist at that path")?; + + contents.parse::() + } } impl Default for Parser { diff --git a/src/resolvers/install.rs b/src/resolvers/install.rs index b472447..88c512b 100644 --- a/src/resolvers/install.rs +++ b/src/resolvers/install.rs @@ -2,6 +2,7 @@ use crate::deps; use super::{DynResolver, Resolver}; +#[allow(dead_code)] #[derive(Debug, Clone)] pub struct Install { deps: deps::Deps, @@ -21,9 +22,7 @@ impl Resolver for Install { } fn matches(&self, _args: &clap::ArgMatches) -> eyre::Result<()> { - let char = self.deps.parser.parse()?; - - dbg!(char); + self.deps.downloader.download()?; Ok(()) } diff --git a/src/services/downloader.rs b/src/services/downloader.rs new file mode 100644 index 0000000..6a84500 --- /dev/null +++ b/src/services/downloader.rs @@ -0,0 +1,96 @@ +use std::{fs::canonicalize, path::PathBuf}; + +use crate::{ + context::{Context, ContextBuilder}, + models::{Char, Conf}, + parser::Parser, +}; + +#[derive(Debug, Clone)] +pub struct Downloader { + parser: Parser, +} +#[allow(dead_code)] +impl Downloader { + pub fn new(parser: Parser) -> Self { + Self { parser } + } + + /// Unfolds char + /// 1. Download path + /// 2. Parse char in downloaded path + /// 3. Repeat from 1. until there are no more parents + pub fn download(&self) -> eyre::Result { + let mut context_builder = ContextBuilder::new(); + + let char = self.parser.parse()?; + context_builder = context_builder.add_char(&char); + let first_char_path = self.parser.get_path()?; + + let mut root = std::env::current_dir()?; + root = root.join(&first_char_path); + root.push(".char"); + let output = self.create_output_dir(&root)?; + + let mut parent_char = char; + let path = first_char_path; + loop { + parent_char = match &parent_char { + Char::Application { + char, + application: _, + config: _, + } => match char { + Some(c) => self.download_plan(c, &path, &output)?, + None => { + break; + } + }, + Char::Plan { + char, + plan: _, + config: _, + } => match char { + Some(_c) => todo!(), + None => { + break; + } + }, + } + } + + Ok(context_builder.build()) + } + + fn download_plan( + &self, + conf: &Conf, + path: &PathBuf, + output_path: &PathBuf, + ) -> eyre::Result { + let plan = &conf.plan; + + // TODO: decide whether it is a file or a git repo + // TODO: Starting with files only, as such implement git repo later + + let path_buf = std::path::PathBuf::from(plan); + let path = path.join(path_buf); + if !path.exists() { + eyre::bail!("path doesn't exist: {}", path.to_string_lossy()) + } + let path = canonicalize(path)?; + + dbg!(path); + dbg!(output_path); + + todo!() + } + + fn create_output_dir(&self, root: &PathBuf) -> eyre::Result { + let mut output = root.clone(); + output.push("plans"); + std::fs::create_dir_all(&output)?; + + Ok(output) + } +} diff --git a/src/services/mod.rs b/src/services/mod.rs new file mode 100644 index 0000000..acb5733 --- /dev/null +++ b/src/services/mod.rs @@ -0,0 +1 @@ +pub mod downloader;