cw_orch_core/contract/
paths.rs1pub use artifacts_dir::from_workspace;
2pub use artifacts_dir::ArtifactsDir;
3pub use wasm_path::WasmPath;
4
5mod wasm_path {
6 use crate::error::CwEnvError;
7 use cosmwasm_std::{ensure_eq, Checksum};
8 use std::{
9 io::Read,
10 path::{Path, PathBuf},
11 };
12
13 #[derive(Debug, Clone)]
28 pub struct WasmPath(PathBuf);
29
30 impl WasmPath {
31 pub fn new(path: impl Into<PathBuf>) -> Result<Self, CwEnvError> {
33 let path: PathBuf = path.into();
34 assert!(
35 path.exists(),
36 "provided path {} does not exist",
37 path.display()
38 );
39 ensure_eq!(
40 path.extension(),
41 Some("wasm".as_ref()),
42 CwEnvError::NotWasm {}
43 );
44 Ok(Self(path))
45 }
46
47 pub fn path(&self) -> &Path {
49 self.0.as_path()
50 }
51
52 pub fn checksum(&self) -> Result<Checksum, CwEnvError> {
54 let mut file = std::fs::File::open(self.path())?;
55 let mut wasm = Vec::<u8>::new();
56 file.read_to_end(&mut wasm)?;
57 Ok(Checksum::generate(&wasm))
58 }
59 }
60}
61
62mod artifacts_dir {
63 const ARM_POSTFIX: &str = "-aarch64";
64
65 use super::WasmPath;
66 use crate::{
67 build::BuildPostfix, env::ARTIFACTS_DIR_ENV_NAME, error::CwEnvError, log::local_target,
68 CoreEnvVars,
69 };
70
71 use std::{env, fs, path::PathBuf};
72
73 pub fn find_workspace_dir(start_path: Option<String>) -> ::std::path::PathBuf {
74 let crate_path = start_path.unwrap_or(env!("CARGO_MANIFEST_DIR").to_string());
75 let mut current_dir = ::std::path::PathBuf::from(crate_path);
76 match find_workspace_dir_worker(&mut current_dir) {
77 Some(path) => path,
78 None => current_dir,
79 }
80 }
81
82 fn find_workspace_dir_worker(dir: &mut ::std::path::PathBuf) -> Option<::std::path::PathBuf> {
83 loop {
84 let artifacts_dir = dir.join("artifacts");
85 if ::std::fs::metadata(&artifacts_dir).is_ok() {
86 return Some(dir.clone());
87 }
88 if !dir.pop() {
90 return None;
91 }
92 }
93 }
94
95 #[macro_export]
96 macro_rules! from_workspace {
100 () => {
101 ArtifactsDir::auto(Some(env!("CARGO_MANIFEST_DIR").to_string()))
102 };
103 }
104 pub use from_workspace;
105
106 pub struct ArtifactsDir(PathBuf);
121
122 impl ArtifactsDir {
123 pub fn env() -> Self {
125 let dir = CoreEnvVars::artifacts_dir()
126 .unwrap_or_else(|| panic!("{} env variable not set", ARTIFACTS_DIR_ENV_NAME));
127 Self::new(dir)
128 }
129
130 pub fn auto(start_path: Option<String>) -> Self {
132 let workspace_dir = find_workspace_dir(start_path).join("artifacts");
134 log::debug!(target: &local_target(), "Found artifacts dir at {:?}", workspace_dir);
135 Self::new(workspace_dir)
136 }
137
138 pub fn new(path: impl Into<PathBuf>) -> Self {
140 let path: PathBuf = path.into();
141 assert!(
142 path.exists(),
143 "provided path {} does not exist",
144 path.display()
145 );
146 Self(path)
147 }
148
149 pub fn path(&self) -> &PathBuf {
151 &self.0
152 }
153
154 pub fn find_wasm_path(&self, name: &str) -> Result<WasmPath, CwEnvError> {
156 self.find_wasm_path_with_build_postfix(name, <BuildPostfix>::None)
157 }
158
159 pub fn find_wasm_path_with_build_postfix(
163 &self,
164 name: &str,
165 build_postfix: BuildPostfix,
166 ) -> Result<WasmPath, CwEnvError> {
167 let build_postfix: String = build_postfix.into();
168 let mut wasm_with_postfix = None;
171 let mut arm_wasm_with_postfix = None;
172 let mut default_wasm = None;
173 let mut arm_default_wasm = None;
174
175 for entry in fs::read_dir(self.path())?.flatten() {
176 let path = entry.path();
177 if !path.is_file() || path.extension().unwrap_or_default() != "wasm" {
179 continue;
180 }
181
182 let file_name = path.file_name().unwrap_or_default().to_string_lossy();
183 if is_artifact_with_build_postfix(&file_name, name, &build_postfix) {
185 wasm_with_postfix = Some(file_name.into_owned());
186 break;
188 }
189
190 if is_arm_artifact_with_build_postfix(&file_name, name, &build_postfix) {
192 arm_wasm_with_postfix = Some(file_name.into_owned())
194 } else if is_default_artifact(&file_name, name) {
195 default_wasm = Some(file_name.into_owned())
197 } else if is_default_arm_artifact(&file_name, name) {
198 arm_default_wasm = Some(file_name.into_owned())
200 }
201 }
202
203 let path_str = wasm_with_postfix
204 .or(arm_wasm_with_postfix)
205 .or(default_wasm)
206 .or(arm_default_wasm)
207 .ok_or_else(|| {
208 CwEnvError::WasmNotFound(
209 name.to_owned(),
210 self.path().to_str().unwrap_or_default().to_owned(),
211 )
212 })?;
213 WasmPath::new(self.path().join(path_str))
214 }
215 }
216
217 fn is_artifact(file_name: &str, contract_name: &str) -> bool {
218 file_name.contains(contract_name)
219 }
220
221 fn is_default_artifact(file_name: &str, contract_name: &str) -> bool {
222 file_name.ends_with(format!("{contract_name}.wasm").as_str())
223 }
224
225 fn is_default_arm_artifact(file_name: &str, contract_name: &str) -> bool {
226 file_name.ends_with(format!("{contract_name}{ARM_POSTFIX}.wasm").as_str())
227 }
228
229 fn is_artifact_with_build_postfix(
230 file_name: &str,
231 contract_name: &str,
232 build_postfix: &str,
233 ) -> bool {
234 is_artifact(file_name, contract_name)
235 && file_name.ends_with(format!("{build_postfix}.wasm").as_str())
236 }
237
238 fn is_arm_artifact_with_build_postfix(
239 file_name: &str,
240 contract_name: &str,
241 build_postfix: &str,
242 ) -> bool {
243 is_artifact(file_name, contract_name)
244 && file_name.ends_with(format!("{build_postfix}{ARM_POSTFIX}.wasm").as_str())
245 }
246}