Skip to content

Commit d28c61c

Browse files
authored
Add explicit --prod flag for rewatch commands (#8347)
* Add --prod flag to rewatch build, watch, and clean commands Skip dev-dependencies and dev source folders (type: "dev") when --prod is passed, enabling production builds without dev tooling installed. Signed-Off-By: Jono Prest <jjprest@gmail.com> * Add tests * Run cargo fmt * Update cli help test * Update changelog --------- Signed-off-by: Jono Prest <jjprest@gmail.com>
1 parent 4143b81 commit d28c61c

11 files changed

Lines changed: 198 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
#### :rocket: New Feature
2323

24+
- Rewatch: add `--prod` flag to `build`, `watch`, and `clean` to skip dev-dependencies and dev sources (`"type": "dev"`), enabling builds in environments where dev packages aren't installed (e.g. after `pnpm install --prod`). https://github.com/rescript-lang/rescript/pull/8347
25+
2426
#### :bug: Bug fix
2527

2628
- Fix partial application generalization for `...`. https://github.com/rescript-lang/rescript/pull/8343

rewatch/src/build.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,13 @@ pub fn initialize_build(
134134
path: &Path,
135135
plain_output: bool,
136136
warn_error: Option<String>,
137+
prod: bool,
137138
) -> Result<BuildCommandState> {
138139
let project_context = ProjectContext::new(path)?;
139140
let compiler = get_compiler_info(&project_context)?;
140141

141142
let timing_clean_start = Instant::now();
142-
let packages = packages::make(filter, &project_context, show_progress)?;
143+
let packages = packages::make(filter, &project_context, show_progress, prod)?;
143144

144145
let compiler_check = verify_compiler_info(&packages, &compiler);
145146

@@ -489,6 +490,7 @@ pub fn build(
489490
create_sourcedirs: bool,
490491
plain_output: bool,
491492
warn_error: Option<String>,
493+
prod: bool,
492494
) -> Result<BuildCommandState> {
493495
let default_timing: Option<std::time::Duration> = if no_timing {
494496
Some(std::time::Duration::new(0.0 as u64, 0.0 as u32))
@@ -503,6 +505,7 @@ pub fn build(
503505
path,
504506
plain_output,
505507
warn_error,
508+
prod,
506509
)
507510
.with_context(|| "Could not initialize build")?;
508511

rewatch/src/build/clean.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,10 +332,10 @@ pub fn cleanup_after_build(build_state: &BuildCommandState) {
332332
});
333333
}
334334

335-
pub fn clean(path: &Path, show_progress: bool, plain_output: bool) -> Result<()> {
335+
pub fn clean(path: &Path, show_progress: bool, plain_output: bool, prod: bool) -> Result<()> {
336336
let project_context = ProjectContext::new(path)?;
337337
let compiler_info = build::get_compiler_info(&project_context)?;
338-
let packages = packages::make(&None, &project_context, show_progress)?;
338+
let packages = packages::make(&None, &project_context, show_progress, prod)?;
339339

340340
let timing_clean_compiler_assets = Instant::now();
341341
if !plain_output && show_progress {

rewatch/src/build/packages.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,11 +285,15 @@ fn read_dependencies(
285285
package_config: &Config,
286286
show_progress: bool,
287287
is_local_dep: bool,
288+
prod: bool,
288289
) -> Vec<Dependency> {
289290
let mut dependencies = package_config.dependencies.to_owned().unwrap_or_default();
290291

291-
// Concatenate dev dependencies if is_local_dep is true
292-
if is_local_dep && let Some(dev_deps) = package_config.dev_dependencies.to_owned() {
292+
// Concatenate dev dependencies if is_local_dep is true and not in prod mode
293+
if is_local_dep
294+
&& !prod
295+
&& let Some(dev_deps) = package_config.dev_dependencies.to_owned()
296+
{
293297
dependencies.extend(dev_deps);
294298
}
295299

@@ -395,6 +399,7 @@ fn read_dependencies(
395399
&config,
396400
show_progress,
397401
is_local_dep,
402+
prod,
398403
);
399404

400405
Dependency {
@@ -509,7 +514,11 @@ This inconsistency will cause issues with package resolution.\n",
509514
})
510515
}
511516

512-
fn read_packages(project_context: &ProjectContext, show_progress: bool) -> Result<AHashMap<String, Package>> {
517+
fn read_packages(
518+
project_context: &ProjectContext,
519+
show_progress: bool,
520+
prod: bool,
521+
) -> Result<AHashMap<String, Package>> {
513522
// Store all packages and completely deduplicate them
514523
let mut map: AHashMap<String, Package> = AHashMap::new();
515524

@@ -531,6 +540,7 @@ fn read_packages(project_context: &ProjectContext, show_progress: bool) -> Resul
531540
&project_context.current_config,
532541
show_progress,
533542
/* is local dep */ true,
543+
prod,
534544
));
535545

536546
for d in dependencies.iter() {
@@ -594,6 +604,7 @@ pub fn get_source_files(
594604
fn extend_with_children(
595605
filter: &Option<regex::Regex>,
596606
mut build: AHashMap<String, Package>,
607+
prod: bool,
597608
) -> AHashMap<String, Package> {
598609
for (_key, package) in build.iter_mut() {
599610
let mut map: AHashMap<PathBuf, SourceFileMeta> = AHashMap::new();
@@ -606,7 +617,7 @@ fn extend_with_children(
606617
Path::new(&package.path),
607618
filter,
608619
source,
609-
package.is_local_dep,
620+
package.is_local_dep && !prod,
610621
)
611622
})
612623
.collect::<Vec<AHashMap<PathBuf, SourceFileMeta>>>()
@@ -649,12 +660,13 @@ pub fn make(
649660
filter: &Option<regex::Regex>,
650661
project_context: &ProjectContext,
651662
show_progress: bool,
663+
prod: bool,
652664
) -> Result<AHashMap<String, Package>> {
653-
let map = read_packages(project_context, show_progress)?;
665+
let map = read_packages(project_context, show_progress, prod)?;
654666

655667
/* Once we have the deduplicated packages, we can add the source files for each - to minimize
656668
* the IO */
657-
let result = extend_with_children(filter, map);
669+
let result = extend_with_children(filter, map, prod);
658670

659671
Ok(result)
660672
}

rewatch/src/cli.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ pub struct BuildArgs {
219219
/// Disable output timing
220220
#[arg(short, long, default_value_t = false, num_args = 0..=1)]
221221
pub no_timing: bool,
222+
223+
/// Skip dev-dependencies and dev sources (type: "dev")
224+
#[arg(long, default_value_t = false)]
225+
pub prod: bool,
222226
}
223227

224228
#[cfg(test)]
@@ -348,6 +352,57 @@ mod tests {
348352
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
349353
}
350354

355+
// --prod flag tests.
356+
#[test]
357+
fn build_prod_flag_is_parsed() {
358+
let cli = parse(&["rescript", "build", "--prod"]).expect("expected build command");
359+
360+
match cli.command {
361+
Command::Build(build_args) => assert!(build_args.prod),
362+
other => panic!("expected build command, got {other:?}"),
363+
}
364+
}
365+
366+
#[test]
367+
fn build_prod_flag_defaults_to_false() {
368+
let cli = parse(&["rescript", "build"]).expect("expected build command");
369+
370+
match cli.command {
371+
Command::Build(build_args) => assert!(!build_args.prod),
372+
other => panic!("expected build command, got {other:?}"),
373+
}
374+
}
375+
376+
#[test]
377+
fn watch_prod_flag_is_parsed() {
378+
let cli = parse(&["rescript", "watch", "--prod"]).expect("expected watch command");
379+
380+
match cli.command {
381+
Command::Watch(watch_args) => assert!(watch_args.prod),
382+
other => panic!("expected watch command, got {other:?}"),
383+
}
384+
}
385+
386+
#[test]
387+
fn clean_prod_flag_is_parsed() {
388+
let cli = parse(&["rescript", "clean", "--prod"]).expect("expected clean command");
389+
390+
match cli.command {
391+
Command::Clean { prod, .. } => assert!(prod),
392+
other => panic!("expected clean command, got {other:?}"),
393+
}
394+
}
395+
396+
#[test]
397+
fn prod_flag_defaults_to_build_command() {
398+
let cli = parse(&["rescript", "--prod"]).expect("expected default build command");
399+
400+
match cli.command {
401+
Command::Build(build_args) => assert!(build_args.prod),
402+
other => panic!("expected build command, got {other:?}"),
403+
}
404+
}
405+
351406
#[cfg(unix)]
352407
#[test]
353408
fn non_utf_argument_returns_error() {
@@ -372,6 +427,10 @@ pub struct WatchArgs {
372427

373428
#[command(flatten)]
374429
pub warn_error: WarnErrorArg,
430+
431+
/// Skip dev-dependencies and dev sources (type: "dev")
432+
#[arg(long, default_value_t = false)]
433+
pub prod: bool,
375434
}
376435

377436
impl From<BuildArgs> for WatchArgs {
@@ -381,6 +440,7 @@ impl From<BuildArgs> for WatchArgs {
381440
filter: build_args.filter,
382441
after_build: build_args.after_build,
383442
warn_error: build_args.warn_error,
443+
prod: build_args.prod,
384444
}
385445
}
386446
}
@@ -395,6 +455,10 @@ pub enum Command {
395455
Clean {
396456
#[command(flatten)]
397457
folder: FolderArg,
458+
459+
/// Skip dev-dependencies and dev sources (type: "dev")
460+
#[arg(long, default_value_t = false)]
461+
prod: bool,
398462
},
399463
/// Format ReScript files.
400464
Format {

rewatch/src/format.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn get_files_in_scope() -> Result<Vec<String>> {
3636
let current_dir = std::env::current_dir()?;
3737
let project_context = project_context::ProjectContext::new(&current_dir)?;
3838

39-
let packages = packages::make(&None, &project_context, false)?;
39+
let packages = packages::make(&None, &project_context, false, false)?;
4040
let mut files: Vec<String> = Vec::new();
4141
let packages_to_format = project_context.get_scoped_local_packages();
4242

rewatch/src/main.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ fn main() -> Result<()> {
5454
true, // create_sourcedirs is now always enabled
5555
plain_output,
5656
(*build_args.warn_error).clone(),
57+
build_args.prod,
5758
) {
5859
Err(e) => {
5960
eprintln!("{:#}", e);
@@ -78,6 +79,7 @@ fn main() -> Result<()> {
7879
true, // create_sourcedirs is now always enabled
7980
plain_output,
8081
(*watch_args.warn_error).clone(),
82+
watch_args.prod,
8183
) {
8284
Err(e) => {
8385
eprintln!("{:#}", e);
@@ -86,9 +88,9 @@ fn main() -> Result<()> {
8688
Ok(_) => Ok(()),
8789
}
8890
}
89-
cli::Command::Clean { folder } => {
91+
cli::Command::Clean { folder, prod } => {
9092
let _lock = get_lock_or_exit(LockKind::Build, &folder);
91-
let result = build::clean::clean(Path::new(&folder as &str), show_progress, plain_output);
93+
let result = build::clean::clean(Path::new(&folder as &str), show_progress, plain_output, prod);
9294
let _lock = drop_lock(LockKind::Build, &folder);
9395

9496
result

rewatch/src/watcher.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ struct AsyncWatchArgs<'a> {
189189
after_build: Option<String>,
190190
create_sourcedirs: bool,
191191
plain_output: bool,
192+
prod: bool,
192193
}
193194

194195
async fn async_watch(
@@ -203,6 +204,7 @@ async fn async_watch(
203204
after_build,
204205
create_sourcedirs,
205206
plain_output,
207+
prod,
206208
}: AsyncWatchArgs<'_>,
207209
) -> Result<()> {
208210
let mut build_state = initial_build_state;
@@ -419,6 +421,7 @@ async fn async_watch(
419421
path,
420422
plain_output,
421423
build_state.get_warn_error_override(),
424+
prod,
422425
)
423426
.expect("Could not initialize build");
424427

@@ -478,6 +481,7 @@ pub fn start(
478481
create_sourcedirs: bool,
479482
plain_output: bool,
480483
warn_error: Option<String>,
484+
prod: bool,
481485
) -> Result<()> {
482486
futures::executor::block_on(async {
483487
let queue = Arc::new(FifoQueue::<Result<Event, Error>>::new());
@@ -497,6 +501,7 @@ pub fn start(
497501
path,
498502
plain_output,
499503
warn_error.clone(),
504+
prod,
500505
)
501506
.with_context(|| "Could not initialize build")?;
502507

@@ -515,6 +520,7 @@ pub fn start(
515520
after_build,
516521
create_sourcedirs,
517522
plain_output,
523+
prod,
518524
})
519525
.await
520526
})

0 commit comments

Comments
 (0)