1pub use crate::{AppConfig, AppInfo, AppManifest};
2use std::env;
4use std::fs;
5use std::path::{Path, PathBuf};
6
7pub fn get_rew_root() -> PathBuf {
9 if let Ok(rew_root) = env::var("REW_ROOT") {
11 return PathBuf::from(rew_root);
12 }
13
14 #[cfg(target_os = "windows")]
16 {
17 let local_app_data = env::var("LOCALAPPDATA").unwrap_or_else(|_| {
18 let home = env::var("USERPROFILE").unwrap_or_else(|_| ".".to_string());
19 format!("{}\\AppData\\Local", home)
20 });
21 PathBuf::from(format!("{}\\rew", local_app_data))
22 }
23
24 #[cfg(not(target_os = "windows"))]
25 {
26 if std::path::Path::new("/opt/rew").exists() {
27 PathBuf::from("/opt/rew")
28 } else {
29 let home = env::var("HOME").unwrap_or_else(|_| ".".to_string());
30 PathBuf::from(format!("{}/.rew", home))
31 }
32 }
33}
34
35pub fn find_app_by_package(package_name: &str) -> Option<AppInfo> {
37 let rew_root = get_rew_root();
38 let apps_dir = rew_root.join("apps");
39
40 if !apps_dir.exists() {
41 return None;
42 }
43
44 let app_dirs = fs::read_dir(&apps_dir).ok()?;
45
46 for dir_entry in app_dirs.flatten() {
47 let app_dir = dir_entry.path();
48 if !app_dir.is_dir() {
49 continue;
50 }
51
52 let config_path = app_dir.join("app.yaml");
53 if !config_path.exists() {
54 continue;
55 }
56
57 let config_str = fs::read_to_string(&config_path).ok()?;
59 let config: AppConfig = serde_yaml::from_str(&config_str).ok()?;
60
61 if let Some(manifest) = &config.manifest {
63 if let Some(pkg) = &manifest.package {
64 if pkg == package_name {
65 return Some(AppInfo {
66 path: app_dir,
67 config,
68 });
69 }
70 }
71 }
72 }
73
74 None
75}
76
77pub fn find_app_info(file_path: &Path) -> Option<AppInfo> {
79 let mut current = file_path;
80
81 while let Some(parent) = current.parent() {
83 let config_path = parent.join("app.yaml");
84 if config_path.exists() {
85 let config_str = fs::read_to_string(&config_path).ok()?;
87 let config: AppConfig = serde_yaml::from_str(&config_str).ok()?;
88
89 return Some(AppInfo {
90 path: parent.to_path_buf(),
91 config,
92 });
93 }
94 current = parent;
95 }
96
97 None
98}
99
100pub fn resolve_app_entry(package_name: &str, entry_name: Option<&str>) -> Option<PathBuf> {
102 let app_info = find_app_by_package(package_name)?;
103
104 let entries = app_info.config.entries.as_ref()?;
106
107 let entry_key = entry_name.unwrap_or("main");
109 let entry_path = entries.get(entry_key)?;
110
111 Some(app_info.path.join(entry_path))
113}
114
115pub fn find_app_path(dir_path: &Path) -> Option<PathBuf> {
117 let mut current = dir_path;
118
119 while let Some(parent) = current.parent() {
121 let config_path = parent.join("app.yaml");
122 if config_path.exists() {
123 return Some(parent.to_path_buf());
124 }
125 current = parent;
126 }
127
128 None
129}
130
131#[allow(unused)]
132pub fn is_valid_utf8<P: AsRef<Path>>(path: P) -> std::io::Result<bool> {
133 let bytes = std::fs::read(path)?;
134 Ok(std::str::from_utf8(&bytes).is_ok())
135}