1use std::env;
8use std::fs;
9use std::path::PathBuf;
10
11pub struct Context {
12 pub root: PathBuf,
14 pub is_project: bool,
16}
17
18impl Context {
19 pub fn resolve() -> Self {
22 if let Some(project_root) = find_project_root() {
23 Context { root: project_root, is_project: true }
24 } else {
25 Context { root: global_root(), is_project: false }
26 }
27 }
28
29 pub fn with_root(root: PathBuf) -> Self {
31 let is_project = root.join("Cargo.toml").exists();
32 Context { root, is_project }
33 }
34
35 pub fn libtorch_dir(&self) -> PathBuf {
37 self.root.join("libtorch")
38 }
39
40 pub fn label(&self) -> String {
42 if self.is_project {
43 format!("project ({})", self.root.display())
44 } else {
45 format!("global ({})", self.root.display())
46 }
47 }
48}
49
50fn find_project_root() -> Option<PathBuf> {
52 let mut dir = env::current_dir().ok()?;
53 loop {
54 if dir.join("libtorch/.active").exists() {
56 return Some(dir);
57 }
58 let cargo_toml = dir.join("Cargo.toml");
60 if cargo_toml.exists() {
61 if let Ok(contents) = fs::read_to_string(&cargo_toml) {
62 if contents.contains("flodl") {
63 return Some(dir);
64 }
65 }
66 }
67 if !dir.pop() {
68 return None;
69 }
70 }
71}
72
73fn global_root() -> PathBuf {
75 env::var("FLODL_HOME")
76 .map(PathBuf::from)
77 .unwrap_or_else(|_| home_dir().join(".flodl"))
78}
79
80fn home_dir() -> PathBuf {
81 env::var("HOME")
82 .or_else(|_| env::var("USERPROFILE"))
83 .map(PathBuf::from)
84 .unwrap_or_else(|_| PathBuf::from("."))
85}