From b98c06d558dcf734e0cc3c706600b6afe98a3d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20P=C5=82askonka?= Date: Thu, 16 May 2024 11:47:43 +0200 Subject: [PATCH] List templates. --- src/actions.rs | 3 +- src/actions/build.rs | 3 +- src/actions/init.rs | 49 +++------------------------- src/actions/list_templates.rs | 33 +++++++++++++++++++ src/actions/schema.rs | 3 +- src/cli.rs | 24 ++++++++++---- src/lib.rs | 1 + src/project.rs | 61 +++++++++++++++++++++++++++-------- src/template.rs | 2 +- src/{actions => }/utils.rs | 24 +++++++++++++- 10 files changed, 133 insertions(+), 70 deletions(-) create mode 100644 src/actions/list_templates.rs rename src/{actions => }/utils.rs (75%) diff --git a/src/actions.rs b/src/actions.rs index 3b22523..a869022 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -6,4 +6,5 @@ pub mod generate; pub mod init; pub mod schema; pub mod test; -mod utils; + +pub mod list_templates; diff --git a/src/actions/build.rs b/src/actions/build.rs index ee31a1b..59505da 100644 --- a/src/actions/build.rs +++ b/src/actions/build.rs @@ -1,7 +1,6 @@ //! Module for managing and building wasm files. -use super::utils; -use crate::{command, errors::Error, log, paths, project::Project}; +use crate::{command, errors::Error, log, paths, project::Project, utils}; /// BuildAction configuration. pub struct BuildAction<'a> { diff --git a/src/actions/init.rs b/src/actions/init.rs index 1b25296..2a6c19f 100644 --- a/src/actions/init.rs +++ b/src/actions/init.rs @@ -5,17 +5,17 @@ use std::path::{Path, PathBuf}; use cargo_generate::{GenerateArgs, TemplatePath, Vcs}; use cargo_toml::{Dependency, DependencyDetail}; use chrono::Utc; -use ureq::serde_json; use crate::{ cli::InitCommand, command::{rename_file, replace_in_file}, - consts::{ODRA_GITHUB_API_DATA, ODRA_TEMPLATE_GH_RAW_REPO, ODRA_TEMPLATE_GH_REPO}, + consts::{ODRA_TEMPLATE_GH_RAW_REPO, ODRA_TEMPLATE_GH_REPO}, errors::Error, log, paths, project::OdraLocation, template::TemplateGenerator, + utils::odra_latest_version, }; /// InitAction configuration. @@ -31,7 +31,7 @@ impl InitAction { log::info("Generating a new project..."); - let odra_location = Self::odra_location(init_command.source); + let odra_location = OdraLocation::from_source(init_command.source); let template_repository_path = TemplateGenerator::new(ODRA_TEMPLATE_GH_RAW_REPO.to_string(), odra_location.clone()) @@ -74,14 +74,12 @@ impl InitAction { }, }; - dbg!("generating"); - cargo_generate::generate(GenerateArgs { template_path, list_favorites: false, name: Some(paths::to_snake_case(&init_command.name)), force: true, - verbose: true, + verbose: false, template_values_file: None, silent: false, config: None, @@ -102,7 +100,6 @@ impl InitAction { Error::FailedToGenerateProjectFromTemplate(e.to_string()).print_and_die(); }); - dbg!("generating 2"); let cargo_toml_path = match init { true => { let mut path = current_dir; @@ -117,7 +114,6 @@ impl InitAction { } }; - dbg!("generating 3"); Self::replace_package_placeholder( init, &odra_location, @@ -185,41 +181,6 @@ impl InitAction { } } - fn odra_location(source: Option) -> OdraLocation { - let source = if let Some(source) = source { - source - } else { - Self::odra_latest_version() - }; - - // location on disk - let local = PathBuf::from(&source); - if local.exists() { - OdraLocation::Local(local) - } else { - // version - let version_regex = regex::Regex::new(r"^\d+\.\d+\.\d+$").unwrap(); - if version_regex.is_match(&source) { - OdraLocation::CratesIO(source) - } else { - // branch - OdraLocation::Remote(ODRA_TEMPLATE_GH_REPO.to_string(), Some(source)) - } - } - } - fn odra_latest_version() -> String { - let response: serde_json::Value = ureq::get(ODRA_GITHUB_API_DATA) - .call() - .unwrap_or_else(|_| { - Error::FailedToFetchTemplate(ODRA_GITHUB_API_DATA.to_string()).print_and_die() - }) - .into_json() - .unwrap_or_else(|_| { - Error::FailedToParseTemplate(ODRA_GITHUB_API_DATA.to_string()).print_and_die() - }); - response["tag_name"].as_str().unwrap().to_string() - } - fn odra_project_dependency( odra_location: OdraLocation, crate_name: &str, @@ -240,7 +201,7 @@ impl InitAction { (None, Some(path), None, None) } OdraLocation::Remote(repo, branch) => match branch { - None => (Some(Self::odra_latest_version()), None, None, None), + None => (Some(odra_latest_version()), None, None, None), Some(branch) => (None, None, Some(repo), Some(branch)), }, OdraLocation::CratesIO(version) => (Some(version), None, None, None), diff --git a/src/actions/list_templates.rs b/src/actions/list_templates.rs new file mode 100644 index 0000000..bc2cf99 --- /dev/null +++ b/src/actions/list_templates.rs @@ -0,0 +1,33 @@ +//! Module responsible for listing templates in cli. + +use crate::{ + consts::ODRA_TEMPLATE_GH_RAW_REPO, + project::OdraLocation, + template::{TemplateGenerator, TemplateType}, +}; + +/// ListTemplatesAction configuration. +#[derive(Clone)] +pub struct ListTemplatesAction {} + +impl ListTemplatesAction { + pub fn list(odra_location: OdraLocation) { + let templates = + TemplateGenerator::new(ODRA_TEMPLATE_GH_RAW_REPO.to_string(), odra_location) + .fetch_templates(); + println!("Available contract templates:"); + templates + .iter() + .filter(|template| template.template_type == TemplateType::Contract) + .for_each(|template| { + println!("{:<15}{}", template.name, template.description); + }); + println!("\nAvailable project templates:"); + templates + .iter() + .filter(|template| template.template_type == TemplateType::Project) + .for_each(|template| { + println!("{:<15}{}", template.name, template.description); + }); + } +} diff --git a/src/actions/schema.rs b/src/actions/schema.rs index 408bf24..1b41a84 100644 --- a/src/actions/schema.rs +++ b/src/actions/schema.rs @@ -1,7 +1,6 @@ //! Module for generating contracts schema. -use super::utils; -use crate::{command, errors::Error, log, project::Project}; +use crate::{command, errors::Error, log, project::Project, utils}; /// SchemaAction configuration. pub struct SchemaAction<'a> { diff --git a/src/cli.rs b/src/cli.rs index 6694586..04ce19d 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -10,12 +10,14 @@ use crate::{ clean::clean_action, generate::GenerateAction, init::InitAction, + list_templates::ListTemplatesAction, schema::SchemaAction, test::TestAction, }, + cargo_toml::load_cargo_toml, consts, errors::Error, - project::Project, + project::{OdraLocation, Project}, }; #[derive(Parser)] @@ -60,7 +62,7 @@ pub enum OdraSubcommand { /// Cleans all temporary data generated by cargo odra. Clean(CleanCommand), /// Lists all available templates. - ListTemplates, + ListTemplates(ListTemplatesCommand), /// Generates completions for given shell Completions { /// The shell to generate the completions for @@ -127,8 +129,9 @@ pub struct GenerateCommand { /// Name of the module in which the contract will be created. #[clap(value_parser, long, short)] pub module: Option, - /// Name of the template to use. - #[clap(value_parser, long, short)] + /// Template to use. + /// To see all available templates, run `cargo odra list-templates`. + #[clap(value_parser, long, short, default_value = consts::MODULE_TEMPLATE)] pub template: Option, } @@ -192,8 +195,17 @@ pub fn make_action() { let project = Project::detect(current_dir); SchemaAction::new(&project, schema.contracts_names).build(); } - OdraSubcommand::ListTemplates => { - println!("Available templates:"); + OdraSubcommand::ListTemplates(list) => { + let cargo_toml = Project::find_odra_cargo_toml(current_dir.clone()); + let odra_location = match cargo_toml { + None => OdraLocation::from_source(list.source), + Some(cargo_toml_path) => match list.source { + None => OdraLocation::from_project(load_cargo_toml(&cargo_toml_path)), + Some(source) => OdraLocation::from_source(Some(source)), + }, + }; + + ListTemplatesAction::list(odra_location); } } } diff --git a/src/lib.rs b/src/lib.rs index 4d2e59f..24a3d2b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,3 +15,4 @@ mod odra_toml; mod paths; mod project; mod template; +mod utils; diff --git a/src/project.rs b/src/project.rs index 097d26d..137cd33 100644 --- a/src/project.rs +++ b/src/project.rs @@ -3,9 +3,15 @@ use std::{ path::{Path, PathBuf}, }; -use cargo_toml::{Dependency, DependencyDetail}; +use cargo_toml::{Dependency, DependencyDetail, Manifest}; -use crate::{cargo_toml::load_cargo_toml, errors::Error, odra_toml::OdraToml}; +use crate::{ + cargo_toml::load_cargo_toml, + consts::ODRA_TEMPLATE_GH_REPO, + errors::Error, + odra_toml::OdraToml, + utils::odra_latest_version, +}; /// Struct representing the whole project. #[derive(Debug, Clone)] @@ -28,7 +34,7 @@ impl Project { let odra_toml_path = Self::find_odra_toml(path.clone()).unwrap_or_else(|| { Error::NotAnOdraProject.print_and_die(); }); - let cargo_toml_path = Self::find_cargo_toml(path).unwrap_or_else(|| { + let cargo_toml_path = Self::find_odra_cargo_toml(path).unwrap_or_else(|| { Error::NotAnOdraProject.print_and_die(); }); let root = odra_toml_path.parent().unwrap().to_path_buf(); @@ -99,7 +105,8 @@ impl Project { } /// Searches for main Projects' Cargo.toml. - pub fn find_cargo_toml(path: PathBuf) -> Option { + /// Ensures that the project is an Odra project. + pub fn find_odra_cargo_toml(path: PathBuf) -> Option { match Self::find_file_upwards("Odra.toml", path) { None => None, Some(odra_toml_path) => { @@ -136,7 +143,7 @@ impl Project { .collect() } - fn find_odra_toml(path: PathBuf) -> Option { + pub fn find_odra_toml(path: PathBuf) -> Option { Self::find_file_upwards("Odra.toml", path) } @@ -169,7 +176,20 @@ impl Project { } pub fn project_odra_location(&self) -> OdraLocation { - let cargo_toml = load_cargo_toml(&self.cargo_toml_location); + OdraLocation::from_project(load_cargo_toml(&self.cargo_toml_location)) + } +} + +#[derive(Debug, Clone)] +pub enum OdraLocation { + Local(PathBuf), + /// git repo, branch + Remote(String, Option), + CratesIO(String), +} + +impl OdraLocation { + pub fn from_project(cargo_toml: Manifest) -> OdraLocation { let dependencies = match cargo_toml.workspace { None => cargo_toml.dependencies, Some(workspace) => workspace.dependencies, @@ -212,14 +232,29 @@ impl Project { } } } -} -#[derive(Debug, Clone)] -pub enum OdraLocation { - Local(PathBuf), - /// git repo, branch - Remote(String, Option), - CratesIO(String), + pub fn from_source(source: Option) -> OdraLocation { + let source = if let Some(source) = source { + source + } else { + odra_latest_version() + }; + + // location on disk + let local = PathBuf::from(&source); + if local.exists() { + OdraLocation::Local(local) + } else { + // version + let version_regex = regex::Regex::new(r"^\d+\.\d+\.\d+$").unwrap(); + if version_regex.is_match(&source) { + OdraLocation::CratesIO(source) + } else { + // branch + OdraLocation::Remote(ODRA_TEMPLATE_GH_REPO.to_string(), Some(source)) + } + } + } } #[derive(Debug, Clone)] diff --git a/src/template.rs b/src/template.rs index e5cbe85..636da52 100644 --- a/src/template.rs +++ b/src/template.rs @@ -44,7 +44,7 @@ impl TemplateGenerator { } /// Fetches templates.json - fn fetch_templates(&self) -> Vec