rew_core/
utils.rs

1pub use crate::{AppConfig, AppInfo, AppManifest};
2// use serde::{Deserialize, Serialize};
3use std::env;
4use std::fs;
5use std::path::{Path, PathBuf};
6
7// Get the Rew root directory
8pub fn get_rew_root() -> PathBuf {
9  // First check for REW_ROOT environment variable
10  if let Ok(rew_root) = env::var("REW_ROOT") {
11    return PathBuf::from(rew_root);
12  }
13
14  // Otherwise use the default location based on platform
15  #[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 pimmy_data_path() -> Option<PathBuf> {
36  Some(get_rew_root().join(".pimmy"))
37}
38
39// Find an app by package name
40pub fn find_app_by_package(package_name: &str) -> Option<AppInfo> {
41  let rew_root = get_rew_root();
42  let apps_dir = rew_root.join("apps");
43
44  if !apps_dir.exists() {
45    return None;
46  }
47
48  let app_dirs = fs::read_dir(&apps_dir).ok()?;
49
50  for dir_entry in app_dirs.flatten() {
51    let app_dir = dir_entry.path();
52    if !app_dir.is_dir() {
53      continue;
54    }
55
56    let config_path = app_dir.join("app.yaml");
57    if !config_path.exists() {
58      continue;
59    }
60
61    // Read and parse the app.yaml file
62    let config_str = fs::read_to_string(&config_path).ok()?;
63    let config: AppConfig = serde_yaml::from_str(&config_str).ok()?;
64
65    // Check if this app has the requested package name
66    if let Some(manifest) = &config.manifest {
67      if let Some(pkg) = &manifest.package {
68        if pkg == package_name {
69          return Some(AppInfo {
70            path: app_dir,
71            config,
72          });
73        }
74      }
75    }
76  }
77
78  None
79}
80
81// Find app info for a file path
82pub fn find_app_info(file_path: &Path) -> Option<AppInfo> {
83  let mut current = file_path;
84
85  // Walk up the directory tree looking for app.yaml
86  while let Some(parent) = current.parent() {
87    let config_path = parent.join("app.yaml");
88    if config_path.exists() {
89      // Found an app.yaml, parse it
90      let config_str = fs::read_to_string(&config_path).ok()?;
91      let config: AppConfig = serde_yaml::from_str(&config_str).ok()?;
92
93      return Some(AppInfo {
94        path: parent.to_path_buf(),
95        config,
96      });
97    }
98    current = parent;
99  }
100
101  None
102}
103
104// Resolve an app entry point
105pub fn resolve_app_entry(package_name: &str, entry_name: Option<&str>) -> Option<PathBuf> {
106  let app_info = find_app_by_package(package_name)?;
107
108  // Get the entries from the config
109  let entries = app_info.config.entries.as_ref()?;
110
111  // Determine which entry to use
112  let entry_key = entry_name.unwrap_or("main");
113  let entry_path = entries.get(entry_key)?;
114
115  // Resolve the entry path relative to the app directory
116  Some(app_info.path.join(entry_path))
117}
118
119// Find the app path for a given file
120pub fn find_app_path(dir_path: &Path) -> Option<PathBuf> {
121  let mut current = dir_path;
122
123  // Walk up the directory tree looking for app.yaml
124  while let Some(parent) = current.parent() {
125    let config_path = parent.join("app.yaml");
126    if config_path.exists() {
127      return Some(parent.to_path_buf());
128    }
129    current = parent;
130  }
131
132  None
133}
134
135pub fn is_valid_utf8<P: AsRef<Path>>(path: P) -> std::io::Result<bool> {
136  let bytes = std::fs::read(path)?;
137  Ok(std::str::from_utf8(&bytes).is_ok())
138}