summaryrefslogtreecommitdiff
path: root/cli/main.rs
diff options
context:
space:
mode:
authorYusuke Tanaka <yusuktan@maguro.dev>2020-11-23 05:45:44 +0900
committerGitHub <noreply@github.com>2020-11-22 21:45:44 +0100
commite3f73d3ec0aa822c9d125374ec34b7d8d5dfc0a5 (patch)
tree1f61389d70aeb116bb7075d5489c042d5d8a2d52 /cli/main.rs
parent17d4cd92133bb822ff3a4f2f5bb32dfd17f99282 (diff)
feat(unstable): Support --watch flag for bundle and fmt subcommands (#8276)
This commit adds support for "--watch" flag for "bundle" and "fmt" subcommands. In addition to this, it refactors "run --watch" command so that module resolution will occur every time the file watcher detects file addition/deletion, which allows the watcher to observe a file that is newly added to the dependency as well.
Diffstat (limited to 'cli/main.rs')
-rw-r--r--cli/main.rs281
1 files changed, 176 insertions, 105 deletions
diff --git a/cli/main.rs b/cli/main.rs
index e351060f1..47dd4087d 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -302,84 +302,130 @@ async fn bundle_command(
source_file: String,
out_file: Option<PathBuf>,
) -> Result<(), AnyError> {
- let module_specifier = ModuleSpecifier::resolve_url_or_path(&source_file)?;
+ let debug = flags.log_level == Some(log::Level::Debug);
- debug!(">>>>> bundle START");
- let program_state = ProgramState::new(flags.clone())?;
+ let module_resolver = || {
+ let flags = flags.clone();
+ let source_file = source_file.clone();
+ async move {
+ let module_specifier =
+ ModuleSpecifier::resolve_url_or_path(&source_file)?;
+
+ debug!(">>>>> bundle START");
+ let program_state = ProgramState::new(flags.clone())?;
+
+ info!(
+ "{} {}",
+ colors::green("Bundle"),
+ module_specifier.to_string()
+ );
+
+ let handler = Rc::new(RefCell::new(FetchHandler::new(
+ &program_state,
+ // when bundling, dynamic imports are only access for their type safety,
+ // therefore we will allow the graph to access any module.
+ Permissions::allow_all(),
+ )?));
+ let mut builder = module_graph::GraphBuilder::new(
+ handler,
+ program_state.maybe_import_map.clone(),
+ program_state.lockfile.clone(),
+ );
+ builder.add(&module_specifier, false).await?;
+ let module_graph = builder.get_graph();
+
+ if !flags.no_check {
+ // TODO(@kitsonk) support bundling for workers
+ let lib = if flags.unstable {
+ module_graph::TypeLib::UnstableDenoWindow
+ } else {
+ module_graph::TypeLib::DenoWindow
+ };
+ let result_info =
+ module_graph.clone().check(module_graph::CheckOptions {
+ debug,
+ emit: false,
+ lib,
+ maybe_config_path: flags.config_path.clone(),
+ reload: flags.reload,
+ })?;
+
+ debug!("{}", result_info.stats);
+ if let Some(ignored_options) = result_info.maybe_ignored_options {
+ eprintln!("{}", ignored_options);
+ }
+ if !result_info.diagnostics.is_empty() {
+ return Err(generic_error(result_info.diagnostics.to_string()));
+ }
+ }
- info!(
- "{} {}",
- colors::green("Bundle"),
- module_specifier.to_string()
- );
+ let mut paths_to_watch: Vec<PathBuf> = module_graph
+ .get_modules()
+ .iter()
+ .filter_map(|specifier| specifier.as_url().to_file_path().ok())
+ .collect();
- let handler = Rc::new(RefCell::new(FetchHandler::new(
- &program_state,
- // when bundling, dynamic imports are only access for their type safety,
- // therefore we will allow the graph to access any module.
- Permissions::allow_all(),
- )?));
- let mut builder = module_graph::GraphBuilder::new(
- handler,
- program_state.maybe_import_map.clone(),
- program_state.lockfile.clone(),
- );
- builder.add(&module_specifier, false).await?;
- let graph = builder.get_graph();
+ if let Some(import_map) = program_state.flags.import_map_path.as_ref() {
+ paths_to_watch
+ .push(fs_util::resolve_from_cwd(std::path::Path::new(import_map))?);
+ }
- let debug = flags.log_level == Some(log::Level::Debug);
- if !flags.no_check {
- // TODO(@kitsonk) support bundling for workers
- let lib = if flags.unstable {
- module_graph::TypeLib::UnstableDenoWindow
- } else {
- module_graph::TypeLib::DenoWindow
- };
- let graph = graph.clone();
- let result_info = graph.check(module_graph::CheckOptions {
- debug,
- emit: false,
- lib,
- maybe_config_path: flags.config_path.clone(),
- reload: flags.reload,
- })?;
-
- debug!("{}", result_info.stats);
- if let Some(ignored_options) = result_info.maybe_ignored_options {
- eprintln!("{}", ignored_options);
+ Ok((paths_to_watch, module_graph))
}
- if !result_info.diagnostics.is_empty() {
- return Err(generic_error(result_info.diagnostics.to_string()));
- }
- }
+ .boxed_local()
+ };
- let (output, stats, maybe_ignored_options) =
- graph.bundle(module_graph::BundleOptions {
- debug,
- maybe_config_path: flags.config_path,
- })?;
+ let operation = |module_graph: module_graph::Graph| {
+ let flags = flags.clone();
+ let out_file = out_file.clone();
+ async move {
+ let (output, stats, maybe_ignored_options) =
+ module_graph.bundle(module_graph::BundleOptions {
+ debug,
+ maybe_config_path: flags.config_path,
+ })?;
- if flags.no_check && maybe_ignored_options.is_some() {
- let ignored_options = maybe_ignored_options.unwrap();
- eprintln!("{}", ignored_options);
- }
- debug!("{}", stats);
-
- debug!(">>>>> bundle END");
-
- if let Some(out_file_) = out_file.as_ref() {
- let output_bytes = output.as_bytes();
- let output_len = output_bytes.len();
- fs_util::write_file(out_file_, output_bytes, 0o644)?;
- info!(
- "{} {:?} ({})",
- colors::green("Emit"),
- out_file_,
- colors::gray(&info::human_size(output_len as f64))
- );
+ match maybe_ignored_options {
+ Some(ignored_options) if flags.no_check => {
+ eprintln!("{}", ignored_options);
+ }
+ _ => {}
+ }
+ debug!("{}", stats);
+
+ debug!(">>>>> bundle END");
+
+ if let Some(out_file) = out_file.as_ref() {
+ let output_bytes = output.as_bytes();
+ let output_len = output_bytes.len();
+ fs_util::write_file(out_file, output_bytes, 0o644)?;
+ info!(
+ "{} {:?} ({})",
+ colors::green("Emit"),
+ out_file,
+ colors::gray(&info::human_size(output_len as f64))
+ );
+ } else {
+ println!("{}", output);
+ }
+
+ Ok(())
+ }
+ .boxed_local()
+ };
+
+ if flags.watch {
+ file_watcher::watch_func_with_module_resolution(
+ module_resolver,
+ operation,
+ "Bundle",
+ )
+ .await?;
} else {
- println!("{}", output);
+ let (_, module_graph) = module_resolver().await?;
+ operation(module_graph).await?;
}
+
Ok(())
}
@@ -504,6 +550,20 @@ async fn doc_command(
}
}
+async fn format_command(
+ flags: Flags,
+ args: Vec<PathBuf>,
+ ignore: Vec<PathBuf>,
+ check: bool,
+) -> Result<(), AnyError> {
+ if args.len() == 1 && args[0].to_string_lossy() == "-" {
+ return tools::fmt::format_stdin(check);
+ }
+
+ tools::fmt::format(args, ignore, check, flags.watch).await?;
+ Ok(())
+}
+
async fn run_repl(flags: Flags) -> Result<(), AnyError> {
let main_module =
ModuleSpecifier::resolve_url_or_path("./$deno$repl.ts").unwrap();
@@ -548,44 +608,49 @@ async fn run_from_stdin(flags: Flags) -> Result<(), AnyError> {
}
async fn run_with_watch(flags: Flags, script: String) -> Result<(), AnyError> {
- let main_module = ModuleSpecifier::resolve_url_or_path(&script)?;
- let program_state = ProgramState::new(flags.clone())?;
+ let module_resolver = || {
+ let script = script.clone();
+ let flags = flags.clone();
+ async move {
+ let main_module = ModuleSpecifier::resolve_url_or_path(&script)?;
+ let program_state = ProgramState::new(flags)?;
+ let handler = Rc::new(RefCell::new(FetchHandler::new(
+ &program_state,
+ Permissions::allow_all(),
+ )?));
+ let mut builder = module_graph::GraphBuilder::new(
+ handler,
+ program_state.maybe_import_map.clone(),
+ program_state.lockfile.clone(),
+ );
+ builder.add(&main_module, false).await?;
+ let module_graph = builder.get_graph();
+
+ // Find all local files in graph
+ let mut paths_to_watch: Vec<PathBuf> = module_graph
+ .get_modules()
+ .iter()
+ .filter_map(|specifier| specifier.as_url().to_file_path().ok())
+ .collect();
+
+ if let Some(import_map) = program_state.flags.import_map_path.as_ref() {
+ paths_to_watch
+ .push(fs_util::resolve_from_cwd(std::path::Path::new(import_map))?);
+ }
- let handler = Rc::new(RefCell::new(FetchHandler::new(
- &program_state,
- Permissions::allow_all(),
- )?));
- let mut builder = module_graph::GraphBuilder::new(
- handler,
- program_state.maybe_import_map.clone(),
- program_state.lockfile.clone(),
- );
- builder.add(&main_module, false).await?;
- let module_graph = builder.get_graph();
-
- // Find all local files in graph
- let mut paths_to_watch: Vec<PathBuf> = module_graph
- .get_modules()
- .iter()
- .filter(|specifier| specifier.as_url().scheme() == "file")
- .map(|specifier| specifier.as_url().to_file_path().unwrap())
- .collect();
-
- if let Some(import_map) = program_state.flags.import_map_path.clone() {
- paths_to_watch.push(
- fs_util::resolve_from_cwd(std::path::Path::new(&import_map)).unwrap(),
- );
- }
+ Ok((paths_to_watch, main_module))
+ }
+ .boxed_local()
+ };
- // FIXME(bartlomieju): new file watcher is created on after each restart
- file_watcher::watch_func(&paths_to_watch, move || {
- // FIXME(bartlomieju): ProgramState must be created on each restart - otherwise file fetcher
- // will use cached source files
- let gs = ProgramState::new(flags.clone()).unwrap();
+ let operation = |main_module: ModuleSpecifier| {
+ let flags = flags.clone();
let permissions = Permissions::from_flags(&flags);
- let main_module = main_module.clone();
async move {
- let mut worker = MainWorker::new(&gs, main_module.clone(), permissions);
+ let main_module = main_module.clone();
+ let program_state = ProgramState::new(flags)?;
+ let mut worker =
+ MainWorker::new(&program_state, main_module.clone(), permissions);
debug!("main_module {}", main_module);
worker.execute_module(&main_module).await?;
worker.execute("window.dispatchEvent(new Event('load'))")?;
@@ -594,7 +659,13 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<(), AnyError> {
Ok(())
}
.boxed_local()
- })
+ };
+
+ file_watcher::watch_func_with_module_resolution(
+ module_resolver,
+ operation,
+ "Process",
+ )
.await
}
@@ -806,7 +877,7 @@ pub fn main() {
check,
files,
ignore,
- } => tools::fmt::format(files, check, ignore).boxed_local(),
+ } => format_command(flags, files, ignore, check).boxed_local(),
DenoSubcommand::Info { file, json } => {
info_command(flags, file, json).boxed_local()
}