vtcode_config/loader/manager/
inspect.rs1use super::*;
2
3impl ConfigManager {
4 pub fn config(&self) -> &VTCodeConfig {
6 &self.config
7 }
8
9 pub fn phase_timing(&self) -> Option<ConfigPhaseTiming> {
11 self.phase_timing
12 }
13
14 pub fn config_path(&self) -> Option<&Path> {
16 self.config_path.as_deref()
17 }
18
19 #[must_use]
24 pub fn is_repository_controlled_path(&self, path: &Path) -> bool {
25 if self.explicit_config_is_trusted {
26 return false;
27 }
28
29 if self
30 .layer_stack
31 .layers()
32 .iter()
33 .any(|layer| layer.is_enabled() && Self::repository_source_matches_path(&layer.source, path))
34 {
35 return true;
36 }
37
38 self.config_path.is_none()
39 && self.workspace_root.as_deref().is_some_and(|workspace| {
40 Self::repository_source_matches_path(
41 &ConfigLayerSource::Workspace { file: workspace.join(&self.config_file_name) },
42 path,
43 )
44 })
45 }
46
47 pub fn workspace_root(&self) -> Option<&Path> {
49 self.workspace_root.as_deref()
50 }
51
52 pub fn preferred_workspace_config_path(&self, workspace: &Path) -> PathBuf {
60 self.layer_stack
61 .layers()
62 .iter()
63 .rev()
64 .find_map(|layer| match &layer.source {
65 ConfigLayerSource::Workspace { file } if layer.is_enabled() => Some(file.clone()),
66 _ => None,
67 })
68 .unwrap_or_else(|| workspace.join(&self.config_file_name))
69 }
70
71 pub fn config_file_name(&self) -> &str {
73 &self.config_file_name
74 }
75
76 pub fn layer_stack(&self) -> &ConfigLayerStack {
78 &self.layer_stack
79 }
80
81 pub fn preferred_user_config_path(&self) -> Option<PathBuf> {
83 self.canonical_user_config_path.clone()
84 }
85
86 pub fn user_config_paths(&self) -> Vec<PathBuf> {
92 let mut paths = self.tracked_user_config_paths.clone();
93
94 for path in self
95 .layer_stack
96 .layers()
97 .iter()
98 .filter_map(|layer| match (&layer.source, layer.is_enabled()) {
99 (ConfigLayerSource::User { file }, true) => Some(file),
100 _ => None,
101 })
102 {
103 if !paths.iter().any(|existing| existing == path) {
104 paths.push(path.clone());
105 }
106 }
107
108 paths
109 }
110
111 pub fn watched_config_paths(workspace: &Path) -> Vec<PathBuf> {
119 let provider = defaults::current_config_defaults();
120 let config_file_name = provider.config_file_name().to_string();
121 let workspace_paths = provider.workspace_paths_for(workspace);
122 let workspace_root = workspace_paths.workspace_root().to_path_buf();
123 let mut paths = Vec::new();
124
125 let mut push_unique = |path: PathBuf| {
126 if !paths.iter().any(|existing| existing == &path) {
127 paths.push(path);
128 }
129 };
130
131 if let Some(explicit_path) = session_override::explicit_config_path() {
132 push_unique(explicit_path);
133 }
134 if let Ok(system_paths) = provider.system_config_paths(&config_file_name) {
135 for path in system_paths {
136 push_unique(path);
137 }
138 }
139 for path in provider.home_config_paths(&config_file_name) {
140 push_unique(path);
141 }
142 if let Ok(Some(canonical_path)) = provider.canonical_user_config_path(&config_file_name) {
143 push_unique(canonical_path);
144 }
145
146 if let Some(project_name) = Self::current_project_name(&workspace_root) {
147 push_unique(
148 workspace_paths
149 .config_dir()
150 .join("projects")
151 .join(project_name)
152 .join("config")
153 .join(&config_file_name),
154 );
155 }
156
157 push_unique(workspace_paths.config_dir().join(&config_file_name));
158 push_unique(workspace_root.join(&config_file_name));
159 push_unique(workspace_root.join(".vtcode").join("theme.toml"));
160 paths
161 }
162
163 pub(super) fn repository_config_paths(workspace: &Path) -> Vec<PathBuf> {
164 let provider = defaults::current_config_defaults();
165 let config_file_name = provider.config_file_name().to_string();
166 let workspace_paths = provider.workspace_paths_for(workspace);
167 let workspace_root = canonicalize_workspace_root(workspace_paths.workspace_root());
168 let config_dir = workspace_paths.config_dir();
169 let mut paths = Vec::with_capacity(3);
170
171 let mut push_unique = |path: PathBuf| {
172 if !paths.iter().any(|existing| existing == &path) {
173 paths.push(path);
174 }
175 };
176
177 if let Some(project_path) = Self::project_config_path(&config_dir, &workspace_root, &config_file_name) {
178 push_unique(project_path);
179 }
180 push_unique(config_dir.join(&config_file_name));
181 push_unique(workspace_root.join(&config_file_name));
182 paths
183 }
184
185 pub(super) fn repository_source_matches_path(source: &ConfigLayerSource, path: &Path) -> bool {
186 let Some(source_file) = (match source {
187 ConfigLayerSource::Project { file } | ConfigLayerSource::Workspace { file } => Some(file),
188 ConfigLayerSource::System { .. } | ConfigLayerSource::User { .. } | ConfigLayerSource::Runtime => None,
189 }) else {
190 return false;
191 };
192
193 canonicalize_workspace_root(source_file) == canonicalize_workspace_root(path)
194 }
195
196 pub fn effective_config(&self) -> toml::Value {
198 self.layer_stack.effective_config()
199 }
200
201 pub fn has_explicit_top_level_key(&self, key: &str) -> bool {
206 self.layer_stack
207 .layers()
208 .iter()
209 .filter(|layer| layer.is_enabled())
210 .any(|layer| layer.config.as_table().is_some_and(|table| table.contains_key(key)))
211 }
212
213 pub fn session_duration(&self) -> std::time::Duration {
215 std::time::Duration::from_secs(60 * 60) }
217}