1use crate::{
2 cmd::DEPLOY_SUBCOMMAND, container::ContractError, custom_types::CustomTypeSet,
3 DeployedContractsContainer
4};
5use anyhow::Result;
6use clap::{ArgMatches, Command};
7use odra::{host::HostEnv, prelude::OdraError};
8use thiserror::Error;
9
10use super::MutableCommand;
11
12pub(crate) struct DeployCmd {
16 pub script: Box<dyn DeployScript>
17}
18
19impl DeployCmd {
20 pub fn new(script: impl DeployScript + 'static) -> Self {
22 DeployCmd {
23 script: Box::new(script)
24 }
25 }
26}
27
28impl MutableCommand for DeployCmd {
29 fn run(
30 &self,
31 env: &HostEnv,
32 _args: &ArgMatches,
33 _types: &CustomTypeSet,
34 container: &mut DeployedContractsContainer
35 ) -> Result<()> {
36 self.script.deploy(env, container)?;
37 Ok(())
38 }
39}
40
41impl From<&DeployCmd> for Command {
42 fn from(_value: &DeployCmd) -> Self {
43 Command::new(DEPLOY_SUBCOMMAND).about("Runs the deploy script")
44 }
45}
46
47pub trait DeployScript {
52 fn deploy(
53 &self,
54 env: &HostEnv,
55 container: &mut DeployedContractsContainer
56 ) -> core::result::Result<(), DeployError>;
57}
58
59#[derive(Debug, Error)]
61pub enum DeployError {
62 #[error("Deploy error: {message}")]
63 OdraError { message: String },
64 #[error("Contract read error: {0}")]
65 ContractReadError(#[from] ContractError)
66}
67
68impl From<OdraError> for DeployError {
69 fn from(err: OdraError) -> Self {
70 DeployError::OdraError {
71 message: format!("{:?}", err)
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use crate::test_utils;
79
80 use super::*;
81 use odra::host::HostEnv;
82
83 struct MockDeployScript;
84
85 impl DeployScript for MockDeployScript {
86 fn deploy(
87 &self,
88 _env: &HostEnv,
89 _container: &mut DeployedContractsContainer
90 ) -> core::result::Result<(), DeployError> {
91 Ok(())
92 }
93 }
94
95 #[test]
96 fn deploy_cmd_run() {
97 let env = test_utils::mock_host_env();
99 let cmd = DeployCmd::new(MockDeployScript);
100 let mut container = test_utils::mock_contracts_container();
101 let result = cmd.run(
102 &env,
103 &ArgMatches::default(),
104 &CustomTypeSet::default(),
105 &mut container
106 );
107 assert!(result.is_ok());
108 }
109
110 #[test]
111 fn parsing_deploy_cmd() {
112 let cmd = DeployCmd::new(MockDeployScript);
114 let command: Command = (&cmd).into();
115 assert_eq!(command.get_name(), DEPLOY_SUBCOMMAND);
116 assert!(command.get_about().is_some());
117 }
118
119 #[test]
120 fn deploy_does_not_accept_args() {
121 let cmd = DeployCmd::new(MockDeployScript);
123 let command: Command = (&cmd).into();
124
125 let result = command.try_get_matches_from(vec!["test"]);
126 assert!(result.is_ok());
127
128 let command: Command = (&cmd).into();
129 assert_eq!(command.get_arguments().count(), 0);
130 }
131}