From 045323cbb08984e580c2c9715c32d53dd563945f Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 13:49:14 +0300 Subject: [PATCH 01/10] sc-meta template tag, refactor --- .../meta/src/cli_args/cli_args_standalone.rs | 17 ++++-- framework/meta/src/cmd/standalone.rs | 4 +- framework/meta/src/cmd/standalone/info.rs | 5 +- framework/meta/src/cmd/standalone/upgrade.rs | 2 - .../standalone/upgrade/upgrade_selector.rs | 4 +- framework/meta/src/lib.rs | 1 + framework/meta/src/template.rs | 6 ++- framework/meta/src/template/repo_source.rs | 27 ++++++++++ .../meta/src/template/repo_temp_download.rs | 54 +++---------------- framework/meta/src/template/repo_version.rs | 26 +++++++++ .../meta/src/template/template_download.rs | 20 +++++-- framework/meta/src/template/template_list.rs | 9 ++-- .../meta/src/template/template_source.rs | 2 +- ...upgrade_versions.rs => version_history.rs} | 33 ++++++++++-- 14 files changed, 140 insertions(+), 70 deletions(-) create mode 100644 framework/meta/src/template/repo_source.rs create mode 100644 framework/meta/src/template/repo_version.rs rename framework/meta/src/{cmd/standalone/upgrade/upgrade_versions.rs => version_history.rs} (65%) diff --git a/framework/meta/src/cli_args/cli_args_standalone.rs b/framework/meta/src/cli_args/cli_args_standalone.rs index 28fda64b1d..81c23b408f 100644 --- a/framework/meta/src/cli_args/cli_args_standalone.rs +++ b/framework/meta/src/cli_args/cli_args_standalone.rs @@ -58,7 +58,7 @@ pub enum StandaloneCliAction { name = "templates", about = "Creates a contract by a pre-existing template" )] - TemplateList, + TemplateList(TemplateListArgs), #[command( name = "test-gen", about = "Generates Rust integration tests based on scenarios provided in the scenarios folder of each contract." @@ -184,13 +184,17 @@ pub struct LocalDepsArgs { #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] pub struct TemplateArgs { - /// Provide the template you want to clone + /// The new name the contract is to receive. #[arg(long = "name", verbatim_doc_comment)] pub name: PathBuf, - /// Provide the he template you want to clone + /// The contract template to clone. #[arg(long = "template", verbatim_doc_comment)] pub template: String, + + /// The framework version on which the contracts should be created. + #[arg(long = "tag", verbatim_doc_comment)] + pub tag: Option, } impl CliArgsToRaw for TemplateArgs { @@ -199,6 +203,13 @@ impl CliArgsToRaw for TemplateArgs { } } +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct TemplateListArgs { + /// The framework version referred to. + #[arg(long = "tag", verbatim_doc_comment)] + pub tag: Option, +} + #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] pub struct TestGenArgs { /// Target directory where to generate contract integration tests. diff --git a/framework/meta/src/cmd/standalone.rs b/framework/meta/src/cmd/standalone.rs index f1ec44c4a1..89a2e04238 100644 --- a/framework/meta/src/cmd/standalone.rs +++ b/framework/meta/src/cmd/standalone.rs @@ -30,8 +30,8 @@ pub async fn cli_main_standalone() { Some(StandaloneCliAction::Template(args)) => { template_download(args).await; }, - Some(StandaloneCliAction::TemplateList) => { - print_template_names().await; + Some(StandaloneCliAction::TemplateList(args)) => { + print_template_names(args).await; }, Some(StandaloneCliAction::TestGen(args)) => { test_gen_tool(args); diff --git a/framework/meta/src/cmd/standalone/info.rs b/framework/meta/src/cmd/standalone/info.rs index a806aa1997..c086a54de5 100644 --- a/framework/meta/src/cmd/standalone/info.rs +++ b/framework/meta/src/cmd/standalone/info.rs @@ -1,7 +1,8 @@ -use super::upgrade::{print_tree_dir_metadata, DEFAULT_LAST_VERSION}; +use super::upgrade::print_tree_dir_metadata; use crate::{ cli_args::InfoArgs, folder_structure::{dir_pretty_print, RelevantDirectories}, + version_history::LAST_UPGRADE_VERSION, }; pub fn call_info(args: &InfoArgs) { @@ -13,6 +14,6 @@ pub fn call_info(args: &InfoArgs) { let dirs = RelevantDirectories::find_all(path, args.ignore.as_slice()); dir_pretty_print(dirs.iter(), "", &|dir| { - print_tree_dir_metadata(dir, DEFAULT_LAST_VERSION) + print_tree_dir_metadata(dir, LAST_UPGRADE_VERSION) }); } diff --git a/framework/meta/src/cmd/standalone/upgrade.rs b/framework/meta/src/cmd/standalone/upgrade.rs index 2960526702..c54d8e85dc 100644 --- a/framework/meta/src/cmd/standalone/upgrade.rs +++ b/framework/meta/src/cmd/standalone/upgrade.rs @@ -4,8 +4,6 @@ mod upgrade_0_39; pub(crate) mod upgrade_common; mod upgrade_print; mod upgrade_selector; -mod upgrade_versions; pub use upgrade_print::print_tree_dir_metadata; pub use upgrade_selector::upgrade_sc; -pub use upgrade_versions::DEFAULT_LAST_VERSION; diff --git a/framework/meta/src/cmd/standalone/upgrade/upgrade_selector.rs b/framework/meta/src/cmd/standalone/upgrade/upgrade_selector.rs index 589d9ec6bf..db8f0ef404 100644 --- a/framework/meta/src/cmd/standalone/upgrade/upgrade_selector.rs +++ b/framework/meta/src/cmd/standalone/upgrade/upgrade_selector.rs @@ -1,6 +1,7 @@ use crate::{ cli_args::UpgradeArgs, folder_structure::{dir_pretty_print, RelevantDirectories, RelevantDirectory}, + version_history::{versions_iter, LAST_UPGRADE_VERSION, VERSIONS}, }; use super::{ @@ -9,7 +10,6 @@ use super::{ upgrade_0_39::{postprocessing_after_39_0, upgrade_to_39_0}, upgrade_common::{cargo_check, version_bump_in_cargo_toml}, upgrade_print::*, - upgrade_versions::{versions_iter, DEFAULT_LAST_VERSION, VERSIONS}, }; pub fn upgrade_sc(args: &UpgradeArgs) { @@ -22,7 +22,7 @@ pub fn upgrade_sc(args: &UpgradeArgs) { let last_version = args .override_target_version .clone() - .unwrap_or_else(|| DEFAULT_LAST_VERSION.to_string()); + .unwrap_or_else(|| LAST_UPGRADE_VERSION.to_string()); assert!( VERSIONS.contains(&last_version.as_str()), diff --git a/framework/meta/src/lib.rs b/framework/meta/src/lib.rs index d11e491f74..71790e2b01 100644 --- a/framework/meta/src/lib.rs +++ b/framework/meta/src/lib.rs @@ -8,6 +8,7 @@ mod mxsc_file_json; mod print_util; pub mod template; mod tools; +mod version_history; #[macro_use] extern crate lazy_static; diff --git a/framework/meta/src/template.rs b/framework/meta/src/template.rs index 38ec4d37f1..7501291917 100644 --- a/framework/meta/src/template.rs +++ b/framework/meta/src/template.rs @@ -1,11 +1,15 @@ +mod repo_source; mod repo_temp_download; +mod repo_version; mod template_adjuster; mod template_download; mod template_list; mod template_metadata; mod template_source; -pub use repo_temp_download::{RepoSource, RepoTempDownload}; +pub use repo_source::RepoSource; +pub use repo_temp_download::RepoTempDownload; +pub use repo_version::RepoVersion; pub use template_adjuster::TemplateAdjuster; pub use template_download::{template_download, TemplateDownloader}; pub use template_list::{print_template_names, template_names_from_repo}; diff --git a/framework/meta/src/template/repo_source.rs b/framework/meta/src/template/repo_source.rs new file mode 100644 index 0000000000..fda036bacf --- /dev/null +++ b/framework/meta/src/template/repo_source.rs @@ -0,0 +1,27 @@ +use std::path::{Path, PathBuf}; + +use super::{RepoTempDownload, RepoVersion}; + +pub enum RepoSource { + Downloaded(RepoTempDownload), + LocalPath(PathBuf), +} + +impl RepoSource { + pub async fn download_from_github(version: RepoVersion, temp_dir_path: PathBuf) -> Self { + RepoSource::Downloaded(RepoTempDownload::download_from_github(version, temp_dir_path).await) + } + + pub fn from_local_path(repo_local_path: impl AsRef) -> Self { + RepoSource::LocalPath(repo_local_path.as_ref().to_path_buf()) + } + + pub fn repo_path(&self) -> PathBuf { + match self { + RepoSource::Downloaded(repo_temp_download) => { + repo_temp_download.repository_temp_dir_path() + }, + RepoSource::LocalPath(local_path) => local_path.clone(), + } + } +} diff --git a/framework/meta/src/template/repo_temp_download.rs b/framework/meta/src/template/repo_temp_download.rs index 4c7113b81c..f8b781f47f 100644 --- a/framework/meta/src/template/repo_temp_download.rs +++ b/framework/meta/src/template/repo_temp_download.rs @@ -4,44 +4,20 @@ use std::{ path::{Path, PathBuf}, }; -const REPOSITORY: &str = "https://github.com/multiversx/mx-sdk-rs/archive/refs/heads/master.zip"; -const ZIP_NAME: &str = "./master.zip"; -const REPOSITORY_TEMP_DIR_NAME: &str = "mx-sdk-rs-master"; +use super::RepoVersion; -pub enum RepoSource { - Downloaded(RepoTempDownload), - LocalPath(PathBuf), -} - -impl RepoSource { - pub async fn download_from_github(temp_dir_path: PathBuf) -> Self { - RepoSource::Downloaded(RepoTempDownload::download_from_github(temp_dir_path).await) - } - - pub fn from_local_path(repo_local_path: impl AsRef) -> Self { - RepoSource::LocalPath(repo_local_path.as_ref().to_path_buf()) - } - - pub fn repo_path(&self) -> PathBuf { - match self { - RepoSource::Downloaded(repo_temp_download) => { - repo_temp_download.repository_temp_dir_path() - }, - RepoSource::LocalPath(local_path) => local_path.clone(), - } - } -} +const ZIP_NAME: &str = "mx-sdk-rs-download.zip"; pub struct RepoTempDownload { + pub version: RepoVersion, pub temp_dir_path: PathBuf, - pub repo_temp_dir_name: String, } impl RepoTempDownload { - pub async fn download_from_github(temp_dir_path: PathBuf) -> Self { + pub async fn download_from_github(version: RepoVersion, temp_dir_path: PathBuf) -> Self { let tt_download = RepoTempDownload { + version, temp_dir_path, - repo_temp_dir_name: REPOSITORY_TEMP_DIR_NAME.to_string(), }; tt_download.download_binaries().await.unwrap(); tt_download.delete_temp_folder(); @@ -50,32 +26,16 @@ impl RepoTempDownload { tt_download } - pub fn from_local_copy(repo_local_path: &Path, temp_dir_path: PathBuf) -> Self { - let tt_download = RepoTempDownload { - temp_dir_path, - repo_temp_dir_name: REPOSITORY_TEMP_DIR_NAME.to_string(), - }; - tt_download.delete_temp_folder(); - copy_dir::copy_dir( - repo_local_path, - tt_download - .temp_dir_path - .join(&tt_download.repo_temp_dir_name), - ) - .unwrap(); - tt_download - } - fn zip_path(&self) -> PathBuf { self.temp_dir_path.join(ZIP_NAME) } pub fn repository_temp_dir_path(&self) -> PathBuf { - self.temp_dir_path.join(REPOSITORY_TEMP_DIR_NAME) + self.temp_dir_path.join(self.version.temp_dir_name()) } async fn download_binaries(&self) -> Result<(), reqwest::Error> { - let response = reqwest::get(REPOSITORY).await?.bytes().await?; + let response = reqwest::get(self.version.url()).await?.bytes().await?; let mut file = match File::create(self.zip_path()) { Err(why) => panic!("couldn't create {why}"), diff --git a/framework/meta/src/template/repo_version.rs b/framework/meta/src/template/repo_version.rs new file mode 100644 index 0000000000..3eb798a66f --- /dev/null +++ b/framework/meta/src/template/repo_version.rs @@ -0,0 +1,26 @@ +pub enum RepoVersion { + Master, + Tag(String), +} + +impl RepoVersion { + pub fn url(&self) -> String { + match self { + RepoVersion::Master => { + "https://github.com/multiversx/mx-sdk-rs/archive/refs/heads/master.zip".to_string() + }, + RepoVersion::Tag(tag) => { + format!("https://github.com/multiversx/mx-sdk-rs/archive/refs/tags/v{tag}.zip") + }, + } + } + + pub fn temp_dir_name(&self) -> String { + match self { + RepoVersion::Master => "mx-sdk-rs-master".to_string(), + RepoVersion::Tag(tag) => { + format!("mx-sdk-rs-{tag}") + }, + } + } +} diff --git a/framework/meta/src/template/template_download.rs b/framework/meta/src/template/template_download.rs index acccb61953..0c169655a0 100644 --- a/framework/meta/src/template/template_download.rs +++ b/framework/meta/src/template/template_download.rs @@ -1,14 +1,17 @@ -use crate::cli_args::TemplateArgs; +use crate::{ + cli_args::TemplateArgs, + version_history::{validate_template_tag, LAST_TEMPLATE_VERSION}, +}; use std::path::PathBuf; use super::{ - repo_temp_download::RepoSource, template_source::{template_sources, TemplateSource}, - TemplateAdjuster, + RepoSource, RepoVersion, TemplateAdjuster, }; pub async fn template_download(args: &TemplateArgs) { - let repo_temp_download = RepoSource::download_from_github(std::env::temp_dir()).await; + let version = get_repo_version(&args.tag); + let repo_temp_download = RepoSource::download_from_github(version, std::env::temp_dir()).await; let downloader = TemplateDownloader::new( &repo_temp_download, args.template.clone(), @@ -19,6 +22,15 @@ pub async fn template_download(args: &TemplateArgs) { downloader.rename_template_to(args.template.clone()); } +pub(crate) fn get_repo_version(args_tag: &Option) -> RepoVersion { + if let Some(tag) = args_tag { + assert!(validate_template_tag(tag), "invalid template tag"); + RepoVersion::Tag(tag.clone()) + } else { + RepoVersion::Tag(LAST_TEMPLATE_VERSION.to_string()) + } +} + pub struct TemplateDownloader<'a> { pub repo_source: &'a RepoSource, pub template_source: TemplateSource<'a>, diff --git a/framework/meta/src/template/template_list.rs b/framework/meta/src/template/template_list.rs index 71134c543b..7dc99121d0 100644 --- a/framework/meta/src/template/template_list.rs +++ b/framework/meta/src/template/template_list.rs @@ -1,7 +1,10 @@ -use super::{repo_temp_download::RepoSource, template_source::template_sources}; +use crate::cli_args::TemplateListArgs; -pub async fn print_template_names() { - let repo_temp_download = RepoSource::download_from_github(std::env::temp_dir()).await; +use super::{template_download::get_repo_version, template_source::template_sources, RepoSource}; + +pub async fn print_template_names(args: &TemplateListArgs) { + let version = get_repo_version(&args.tag); + let repo_temp_download = RepoSource::download_from_github(version, std::env::temp_dir()).await; let template_names = template_names_from_repo(&repo_temp_download); for template_name in template_names { println!("{template_name}"); diff --git a/framework/meta/src/template/template_source.rs b/framework/meta/src/template/template_source.rs index d974b33c9e..29defc977e 100644 --- a/framework/meta/src/template/template_source.rs +++ b/framework/meta/src/template/template_source.rs @@ -5,7 +5,7 @@ use std::{ use crate::folder_structure::{whitelisted_deep_copy, RelevantDirectories}; -use super::{repo_temp_download::RepoSource, template_metadata::TemplateMetadata}; +use super::{template_metadata::TemplateMetadata, RepoSource}; const TEMPLATES_PATH_IN_REPO: &str = "contracts/examples"; const TEMPLATE_TOML_FILE_NAME: &str = "mxsc-template.toml"; diff --git a/framework/meta/src/cmd/standalone/upgrade/upgrade_versions.rs b/framework/meta/src/version_history.rs similarity index 65% rename from framework/meta/src/cmd/standalone/upgrade/upgrade_versions.rs rename to framework/meta/src/version_history.rs index c7f1b77e11..49f404ede5 100644 --- a/framework/meta/src/cmd/standalone/upgrade/upgrade_versions.rs +++ b/framework/meta/src/version_history.rs @@ -1,9 +1,14 @@ -/// Not necessarily the last entry in `VERSIONS`. +/// The last version to be used for upgrades and templates. /// +/// Should be edited every time a new version of the framework is released. +pub const LAST_VERSION: &str = "0.43.0"; + /// Indicates where to stop with the upgrades. -pub const DEFAULT_LAST_VERSION: &str = "0.43.0"; +pub const LAST_UPGRADE_VERSION: &str = LAST_VERSION; + +pub const LAST_TEMPLATE_VERSION: &str = LAST_VERSION; -/// Known version for the upgrader. +/// Known versions for the upgrader. #[rustfmt::skip] pub const VERSIONS: &[&str] = &[ "0.28.0", @@ -42,6 +47,15 @@ pub const VERSIONS: &[&str] = &[ "0.43.0", ]; +/// We started supporting contract templates with version 0.43.0. +pub fn template_versions() -> &'static [&'static str] { + &VERSIONS[33..] +} + +pub fn validate_template_tag(tag: &str) -> bool { + template_versions().iter().all(|&tt| tt == tag) +} + pub struct VersionIterator { next_version: usize, last_version: String, @@ -80,3 +94,16 @@ pub fn versions_iter(last_version: String) -> VersionIterator { last_version, } } + +#[cfg(test)] +pub mod tests { + use super::*; + + #[test] + fn template_versions_test() { + assert_eq!(template_versions()[0], "0.43.0"); + + assert!(validate_template_tag("0.43.0")); + assert!(!validate_template_tag("0.42.0")); + } +} From 2447cb6bf00e0c01636ed12336d91af86774c53f Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 18:22:47 +0300 Subject: [PATCH 02/10] sc-meta template refactor & test with preserved paths --- .github/workflows/template-test.yml | 2 +- .gitignore | 1 + framework/meta/Cargo.toml | 2 +- .../meta/src/cli_args/cli_args_standalone.rs | 14 ++- framework/meta/src/cmd/standalone.rs | 4 +- framework/meta/src/template.rs | 6 +- .../meta/src/template/contract_creator.rs | 92 ++++++++++++++ .../src/template/contract_creator_target.rs | 13 ++ .../meta/src/template/template_adjuster.rs | 114 +++++++++--------- .../meta/src/template/template_download.rs | 68 ----------- framework/meta/src/template/template_list.rs | 2 +- .../meta/src/template/template_source.rs | 8 +- framework/meta/tests/template_test.rs | 74 +++++++----- 13 files changed, 232 insertions(+), 168 deletions(-) create mode 100644 framework/meta/src/template/contract_creator.rs create mode 100644 framework/meta/src/template/contract_creator_target.rs delete mode 100644 framework/meta/src/template/template_download.rs diff --git a/.github/workflows/template-test.yml b/.github/workflows/template-test.yml index 163220a9f2..aa6427e9d2 100644 --- a/.github/workflows/template-test.yml +++ b/.github/workflows/template-test.yml @@ -23,4 +23,4 @@ jobs: - name: Run template tool test run: | cd framework/meta - cargo test --features template-test + cargo test --features template-test-current diff --git a/.gitignore b/.gitignore index e50fdfaa61..3f6e39d9a1 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ my-vm-tests.sh quick.sh twiggy* template-test +template-test-current # Zip output with example wasm binaries examples-wasm.zip diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index c18a5ab8da..f6fb8b4764 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -21,7 +21,7 @@ name = "sc-meta" path = "src/main.rs" [features] -template-test = [] +template-test-current = [] [dependencies] tokio = { version = "1.24", features = ["full"] } diff --git a/framework/meta/src/cli_args/cli_args_standalone.rs b/framework/meta/src/cli_args/cli_args_standalone.rs index 81c23b408f..c9cbde5f5a 100644 --- a/framework/meta/src/cli_args/cli_args_standalone.rs +++ b/framework/meta/src/cli_args/cli_args_standalone.rs @@ -185,16 +185,22 @@ pub struct LocalDepsArgs { #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] pub struct TemplateArgs { /// The new name the contract is to receive. - #[arg(long = "name", verbatim_doc_comment)] - pub name: PathBuf, + /// If missing, the template name will be considered. + #[arg(long, verbatim_doc_comment)] + pub name: Option, /// The contract template to clone. - #[arg(long = "template", verbatim_doc_comment)] + #[arg(long, verbatim_doc_comment)] pub template: String, /// The framework version on which the contracts should be created. - #[arg(long = "tag", verbatim_doc_comment)] + #[arg(long, verbatim_doc_comment)] pub tag: Option, + + /// Target directory where to create the new contract directory. + /// Will be current directory if not specified. + #[arg(long, verbatim_doc_comment)] + pub path: Option, } impl CliArgsToRaw for TemplateArgs { diff --git a/framework/meta/src/cmd/standalone.rs b/framework/meta/src/cmd/standalone.rs index 89a2e04238..b2a34cf0f0 100644 --- a/framework/meta/src/cmd/standalone.rs +++ b/framework/meta/src/cmd/standalone.rs @@ -6,7 +6,7 @@ pub(crate) mod upgrade; use crate::{ cli_args::{StandaloneCliAction, StandaloneCliArgs}, - template::{print_template_names, template_download}, + template::{create_contract, print_template_names}, }; use all::call_all_meta; use clap::Parser; @@ -28,7 +28,7 @@ pub async fn cli_main_standalone() { local_deps(args); }, Some(StandaloneCliAction::Template(args)) => { - template_download(args).await; + create_contract(args).await; }, Some(StandaloneCliAction::TemplateList(args)) => { print_template_names(args).await; diff --git a/framework/meta/src/template.rs b/framework/meta/src/template.rs index 7501291917..36f3a4fb7e 100644 --- a/framework/meta/src/template.rs +++ b/framework/meta/src/template.rs @@ -1,15 +1,17 @@ +mod contract_creator; +mod contract_creator_target; mod repo_source; mod repo_temp_download; mod repo_version; mod template_adjuster; -mod template_download; mod template_list; mod template_metadata; mod template_source; +pub use contract_creator::{create_contract, ContractCreator}; +pub use contract_creator_target::ContractCreatorTarget; pub use repo_source::RepoSource; pub use repo_temp_download::RepoTempDownload; pub use repo_version::RepoVersion; pub use template_adjuster::TemplateAdjuster; -pub use template_download::{template_download, TemplateDownloader}; pub use template_list::{print_template_names, template_names_from_repo}; diff --git a/framework/meta/src/template/contract_creator.rs b/framework/meta/src/template/contract_creator.rs new file mode 100644 index 0000000000..2f85216331 --- /dev/null +++ b/framework/meta/src/template/contract_creator.rs @@ -0,0 +1,92 @@ +use crate::{ + cli_args::TemplateArgs, + version_history::{validate_template_tag, LAST_TEMPLATE_VERSION}, +}; + +use super::{ + template_source::{template_sources, TemplateSource}, + ContractCreatorTarget, RepoSource, RepoVersion, TemplateAdjuster, +}; + +/// Creates a new contract on disk, from a template, given a name. +pub async fn create_contract(args: &TemplateArgs) { + let version = get_repo_version(&args.tag); + let repo_temp_download = RepoSource::download_from_github(version, std::env::temp_dir()).await; + let target = target_from_args(args); + + let creator = ContractCreator::new(&repo_temp_download, args.template.clone(), target, false); + + creator.create_contract(); +} + +fn target_from_args(args: &TemplateArgs) -> ContractCreatorTarget { + let new_name = args.name.clone().unwrap_or_else(|| args.template.clone()); + let target_path = args.path.clone().unwrap_or_default(); + ContractCreatorTarget { + target_path, + new_name, + } +} + +pub(crate) fn get_repo_version(args_tag: &Option) -> RepoVersion { + if let Some(tag) = args_tag { + assert!(validate_template_tag(tag), "invalid template tag"); + RepoVersion::Tag(tag.clone()) + } else { + RepoVersion::Tag(LAST_TEMPLATE_VERSION.to_string()) + } +} + +/// Coordinates the creation of a new contract from a template. +pub struct ContractCreator<'a> { + pub repo_source: &'a RepoSource, + pub template_source: TemplateSource<'a>, + pub target: ContractCreatorTarget, + pub adjuster: TemplateAdjuster, +} + +impl<'a> ContractCreator<'a> { + pub fn new( + repo_source: &'a RepoSource, + template_name: String, + target: ContractCreatorTarget, + keep_paths: bool, + ) -> Self { + let template_sources = template_sources(repo_source); + let template_source = template_sources + .into_iter() + .find(|source| source.metadata.name == template_name) + .unwrap_or_else(|| panic!("Unknown template {template_name}")); + + let metadata = template_source.metadata.clone(); + ContractCreator { + repo_source, + template_source, + target: target.clone(), + adjuster: TemplateAdjuster { + metadata, + target, + keep_paths, + }, + } + } + + pub fn create_contract(&self) { + self.copy_template(); + self.update_dependencies(); + self.rename_template(); + } + + pub fn copy_template(&self) { + self.template_source + .copy_template(self.target.contract_dir()); + } + + pub fn update_dependencies(&self) { + self.adjuster.update_dependencies(); + } + + pub fn rename_template(&self) { + self.adjuster.rename_template_to(); + } +} diff --git a/framework/meta/src/template/contract_creator_target.rs b/framework/meta/src/template/contract_creator_target.rs new file mode 100644 index 0000000000..4904b48d05 --- /dev/null +++ b/framework/meta/src/template/contract_creator_target.rs @@ -0,0 +1,13 @@ +use std::path::PathBuf; + +#[derive(Clone)] +pub struct ContractCreatorTarget { + pub target_path: PathBuf, + pub new_name: String, +} + +impl ContractCreatorTarget { + pub fn contract_dir(&self) -> PathBuf { + self.target_path.join(&self.new_name) + } +} diff --git a/framework/meta/src/template/template_adjuster.rs b/framework/meta/src/template/template_adjuster.rs index 9811320588..20082163b3 100644 --- a/framework/meta/src/template/template_adjuster.rs +++ b/framework/meta/src/template/template_adjuster.rs @@ -1,6 +1,4 @@ -use std::path::PathBuf; - -use super::template_metadata::TemplateMetadata; +use super::{template_metadata::TemplateMetadata, ContractCreatorTarget}; use crate::{ cmd::standalone::upgrade::upgrade_common::{rename_files, replace_in_files}, CargoTomlContents, @@ -15,17 +13,11 @@ const META_CARGO_TOML: &str = "./meta/Cargo.toml"; const WASM_CARGO_TOML: &str = "./wasm/Cargo.toml"; pub struct TemplateAdjuster { - pub target_path: PathBuf, pub metadata: TemplateMetadata, + pub target: ContractCreatorTarget, + pub keep_paths: bool, } impl TemplateAdjuster { - pub fn new(target_path: PathBuf, metadata: TemplateMetadata) -> Self { - Self { - target_path, - metadata, - } - } - pub fn update_dependencies(&self) { self.update_dependencies_root(); self.update_dependencies_wasm(); @@ -33,117 +25,120 @@ impl TemplateAdjuster { } fn update_dependencies_root(&self) { - let cargo_toml_path = self.target_path.join(ROOT_CARGO_TOML); + let cargo_toml_path = self.target.contract_dir().join(ROOT_CARGO_TOML); let mut toml = CargoTomlContents::load_from_file(&cargo_toml_path); - let deps_map = toml.dependencies_mut(); - remove_paths_from_dependencies(deps_map, &[]); + if !self.keep_paths { + remove_paths_from_deps(&mut toml, &[]); + } - let dev_deps_map = toml.dev_dependencies_mut(); - remove_paths_from_dependencies(dev_deps_map, &[]); toml.insert_default_workspace(); toml.save_to_file(&cargo_toml_path); } fn update_dependencies_meta(&self) { - let cargo_toml_path = self.target_path.join(META_CARGO_TOML); + let cargo_toml_path = self.target.contract_dir().join(META_CARGO_TOML); let mut toml = CargoTomlContents::load_from_file(&cargo_toml_path); - let deps_map = toml.dependencies_mut(); - remove_paths_from_dependencies(deps_map, &[&self.metadata.name]); + if !self.keep_paths { + remove_paths_from_deps(&mut toml, &[&self.metadata.name]); + } toml.save_to_file(&cargo_toml_path); } fn update_dependencies_wasm(&self) { - let cargo_toml_path = self.target_path.join(WASM_CARGO_TOML); + let cargo_toml_path = self.target.contract_dir().join(WASM_CARGO_TOML); let mut toml = CargoTomlContents::load_from_file(&cargo_toml_path); - let deps_map = toml.dependencies_mut(); - remove_paths_from_dependencies(deps_map, &[&self.metadata.name]); + if !self.keep_paths { + remove_paths_from_deps(&mut toml, &[&self.metadata.name]); + } toml.save_to_file(&cargo_toml_path); } - pub fn rename_template_to(&self, new_name: String) { - self.rename_trait_to(&new_name.to_case(Case::UpperCamel)); - self.rename_in_cargo_toml_root(&new_name); - self.rename_in_cargo_toml_meta(&new_name); - self.rename_in_cargo_toml_wasm(&new_name); - self.rename_in_tests(&new_name); - self.rename_solution_files(&new_name); + pub fn rename_template_to(&self) { + self.rename_trait_to(); + self.rename_in_cargo_toml_root(); + self.rename_in_cargo_toml_meta(); + self.rename_in_cargo_toml_wasm(); + self.rename_in_tests(); + self.rename_solution_files(); } - fn rename_trait_to(&self, new_template_name: &str) { - let new_name = new_template_name.to_case(Case::Snake); + fn rename_trait_to(&self) { + let new_trait = self.target.new_name.to_case(Case::UpperCamel); + let old_trait = &self.metadata.contract_trait; + let new_name = self.target.new_name.to_case(Case::Snake); let old_name = self.metadata.name.to_case(Case::Snake); let new_package = format!("{new_name}::"); let old_package = format!("{old_name}::"); replace_in_files( - &self.target_path, + &self.target.contract_dir(), "*rs", &[ - Query::substring(&self.metadata.contract_trait, new_template_name), + Query::substring(old_trait, &new_trait), Query::substring(&old_package, &new_package), ][..], ); } - fn rename_in_cargo_toml_root(&self, new_template_name: &str) { + fn rename_in_cargo_toml_root(&self) { let old_path = self.metadata.src_file.clone(); - let new_path = rs_file_name(&new_template_name.to_case(Case::Snake)); + let new_path = rs_file_name(&self.target.new_name.to_case(Case::Snake)); replace_in_files( - &self.target_path, + &self.target.contract_dir(), "*Cargo.toml", &[ Query::substring( &package_name_expr(&self.metadata.name), - &package_name_expr(new_template_name), + &package_name_expr(&self.target.new_name), ), Query::substring(&old_path, &new_path), ][..], ); } - fn rename_in_cargo_toml_meta(&self, new_template_name: &str) { + fn rename_in_cargo_toml_meta(&self) { let old_meta = format!("{}-meta", self.metadata.name.clone()); - let new_meta = format!("{}-meta", new_template_name.to_owned()); + let new_meta = format!("{}-meta", &self.target.new_name); replace_in_files( - &self.target_path, + &self.target.contract_dir(), "*Cargo.toml", &[ Query::substring(&package_name_expr(&old_meta), &package_name_expr(&new_meta)), Query::substring( &dependecy_decl_expr(&self.metadata.name), - &dependecy_decl_expr(new_template_name), + &dependecy_decl_expr(&self.target.new_name), ), ][..], ); } - fn rename_in_cargo_toml_wasm(&self, new_template_name: &str) { + fn rename_in_cargo_toml_wasm(&self) { let old_wasm = format!("{}-wasm", self.metadata.name.clone()); - let new_wasm = format!("{}-wasm", new_template_name.to_owned()); + let new_wasm = format!("{}-wasm", &self.target.new_name); replace_in_files( - &self.target_path, + &self.target.contract_dir(), "*Cargo.toml", &[ Query::substring(&package_name_expr(&old_wasm), &package_name_expr(&new_wasm)), Query::substring( &dependecy_decl_expr(&self.metadata.name), - &dependecy_decl_expr(new_template_name), + &dependecy_decl_expr(&self.target.new_name), ), ][..], ); } - fn rename_in_tests(&self, new_template_name: &str) { - let new_name = new_template_name.to_case(Case::Snake); + fn rename_in_tests(&self) { + let new_name = self.target.new_name.to_case(Case::Snake); let old_name = self.metadata.name.to_case(Case::Snake); let mut queries = Vec::::new(); @@ -151,7 +146,7 @@ impl TemplateAdjuster { queries.push(Query::substring(old, new)) } - let new_path = as_path(new_template_name); + let new_path = as_path(&self.target.new_name); let old_path = as_path(&self.metadata.name); queries.push(Query::substring(&old_path, &new_path)); @@ -160,28 +155,32 @@ impl TemplateAdjuster { queries.push(Query::substring(&old_scenarios, &new_scenarios)); let old_wasm = wasm_file_name(&self.metadata.name); - let new_wasm = wasm_file_name(new_template_name); + let new_wasm = wasm_file_name(&self.target.new_name); replace_in_files( - &self.target_path, + &self.target.contract_dir(), "*.scen.json", &[Query::substring(&old_wasm, &new_wasm)][..], ); queries.push(Query::substring(&old_wasm, &new_wasm)); - replace_in_files(&self.target_path.join(TEST_DIRECTORY), "*.rs", &queries); + replace_in_files( + &self.target.contract_dir().join(TEST_DIRECTORY), + "*.rs", + &queries, + ); } - fn rename_solution_files(&self, new_template_name: &str) { - let new_name = new_template_name.to_case(Case::Snake); + fn rename_solution_files(&self) { + let new_name = self.target.new_name.to_case(Case::Snake); let new_src_name = rs_file_name(&new_name); let pattern: &[(&str, &str)] = &[ (&self.metadata.src_file, &new_src_name), (&self.metadata.name, &new_name), ]; - rename_files(&self.target_path, pattern); + rename_files(&self.target.target_path, pattern); } } @@ -207,7 +206,7 @@ fn dependecy_decl_expr(template: &str) -> String { format!("dependencies.{template}") } -pub fn remove_paths_from_dependencies(deps_map: &mut Table, ignore_deps: &[&str]) { +pub fn remove_paths_from_deps_map(deps_map: &mut Table, ignore_deps: &[&str]) { for (key, value) in deps_map { if ignore_deps.contains(&key.as_str()) { continue; @@ -217,3 +216,8 @@ pub fn remove_paths_from_dependencies(deps_map: &mut Table, ignore_deps: &[&str] } } } + +pub fn remove_paths_from_deps(toml: &mut CargoTomlContents, ignore_deps: &[&str]) { + remove_paths_from_deps_map(toml.dependencies_mut(), ignore_deps); + remove_paths_from_deps_map(toml.dev_dependencies_mut(), ignore_deps); +} diff --git a/framework/meta/src/template/template_download.rs b/framework/meta/src/template/template_download.rs deleted file mode 100644 index 0c169655a0..0000000000 --- a/framework/meta/src/template/template_download.rs +++ /dev/null @@ -1,68 +0,0 @@ -use crate::{ - cli_args::TemplateArgs, - version_history::{validate_template_tag, LAST_TEMPLATE_VERSION}, -}; -use std::path::PathBuf; - -use super::{ - template_source::{template_sources, TemplateSource}, - RepoSource, RepoVersion, TemplateAdjuster, -}; - -pub async fn template_download(args: &TemplateArgs) { - let version = get_repo_version(&args.tag); - let repo_temp_download = RepoSource::download_from_github(version, std::env::temp_dir()).await; - let downloader = TemplateDownloader::new( - &repo_temp_download, - args.template.clone(), - args.name.clone(), - ); - downloader.copy_template(&downloader.template_source.metadata.files_include); - downloader.update_dependencies(); - downloader.rename_template_to(args.template.clone()); -} - -pub(crate) fn get_repo_version(args_tag: &Option) -> RepoVersion { - if let Some(tag) = args_tag { - assert!(validate_template_tag(tag), "invalid template tag"); - RepoVersion::Tag(tag.clone()) - } else { - RepoVersion::Tag(LAST_TEMPLATE_VERSION.to_string()) - } -} - -pub struct TemplateDownloader<'a> { - pub repo_source: &'a RepoSource, - pub template_source: TemplateSource<'a>, - pub target_path: PathBuf, - pub adjuster: TemplateAdjuster, -} - -impl<'a> TemplateDownloader<'a> { - pub fn new(repo_source: &'a RepoSource, template_name: String, target_path: PathBuf) -> Self { - let template_sources = template_sources(repo_source); - let template_source = template_sources - .into_iter() - .find(|source| source.metadata.name == template_name) - .unwrap_or_else(|| panic!("Unknown template {template_name}")); - - let metadata = template_source.metadata.clone(); - TemplateDownloader { - repo_source, - template_source, - target_path: target_path.clone(), - adjuster: TemplateAdjuster::new(target_path, metadata), - } - } - - pub fn copy_template(&self, files_to_copy: &[String]) { - self.template_source - .copy_template(&self.target_path, files_to_copy); - } - pub fn update_dependencies(&self) { - self.adjuster.update_dependencies(); - } - pub fn rename_template_to(&self, new_template_name: String) { - self.adjuster.rename_template_to(new_template_name); - } -} diff --git a/framework/meta/src/template/template_list.rs b/framework/meta/src/template/template_list.rs index 7dc99121d0..7328b83c86 100644 --- a/framework/meta/src/template/template_list.rs +++ b/framework/meta/src/template/template_list.rs @@ -1,6 +1,6 @@ use crate::cli_args::TemplateListArgs; -use super::{template_download::get_repo_version, template_source::template_sources, RepoSource}; +use super::{contract_creator::get_repo_version, template_source::template_sources, RepoSource}; pub async fn print_template_names(args: &TemplateListArgs) { let version = get_repo_version(&args.tag); diff --git a/framework/meta/src/template/template_source.rs b/framework/meta/src/template/template_source.rs index 29defc977e..8e2e81a843 100644 --- a/framework/meta/src/template/template_source.rs +++ b/framework/meta/src/template/template_source.rs @@ -17,8 +17,12 @@ pub struct TemplateSource<'a> { } impl<'a> TemplateSource<'a> { - pub fn copy_template(&self, target_path: impl AsRef, whitelist: &[String]) { - whitelisted_deep_copy(&self.source_path, target_path.as_ref(), whitelist); + pub fn copy_template(&self, target_path: impl AsRef) { + whitelisted_deep_copy( + &self.source_path, + target_path.as_ref(), + &self.metadata.files_include, + ); } } diff --git a/framework/meta/tests/template_test.rs b/framework/meta/tests/template_test.rs index b580779afa..075abf33d3 100644 --- a/framework/meta/tests/template_test.rs +++ b/framework/meta/tests/template_test.rs @@ -1,11 +1,13 @@ -use multiversx_sc_meta::template::{template_names_from_repo, RepoSource, TemplateDownloader}; +use multiversx_sc_meta::template::{ + template_names_from_repo, ContractCreator, ContractCreatorTarget, RepoSource, +}; use std::{ fs, path::{Path, PathBuf}, process::Command, }; -const TEMPLATE_TEMP_DIR_NAME: &str = "template-test"; +const TEMPLATE_TEMP_DIR_NAME: &str = "template-test-current"; const BUILD_CONTRACTS: bool = false; #[test] @@ -25,53 +27,61 @@ fn test_template_list() { } #[test] -#[cfg_attr(not(feature = "template-test"), ignore)] -fn template_test_adder() { - template_test("adder", "new-adder"); +#[cfg_attr(not(feature = "template-test-current"), ignore)] +fn template_test_current_adder() { + template_test_current("adder", "examples", "new-adder"); } #[test] -#[cfg_attr(not(feature = "template-test"), ignore)] -fn template_test_crypto_zombies() { - template_test("crypto-zombies", "new-crypto-zombies"); +#[cfg_attr(not(feature = "template-test-current"), ignore)] +fn template_test_current_crypto_zombies() { + template_test_current("crypto-zombies", "examples", "new-crypto-zombies"); } #[test] -#[cfg_attr(not(feature = "template-test"), ignore)] -fn template_test_empty() { - template_test("empty", "new-empty"); +#[cfg_attr(not(feature = "template-test-current"), ignore)] +fn template_test_current_empty() { + template_test_current("empty", "examples", "new-empty"); } -fn template_test(template_name: &str, new_name: &str) { +/// Recreates the folder structure in `contracts`, on the same level. +/// This way, the relative paths are still valid in this case, and we can test the templates with the versions on the current branch. +fn template_test_current(template_name: &str, sub_path: &str, new_name: &str) { let workspace_path = find_workspace(); + let target = ContractCreatorTarget { + target_path: workspace_path.join(TEMPLATE_TEMP_DIR_NAME).join(sub_path), + new_name: new_name.to_string(), + }; + let repo_source = RepoSource::from_local_path(workspace_path); - let target_dir = prepare_target_dir(new_name); + prepare_target_dir(&target); + + let downloader = ContractCreator::new( + &repo_source, + template_name.to_string(), + target.clone(), + true, + ); + + downloader.create_contract(); - let downloader = - TemplateDownloader::new(&repo_source, template_name.to_string(), target_dir.clone()); - downloader.copy_template(&downloader.template_source.metadata.files_include); - downloader.update_dependencies(); - downloader.rename_template_to(new_name.to_string()); if BUILD_CONTRACTS { - build_contract(&target_dir); + build_contract(&target); } - cargo_test(&target_dir); + cargo_test(&target); } -fn prepare_target_dir(new_name: &str) -> PathBuf { - let template_temp_path = find_workspace().join(TEMPLATE_TEMP_DIR_NAME); - fs::create_dir_all(&template_temp_path).unwrap(); +fn prepare_target_dir(target: &ContractCreatorTarget) { + fs::create_dir_all(&target.target_path).unwrap(); - let target_dir = template_temp_path.join(new_name); - if target_dir.exists() { - fs::remove_dir_all(&target_dir).unwrap(); + let contract_dir = target.contract_dir(); + if contract_dir.exists() { + fs::remove_dir_all(&contract_dir).unwrap(); } - - target_dir } -pub fn cargo_test(contract_location: &Path) { +pub fn cargo_test(target: &ContractCreatorTarget) { let workspace_target_dir = find_workspace().join("target"); let mut args = vec![ @@ -86,7 +96,7 @@ pub fn cargo_test(contract_location: &Path) { let exit_status = Command::new("cargo") .args(args) - .current_dir(contract_location) + .current_dir(target.contract_dir()) .spawn() .expect("failed to spawn contract clean process") .wait() @@ -95,7 +105,7 @@ pub fn cargo_test(contract_location: &Path) { assert!(exit_status.success(), "contract test process failed"); } -pub fn build_contract(contract_location: &Path) { +pub fn build_contract(target: &ContractCreatorTarget) { let workspace_target_dir = find_workspace().join("target"); let exit_status = Command::new("cargo") @@ -105,7 +115,7 @@ pub fn build_contract(contract_location: &Path) { "--target-dir", workspace_target_dir.to_str().unwrap(), ]) - .current_dir(contract_location.join("meta")) + .current_dir(target.contract_dir().join("meta")) .spawn() .expect("failed to spawn contract clean process") .wait() From d9349f33cb7090c2b515bee6f1bdca14483b42ac Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 19:02:52 +0300 Subject: [PATCH 03/10] sc-meta template tests from released tag --- ...ate-test.yml => template-test-current.yml} | 2 +- .github/workflows/template-test-released.yml | 26 +++++++ .gitignore | 1 - framework/meta/Cargo.toml | 1 + framework/meta/src/cargo_toml_contents.rs | 8 +++ framework/meta/src/lib.rs | 2 +- .../meta/src/template/template_adjuster.rs | 8 ++- framework/meta/tests/template_test.rs | 71 ++++++++++++++++--- 8 files changed, 106 insertions(+), 13 deletions(-) rename .github/workflows/{template-test.yml => template-test-current.yml} (88%) create mode 100644 .github/workflows/template-test-released.yml diff --git a/.github/workflows/template-test.yml b/.github/workflows/template-test-current.yml similarity index 88% rename from .github/workflows/template-test.yml rename to .github/workflows/template-test-current.yml index aa6427e9d2..bafe90216d 100644 --- a/.github/workflows/template-test.yml +++ b/.github/workflows/template-test-current.yml @@ -12,7 +12,7 @@ permissions: jobs: template_test: - name: Template tool test + name: Template tool test - current (unreleased) templates runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/template-test-released.yml b/.github/workflows/template-test-released.yml new file mode 100644 index 0000000000..5e256dd39f --- /dev/null +++ b/.github/workflows/template-test-released.yml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + +permissions: + checks: write + pull-requests: write + +jobs: + template_test: + name: Template tool test - released contracts + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + default: true + toolchain: nightly-2023-08-08 + - name: Run template tool test + run: | + cd framework/meta + cargo test --features template-test-released diff --git a/.gitignore b/.gitignore index 3f6e39d9a1..e50fdfaa61 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,6 @@ my-vm-tests.sh quick.sh twiggy* template-test -template-test-current # Zip output with example wasm binaries examples-wasm.zip diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index f6fb8b4764..c035a2aeb2 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -22,6 +22,7 @@ path = "src/main.rs" [features] template-test-current = [] +template-test-released = [] [dependencies] tokio = { version = "1.24", features = ["full"] } diff --git a/framework/meta/src/cargo_toml_contents.rs b/framework/meta/src/cargo_toml_contents.rs index 00d388f7b2..2a7c944208 100644 --- a/framework/meta/src/cargo_toml_contents.rs +++ b/framework/meta/src/cargo_toml_contents.rs @@ -84,6 +84,10 @@ impl CargoTomlContents { } } + pub fn has_dependencies(&self) -> bool { + self.toml_value.get(CARGO_TOML_DEPENDENCIES).is_some() + } + pub fn dependencies_mut(&mut self) -> &mut Table { self.toml_value .get_mut(CARGO_TOML_DEPENDENCIES) @@ -92,6 +96,10 @@ impl CargoTomlContents { .expect("malformed crate Cargo.toml") } + pub fn has_dev_dependencies(&self) -> bool { + self.toml_value.get(CARGO_TOML_DEV_DEPENDENCIES).is_some() + } + pub fn dev_dependencies_mut(&mut self) -> &mut Table { self.toml_value .get_mut(CARGO_TOML_DEV_DEPENDENCIES) diff --git a/framework/meta/src/lib.rs b/framework/meta/src/lib.rs index 71790e2b01..8d62eaf391 100644 --- a/framework/meta/src/lib.rs +++ b/framework/meta/src/lib.rs @@ -8,7 +8,7 @@ mod mxsc_file_json; mod print_util; pub mod template; mod tools; -mod version_history; +pub mod version_history; #[macro_use] extern crate lazy_static; diff --git a/framework/meta/src/template/template_adjuster.rs b/framework/meta/src/template/template_adjuster.rs index 20082163b3..44eb30a7c3 100644 --- a/framework/meta/src/template/template_adjuster.rs +++ b/framework/meta/src/template/template_adjuster.rs @@ -218,6 +218,10 @@ pub fn remove_paths_from_deps_map(deps_map: &mut Table, ignore_deps: &[&str]) { } pub fn remove_paths_from_deps(toml: &mut CargoTomlContents, ignore_deps: &[&str]) { - remove_paths_from_deps_map(toml.dependencies_mut(), ignore_deps); - remove_paths_from_deps_map(toml.dev_dependencies_mut(), ignore_deps); + if toml.has_dependencies() { + remove_paths_from_deps_map(toml.dependencies_mut(), ignore_deps); + } + if toml.has_dev_dependencies() { + remove_paths_from_deps_map(toml.dev_dependencies_mut(), ignore_deps); + } } diff --git a/framework/meta/tests/template_test.rs b/framework/meta/tests/template_test.rs index 075abf33d3..9dbe02cc88 100644 --- a/framework/meta/tests/template_test.rs +++ b/framework/meta/tests/template_test.rs @@ -1,5 +1,8 @@ -use multiversx_sc_meta::template::{ - template_names_from_repo, ContractCreator, ContractCreatorTarget, RepoSource, +use multiversx_sc_meta::{ + template::{ + template_names_from_repo, ContractCreator, ContractCreatorTarget, RepoSource, RepoVersion, + }, + version_history, }; use std::{ fs, @@ -7,8 +10,8 @@ use std::{ process::Command, }; -const TEMPLATE_TEMP_DIR_NAME: &str = "template-test-current"; -const BUILD_CONTRACTS: bool = false; +const TEMPLATE_TEMP_DIR_NAME: &str = "template-test"; +const BUILD_CONTRACTS: bool = true; #[test] fn test_template_list() { @@ -45,7 +48,8 @@ fn template_test_current_empty() { } /// Recreates the folder structure in `contracts`, on the same level. -/// This way, the relative paths are still valid in this case, and we can test the templates with the versions on the current branch. +/// This way, the relative paths are still valid in this case, +/// and we can test the templates with the framework version of the current branch. fn template_test_current(template_name: &str, sub_path: &str, new_name: &str) { let workspace_path = find_workspace(); let target = ContractCreatorTarget { @@ -57,14 +61,65 @@ fn template_test_current(template_name: &str, sub_path: &str, new_name: &str) { prepare_target_dir(&target); - let downloader = ContractCreator::new( + ContractCreator::new( &repo_source, template_name.to_string(), target.clone(), true, - ); + ) + .create_contract(); + + if BUILD_CONTRACTS { + build_contract(&target); + } + cargo_test(&target); +} + +#[tokio::test] +#[cfg_attr(not(feature = "template-test-released"), ignore)] +async fn template_test_released_adder() { + template_test_released("adder", "released-adder").await; +} + +#[tokio::test] +#[cfg_attr(not(feature = "template-test-released"), ignore)] +async fn template_test_released_crypto_zombies() { + template_test_released("crypto-zombies", "released-crypto-zombies").await; +} + +#[tokio::test] +#[cfg_attr(not(feature = "template-test-released"), ignore)] +async fn template_test_released_empty() { + template_test_released("empty", "released-empty").await; +} + +/// These tests fully replicate the templating process. They +/// - download the last released version of the repo, +/// - create proper contracts, +/// - build the newly created contracts (to wasm) +/// - run all tests (including Go scenarios) on them. +async fn template_test_released(template_name: &str, new_name: &str) { + let workspace_path = find_workspace(); + let target = ContractCreatorTarget { + target_path: workspace_path.join(TEMPLATE_TEMP_DIR_NAME), + new_name: new_name.to_string(), + }; - downloader.create_contract(); + let repo_source = RepoSource::download_from_github( + RepoVersion::Tag(version_history::LAST_TEMPLATE_VERSION.to_string()), + std::env::temp_dir(), + ) + .await; + + prepare_target_dir(&target); + + ContractCreator::new( + &repo_source, + template_name.to_string(), + target.clone(), + false, + ) + .create_contract(); if BUILD_CONTRACTS { build_contract(&target); From 89e1aa93caa51cd2f7352297ab3b3f4452f11a17 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 19:06:24 +0300 Subject: [PATCH 04/10] template tests - disable build --- framework/meta/tests/template_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/meta/tests/template_test.rs b/framework/meta/tests/template_test.rs index 9dbe02cc88..c9498840b3 100644 --- a/framework/meta/tests/template_test.rs +++ b/framework/meta/tests/template_test.rs @@ -11,7 +11,7 @@ use std::{ }; const TEMPLATE_TEMP_DIR_NAME: &str = "template-test"; -const BUILD_CONTRACTS: bool = true; +const BUILD_CONTRACTS: bool = false; #[test] fn test_template_list() { From 5973ae4fa980654f6d6519a0e67e88c0ff5fe89b Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 19:34:47 +0300 Subject: [PATCH 05/10] template --target-dir backwards compatibility --- framework/meta/src/cli_args/cli_args_build.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/framework/meta/src/cli_args/cli_args_build.rs b/framework/meta/src/cli_args/cli_args_build.rs index fab772791f..daaf08039a 100644 --- a/framework/meta/src/cli_args/cli_args_build.rs +++ b/framework/meta/src/cli_args/cli_args_build.rs @@ -146,7 +146,8 @@ impl CliArgsToRaw for BuildArgs { raw.push("--no-imports".to_string()); } if let Some(target_dir_wasm) = &self.target_dir_wasm { - raw.push("--target-dir-wasm".to_string()); + // not using --target-dir-wasm, for backward compatibility + raw.push("--target-dir".to_string()); raw.push(target_dir_wasm.clone()); } if self.twiggy_top { @@ -214,7 +215,8 @@ impl CliArgsToRaw for BuildDbgArgs { fn to_raw(&self) -> Vec { let mut raw = Vec::new(); if let Some(target_dir_wasm) = &self.target_dir_wasm { - raw.push("--target-dir-wasm".to_string()); + // not using --target-dir-wasm, for backward compatibility + raw.push("--target-dir".to_string()); raw.push(target_dir_wasm.clone()); } if self.twiggy_top { @@ -259,7 +261,8 @@ impl CliArgsToRaw for TwiggyArgs { fn to_raw(&self) -> Vec { let mut raw = Vec::new(); if let Some(target_dir) = &self.target_dir_wasm { - raw.push("--target-dir-wasm".to_string()); + // not using --target-dir-wasm, for backward compatibility + raw.push("--target-dir".to_string()); raw.push(target_dir.clone()); } raw From 5782234469c4969d718f7ca7ae99bcd363ed241d Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 19:35:06 +0300 Subject: [PATCH 06/10] template test rename --- framework/meta/tests/template_test.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/framework/meta/tests/template_test.rs b/framework/meta/tests/template_test.rs index c9498840b3..ee7082672d 100644 --- a/framework/meta/tests/template_test.rs +++ b/framework/meta/tests/template_test.rs @@ -31,19 +31,19 @@ fn test_template_list() { #[test] #[cfg_attr(not(feature = "template-test-current"), ignore)] -fn template_test_current_adder() { +fn template_current_adder() { template_test_current("adder", "examples", "new-adder"); } #[test] #[cfg_attr(not(feature = "template-test-current"), ignore)] -fn template_test_current_crypto_zombies() { +fn template_current_crypto_zombies() { template_test_current("crypto-zombies", "examples", "new-crypto-zombies"); } #[test] #[cfg_attr(not(feature = "template-test-current"), ignore)] -fn template_test_current_empty() { +fn template_current_empty() { template_test_current("empty", "examples", "new-empty"); } @@ -77,19 +77,19 @@ fn template_test_current(template_name: &str, sub_path: &str, new_name: &str) { #[tokio::test] #[cfg_attr(not(feature = "template-test-released"), ignore)] -async fn template_test_released_adder() { +async fn template_released_adder() { template_test_released("adder", "released-adder").await; } #[tokio::test] #[cfg_attr(not(feature = "template-test-released"), ignore)] -async fn template_test_released_crypto_zombies() { +async fn template_released_crypto_zombies() { template_test_released("crypto-zombies", "released-crypto-zombies").await; } #[tokio::test] #[cfg_attr(not(feature = "template-test-released"), ignore)] -async fn template_test_released_empty() { +async fn template_released_empty() { template_test_released("empty", "released-empty").await; } From 72d9e872ccb0433dbde36f5366d99a6b44238575 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 19:35:49 +0300 Subject: [PATCH 07/10] template download extract error --- framework/meta/src/template/repo_temp_download.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/framework/meta/src/template/repo_temp_download.rs b/framework/meta/src/template/repo_temp_download.rs index f8b781f47f..c7f0403236 100644 --- a/framework/meta/src/template/repo_temp_download.rs +++ b/framework/meta/src/template/repo_temp_download.rs @@ -36,6 +36,12 @@ impl RepoTempDownload { async fn download_binaries(&self) -> Result<(), reqwest::Error> { let response = reqwest::get(self.version.url()).await?.bytes().await?; + if response.len() < 10000 { + panic!( + "Could not download artifact: {}", + String::from_utf8_lossy(&response.to_vec()) + ); + } let mut file = match File::create(self.zip_path()) { Err(why) => panic!("couldn't create {why}"), @@ -48,7 +54,8 @@ impl RepoTempDownload { fn unzip_binaries(&self) { let file = File::open(self.zip_path()).unwrap(); let mut zip = zip::ZipArchive::new(file).unwrap(); - zip.extract(Path::new(&self.temp_dir_path)).unwrap(); + zip.extract(Path::new(&self.temp_dir_path)) + .expect("Could not unzip artifact"); } fn delete_zip(&self) { From 1826c9665ca71dc5accda80cc550f6d8ed14286f Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 20:00:48 +0300 Subject: [PATCH 08/10] template test - separate download temp dirs --- framework/meta/src/template/repo_source.rs | 6 +++++- framework/meta/src/template/repo_temp_download.rs | 2 +- framework/meta/tests/template_test.rs | 6 +++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/framework/meta/src/template/repo_source.rs b/framework/meta/src/template/repo_source.rs index fda036bacf..b1e66063ee 100644 --- a/framework/meta/src/template/repo_source.rs +++ b/framework/meta/src/template/repo_source.rs @@ -1,4 +1,7 @@ -use std::path::{Path, PathBuf}; +use std::{ + fs, + path::{Path, PathBuf}, +}; use super::{RepoTempDownload, RepoVersion}; @@ -9,6 +12,7 @@ pub enum RepoSource { impl RepoSource { pub async fn download_from_github(version: RepoVersion, temp_dir_path: PathBuf) -> Self { + fs::create_dir_all(&temp_dir_path).unwrap(); RepoSource::Downloaded(RepoTempDownload::download_from_github(version, temp_dir_path).await) } diff --git a/framework/meta/src/template/repo_temp_download.rs b/framework/meta/src/template/repo_temp_download.rs index c7f0403236..242d21d0c6 100644 --- a/framework/meta/src/template/repo_temp_download.rs +++ b/framework/meta/src/template/repo_temp_download.rs @@ -39,7 +39,7 @@ impl RepoTempDownload { if response.len() < 10000 { panic!( "Could not download artifact: {}", - String::from_utf8_lossy(&response.to_vec()) + String::from_utf8_lossy(&response) ); } diff --git a/framework/meta/tests/template_test.rs b/framework/meta/tests/template_test.rs index ee7082672d..a986aadb2a 100644 --- a/framework/meta/tests/template_test.rs +++ b/framework/meta/tests/template_test.rs @@ -105,9 +105,13 @@ async fn template_test_released(template_name: &str, new_name: &str) { new_name: new_name.to_string(), }; + let temp_dir_path = workspace_path + .join(TEMPLATE_TEMP_DIR_NAME) + .join("temp-download") + .join(new_name); let repo_source = RepoSource::download_from_github( RepoVersion::Tag(version_history::LAST_TEMPLATE_VERSION.to_string()), - std::env::temp_dir(), + temp_dir_path, ) .await; From 4e74d339236e80ef7109be95ace065bbb9c0e058 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 20:15:44 +0300 Subject: [PATCH 09/10] template rename bugfix --- framework/meta/src/template/template_adjuster.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/meta/src/template/template_adjuster.rs b/framework/meta/src/template/template_adjuster.rs index 44eb30a7c3..d0d4b05c90 100644 --- a/framework/meta/src/template/template_adjuster.rs +++ b/framework/meta/src/template/template_adjuster.rs @@ -180,7 +180,7 @@ impl TemplateAdjuster { (&self.metadata.src_file, &new_src_name), (&self.metadata.name, &new_name), ]; - rename_files(&self.target.target_path, pattern); + rename_files(&self.target.contract_dir(), pattern); } } From e030f91e9036bd89b5dbdc42ace667e59e8b44f5 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 18 Aug 2023 20:19:45 +0300 Subject: [PATCH 10/10] template CI - changed name --- .github/workflows/template-test-released.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/template-test-released.yml b/.github/workflows/template-test-released.yml index 5e256dd39f..a41a1e25a3 100644 --- a/.github/workflows/template-test-released.yml +++ b/.github/workflows/template-test-released.yml @@ -12,7 +12,7 @@ permissions: jobs: template_test: - name: Template tool test - released contracts + name: Template tool test - released templates runs-on: ubuntu-latest steps: - uses: actions/checkout@v2