1use std::fs;
4use std::path::PathBuf;
5
6use anyhow::{Context, Result};
7use multisol_structs::Contract;
8
9pub fn run(contracts: Vec<Contract>) -> Result<()> {
11 let user_provided_contract = contracts.last().with_context(|| "No contracts found")?;
14
15 let output_dir = get_output_dir(&user_provided_contract)?;
17 if output_dir.is_dir() {
18 fs::remove_dir_all(&output_dir)?;
19 }
20 fs::create_dir(&output_dir)?;
21
22 for contract in contracts.iter().rev() {
23 let output_file_path = output_dir.join(contract.file_name());
24 fs::write(output_file_path, contract.source_code())?;
25 }
26
27 println!("✨ contracts written to {:?} folder", output_dir);
28
29 Ok(())
30}
31
32fn get_output_dir(user_provided_contract: &Contract) -> Result<PathBuf> {
34 let contract_file_stem = user_provided_contract.full_path().file_stem().with_context(|| {
35 format!(
36 "Could not get file stem out of contract path: {:?}",
37 user_provided_contract.full_path()
38 )
39 })?;
40
41 let contract_name = contract_file_stem.to_str().with_context(|| {
42 format!(
43 "Contract name contains invalid UTF-8: {:?}",
44 user_provided_contract.file_name()
45 )
46 })?;
47 let contract_name_lowercase = contract_name.to_lowercase();
48 let output_dir_str = ["multisol", &contract_name_lowercase].join("-");
49
50 Ok(PathBuf::from(&output_dir_str))
51}
52
53#[cfg(test)]
54mod tests {
55 use super::{get_output_dir, Contract};
56 use std::ffi::OsString;
57 use std::path::PathBuf;
58
59 #[test]
60 fn gets_correct_output_dir() {
61 let directory = PathBuf::from("/tmp/contracts");
62 let full_path = PathBuf::from("/tmp/contracts/Foo.sol");
63 let contract = Contract::new(directory, false, OsString::from("Foo.sol"), full_path, String::from(""));
64 let output_dir = get_output_dir(&contract).unwrap();
65 assert_eq!(output_dir, PathBuf::from("multisol-foo"));
66 }
67
68 #[test]
71 fn cant_get_file_stem_out_of_contract_path() {
72 let directory = PathBuf::from("/tmp/contracts");
73 let full_path = PathBuf::from("/tmp/contracts/Foo.sol/..");
74 let contract = Contract::new(directory, false, OsString::from("Foo.sol"), full_path, String::from(""));
75 let err = get_output_dir(&contract).unwrap_err();
76 assert_eq!(
77 err.to_string(),
78 format!(
79 "Could not get file stem out of contract path: {:?}",
80 contract.full_path()
81 )
82 );
83 }
84}