1
1
use std:: {
2
2
io:: { BufWriter , Write } ,
3
+ mem:: forget,
3
4
path:: { Path , PathBuf } ,
4
5
} ;
5
6
@@ -8,6 +9,7 @@ use fs_err::File;
8
9
use memofs:: Vfs ;
9
10
use rbx_dom_weak:: types:: Ref ;
10
11
use serde:: Serialize ;
12
+ use tokio:: runtime:: Runtime ;
11
13
12
14
use crate :: {
13
15
serve_session:: ServeSession ,
@@ -50,6 +52,10 @@ pub struct SourcemapCommand {
50
52
/// If non-script files should be included or not. Defaults to false.
51
53
#[ clap( long) ]
52
54
pub include_non_scripts : bool ,
55
+
56
+ /// Whether to automatically recreate a snapshot when any input files change.
57
+ #[ clap( long) ]
58
+ pub watch : bool ,
53
59
}
54
60
55
61
impl SourcemapCommand {
@@ -58,29 +64,35 @@ impl SourcemapCommand {
58
64
59
65
log:: trace!( "Constructing in-memory filesystem" ) ;
60
66
let vfs = Vfs :: new_default ( ) ;
67
+ vfs. set_watch_enabled ( self . watch ) ;
61
68
62
69
let session = ServeSession :: new ( vfs, & project_path) ?;
63
- let tree = session. tree ( ) ;
70
+ let mut cursor = session. message_queue ( ) . cursor ( ) ;
64
71
65
72
let filter = if self . include_non_scripts {
66
73
filter_nothing
67
74
} else {
68
75
filter_non_scripts
69
76
} ;
70
77
71
- let root_node = recurse_create_node ( & tree , tree . get_root_id ( ) , session . root_dir ( ) , filter) ;
78
+ write_sourcemap ( & session , self . output . as_deref ( ) , filter) ? ;
72
79
73
- if let Some ( output_path) = self . output {
74
- let mut file = BufWriter :: new ( File :: create ( & output_path) ?) ;
75
- serde_json:: to_writer ( & mut file, & root_node) ?;
76
- file. flush ( ) ?;
80
+ if self . watch {
81
+ let rt = Runtime :: new ( ) . unwrap ( ) ;
77
82
78
- println ! ( "Created sourcemap at {}" , output_path. display( ) ) ;
79
- } else {
80
- let output = serde_json:: to_string ( & root_node) ?;
81
- println ! ( "{}" , output) ;
83
+ loop {
84
+ let receiver = session. message_queue ( ) . subscribe ( cursor) ;
85
+ let ( new_cursor, _patch_set) = rt. block_on ( receiver) . unwrap ( ) ;
86
+ cursor = new_cursor;
87
+
88
+ write_sourcemap ( & session, self . output . as_deref ( ) , filter) ?;
89
+ }
82
90
}
83
91
92
+ // Avoid dropping ServeSession: it's potentially VERY expensive to drop
93
+ // and we're about to exit anyways.
94
+ forget ( session) ;
95
+
84
96
Ok ( ( ) )
85
97
}
86
98
}
@@ -90,10 +102,10 @@ fn filter_nothing(_instance: &InstanceWithMeta) -> bool {
90
102
}
91
103
92
104
fn filter_non_scripts ( instance : & InstanceWithMeta ) -> bool {
93
- match instance . class_name ( ) {
94
- "Script" | "LocalScript" | "ModuleScript" => true ,
95
- _ => false ,
96
- }
105
+ matches ! (
106
+ instance . class_name ( ) ,
107
+ "Script" | "LocalScript" | "ModuleScript"
108
+ )
97
109
}
98
110
99
111
fn recurse_create_node (
@@ -106,7 +118,7 @@ fn recurse_create_node(
106
118
107
119
let mut children = Vec :: new ( ) ;
108
120
for & child_id in instance. children ( ) {
109
- if let Some ( child_node) = recurse_create_node ( tree, child_id, & project_dir, filter) {
121
+ if let Some ( child_node) = recurse_create_node ( tree, child_id, project_dir, filter) {
110
122
children. push ( child_node) ;
111
123
}
112
124
}
@@ -134,3 +146,26 @@ fn recurse_create_node(
134
146
children,
135
147
} )
136
148
}
149
+
150
+ fn write_sourcemap (
151
+ session : & ServeSession ,
152
+ output : Option < & Path > ,
153
+ filter : fn ( & InstanceWithMeta ) -> bool ,
154
+ ) -> anyhow:: Result < ( ) > {
155
+ let tree = session. tree ( ) ;
156
+
157
+ let root_node = recurse_create_node ( & tree, tree. get_root_id ( ) , session. root_dir ( ) , filter) ;
158
+
159
+ if let Some ( output_path) = output {
160
+ let mut file = BufWriter :: new ( File :: create ( & output_path) ?) ;
161
+ serde_json:: to_writer ( & mut file, & root_node) ?;
162
+ file. flush ( ) ?;
163
+
164
+ println ! ( "Created sourcemap at {}" , output_path. display( ) ) ;
165
+ } else {
166
+ let output = serde_json:: to_string ( & root_node) ?;
167
+ println ! ( "{}" , output) ;
168
+ }
169
+
170
+ Ok ( ( ) )
171
+ }
0 commit comments