@@ -25,8 +25,9 @@ use next_core::{
2525 segment_config:: ParseSegmentMode ,
2626 util:: { NextRuntime , OptionEnvMap } ,
2727} ;
28+ use rustc_hash:: FxHashMap ;
2829use serde:: { Deserialize , Serialize } ;
29- use tracing:: Instrument ;
30+ use tracing:: { Instrument , field :: Empty } ;
3031use turbo_rcstr:: { RcStr , rcstr} ;
3132use turbo_tasks:: {
3233 Completion , Completions , FxIndexMap , IntoTraitRef , NonLocalValue , OperationValue , OperationVc ,
@@ -329,34 +330,125 @@ fn output_fs_operation(project: ResolvedVc<Project>) -> Vc<DiskFileSystem> {
329330 project. project_fs ( )
330331}
331332
333+ enum EnvDiffType {
334+ Added ,
335+ Removed ,
336+ Modified ,
337+ }
338+
339+ fn env_diff (
340+ old : & [ ( RcStr , Option < RcStr > ) ] ,
341+ new : & [ ( RcStr , Option < RcStr > ) ] ,
342+ ) -> Vec < ( RcStr , EnvDiffType ) > {
343+ let mut diffs = Vec :: new ( ) ;
344+ let mut old_map: FxHashMap < _ , _ > = old. iter ( ) . cloned ( ) . collect ( ) ;
345+
346+ for ( key, new_value) in new. iter ( ) {
347+ match old_map. remove ( key) {
348+ Some ( old_value) => {
349+ if & old_value != new_value {
350+ diffs. push ( ( key. clone ( ) , EnvDiffType :: Modified ) ) ;
351+ }
352+ }
353+ None => {
354+ diffs. push ( ( key. clone ( ) , EnvDiffType :: Added ) ) ;
355+ }
356+ }
357+ }
358+
359+ for ( key, _) in old. iter ( ) {
360+ if old_map. contains_key ( key) {
361+ diffs. push ( ( key. clone ( ) , EnvDiffType :: Removed ) ) ;
362+ }
363+ }
364+
365+ diffs
366+ }
367+
368+ fn env_diff_report ( old : & [ ( RcStr , Option < RcStr > ) ] , new : & [ ( RcStr , Option < RcStr > ) ] ) -> String {
369+ use std:: fmt:: Write ;
370+
371+ let diff = env_diff ( old, new) ;
372+
373+ let mut report = String :: new ( ) ;
374+ for ( key, diff_type) in diff {
375+ let symbol = match diff_type {
376+ EnvDiffType :: Added => "+" ,
377+ EnvDiffType :: Removed => "-" ,
378+ EnvDiffType :: Modified => "*" ,
379+ } ;
380+ if !report. is_empty ( ) {
381+ report. push_str ( ", " ) ;
382+ }
383+ write ! ( report, "{}{}" , symbol, key) . unwrap ( ) ;
384+ }
385+ report
386+ }
387+
388+ fn define_env_diff_report ( old : & DefineEnv , new : & DefineEnv ) -> String {
389+ use std:: fmt:: Write ;
390+
391+ let mut report = String :: new ( ) ;
392+ for ( name, old, new) in [
393+ ( "client" , & old. client , & new. client ) ,
394+ ( "edge" , & old. edge , & new. edge ) ,
395+ ( "nodejs" , & old. nodejs , & new. nodejs ) ,
396+ ] {
397+ let diff = env_diff_report ( old, new) ;
398+ if !diff. is_empty ( ) {
399+ if !report. is_empty ( ) {
400+ report. push_str ( ", " ) ;
401+ }
402+ write ! ( report, "{name}: {{ {diff} }}" ) . unwrap ( ) ;
403+ }
404+ }
405+ report
406+ }
407+
332408impl ProjectContainer {
333- #[ tracing:: instrument( level = "info" , name = "initialize project" , skip_all) ]
334409 pub async fn initialize ( self : ResolvedVc < Self > , options : ProjectOptions ) -> Result < ( ) > {
335- let watch = options. watch ;
410+ let span = tracing:: info_span!(
411+ "initialize project" ,
412+ project_name = %self . await ?. name,
413+ env_diff = Empty
414+ ) ;
415+ let span_clone = span. clone ( ) ;
416+ async move {
417+ let watch = options. watch ;
336418
337- self . await ?. options_state . set ( Some ( options) ) ;
419+ let this = self . await ?;
420+ if let Some ( old_options) = & * this. options_state . get_untracked ( ) {
421+ span. record (
422+ "env_diff" ,
423+ define_env_diff_report ( & old_options. define_env , & options. define_env ) . as_str ( ) ,
424+ ) ;
425+ }
426+ this. options_state . set ( Some ( options) ) ;
338427
339- let project = self . project ( ) . to_resolved ( ) . await ?;
340- let project_fs = project_fs_operation ( project)
341- . read_strongly_consistent ( )
342- . await ?;
343- if watch. enable {
344- project_fs
345- . start_watching_with_invalidation_reason ( watch. poll_interval )
428+ let project = self . project ( ) . to_resolved ( ) . await ?;
429+ let project_fs = project_fs_operation ( project)
430+ . read_strongly_consistent ( )
346431 . await ?;
347- } else {
348- project_fs. invalidate_with_reason ( |path| invalidation:: Initialize {
349- // this path is just used for display purposes
432+ if watch. enable {
433+ project_fs
434+ . start_watching_with_invalidation_reason ( watch. poll_interval )
435+ . await ?;
436+ } else {
437+ project_fs. invalidate_with_reason ( |path| invalidation:: Initialize {
438+ // this path is just used for display purposes
439+ path : RcStr :: from ( path. to_string_lossy ( ) ) ,
440+ } ) ;
441+ }
442+ let output_fs = output_fs_operation ( project)
443+ . read_strongly_consistent ( )
444+ . await ?;
445+ output_fs. invalidate_with_reason ( |path| invalidation:: Initialize {
350446 path : RcStr :: from ( path. to_string_lossy ( ) ) ,
351447 } ) ;
448+ Ok ( ( ) )
352449 }
353- let output_fs = output_fs_operation ( project)
354- . read_strongly_consistent ( )
355- . await ?;
356- output_fs. invalidate_with_reason ( |path| invalidation:: Initialize {
357- path : RcStr :: from ( path. to_string_lossy ( ) ) ,
358- } ) ;
359- Ok ( ( ) )
450+ . instrument ( span_clone)
451+ . await
360452 }
361453
362454 #[ tracing:: instrument( level = "info" , name = "update project options" , skip_all) ]
0 commit comments