Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: instantiate tanssi container chains #285

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2ed4d7a
refactor: move extract_template_files into common crate
AlexD10S Aug 16, 2024
de2dcb9
fix: unnnecesary API query
AlexD10S Aug 16, 2024
92b1a07
feat: init tanssi templates
al3mart Aug 16, 2024
b88f23c
Update crates/pop-parachains/src/new_parachain.rs
al3mart Aug 16, 2024
c53ff45
Update crates/pop-parachains/src/new_parachain.rs
al3mart Aug 19, 2024
13f2210
ContainerChain Alias
al3mart Aug 19, 2024
4b3a2da
Tanssi template & runtime dirs
al3mart Aug 19, 2024
c4cb6c6
refactor: directories instead of folders (#286)
al3mart Aug 23, 2024
3636398
chore: merge main
AlexD10S Aug 26, 2024
df689f5
fix: target dir doesn't exist
al3mart Aug 26, 2024
9fbcf6d
feat: container zn template
al3mart Aug 26, 2024
7e35d02
resolve conflicts
al3mart Aug 26, 2024
6db37b6
fix: project manifest
al3mart Aug 28, 2024
2284850
fix: workspace manifest creation
al3mart Sep 13, 2024
e7c4639
refactor: cargo workspace generation
al3mart Sep 13, 2024
3f54786
chore: remove tanssi specifics from pop-common
al3mart Sep 14, 2024
51d562f
Merge pull request #311 from r0gue-io/al3mart/wip-improve-conatiner-c…
al3mart Sep 16, 2024
f72f427
merge main
al3mart Sep 16, 2024
a1871a1
fix: revert extractor changes
al3mart Sep 18, 2024
00594fb
style: tempalte typos
al3mart Sep 18, 2024
412a5d1
extractable .gitignore
al3mart Sep 18, 2024
c1a67c6
remove tanssi evm
al3mart Sep 18, 2024
69ab37c
parameter order
al3mart Sep 18, 2024
1db87cd
style: nightly fmt
al3mart Sep 18, 2024
fbc37a9
template naming
al3mart Sep 23, 2024
a5c360a
nightly fmt
al3mart Sep 23, 2024
e37e97f
refactor: don't use toml_edit
al3mart Sep 23, 2024
730f7ea
remove unwraps
al3mart Sep 24, 2024
509333b
remove unused imports
al3mart Sep 24, 2024
96c2a50
handle errors
al3mart Sep 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,130 changes: 45 additions & 1,085 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion crates/pop-cli/src/commands/new/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,6 @@ async fn choose_release(template: &Parachain) -> Result<Option<String>> {
async fn get_latest_3_releases(repo: &GitHub) -> Result<Vec<Release>> {
let mut latest_3_releases: Vec<Release> =
repo.releases().await?.into_iter().filter(|r| !r.prerelease).take(3).collect();
repo.get_repo_license().await?;
// Get the commit sha for the releases
for release in latest_3_releases.iter_mut() {
let commit = repo.get_commit_sha_from_release(&release.tag_name).await?;
Expand Down
1 change: 1 addition & 0 deletions crates/pop-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub use build::Profile;
pub use errors::Error;
pub use git::{Git, GitHub, Release};
pub use helpers::{get_project_name_from_path, replace_in_file};
pub use templates::extractor::extract_template_files;

static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));

Expand Down
104 changes: 104 additions & 0 deletions crates/pop-common/src/templates/extractor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// SPDX-License-Identifier: GPL-3.0

use std::{fs, io, path::Path};

use anyhow::Result;

/// Extracts the specified template files from the repository folder to the target folder.
///
/// # Arguments
/// * `template_file` - The name of the template to extract.
/// * `repo_folder` - The path to the repository folder containing the template.
al3mart marked this conversation as resolved.
Show resolved Hide resolved
/// * `target_folder` - The destination path where the template files should be copied.
/// * `ignore_folders` - A vector of folder names to ignore during the extraction. If empty, no
/// folders are ignored.
pub fn extract_template_files(
template_file: String,
repo_folder: &Path,
target_folder: &Path,
ignore_folders: Option<Vec<String>>,
) -> Result<()> {
let template_folder = repo_folder.join(&template_file);
if template_folder.is_dir() {
// Recursively copy all folders and files within. Ignores the specified ones.
copy_dir_all(&template_folder, target_folder, &ignore_folders.unwrap_or_else(|| vec![]))?;
return Ok(());
} else {
// If not a dir, just copy the file.
fs::copy(template_folder, target_folder.join(&template_file))?;
Ok(())
}
}

/// Recursively copy a directory and its files.
///
/// # Arguments
/// * `src`: - The source path of the directory to be copied.
/// * `dst`: - The destination path where the directory and its contents will be copied.
/// * `ignore_folders` - Folders to ignore during the copy process.
fn copy_dir_all(
src: impl AsRef<Path>,
dst: impl AsRef<Path>,
ignore_folders: &Vec<String>,
) -> io::Result<()> {
fs::create_dir_all(&dst)?;
for entry in fs::read_dir(src)? {
let entry = entry?;
let ty = entry.file_type()?;
if ty.is_dir() && ignore_folders.contains(&entry.file_name().to_string_lossy().to_string())
{
continue;
} else if ty.is_dir() {
copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()), ignore_folders)?;
} else {
fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
}
}
Ok(())
}

#[cfg(test)]
mod tests {
use std::fs;

use anyhow::{Error, Result};

use super::*;

fn generate_testing_contract(template: &str) -> Result<tempfile::TempDir, Error> {
let temp_dir = tempfile::tempdir()?;
let template_folder = temp_dir.path().join(template.to_string());
fs::create_dir(&template_folder)?;
fs::File::create(&template_folder.join("lib.rs"))?;
fs::File::create(&template_folder.join("Cargo.toml"))?;
fs::create_dir(&temp_dir.path().join("noise_folder"))?;
fs::create_dir(&template_folder.join("frontend"))?;
Ok(temp_dir)
}
#[test]
fn extract_template_files_works() -> Result<(), Error> {
// Contract
let mut temp_dir = generate_testing_contract("erc20")?;
let mut output_dir = tempfile::tempdir()?;
extract_template_files("erc20".to_string(), temp_dir.path(), output_dir.path(), None)?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(output_dir.path().join("frontend").exists());
assert!(!output_dir.path().join("noise_folder").exists());
// ignore the frontend folder
temp_dir = generate_testing_contract("erc721")?;
output_dir = tempfile::tempdir()?;
extract_template_files(
"erc721".to_string(),
temp_dir.path(),
output_dir.path(),
Some(vec!["frontend".to_string()]),
)?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(!output_dir.path().join("frontend").exists());
assert!(!output_dir.path().join("noise_folder").exists());

Ok(())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
use strum::{EnumMessage, EnumProperty, VariantArray};
pub use thiserror::Error;

pub mod extractor;

#[derive(Error, Debug)]
pub enum Error {
#[error("The `Repository` property is missing from the template variant")]
Expand Down
108 changes: 10 additions & 98 deletions crates/pop-contracts/src/new.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
// SPDX-License-Identifier: GPL-3.0

use crate::{
errors::Error,
utils::helpers::{canonicalized_path, copy_dir_all},
Contract,
};
use crate::{errors::Error, utils::helpers::canonicalized_path, Contract};
use anyhow::Result;
use contract_build::new_contract_project;
use heck::ToUpperCamelCase;
use pop_common::{replace_in_file, templates::Template, Git};
use pop_common::{extract_template_files, replace_in_file, templates::Template, Git};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use url::Url;
Expand Down Expand Up @@ -67,12 +63,18 @@ fn create_template_contract(
// Retrieve only the template contract files.
if template == &Contract::PSP22 || template == &Contract::PSP34 {
// Different template structure requires extracting different path
extract_contract_files(String::from(""), temp_dir.path(), canonicalized_path.as_path())?;
extract_template_files(
String::from(""),
temp_dir.path(),
canonicalized_path.as_path(),
None,
)?;
} else {
extract_contract_files(
extract_template_files(
template.to_string(),
temp_dir.path(),
canonicalized_path.as_path(),
Some(vec!["frontend".to_string()]),
)?;
}

Expand All @@ -81,17 +83,6 @@ fn create_template_contract(
Ok(())
}

fn extract_contract_files(
contract_name: String,
repo_folder: &Path,
target_folder: &Path,
) -> Result<()> {
let contract_folder = repo_folder.join(contract_name);
// Recursively copy all folders and files within. Ignores frontend folders.
copy_dir_all(&contract_folder, target_folder)?;
Ok(())
}

pub fn rename_contract(name: &str, path: PathBuf, template: &Contract) -> Result<()> {
let template_name = template.to_string().to_lowercase();
// Replace name in the Cargo.toml file.
Expand Down Expand Up @@ -170,85 +161,6 @@ mod tests {
Ok(())
}

fn generate_testing_files_and_folders(template: Contract) -> Result<tempfile::TempDir, Error> {
let temp_dir = tempfile::tempdir()?;
let contract_folder = temp_dir.path().join(template.to_string());
fs::create_dir(&contract_folder)?;
fs::File::create(&contract_folder.join("lib.rs"))?;
fs::File::create(&contract_folder.join("Cargo.toml"))?;
fs::create_dir(&temp_dir.path().join("noise_folder"))?;
Ok(temp_dir)
}

#[test]
fn test_extract_contract_files() -> Result<(), Error> {
// ERC-20
let mut temp_dir = generate_testing_files_and_folders(Contract::ERC20)?;
let mut output_dir = tempfile::tempdir()?;
extract_contract_files(Contract::ERC20.to_string(), temp_dir.path(), output_dir.path())?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(!output_dir.path().join("noise_folder").exists());
assert!(!output_dir.path().join("frontend").exists());
// ERC-721
temp_dir = generate_testing_files_and_folders(Contract::ERC721)?;
output_dir = tempfile::tempdir()?;
extract_contract_files(Contract::ERC721.to_string(), temp_dir.path(), output_dir.path())?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(!output_dir.path().join("noise_folder").exists());
assert!(!output_dir.path().join("frontend").exists());
// ERC-1155
temp_dir = generate_testing_files_and_folders(Contract::ERC1155)?;
output_dir = tempfile::tempdir()?;
extract_contract_files(Contract::ERC1155.to_string(), temp_dir.path(), output_dir.path())?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(!output_dir.path().join("noise_folder").exists());
assert!(!output_dir.path().join("frontend").exists());
// PSP22
temp_dir = generate_testing_files_and_folders(Contract::PSP22)?;
output_dir = tempfile::tempdir()?;
extract_contract_files(Contract::PSP22.to_string(), temp_dir.path(), output_dir.path())?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(!output_dir.path().join("noise_folder").exists());
// PSP34
temp_dir = generate_testing_files_and_folders(Contract::PSP34)?;
output_dir = tempfile::tempdir()?;
extract_contract_files(Contract::PSP34.to_string(), temp_dir.path(), output_dir.path())?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(!output_dir.path().join("noise_folder").exists());
// DNS
temp_dir = generate_testing_files_and_folders(Contract::DNS)?;
output_dir = tempfile::tempdir()?;
extract_contract_files(Contract::DNS.to_string(), temp_dir.path(), output_dir.path())?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(!output_dir.path().join("noise_folder").exists());
// CrossContract
temp_dir = generate_testing_files_and_folders(Contract::CrossContract)?;
output_dir = tempfile::tempdir()?;
extract_contract_files(
Contract::CrossContract.to_string(),
temp_dir.path(),
output_dir.path(),
)?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(!output_dir.path().join("noise_folder").exists());
// Multisig
temp_dir = generate_testing_files_and_folders(Contract::Multisig)?;
output_dir = tempfile::tempdir()?;
extract_contract_files(Contract::Multisig.to_string(), temp_dir.path(), output_dir.path())?;
assert!(output_dir.path().join("lib.rs").exists());
assert!(output_dir.path().join("Cargo.toml").exists());
assert!(!output_dir.path().join("noise_folder").exists());

Ok(())
}

fn generate_contract_folder() -> Result<tempfile::TempDir, Error> {
let temp_dir = tempfile::tempdir()?;
let config = temp_dir.path().join("Cargo.toml");
Expand Down
24 changes: 0 additions & 24 deletions crates/pop-contracts/src/utils/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use contract_build::ManifestPath;
use contract_extrinsics::BalanceVariant;
use ink_env::{DefaultEnvironment, Environment};
use std::{
fs, io,
path::{Path, PathBuf},
str::FromStr,
};
Expand Down Expand Up @@ -46,29 +45,6 @@ pub fn canonicalized_path(target: &Path) -> Result<PathBuf, Error> {
// If an I/O error occurs during canonicalization, convert it into an Error enum variant.
.map_err(|e| Error::IO(e))
}
/// Recursively copy a directory and its files.
///
/// # Arguments
///
/// * `src`: - Path to copy from
/// * `dst`: - Path to copy to
///
pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
fs::create_dir_all(&dst)?;
for entry in fs::read_dir(src)? {
let entry = entry?;
let ty = entry.file_type()?;
// Ignore frontend folder in templates
if ty.is_dir() && entry.file_name() == "frontend" {
continue;
} else if ty.is_dir() {
copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
} else {
fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
}
}
Ok(())
}

#[cfg(test)]
mod tests {
Expand Down
Loading