diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-06-14 18:29:19 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-14 22:29:19 +0000 |
commit | 84c793275b324c262dde02a432462565584c83f7 (patch) | |
tree | a5995a842fabb37b2ecdab794dbbce76b530ac3a /cli/graph_util.rs | |
parent | 48c6f7178703d448da229a5baf19efb403416da0 (diff) |
fix: reload config files on watcher restarts (#19487)
Closes #19468
Diffstat (limited to 'cli/graph_util.rs')
-rw-r--r-- | cli/graph_util.rs | 87 |
1 files changed, 79 insertions, 8 deletions
diff --git a/cli/graph_util.rs b/cli/graph_util.rs index 530b0a974..0d3548205 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -34,6 +34,7 @@ use deno_runtime::permissions::PermissionsContainer; use import_map::ImportMapError; use std::collections::HashMap; use std::collections::HashSet; +use std::path::PathBuf; use std::sync::Arc; #[derive(Clone, Copy)] @@ -169,6 +170,7 @@ pub struct ModuleGraphBuilder { npm_resolver: Arc<CliNpmResolver>, parsed_source_cache: Arc<ParsedSourceCache>, lockfile: Option<Arc<Mutex<Lockfile>>>, + maybe_file_watcher_reporter: Option<FileWatcherReporter>, emit_cache: cache::EmitCache, file_fetcher: Arc<FileFetcher>, type_checker: Arc<TypeChecker>, @@ -182,6 +184,7 @@ impl ModuleGraphBuilder { npm_resolver: Arc<CliNpmResolver>, parsed_source_cache: Arc<ParsedSourceCache>, lockfile: Option<Arc<Mutex<Lockfile>>>, + maybe_file_watcher_reporter: Option<FileWatcherReporter>, emit_cache: cache::EmitCache, file_fetcher: Arc<FileFetcher>, type_checker: Arc<TypeChecker>, @@ -192,6 +195,7 @@ impl ModuleGraphBuilder { npm_resolver, parsed_source_cache, lockfile, + maybe_file_watcher_reporter, emit_cache, file_fetcher, type_checker, @@ -210,6 +214,10 @@ impl ModuleGraphBuilder { let graph_resolver = cli_resolver.as_graph_resolver(); let graph_npm_resolver = cli_resolver.as_graph_npm_resolver(); let analyzer = self.parsed_source_cache.as_analyzer(); + let maybe_file_watcher_reporter = self + .maybe_file_watcher_reporter + .as_ref() + .map(|r| r.as_reporter()); let mut graph = ModuleGraph::new(graph_kind); self @@ -223,7 +231,7 @@ impl ModuleGraphBuilder { resolver: Some(graph_resolver), npm_resolver: Some(graph_npm_resolver), module_analyzer: Some(&*analyzer), - reporter: None, + reporter: maybe_file_watcher_reporter, }, ) .await?; @@ -250,6 +258,11 @@ impl ModuleGraphBuilder { let analyzer = self.parsed_source_cache.as_analyzer(); let graph_kind = self.options.type_check_mode().as_graph_kind(); let mut graph = ModuleGraph::new(graph_kind); + let maybe_file_watcher_reporter = self + .maybe_file_watcher_reporter + .as_ref() + .map(|r| r.as_reporter()); + self .build_graph_with_npm_resolution( &mut graph, @@ -261,7 +274,7 @@ impl ModuleGraphBuilder { resolver: Some(graph_resolver), npm_resolver: Some(graph_npm_resolver), module_analyzer: Some(&*analyzer), - reporter: None, + reporter: maybe_file_watcher_reporter, }, ) .await?; @@ -415,7 +428,6 @@ struct GraphData { /// Holds the `ModuleGraph` and what parts of it are type checked. pub struct ModuleGraphContainer { - graph_kind: GraphKind, // Allow only one request to update the graph data at a time, // but allow other requests to read from it at any time even // while another request is updating the data. @@ -426,7 +438,6 @@ pub struct ModuleGraphContainer { impl ModuleGraphContainer { pub fn new(graph_kind: GraphKind) -> Self { Self { - graph_kind, update_queue: Default::default(), graph_data: Arc::new(RwLock::new(GraphData { graph: Arc::new(ModuleGraph::new(graph_kind)), @@ -435,10 +446,6 @@ impl ModuleGraphContainer { } } - pub fn clear(&self) { - self.graph_data.write().graph = Arc::new(ModuleGraph::new(self.graph_kind)); - } - /// Acquires a permit to modify the module graph without other code /// having the chance to modify it. In the meantime, other code may /// still read from the existing module graph. @@ -496,6 +503,33 @@ impl ModuleGraphContainer { } } +/// Gets if any of the specified root's "file:" dependents are in the +/// provided changed set. +pub fn has_graph_root_local_dependent_changed( + graph: &ModuleGraph, + root: &ModuleSpecifier, + changed_specifiers: &HashSet<ModuleSpecifier>, +) -> bool { + let roots = vec![root.clone()]; + let mut dependent_specifiers = graph.walk( + &roots, + deno_graph::WalkOptions { + follow_dynamic: true, + follow_type_only: true, + check_js: true, + }, + ); + while let Some((s, _)) = dependent_specifiers.next() { + if s.scheme() != "file" { + // skip walking this remote module's dependencies + dependent_specifiers.skip_previous_dependencies(); + } else if changed_specifiers.contains(s) { + return true; + } + } + false +} + /// A permit for updating the module graph. When complete and /// everything looks fine, calling `.commit()` will store the /// new graph in the ModuleGraphContainer. @@ -521,6 +555,43 @@ impl<'a> ModuleGraphUpdatePermit<'a> { } } +#[derive(Clone, Debug)] +pub struct FileWatcherReporter { + sender: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>, + file_paths: Arc<Mutex<Vec<PathBuf>>>, +} + +impl FileWatcherReporter { + pub fn new(sender: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>) -> Self { + Self { + sender, + file_paths: Default::default(), + } + } + + pub fn as_reporter(&self) -> &dyn deno_graph::source::Reporter { + self + } +} + +impl deno_graph::source::Reporter for FileWatcherReporter { + fn on_load( + &self, + specifier: &ModuleSpecifier, + modules_done: usize, + modules_total: usize, + ) { + let mut file_paths = self.file_paths.lock(); + if specifier.scheme() == "file" { + file_paths.push(specifier.to_file_path().unwrap()); + } + + if modules_done == modules_total { + self.sender.send(file_paths.drain(..).collect()).unwrap(); + } + } +} + #[cfg(test)] mod test { use std::sync::Arc; |