| 85 | } |
| 86 | |
| 87 | pub fn load_project<P: AsRef<Path>>(&mut self, project_dir: P) -> Result<()> { |
| 88 | let input = project_dir.as_ref(); |
| 89 | let start_dir = if input.is_dir() { |
| 90 | input.to_path_buf() |
| 91 | } else { |
| 92 | input |
| 93 | .parent() |
| 94 | .map(|p| p.to_path_buf()) |
| 95 | .unwrap_or_else(|| input.to_path_buf()) |
| 96 | }; |
| 97 | let start_dir = normalize_existing_path(&start_dir); |
| 98 | let stop_dir = detect_worktree_stop(&start_dir); |
| 99 | |
| 100 | // TS parity: findUp per target, then load from ancestor -> descendant. |
| 101 | for target in [ |
| 102 | "opencode.jsonc", |
| 103 | "opencode.json", |
| 104 | ".opencode/opencode.jsonc", |
| 105 | ".opencode/opencode.json", |
| 106 | ] { |
| 107 | let found = find_up(target, &start_dir, &stop_dir); |
| 108 | for path in found.into_iter().rev() { |
| 109 | self.load_from_file(path)?; |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | Ok(()) |
| 114 | } |
| 115 | |
| 116 | pub fn load_from_env(&mut self) -> Result<()> { |
| 117 | if let Ok(config_path) = env::var("OPENCODE_CONFIG") { |