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

[sozo] Detect and manage manifests and artifacts discrepancies #1672

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions bin/sozo/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use tracing_log::AsTrace;

use crate::commands::auth::AuthArgs;
use crate::commands::build::BuildArgs;
use crate::commands::clean::CleanArgs;
use crate::commands::completions::CompletionsArgs;
use crate::commands::dev::DevArgs;
use crate::commands::events::EventsArgs;
Expand Down Expand Up @@ -54,6 +55,8 @@ pub enum Commands {
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<MigrateArgs>),
Expand Down
55 changes: 55 additions & 0 deletions bin/sozo/src/commands/clean.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use std::fs;

use anyhow::Result;
use camino::Utf8PathBuf;
use clap::Args;
use dojo_lang::compiler::{ABIS_DIR, MANIFESTS_DIR};
use scarb::core::Config;

#[derive(Debug, Args)]
pub struct CleanArgs {
#[arg(short, long)]
#[arg(help = "Remove manifests and abis only.")]
#[arg(long_help = "Remove manifests and abis only.")]
pub manifests_abis: bool,

Check warning on line 14 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L14

Added line #L14 was not covered by tests

#[arg(short, long)]
#[arg(help = "Remove artifacts only.")]
#[arg(long_help = "Remove artifacts only.")]
pub artifacts: bool,

Check warning on line 19 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L19

Added line #L19 was not covered by tests
}

impl CleanArgs {
pub fn clean_manifests_abis(&self, root_dir: &Utf8PathBuf) -> Result<()> {
let manifest_dir = root_dir.join(MANIFESTS_DIR);
let abis_dir = root_dir.join(ABIS_DIR);

if manifest_dir.exists() {
fs::remove_dir_all(manifest_dir)?;
}

Check warning on line 29 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L23-L29

Added lines #L23 - L29 were not covered by tests

if abis_dir.exists() {
fs::remove_dir_all(abis_dir)?;
}

Check warning on line 33 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L31-L33

Added lines #L31 - L33 were not covered by tests

Ok(())
}

Check warning on line 36 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L35-L36

Added lines #L35 - L36 were not covered by tests

pub fn run(self, config: &Config) -> Result<()> {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;

Check warning on line 39 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L38-L39

Added lines #L38 - L39 were not covered by tests

let clean_manifests_abis = self.manifests_abis || !self.artifacts;
let clean_artifacts = self.artifacts || !self.manifests_abis;

Check warning on line 42 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L41-L42

Added lines #L41 - L42 were not covered by tests

if clean_manifests_abis {
let manifest_dir = ws.manifest_path().parent().unwrap().to_path_buf();
self.clean_manifests_abis(&manifest_dir)?;
}

Check warning on line 47 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L44-L47

Added lines #L44 - L47 were not covered by tests

if clean_artifacts {
scarb::ops::clean(config)?;
}

Check warning on line 51 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L49-L51

Added lines #L49 - L51 were not covered by tests

Ok(())
}

Check warning on line 54 in bin/sozo/src/commands/clean.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/clean.rs#L53-L54

Added lines #L53 - L54 were not covered by tests
}
2 changes: 2 additions & 0 deletions bin/sozo/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

pub(crate) mod auth;
pub(crate) mod build;
pub(crate) mod clean;
pub(crate) mod completions;
pub(crate) mod dev;
pub(crate) mod events;
Expand All @@ -19,6 +20,7 @@
pub fn run(command: Commands, config: &Config) -> Result<()> {
match command {
Commands::Init(args) => args.run(config),
Commands::Clean(args) => args.run(config),

Check warning on line 23 in bin/sozo/src/commands/mod.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/mod.rs#L23

Added line #L23 was not covered by tests
Commands::Test(args) => args.run(config),
Commands::Build(args) => args.run(config),
Commands::Migrate(args) => args.run(config),
Expand Down
40 changes: 36 additions & 4 deletions bin/sozo/src/ops/migration/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::Path;

use anyhow::{anyhow, bail, Context, Result};
use camino::Utf8PathBuf;
use dojo_lang::compiler::{ABIS_DIR, BASE_DIR, DEPLOYMENTS_DIR, MANIFESTS_DIR, OVERLAYS_DIR};
Expand Down Expand Up @@ -71,9 +73,14 @@
let target_dir = target_dir.join(ws.config().profile().as_str());

// Load local and remote World manifests.

let (local_manifest, remote_manifest) =
load_world_manifests(&manifest_dir, &account, world_address, &ui).await?;
load_world_manifests(&manifest_dir, &account, world_address, &ui).await.map_err(|e| {

Check warning on line 77 in bin/sozo/src/ops/migration/mod.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/ops/migration/mod.rs#L77

Added line #L77 was not covered by tests
ui.error(e.to_string());
anyhow!(
"\n Use `sozo clean` to clean your project, or `sozo clean --manifests-abis` to \
clean manifest and abi files only.\nThen, rebuild your project with `sozo build`.",
)
})?;

Check warning on line 83 in bin/sozo/src/ops/migration/mod.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/ops/migration/mod.rs#L80-L83

Added lines #L80 - L83 were not covered by tests

// Calculate diff between local and remote World manifests.

Expand Down Expand Up @@ -306,12 +313,14 @@
ui.print_step(1, "🌎", "Building World state...");

let mut local_manifest =
BaseManifest::load_from_path(&manifest_dir.join(MANIFESTS_DIR).join(BASE_DIR))?;
BaseManifest::load_from_path(&manifest_dir.join(MANIFESTS_DIR).join(BASE_DIR))
.map_err(|_| anyhow!("Fail to load local manifest file."))?;

Check warning on line 317 in bin/sozo/src/ops/migration/mod.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/ops/migration/mod.rs#L317

Added line #L317 was not covered by tests

let overlay_path = manifest_dir.join(MANIFESTS_DIR).join(OVERLAYS_DIR);
if overlay_path.exists() {
let overlay_manifest =
OverlayManifest::load_from_path(&manifest_dir.join(MANIFESTS_DIR).join(OVERLAYS_DIR))?;
OverlayManifest::load_from_path(&manifest_dir.join(MANIFESTS_DIR).join(OVERLAYS_DIR))

Check warning on line 322 in bin/sozo/src/ops/migration/mod.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/ops/migration/mod.rs#L322

Added line #L322 was not covered by tests
.map_err(|_| anyhow!("Fail to load overlay manifest file."))?;

// merge user defined changes to base manifest
local_manifest.merge(overlay_manifest);
Expand Down Expand Up @@ -405,6 +414,9 @@
Err(MigrationError::ClassAlreadyDeclared) => {
ui.print_sub(format!("Already declared: {:#x}", base.diff.local));
}
Err(MigrationError::ArtifactError(e)) => {
return Err(handle_artifact_error(&ui, base.artifact_path(), e));
}
Err(e) => {
ui.verbose(format!("{e:?}"));
return Err(e.into());
Expand Down Expand Up @@ -530,6 +542,9 @@
Err(MigrationError::ContractAlreadyDeployed(contract_address)) => {
Ok(ContractDeploymentOutput::AlreadyDeployed(contract_address))
}
Err(MigrationError::ArtifactError(e)) => {
return Err(handle_artifact_error(ui, contract.artifact_path(), e));

Check warning on line 546 in bin/sozo/src/ops/migration/mod.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/ops/migration/mod.rs#L545-L546

Added lines #L545 - L546 were not covered by tests
}
Err(e) => {
ui.verbose(format!("{e:?}"));
Err(anyhow!("Failed to migrate {contract_id}: {e}"))
Expand Down Expand Up @@ -574,6 +589,9 @@
ui.print_sub(format!("Already declared: {:#x}", c.diff.local));
continue;
}
Err(MigrationError::ArtifactError(e)) => {
return Err(handle_artifact_error(ui, c.artifact_path(), e));
}

Check warning on line 594 in bin/sozo/src/ops/migration/mod.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/ops/migration/mod.rs#L593-L594

Added lines #L593 - L594 were not covered by tests
Err(e) => {
ui.verbose(format!("{e:?}"));
bail!("Failed to declare model {}: {e}", c.diff.name)
Expand Down Expand Up @@ -654,6 +672,9 @@
ui.print_sub(format!("Already deployed: {:#x}", contract_address));
deploy_output.push(None);
}
Err(MigrationError::ArtifactError(e)) => {
return Err(handle_artifact_error(ui, contract.artifact_path(), e));
}
Err(e) => {
ui.verbose(format!("{e:?}"));
return Err(anyhow!("Failed to migrate {name}: {e}"));
Expand All @@ -663,3 +684,14 @@

Ok(deploy_output)
}

pub fn handle_artifact_error(ui: &Ui, artifact_path: &Path, error: anyhow::Error) -> anyhow::Error {
let path = artifact_path.to_string_lossy();

Check warning on line 689 in bin/sozo/src/ops/migration/mod.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/ops/migration/mod.rs#L689

Added line #L689 was not covered by tests
let name = artifact_path.file_name().unwrap().to_string_lossy();
ui.verbose(format!("{path}: {error:?}"));

anyhow!(
"Discrepancy detected in {name}.\nUse `sozo clean` to clean your project or `sozo clean \
--artifacts` to clean artifacts only.\nThen, rebuild your project with `sozo build`."
)
}
13 changes: 6 additions & 7 deletions crates/dojo-world/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#[error(transparent)]
Model(#[from] ModelError),
#[error(transparent)]
TOML(#[from] toml::de::Error),
#[error(transparent)]
IO(#[from] io::Error),
}

Expand Down Expand Up @@ -251,11 +253,8 @@
let contract_dir = path.join("contracts");
let model_dir = path.join("models");

let world: Manifest<Class> =
toml::from_str(&fs::read_to_string(path.join("world.toml"))?).unwrap();
let base: Manifest<Class> =
toml::from_str(&fs::read_to_string(path.join("base.toml"))?).unwrap();

let world: Manifest<Class> = toml::from_str(&fs::read_to_string(path.join("world.toml"))?)?;
let base: Manifest<Class> = toml::from_str(&fs::read_to_string(path.join("base.toml"))?)?;
let contracts = elements_from_path::<DojoContract>(&contract_dir)?;
let models = elements_from_path::<DojoModel>(&model_dir)?;

Expand Down Expand Up @@ -590,7 +589,7 @@
let entry = entry?;
let path = entry.path();
if path.is_file() {
let manifest: Manifest<T> = toml::from_str(&fs::read_to_string(path)?).unwrap();
let manifest: Manifest<T> = toml::from_str(&fs::read_to_string(path)?)?;
elements.push(manifest);
} else {
continue;
Expand All @@ -610,7 +609,7 @@
let entry = entry?;
let path = entry.path();
if path.is_file() {
let manifest: T = toml::from_str(&fs::read_to_string(path)?).unwrap();
let manifest: T = toml::from_str(&fs::read_to_string(path)?)?;

Check warning on line 612 in crates/dojo-world/src/manifest.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo-world/src/manifest.rs#L612

Added line #L612 was not covered by tests
elements.push(manifest);
} else {
continue;
Expand Down
9 changes: 4 additions & 5 deletions crates/dojo-world/src/migration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
Provider(#[from] ProviderError),
#[error(transparent)]
WaitingError(#[from] TransactionWaitingError),
#[error(transparent)]
ArtifactError(#[from] anyhow::Error),
}

/// Represents the type of migration that should be performed.
Expand Down Expand Up @@ -98,7 +100,7 @@
S: Signer + Sync + Send,
{
let (flattened_class, casm_class_hash) =
prepare_contract_declaration_params(self.artifact_path()).unwrap();
prepare_contract_declaration_params(self.artifact_path())?;

match account
.provider()
Expand Down Expand Up @@ -146,10 +148,7 @@
let declare = match self.declare(account, txn_config).await {
Ok(res) => Some(res),
Err(MigrationError::ClassAlreadyDeclared) => None,
Err(e) => {
println!("{:?}", e);
return Err(e);
}
Err(e) => return Err(e),

Check warning on line 151 in crates/dojo-world/src/migration/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo-world/src/migration/mod.rs#L151

Added line #L151 was not covered by tests
};

let base_class_hash = account
Expand Down
Loading