diff --git a/bin/sozo/src/args.rs b/bin/sozo/src/args.rs index 4dbc54003d..142d1ee90f 100644 --- a/bin/sozo/src/args.rs +++ b/bin/sozo/src/args.rs @@ -1,38 +1,14 @@ use anyhow::Result; use camino::Utf8PathBuf; -use clap::{Parser, Subcommand}; +use clap::Parser; use scarb::compiler::Profile; use scarb_ui::Verbosity; use smol_str::SmolStr; use tracing::level_filters::LevelFilter; use tracing_log::AsTrace; -use crate::commands::auth::AuthArgs; -use crate::commands::build::BuildArgs; -use crate::commands::call::CallArgs; -use crate::commands::clean::CleanArgs; -use crate::commands::completions::CompletionsArgs; -use crate::commands::dev::DevArgs; -use crate::commands::events::EventsArgs; -use crate::commands::execute::ExecuteArgs; -use crate::commands::init::InitArgs; -use crate::commands::migrate::MigrateArgs; -use crate::commands::model::ModelArgs; -use crate::commands::register::RegisterArgs; -use crate::commands::test::TestArgs; - -fn generate_version() -> String { - const DOJO_VERSION: &str = env!("CARGO_PKG_VERSION"); - let scarb_version = scarb::version::get().version; - let scarb_sierra_version = scarb::version::get().sierra.version; - let scarb_cairo_version = scarb::version::get().cairo.version; - - let version_string = format!( - "{}\nscarb: {}\ncairo: {}\nsierra: {}", - DOJO_VERSION, scarb_version, scarb_cairo_version, scarb_sierra_version, - ); - version_string -} +use crate::commands::Commands; +use crate::utils::generate_version; #[derive(Parser)] #[command(author, version=generate_version(), about, long_about = None)] @@ -63,37 +39,6 @@ pub struct SozoArgs { pub command: Commands, } -#[derive(Subcommand)] -pub enum Commands { - #[command(about = "Build the world, generating the necessary artifacts for deployment")] - Build(BuildArgs), - #[command(about = "Initialize a new project")] - Init(InitArgs), - #[command(about = "Remove generated artifacts, manifests and abis")] - Clean(CleanArgs), - #[command(about = "Run a migration, declaring and deploying contracts as necessary to \ - update the world")] - Migrate(Box), - #[command(about = "Developer mode: watcher for building and migration")] - Dev(DevArgs), - #[command(about = "Test the project's smart contracts")] - Test(TestArgs), - #[command(about = "Execute a world's system")] - Execute(ExecuteArgs), - #[command(about = "Call a world's system")] - Call(CallArgs), - #[command(about = "Interact with a worlds models")] - Model(ModelArgs), - #[command(about = "Register new models")] - Register(RegisterArgs), - #[command(about = "Queries world events")] - Events(EventsArgs), - #[command(about = "Manage world authorization")] - Auth(AuthArgs), - #[command(about = "Generate shell completion file for specified shell")] - Completions(CompletionsArgs), -} - impl SozoArgs { pub fn ui_verbosity(&self) -> Verbosity { let filter = self.verbose.log_level_filter().as_trace(); diff --git a/bin/sozo/src/commands/auth.rs b/bin/sozo/src/commands/auth.rs index cca991be77..434e8c0313 100644 --- a/bin/sozo/src/commands/auth.rs +++ b/bin/sozo/src/commands/auth.rs @@ -16,6 +16,59 @@ pub struct AuthArgs { pub command: AuthCommand, } +#[derive(Debug, Subcommand)] +pub enum AuthCommand { + #[command(about = "Grant an auth role.")] + Grant { + #[command(subcommand)] + kind: AuthKind, + + #[command(flatten)] + world: WorldOptions, + + #[command(flatten)] + starknet: StarknetOptions, + + #[command(flatten)] + account: AccountOptions, + + #[command(flatten)] + transaction: TransactionOptions, + }, + #[command(about = "Revoke an auth role.")] + Revoke { + #[command(subcommand)] + kind: AuthKind, + + #[command(flatten)] + world: WorldOptions, + + #[command(flatten)] + starknet: StarknetOptions, + + #[command(flatten)] + account: AccountOptions, + + #[command(flatten)] + transaction: TransactionOptions, + }, +} + +impl AuthArgs { + pub fn run(self, config: &Config) -> Result<()> { + let env_metadata = utils::load_metadata_from_config(config)?; + + match self.command { + AuthCommand::Grant { kind, world, starknet, account, transaction } => config + .tokio_handle() + .block_on(grant(world, account, starknet, env_metadata, kind, transaction)), + AuthCommand::Revoke { kind, world, starknet, account, transaction } => config + .tokio_handle() + .block_on(revoke(world, account, starknet, env_metadata, kind, transaction)), + } + } +} + #[derive(Debug, Subcommand)] pub enum AuthKind { #[command(about = "Grant a contract permission to write to a model.")] @@ -82,59 +135,6 @@ pub async fn revoke( } } -#[derive(Debug, Subcommand)] -pub enum AuthCommand { - #[command(about = "Grant an auth role.")] - Grant { - #[command(subcommand)] - kind: AuthKind, - - #[command(flatten)] - world: WorldOptions, - - #[command(flatten)] - starknet: StarknetOptions, - - #[command(flatten)] - account: AccountOptions, - - #[command(flatten)] - transaction: TransactionOptions, - }, - #[command(about = "Revoke an auth role.")] - Revoke { - #[command(subcommand)] - kind: AuthKind, - - #[command(flatten)] - world: WorldOptions, - - #[command(flatten)] - starknet: StarknetOptions, - - #[command(flatten)] - account: AccountOptions, - - #[command(flatten)] - transaction: TransactionOptions, - }, -} - -impl AuthArgs { - pub fn run(self, config: &Config) -> Result<()> { - let env_metadata = utils::load_metadata_from_config(config)?; - - match self.command { - AuthCommand::Grant { kind, world, starknet, account, transaction } => config - .tokio_handle() - .block_on(grant(world, account, starknet, env_metadata, kind, transaction)), - AuthCommand::Revoke { kind, world, starknet, account, transaction } => config - .tokio_handle() - .block_on(revoke(world, account, starknet, env_metadata, kind, transaction)), - } - } -} - #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/bin/sozo/src/commands/build.rs b/bin/sozo/src/commands/build.rs index bb45c1f6c4..f3347fd449 100644 --- a/bin/sozo/src/commands/build.rs +++ b/bin/sozo/src/commands/build.rs @@ -5,7 +5,7 @@ use dojo_lang::scarb_internal::compile_workspace; use scarb::core::{Config, TargetKind}; use scarb::ops::CompileOpts; -#[derive(Args, Debug)] +#[derive(Debug, Args)] pub struct BuildArgs { #[arg(long)] #[arg(help = "Generate Typescript bindings.")] diff --git a/bin/sozo/src/commands/clean.rs b/bin/sozo/src/commands/clean.rs index 42129aed84..6ed05e1837 100644 --- a/bin/sozo/src/commands/clean.rs +++ b/bin/sozo/src/commands/clean.rs @@ -20,21 +20,6 @@ pub struct CleanArgs { } impl CleanArgs { - pub fn clean_manifests_abis(&self, root_dir: &Utf8PathBuf, profile_name: &str) -> Result<()> { - let dirs = vec![ - root_dir.join(MANIFESTS_DIR).join(profile_name).join(BASE_DIR), - root_dir.join(MANIFESTS_DIR).join(profile_name).join(ABIS_DIR).join(BASE_DIR), - ]; - - for d in dirs { - if d.exists() { - fs::remove_dir_all(d)?; - } - } - - Ok(()) - } - pub fn run(self, config: &Config) -> Result<()> { let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; @@ -55,4 +40,19 @@ impl CleanArgs { Ok(()) } + + pub fn clean_manifests_abis(&self, root_dir: &Utf8PathBuf, profile_name: &str) -> Result<()> { + let dirs = vec![ + root_dir.join(MANIFESTS_DIR).join(profile_name).join(BASE_DIR), + root_dir.join(MANIFESTS_DIR).join(profile_name).join(ABIS_DIR).join(BASE_DIR), + ]; + + for d in dirs { + if d.exists() { + fs::remove_dir_all(d)?; + } + } + + Ok(()) + } } diff --git a/bin/sozo/src/commands/completions.rs b/bin/sozo/src/commands/completions.rs index 65c99ac2bb..1f71098822 100644 --- a/bin/sozo/src/commands/completions.rs +++ b/bin/sozo/src/commands/completions.rs @@ -6,7 +6,7 @@ use clap_complete::{generate, Shell}; use crate::args::SozoArgs; -#[derive(Args, Debug)] +#[derive(Debug, Args)] pub struct CompletionsArgs { shell: Shell, } diff --git a/bin/sozo/src/commands/dev.rs b/bin/sozo/src/commands/dev.rs index f92eda68d4..47fd5f5ba5 100644 --- a/bin/sozo/src/commands/dev.rs +++ b/bin/sozo/src/commands/dev.rs @@ -31,7 +31,7 @@ use super::options::world::WorldOptions; pub(crate) const LOG_TARGET: &str = "sozo::cli::commands::dev"; -#[derive(Args)] +#[derive(Debug, Args)] pub struct DevArgs { #[arg(long)] #[arg(help = "Name of the World.")] @@ -49,6 +49,106 @@ pub struct DevArgs { pub account: AccountOptions, } +impl DevArgs { + pub fn run(self, config: &Config) -> Result<()> { + let env_metadata = if config.manifest_path().exists() { + let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; + + dojo_metadata_from_workspace(&ws).env().cloned() + } else { + None + }; + + let mut context = load_context(config)?; + let (tx, rx) = channel(); + let mut debouncer = new_debouncer(Duration::from_secs(1), None, tx)?; + + debouncer.watcher().watch( + config.manifest_path().parent().unwrap().as_std_path(), + RecursiveMode::Recursive, + )?; + let name = self.name.clone(); + let mut previous_manifest: Option = Option::None; + let result = build(&mut context); + + let Some((mut world_address, account, _, _)) = context + .ws + .config() + .tokio_handle() + .block_on(setup_env( + &context.ws, + self.account, + self.starknet, + self.world, + name.as_ref(), + env_metadata.as_ref(), + )) + .ok() + else { + return Err(anyhow!("Failed to setup environment")); + }; + + match context.ws.config().tokio_handle().block_on(migrate( + world_address, + &account, + name.clone(), + &context.ws, + previous_manifest.clone(), + )) { + Ok((manifest, address)) => { + previous_manifest = Some(manifest); + world_address = address; + } + Err(error) => { + error!( + target: LOG_TARGET, + error = ?error, + address = ?world_address, + "Migrating world." + ); + } + } + loop { + let action = match rx.recv() { + Ok(Ok(events)) => events + .iter() + .map(|event| process_event(event, &mut context)) + .last() + .unwrap_or(DevAction::None), + Ok(Err(_)) => DevAction::None, + Err(error) => { + error!(target: LOG_TARGET, error = ?error, "Receiving dev action."); + break; + } + }; + + if action != DevAction::None && build(&mut context).is_ok() { + match context.ws.config().tokio_handle().block_on(migrate( + world_address, + &account, + name.clone(), + &context.ws, + previous_manifest.clone(), + )) { + Ok((manifest, address)) => { + previous_manifest = Some(manifest); + world_address = address; + } + Err(error) => { + error!( + target: LOG_TARGET, + error = ?error, + address = ?world_address, + "Migrating world.", + ); + } + } + } + } + result + } +} + #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] enum DevAction { None, @@ -193,103 +293,3 @@ fn handle_reload_action(context: &mut DevContext<'_>) { let new_context = load_context(config).expect("Failed to load context"); let _ = mem::replace(context, new_context); } - -impl DevArgs { - pub fn run(self, config: &Config) -> Result<()> { - let env_metadata = if config.manifest_path().exists() { - let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; - - dojo_metadata_from_workspace(&ws).env().cloned() - } else { - None - }; - - let mut context = load_context(config)?; - let (tx, rx) = channel(); - let mut debouncer = new_debouncer(Duration::from_secs(1), None, tx)?; - - debouncer.watcher().watch( - config.manifest_path().parent().unwrap().as_std_path(), - RecursiveMode::Recursive, - )?; - let name = self.name.clone(); - let mut previous_manifest: Option = Option::None; - let result = build(&mut context); - - let Some((mut world_address, account, _, _)) = context - .ws - .config() - .tokio_handle() - .block_on(setup_env( - &context.ws, - self.account, - self.starknet, - self.world, - name.as_ref(), - env_metadata.as_ref(), - )) - .ok() - else { - return Err(anyhow!("Failed to setup environment")); - }; - - match context.ws.config().tokio_handle().block_on(migrate( - world_address, - &account, - name.clone(), - &context.ws, - previous_manifest.clone(), - )) { - Ok((manifest, address)) => { - previous_manifest = Some(manifest); - world_address = address; - } - Err(error) => { - error!( - target: LOG_TARGET, - error = ?error, - address = ?world_address, - "Migrating world." - ); - } - } - loop { - let action = match rx.recv() { - Ok(Ok(events)) => events - .iter() - .map(|event| process_event(event, &mut context)) - .last() - .unwrap_or(DevAction::None), - Ok(Err(_)) => DevAction::None, - Err(error) => { - error!(target: LOG_TARGET, error = ?error, "Receiving dev action."); - break; - } - }; - - if action != DevAction::None && build(&mut context).is_ok() { - match context.ws.config().tokio_handle().block_on(migrate( - world_address, - &account, - name.clone(), - &context.ws, - previous_manifest.clone(), - )) { - Ok((manifest, address)) => { - previous_manifest = Some(manifest); - world_address = address; - } - Err(error) => { - error!( - target: LOG_TARGET, - error = ?error, - address = ?world_address, - "Migrating world.", - ); - } - } - } - } - result - } -} diff --git a/bin/sozo/src/commands/events.rs b/bin/sozo/src/commands/events.rs index cd1aac2e13..d08a3a74d3 100644 --- a/bin/sozo/src/commands/events.rs +++ b/bin/sozo/src/commands/events.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use clap::Parser; +use clap::Args; use scarb::core::Config; use sozo_ops::events; @@ -7,7 +7,7 @@ use super::options::starknet::StarknetOptions; use super::options::world::WorldOptions; use crate::utils; -#[derive(Parser, Debug)] +#[derive(Debug, Args)] pub struct EventsArgs { #[arg(help = "List of specific events to be filtered")] #[arg(value_delimiter = ',')] diff --git a/bin/sozo/src/commands/init.rs b/bin/sozo/src/commands/init.rs index 7fffbbb2e9..f37bc70036 100644 --- a/bin/sozo/src/commands/init.rs +++ b/bin/sozo/src/commands/init.rs @@ -7,7 +7,7 @@ use anyhow::{ensure, Result}; use clap::Args; use scarb::core::Config; -#[derive(Args, Debug)] +#[derive(Debug, Args)] pub struct InitArgs { #[arg(help = "Target directory")] path: Option, diff --git a/bin/sozo/src/commands/migrate.rs b/bin/sozo/src/commands/migrate.rs index fc56cdee0e..3046c26b60 100644 --- a/bin/sozo/src/commands/migrate.rs +++ b/bin/sozo/src/commands/migrate.rs @@ -65,65 +65,6 @@ pub enum MigrateCommand { }, } -pub async fn setup_env<'a>( - ws: &'a Workspace<'a>, - account: AccountOptions, - starknet: StarknetOptions, - world: WorldOptions, - name: Option<&'a String>, - env: Option<&'a Environment>, -) -> Result<( - Option, - SingleOwnerAccount, LocalWallet>, - String, - String, -)> { - let ui = ws.config().ui(); - - let world_address = world.address(env).ok(); - - let (account, chain_id, rpc_url) = { - let provider = starknet.provider(env)?; - - let spec_version = provider.spec_version().await?; - - if spec_version != RPC_SPEC_VERSION { - return Err(anyhow!( - "Unsupported Starknet RPC version: {}, expected {}.", - spec_version, - RPC_SPEC_VERSION - )); - } - - let rpc_url = starknet.url(env)?; - - let chain_id = provider.chain_id().await?; - let chain_id = parse_cairo_short_string(&chain_id) - .with_context(|| "Cannot parse chain_id as string")?; - - let mut account = account.account(provider, env).await?; - account.set_block_id(BlockId::Tag(BlockTag::Pending)); - - let address = account.address(); - - ui.print(format!("\nMigration account: {address:#x}")); - if let Some(name) = name { - ui.print(format!("\nWorld name: {name}\n")); - } - - match account.provider().get_class_hash_at(BlockId::Tag(BlockTag::Pending), address).await { - Ok(_) => Ok((account, chain_id, rpc_url)), - Err(ProviderError::StarknetError(StarknetError::ContractNotFound)) => { - Err(anyhow!("Account with address {:#x} doesn't exist.", account.address())) - } - Err(e) => Err(e.into()), - } - } - .with_context(|| "Problem initializing account for migration.")?; - - Ok((world_address, account, chain_id, rpc_url.to_string())) -} - impl MigrateArgs { pub fn run(self, config: &Config) -> Result<()> { let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; @@ -207,3 +148,62 @@ impl MigrateArgs { } } } + +pub async fn setup_env<'a>( + ws: &'a Workspace<'a>, + account: AccountOptions, + starknet: StarknetOptions, + world: WorldOptions, + name: Option<&'a String>, + env: Option<&'a Environment>, +) -> Result<( + Option, + SingleOwnerAccount, LocalWallet>, + String, + String, +)> { + let ui = ws.config().ui(); + + let world_address = world.address(env).ok(); + + let (account, chain_id, rpc_url) = { + let provider = starknet.provider(env)?; + + let spec_version = provider.spec_version().await?; + + if spec_version != RPC_SPEC_VERSION { + return Err(anyhow!( + "Unsupported Starknet RPC version: {}, expected {}.", + spec_version, + RPC_SPEC_VERSION + )); + } + + let rpc_url = starknet.url(env)?; + + let chain_id = provider.chain_id().await?; + let chain_id = parse_cairo_short_string(&chain_id) + .with_context(|| "Cannot parse chain_id as string")?; + + let mut account = account.account(provider, env).await?; + account.set_block_id(BlockId::Tag(BlockTag::Pending)); + + let address = account.address(); + + ui.print(format!("\nMigration account: {address:#x}")); + if let Some(name) = name { + ui.print(format!("\nWorld name: {name}\n")); + } + + match account.provider().get_class_hash_at(BlockId::Tag(BlockTag::Pending), address).await { + Ok(_) => Ok((account, chain_id, rpc_url)), + Err(ProviderError::StarknetError(StarknetError::ContractNotFound)) => { + Err(anyhow!("Account with address {:#x} doesn't exist.", account.address())) + } + Err(e) => Err(e.into()), + } + } + .with_context(|| "Problem initializing account for migration.")?; + + Ok((world_address, account, chain_id, rpc_url.to_string())) +} diff --git a/bin/sozo/src/commands/mod.rs b/bin/sozo/src/commands/mod.rs index d0f563bce4..b7b2d53b64 100644 --- a/bin/sozo/src/commands/mod.rs +++ b/bin/sozo/src/commands/mod.rs @@ -1,8 +1,7 @@ use anyhow::Result; +use clap::{command, Subcommand}; use scarb::core::Config; -use crate::args::Commands; - pub(crate) mod auth; pub(crate) mod build; pub(crate) mod call; @@ -18,6 +17,51 @@ pub(crate) mod options; pub(crate) mod register; pub(crate) mod test; +use auth::AuthArgs; +use build::BuildArgs; +use call::CallArgs; +use clean::CleanArgs; +use completions::CompletionsArgs; +use dev::DevArgs; +use events::EventsArgs; +use execute::ExecuteArgs; +use init::InitArgs; +use migrate::MigrateArgs; +use model::ModelArgs; +use register::RegisterArgs; +use test::TestArgs; + +#[derive(Subcommand)] +pub enum Commands { + #[command(about = "Build the world, generating the necessary artifacts for deployment")] + Build(BuildArgs), + #[command(about = "Initialize a new project")] + Init(InitArgs), + #[command(about = "Remove generated artifacts, manifests and abis")] + Clean(CleanArgs), + #[command(about = "Run a migration, declaring and deploying contracts as necessary to \ + update the world")] + Migrate(Box), + #[command(about = "Developer mode: watcher for building and migration")] + Dev(DevArgs), + #[command(about = "Test the project's smart contracts")] + Test(TestArgs), + #[command(about = "Execute a world's system")] + Execute(ExecuteArgs), + #[command(about = "Call a world's system")] + Call(CallArgs), + #[command(about = "Interact with a worlds models")] + Model(ModelArgs), + #[command(about = "Register new models")] + Register(RegisterArgs), + #[command(about = "Queries world events")] + Events(EventsArgs), + #[command(about = "Manage world authorization")] + Auth(AuthArgs), + #[command(about = "Generate shell completion file for specified shell")] + Completions(CompletionsArgs), +} + pub fn run(command: Commands, config: &Config) -> Result<()> { match command { Commands::Init(args) => args.run(config), diff --git a/bin/sozo/src/commands/model.rs b/bin/sozo/src/commands/model.rs index 1c69bbe3fe..e5e0aae244 100644 --- a/bin/sozo/src/commands/model.rs +++ b/bin/sozo/src/commands/model.rs @@ -11,11 +11,11 @@ use crate::utils; #[derive(Debug, Args)] pub struct ModelArgs { #[command(subcommand)] - command: ModelCommands, + command: ModelCommand, } #[derive(Debug, Subcommand)] -pub enum ModelCommands { +pub enum ModelCommand { #[command(about = "Retrieve the class hash of a model")] ClassHash { #[arg(help = "The name of the model")] @@ -80,22 +80,22 @@ impl ModelArgs { config.tokio_handle().block_on(async { match self.command { - ModelCommands::ClassHash { name, starknet, world } => { + ModelCommand::ClassHash { name, starknet, world } => { let world_address = world.address(env_metadata.as_ref()).unwrap(); let provider = starknet.provider(env_metadata.as_ref()).unwrap(); model::model_class_hash(name, world_address, provider).await } - ModelCommands::ContractAddress { name, starknet, world } => { + ModelCommand::ContractAddress { name, starknet, world } => { let world_address = world.address(env_metadata.as_ref()).unwrap(); let provider = starknet.provider(env_metadata.as_ref()).unwrap(); model::model_contract_address(name, world_address, provider).await } - ModelCommands::Schema { name, to_json, starknet, world } => { + ModelCommand::Schema { name, to_json, starknet, world } => { let world_address = world.address(env_metadata.as_ref()).unwrap(); let provider = starknet.provider(env_metadata.as_ref()).unwrap(); model::model_schema(name, world_address, provider, to_json).await } - ModelCommands::Get { name, keys, starknet, world } => { + ModelCommand::Get { name, keys, starknet, world } => { let world_address = world.address(env_metadata.as_ref()).unwrap(); let provider = starknet.provider(env_metadata.as_ref()).unwrap(); model::model_get(name, keys, world_address, provider).await diff --git a/bin/sozo/src/commands/options/account.rs b/bin/sozo/src/commands/options/account.rs index 1538e8f106..bf05c5ec11 100644 --- a/bin/sozo/src/commands/options/account.rs +++ b/bin/sozo/src/commands/options/account.rs @@ -13,13 +13,13 @@ use super::{ DOJO_PRIVATE_KEY_ENV_VAR, }; -#[derive(Debug, Args)] -#[command(next_help_heading = "Account options")] // INVARIANT: // - For commandline: we can either specify `private_key` or `keystore_path` along with // `keystore_password`. This is enforced by Clap. // - For `Scarb.toml`: if both private_key and keystore are specified in `Scarb.toml` private_key // will take priority +#[derive(Debug, Args)] +#[command(next_help_heading = "Account options")] pub struct AccountOptions { #[arg(long, env = DOJO_ACCOUNT_ADDRESS_ENV_VAR)] pub account_address: Option, diff --git a/bin/sozo/src/commands/options/transaction.rs b/bin/sozo/src/commands/options/transaction.rs index 7901c6ca6a..a54076cd44 100644 --- a/bin/sozo/src/commands/options/transaction.rs +++ b/bin/sozo/src/commands/options/transaction.rs @@ -1,7 +1,7 @@ use clap::Args; use dojo_world::migration::TxConfig; -#[derive(Debug, Args, Clone)] +#[derive(Debug, Args)] #[command(next_help_heading = "Transaction options")] pub struct TransactionOptions { #[arg(long)] diff --git a/bin/sozo/src/commands/test.rs b/bin/sozo/src/commands/test.rs index d64dde856d..9ca645c72c 100644 --- a/bin/sozo/src/commands/test.rs +++ b/bin/sozo/src/commands/test.rs @@ -21,7 +21,7 @@ use tracing::trace; pub(crate) const LOG_TARGET: &str = "sozo::cli::commands::test"; /// Execute all unit tests of a local package. -#[derive(Args, Clone)] +#[derive(Debug, Args)] pub struct TestArgs { /// The filter for the tests, running only tests containing the filter string. #[arg(short, long, default_value_t = String::default())] diff --git a/bin/sozo/src/main.rs b/bin/sozo/src/main.rs index 060a9d0cf9..18da01da73 100644 --- a/bin/sozo/src/main.rs +++ b/bin/sozo/src/main.rs @@ -1,17 +1,16 @@ use std::env; use std::process::exit; -use std::str::FromStr; use anyhow::Result; -use args::{Commands, SozoArgs}; -use camino::Utf8PathBuf; +use args::SozoArgs; use clap::Parser; use dojo_lang::compiler::DojoCompiler; use dojo_lang::plugin::CairoPluginRepository; use scarb::compiler::CompilerRepository; -use scarb::core::{Config, TomlManifest}; +use scarb::core::Config; use scarb_ui::{OutputFormat, Ui}; -use semver::Version; + +use crate::commands::Commands; mod args; mod commands; @@ -41,7 +40,7 @@ fn cli_main(args: SozoArgs) -> Result<()> { let manifest_path = scarb::ops::find_manifest_path(args.manifest_path.as_deref())?; - verify_cairo_version_compatibility(&manifest_path)?; + utils::verify_cairo_version_compatibility(&manifest_path)?; let config = Config::builder(manifest_path) .log_filter_directive(env::var_os("SCARB_LOG")) @@ -54,26 +53,3 @@ fn cli_main(args: SozoArgs) -> Result<()> { commands::run(args.command, &config) } - -fn verify_cairo_version_compatibility(manifest_path: &Utf8PathBuf) -> Result<()> { - let scarb_cairo_version = scarb::version::get().cairo; - // When manifest file doesn't exists ignore it. Would be the case during `sozo init` - let Ok(manifest) = TomlManifest::read_from_path(manifest_path) else { return Ok(()) }; - - // For any kind of error, like package not specified, cairo version not specified return - // without an error - let Some(package) = manifest.package else { return Ok(()) }; - - let Some(cairo_version) = package.cairo_version else { return Ok(()) }; - - // only when cairo version is found in manifest file confirm that it matches - let version_req = cairo_version.as_defined().unwrap(); - let version = Version::from_str(scarb_cairo_version.version).unwrap(); - if !version_req.matches(&version) { - anyhow::bail!( - "Specified cairo version not supported by dojo. Please verify and update dojo." - ); - }; - - Ok(()) -} diff --git a/bin/sozo/src/utils.rs b/bin/sozo/src/utils.rs index 7dbbfe28fd..d277c8d910 100644 --- a/bin/sozo/src/utils.rs +++ b/bin/sozo/src/utils.rs @@ -1,8 +1,12 @@ -use anyhow::Error; +use std::str::FromStr; + +use anyhow::{Error, Result}; +use camino::Utf8PathBuf; use dojo_world::contracts::world::WorldContract; use dojo_world::contracts::WorldContractReader; use dojo_world::metadata::{dojo_metadata_from_workspace, Environment}; -use scarb::core::Config; +use scarb::core::{Config, TomlManifest}; +use semver::Version; use starknet::accounts::SingleOwnerAccount; use starknet::providers::jsonrpc::HttpTransport; use starknet::providers::JsonRpcClient; @@ -79,3 +83,39 @@ pub async fn world_reader_from_env_metadata( Ok(WorldContractReader::new(world_address, provider)) } + +pub fn verify_cairo_version_compatibility(manifest_path: &Utf8PathBuf) -> Result<()> { + let scarb_cairo_version = scarb::version::get().cairo; + // When manifest file doesn't exists ignore it. Would be the case during `sozo init` + let Ok(manifest) = TomlManifest::read_from_path(manifest_path) else { return Ok(()) }; + + // For any kind of error, like package not specified, cairo version not specified return + // without an error + let Some(package) = manifest.package else { return Ok(()) }; + + let Some(cairo_version) = package.cairo_version else { return Ok(()) }; + + // only when cairo version is found in manifest file confirm that it matches + let version_req = cairo_version.as_defined().unwrap(); + let version = Version::from_str(scarb_cairo_version.version).unwrap(); + if !version_req.matches(&version) { + anyhow::bail!( + "Specified cairo version not supported by dojo. Please verify and update dojo." + ); + }; + + Ok(()) +} + +pub fn generate_version() -> String { + const DOJO_VERSION: &str = env!("CARGO_PKG_VERSION"); + let scarb_version = scarb::version::get().version; + let scarb_sierra_version = scarb::version::get().sierra.version; + let scarb_cairo_version = scarb::version::get().cairo.version; + + let version_string = format!( + "{}\nscarb: {}\ncairo: {}\nsierra: {}", + DOJO_VERSION, scarb_version, scarb_cairo_version, scarb_sierra_version, + ); + version_string +} diff --git a/crates/benches/src/deployer.rs b/crates/benches/src/deployer.rs index 663d54e73a..abb0251c07 100644 --- a/crates/benches/src/deployer.rs +++ b/crates/benches/src/deployer.rs @@ -10,7 +10,8 @@ use futures::executor::block_on; use katana_runner::KatanaRunner; use scarb::compiler::CompilerRepository; use scarb::core::Config; -use sozo::args::{Commands, SozoArgs}; +use sozo::args::SozoArgs; +use sozo::commands::Commands; use starknet::core::types::FieldElement; use tokio::process::Command;