@@ -6,9 +6,9 @@ use rsscript::{
66} ;
77
88use super :: {
9- cleanup_temp_dir, default_runtime_path, generated_target_dir_from_env,
10- lower_cli_input_to_rust_package, print_diagnostics, print_usage, required_flag_value ,
11- run_cache_dir,
9+ cleanup_temp_dir, cli_input_package_name , default_runtime_path, generated_target_dir_from_env,
10+ lower_cli_input_to_rust_package, print_diagnostics, print_usage, read_cached_fingerprint ,
11+ required_flag_value , run_cache_dir, run_input_fingerprint , write_cached_fingerprint ,
1212} ;
1313
1414#[ derive( Debug ) ]
@@ -93,6 +93,35 @@ fn run_generated_rust_inner(args: &[String], stream_stdio: bool) -> ExitCode {
9393 return ExitCode :: from ( 2 ) ;
9494 }
9595 } ;
96+ // Fast path: for a default-cache run (no `--out-dir`, not a dry run), reuse a
97+ // previously lowered + compiled package when the source, runtime, and release
98+ // flag are byte-for-byte unchanged. This skips re-lowering entirely and lets
99+ // cargo's own up-to-date check make the rebuild a near no-op (often a direct
100+ // run of the cached binary). Correctness: the fingerprint covers every input
101+ // that affects generated output, so any change forces the full path below.
102+ if !options. dry_run && options. out_dir . is_none ( ) {
103+ if let Some ( package_name) = cli_input_package_name ( path) {
104+ let cache_dir = run_cache_dir ( path, & package_name) ;
105+ let cached_package_present = cache_dir. join ( "Cargo.toml" ) . is_file ( )
106+ && cache_dir. join ( "src/main.rs" ) . is_file ( ) ;
107+ if cached_package_present {
108+ if let Some ( fingerprint) =
109+ run_input_fingerprint ( path, & runtime_path, options. release )
110+ {
111+ if read_cached_fingerprint ( & cache_dir) . as_deref ( ) == Some ( fingerprint. as_str ( ) ) {
112+ return run_cached_package (
113+ & cache_dir,
114+ options. release ,
115+ & options. program_args ,
116+ options. json ,
117+ stream_stdio,
118+ ) ;
119+ }
120+ }
121+ }
122+ }
123+ }
124+
96125 let package = match lower_cli_input_to_rust_package ( path, & runtime_path, options. json ) {
97126 Ok ( package) => package,
98127 Err ( exit_code) => return exit_code,
@@ -123,6 +152,7 @@ fn run_generated_rust_inner(args: &[String], stream_stdio: bool) -> ExitCode {
123152 return ExitCode :: SUCCESS ;
124153 }
125154
155+ let is_default_cache = options. out_dir . is_none ( ) ;
126156 let package_dir = options
127157 . out_dir
128158 . map ( PathBuf :: from)
@@ -135,8 +165,50 @@ fn run_generated_rust_inner(args: &[String], stream_stdio: bool) -> ExitCode {
135165 }
136166 return ExitCode :: from ( 2 ) ;
137167 }
168+ // Record the input fingerprint so the next run of unchanged source hits the
169+ // fast path above. Only for the default cache dir; a user-chosen `--out-dir`
170+ // is left untouched. Written after the package files so a partial write never
171+ // leaves a fingerprint claiming a stale package is current.
172+ if is_default_cache {
173+ if let Some ( fingerprint) = run_input_fingerprint ( path, & runtime_path, options. release ) {
174+ write_cached_fingerprint ( & package_dir, & fingerprint) ;
175+ }
176+ }
177+ build_and_run_package (
178+ & package_dir,
179+ options. release ,
180+ & options. program_args ,
181+ options. json ,
182+ stream_stdio,
183+ )
184+ }
185+
186+ /// Runs the fast-path cache hit: the generated package in `cache_dir` is already
187+ /// up to date for the current source, so cargo's incremental check makes this a
188+ /// near no-op build (or a direct run of the cached binary).
189+ fn run_cached_package (
190+ cache_dir : & Path ,
191+ release : bool ,
192+ program_args : & [ & str ] ,
193+ json : bool ,
194+ stream_stdio : bool ,
195+ ) -> ExitCode {
196+ build_and_run_package ( cache_dir, release, program_args, json, stream_stdio)
197+ }
198+
199+ /// Invokes `cargo run` for the generated package in `package_dir` and translates
200+ /// its result into an [`ExitCode`], remapping backend diagnostics for the
201+ /// captured (non-streaming) path. Shared by the full lower+write path and the
202+ /// cached fast path so both behave identically.
203+ fn build_and_run_package (
204+ package_dir : & Path ,
205+ release : bool ,
206+ program_args : & [ & str ] ,
207+ json : bool ,
208+ stream_stdio : bool ,
209+ ) -> ExitCode {
138210 let mut cargo = Command :: new ( "cargo" ) ;
139- for arg in cargo_run_args ( & package_dir, options . release , & options . program_args ) {
211+ for arg in cargo_run_args ( package_dir, release, program_args) {
140212 cargo. arg ( arg) ;
141213 }
142214 if let Some ( target_dir) = generated_target_dir_from_env ( ) {
@@ -154,15 +226,9 @@ fn run_generated_rust_inner(args: &[String], stream_stdio: bool) -> ExitCode {
154226 Ok ( status) => status,
155227 Err ( error) => {
156228 eprintln ! ( "failed to run cargo: {error}" ) ;
157- if cleanup_package_dir {
158- cleanup_temp_dir ( & package_dir) ;
159- }
160229 return ExitCode :: from ( 2 ) ;
161230 }
162231 } ;
163- if cleanup_package_dir {
164- cleanup_temp_dir ( & package_dir) ;
165- }
166232 return if status. success ( ) {
167233 ExitCode :: SUCCESS
168234 } else {
@@ -176,9 +242,6 @@ fn run_generated_rust_inner(args: &[String], stream_stdio: bool) -> ExitCode {
176242 Ok ( output) => output,
177243 Err ( error) => {
178244 eprintln ! ( "failed to run cargo: {error}" ) ;
179- if cleanup_package_dir {
180- cleanup_temp_dir ( & package_dir) ;
181- }
182245 return ExitCode :: from ( 2 ) ;
183246 }
184247 } ;
@@ -187,27 +250,18 @@ fn run_generated_rust_inner(args: &[String], stream_stdio: bool) -> ExitCode {
187250 print ! ( "{stdout}" ) ;
188251 }
189252 if output. status . success ( ) {
190- if cleanup_package_dir {
191- cleanup_temp_dir ( & package_dir) ;
192- }
193253 return ExitCode :: SUCCESS ;
194254 }
195255
196256 let stderr = String :: from_utf8_lossy ( & output. stderr ) ;
197257 let diagnostics = parse_runtime_diagnostics ( & stderr) ;
198258 if !diagnostics. is_empty ( ) {
199- if cleanup_package_dir {
200- cleanup_temp_dir ( & package_dir) ;
201- }
202- print_diagnostics ( options. json , & diagnostics) ;
259+ print_diagnostics ( json, & diagnostics) ;
203260 return ExitCode :: from ( 1 ) ;
204261 }
205- match check_generated_rust_package ( & package_dir) {
262+ match check_generated_rust_package ( package_dir) {
206263 Ok ( result) if !result. diagnostics . is_empty ( ) => {
207- if cleanup_package_dir {
208- cleanup_temp_dir ( & package_dir) ;
209- }
210- print_diagnostics ( options. json , & result. diagnostics ) ;
264+ print_diagnostics ( json, & result. diagnostics ) ;
211265 return if result
212266 . diagnostics
213267 . iter ( )
@@ -223,9 +277,6 @@ fn run_generated_rust_inner(args: &[String], stream_stdio: bool) -> ExitCode {
223277 eprintln ! ( "{error}" ) ;
224278 }
225279 }
226- if cleanup_package_dir {
227- cleanup_temp_dir ( & package_dir) ;
228- }
229280 if !stderr. trim ( ) . is_empty ( ) {
230281 eprintln ! ( "{}" , stderr. trim( ) ) ;
231282 }
0 commit comments