1use crate::Env;
2use std::fs;
3use std::io;
4use std::path::Path;
5
6pub trait Platform
14where
15 Self: Sized,
16{
17 fn env(&self) -> &Env;
20
21 fn from_path(platform_dir: impl AsRef<Path>) -> io::Result<Self>;
30}
31
32pub(crate) fn read_platform_env(platform_dir: impl AsRef<Path>) -> std::io::Result<Env> {
34 let env_path = platform_dir.as_ref().join("env");
35 let mut env_vars = Env::new();
36
37 match fs::read_dir(env_path) {
38 Ok(entries) => {
39 for entry in entries {
40 let entry = entry?;
41 let path = entry.path();
42
43 if let Some(file_name) = path.file_name() {
44 if path.is_file() {
47 let file_contents = fs::read_to_string(&path)?;
48 env_vars.insert(file_name.to_owned(), file_contents);
49 }
50 }
51 }
52 }
53 Err(err) => {
54 if err.kind() != std::io::ErrorKind::NotFound {
56 return Err(err);
57 }
58 }
59 }
60
61 Ok(env_vars)
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use std::ffi::OsString;
68
69 #[test]
70 fn read_platform_env_reads_correct_env_vars() {
71 let tmpdir = tempfile::tempdir().unwrap();
72 let env_dir = tmpdir.path().join("env");
73 fs::create_dir(&env_dir).unwrap();
74
75 fs::write(env_dir.join("FOO"), "BAR").unwrap();
76 fs::write(env_dir.join("HELLO"), "World!").unwrap();
77
78 let env = read_platform_env(tmpdir.path()).unwrap();
79 assert_eq!(env.get("FOO"), Some(&OsString::from("BAR")));
80 assert_eq!(env.get("HELLO"), Some(&OsString::from("World!")));
81 }
82
83 #[test]
84 fn read_platform_env_handles_directories_in_env_folder() {
85 let tmpdir = tempfile::tempdir().unwrap();
86 let env_dir = tmpdir.path().join("env");
87 fs::create_dir(&env_dir).unwrap();
88 let dummy_dir = env_dir.join("foobar");
89 fs::create_dir(dummy_dir).unwrap();
90 fs::write(env_dir.join("FOO"), "BAR").unwrap();
91
92 let result = read_platform_env(tmpdir.path());
93 assert!(result.is_ok());
94 }
95
96 #[cfg(target_family = "unix")]
98 #[test]
99 fn read_platform_env_handles_directories_via_symlinks() {
100 let tmpdir = tempfile::tempdir().unwrap();
101 let env_dir = tmpdir.path().join("env");
102 fs::create_dir(&env_dir).unwrap();
103 let dummy_dir = env_dir.join("foobar");
104 fs::create_dir(&dummy_dir).unwrap();
105 let dst_symlink = env_dir.join("data");
106 std::os::unix::fs::symlink(&dummy_dir, dst_symlink).unwrap();
107 fs::write(env_dir.join("FOO"), "BAR").unwrap();
108
109 let result = read_platform_env(tmpdir.path());
110 assert!(result.is_ok());
111 }
112
113 #[test]
114 fn read_platform_env_does_not_blow_up_if_platform_env_is_missing() {
115 let tmpdir = tempfile::tempdir().unwrap();
116
117 let result = read_platform_env(tmpdir.path());
118 assert!(result.is_ok());
119 }
120}