1pub(crate) mod package_wizard;
4pub(crate) mod prompts;
5pub(crate) mod render;
6pub(crate) mod timestamp;
7pub(crate) mod unpack;
8
9use std::path::{Path, PathBuf};
10
11use anyhow::{Context as _, Result, bail};
12use wasmer_wasix::runners::MappedDirectory;
13
14fn retrieve_alias_pathbuf(host_dir: &str, guest_dir: &str) -> Result<MappedDirectory> {
15 let host_dir_path = PathBuf::from(&host_dir).canonicalize()?;
16 if let Ok(pb_metadata) = host_dir_path.metadata() {
17 if !pb_metadata.is_dir() {
18 bail!("\"{}\" exists, but it is not a directory", &host_dir);
19 }
20 } else {
21 bail!("Directory \"{}\" does not exist", &host_dir);
22 }
23 Ok(MappedDirectory {
24 host: host_dir_path,
25 guest: guest_dir.to_string(),
26 })
27}
28
29pub fn parse_volume(entry: &str) -> Result<MappedDirectory> {
31 if let Some((host_dir, guest_dir)) = entry.rsplit_once(":") {
33 retrieve_alias_pathbuf(host_dir, guest_dir)
34 } else {
35 retrieve_alias_pathbuf(entry, entry)
36 }
37}
38
39pub fn parse_mapdir(entry: &str) -> Result<MappedDirectory> {
41 if let Some((guest_dir, host_dir)) = entry.rsplit_once(":") {
43 retrieve_alias_pathbuf(host_dir, guest_dir)
44 } else {
45 retrieve_alias_pathbuf(entry, entry)
46 }
47}
48
49pub fn parse_envvar(entry: &str) -> Result<(String, String)> {
51 let entry = entry.trim();
52
53 match entry.find('=') {
54 None => bail!(
55 "Environment variable must be of the form `<name>=<value>`; found `{}`",
56 &entry
57 ),
58
59 Some(0) => bail!(
60 "Environment variable is not well formed, the `name` is missing in `<name>=<value>`; got `{}`",
61 &entry
62 ),
63
64 Some(position) if position == entry.len() - 1 => bail!(
65 "Environment variable is not well formed, the `value` is missing in `<name>=<value>`; got `{}`",
66 &entry
67 ),
68
69 Some(position) => Ok((entry[..position].into(), entry[position + 1..].into())),
70 }
71}
72
73pub(crate) const DEFAULT_PACKAGE_MANIFEST_FILE: &str = "wasmer.toml";
74
75pub fn load_package_manifest(
79 path: &Path,
80) -> Result<Option<(PathBuf, wasmer_config::package::Manifest)>, anyhow::Error> {
81 let file_path = if path.is_file() {
82 path.to_owned()
83 } else {
84 path.join(DEFAULT_PACKAGE_MANIFEST_FILE)
85 };
86
87 let contents = match std::fs::read_to_string(&file_path) {
88 Ok(c) => c,
89 Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),
90 Err(err) => {
91 return Err(err).with_context(|| {
92 format!(
93 "Could not read package manifest at '{}'",
94 file_path.display()
95 )
96 });
97 }
98 };
99
100 let manifest = wasmer_config::package::Manifest::parse(&contents).with_context(|| {
101 format!(
102 "Could not parse package config at: '{}' - full config: {}",
103 file_path.display(),
104 contents
105 )
106 })?;
107
108 Ok(Some((file_path, manifest)))
109}
110
111pub(crate) fn merge_yaml_values(a: &serde_yaml::Value, b: &serde_yaml::Value) -> serde_yaml::Value {
115 use serde_yaml::Value as V;
116 match (a, b) {
117 (V::Mapping(a), V::Mapping(b)) => {
118 let mut m = a.clone();
119 for (k, v) in b.iter() {
120 let newval = if let Some(old) = a.get(k) {
121 merge_yaml_values(old, v)
122 } else {
123 v.clone()
124 };
125 m.insert(k.clone(), newval);
126 }
127 V::Mapping(m)
128 }
129 _ => b.clone(),
130 }
131}
132
133#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn test_merge_yaml_values() {
151 use serde_yaml::Value;
152 let v1 = r#"
153a: a
154b:
155 b1: b1
156c: c
157 "#;
158 let v2 = r#"
159a: a1
160b:
161 b2: b2
162 "#;
163 let v3 = r#"
164a: a1
165b:
166 b1: b1
167 b2: b2
168c: c
169 "#;
170
171 let a: Value = serde_yaml::from_str(v1).unwrap();
172 let b: Value = serde_yaml::from_str(v2).unwrap();
173 let c: Value = serde_yaml::from_str(v3).unwrap();
174 let merged = merge_yaml_values(&a, &b);
175 assert_eq!(merged, c);
176 }
177
178 #[test]
179 fn test_parse_envvar() {
180 assert_eq!(
181 parse_envvar("A").unwrap_err().to_string(),
182 "Environment variable must be of the form `<name>=<value>`; found `A`"
183 );
184 assert_eq!(
185 parse_envvar("=A").unwrap_err().to_string(),
186 "Environment variable is not well formed, the `name` is missing in `<name>=<value>`; got `=A`"
187 );
188 assert_eq!(
189 parse_envvar("A=").unwrap_err().to_string(),
190 "Environment variable is not well formed, the `value` is missing in `<name>=<value>`; got `A=`"
191 );
192 assert_eq!(parse_envvar("A=B").unwrap(), ("A".into(), "B".into()));
193 assert_eq!(parse_envvar(" A=B\t").unwrap(), ("A".into(), "B".into()));
194 assert_eq!(
195 parse_envvar("A=B=C=D").unwrap(),
196 ("A".into(), "B=C=D".into())
197 );
198 }
199}