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