@@ -7,6 +7,7 @@ use anyhow::Context;
7
7
use async_trait:: async_trait;
8
8
use spin_common:: ui:: quoted_path;
9
9
use spin_manifest:: schema:: v2;
10
+ use watchexec:: filter:: Filterer ;
10
11
11
12
#[ async_trait]
12
13
pub ( crate ) trait FilterFactory : Send + Sync {
@@ -15,7 +16,7 @@ pub(crate) trait FilterFactory: Send + Sync {
15
16
manifest_file : & Path ,
16
17
manifest_dir : & Path ,
17
18
manifest : & v2:: AppManifest ,
18
- ) -> anyhow:: Result < Arc < watchexec_filterer_globset :: GlobsetFilterer > > ;
19
+ ) -> anyhow:: Result < Arc < dyn Filterer > > ;
19
20
}
20
21
21
22
pub ( crate ) struct ArtifactFilterFactory {
@@ -33,7 +34,7 @@ impl FilterFactory for ArtifactFilterFactory {
33
34
manifest_file : & Path ,
34
35
manifest_dir : & Path ,
35
36
manifest : & v2:: AppManifest ,
36
- ) -> anyhow:: Result < Arc < watchexec_filterer_globset :: GlobsetFilterer > > {
37
+ ) -> anyhow:: Result < Arc < dyn Filterer > > {
37
38
let manifest_glob = if self . skip_build {
38
39
vec ! [ manifest_path_to_watch( manifest_file) ?]
39
40
} else {
@@ -63,17 +64,9 @@ impl FilterFactory for ArtifactFilterFactory {
63
64
. into_iter ( )
64
65
. chain ( wasm_globs)
65
66
. chain ( asset_globs)
66
- . map ( |s| ( s, None ) )
67
67
. collect :: < Vec < _ > > ( ) ;
68
68
69
- let filterer = watchexec_filterer_globset:: GlobsetFilterer :: new (
70
- manifest_dir,
71
- artifact_globs,
72
- standard_ignores ( ) ,
73
- [ ] ,
74
- [ ] ,
75
- )
76
- . await ?;
69
+ let filterer = globset_filter ( manifest_dir, artifact_globs) . await ?;
77
70
78
71
Ok ( Arc :: new ( filterer) )
79
72
}
@@ -95,28 +88,22 @@ impl FilterFactory for BuildFilterFactory {
95
88
manifest_file : & Path ,
96
89
manifest_dir : & Path ,
97
90
manifest : & v2:: AppManifest ,
98
- ) -> anyhow:: Result < Arc < watchexec_filterer_globset:: GlobsetFilterer > > {
99
- let manifest_glob = vec ! [ manifest_path_to_watch( manifest_file) ?] ;
100
- let src_globs = manifest
101
- . components
102
- . iter ( )
103
- . flat_map ( |( cid, c) | create_source_globs ( cid. as_ref ( ) , c) )
104
- . collect :: < Vec < _ > > ( ) ;
91
+ ) -> anyhow:: Result < Arc < dyn Filterer > > {
92
+ let mut filterers: Vec < Box < dyn Filterer > > =
93
+ Vec :: with_capacity ( manifest. components . len ( ) + 1 ) ;
105
94
106
- let build_globs = manifest_glob
107
- . into_iter ( )
108
- . chain ( src_globs)
109
- . map ( |s| ( s, None ) )
110
- . collect :: < Vec < _ > > ( ) ;
95
+ let manifest_globs = vec ! [ manifest_path_to_watch( manifest_file) ?] ;
96
+ let manifest_filterer = globset_filter ( manifest_dir, manifest_globs) . await ?;
111
97
112
- let filterer = watchexec_filterer_globset:: GlobsetFilterer :: new (
113
- manifest_dir,
114
- build_globs,
115
- standard_ignores ( ) ,
116
- [ ] ,
117
- [ ] ,
118
- )
119
- . await ?;
98
+ filterers. push ( Box :: new ( manifest_filterer) ) ;
99
+
100
+ for ( cid, c) in & manifest. components {
101
+ let build_globs = create_source_globs ( cid. as_ref ( ) , c) ;
102
+ let build_filterer = globset_filter ( manifest_dir, build_globs) . await ?;
103
+ filterers. push ( Box :: new ( build_filterer) ) ;
104
+ }
105
+
106
+ let filterer = CompositeFilterer { filterers } ;
120
107
121
108
Ok ( Arc :: new ( filterer) )
122
109
}
@@ -152,22 +139,31 @@ impl FilterFactory for ManifestFilterFactory {
152
139
manifest_file : & Path ,
153
140
manifest_dir : & Path ,
154
141
_: & v2:: AppManifest ,
155
- ) -> anyhow:: Result < Arc < watchexec_filterer_globset :: GlobsetFilterer > > {
142
+ ) -> anyhow:: Result < Arc < dyn Filterer > > {
156
143
let manifest_glob = manifest_path_to_watch ( manifest_file) ?;
157
144
158
- let filterer = watchexec_filterer_globset:: GlobsetFilterer :: new (
159
- manifest_dir,
160
- vec ! [ ( manifest_glob, None ) ] ,
161
- standard_ignores ( ) ,
162
- [ ] ,
163
- [ ] ,
164
- )
165
- . await ?;
145
+ let filterer = globset_filter ( manifest_dir, [ manifest_glob] ) . await ?;
166
146
167
147
Ok ( Arc :: new ( filterer) )
168
148
}
169
149
}
170
150
151
+ async fn globset_filter (
152
+ manifest_dir : & Path ,
153
+ globs : impl IntoIterator < Item = String > ,
154
+ ) -> anyhow:: Result < watchexec_filterer_globset:: GlobsetFilterer > {
155
+ let filterer = watchexec_filterer_globset:: GlobsetFilterer :: new (
156
+ manifest_dir,
157
+ globs. into_iter ( ) . map ( |s| ( s, None ) ) ,
158
+ standard_ignores ( ) ,
159
+ [ ] ,
160
+ [ ] ,
161
+ )
162
+ . await ?;
163
+
164
+ Ok ( filterer)
165
+ }
166
+
171
167
// Although manifest dir must be absolute, and most things are safer with abs
172
168
// file paths, the manifest _path_ for the watchers must be relative to manifest dir
173
169
fn manifest_path_to_watch ( path : & Path ) -> anyhow:: Result < String > {
@@ -185,3 +181,24 @@ fn standard_ignores() -> Vec<(String, Option<PathBuf>)> {
185
181
. map ( |pat| ( pat. to_owned ( ) , None ) )
186
182
. collect ( )
187
183
}
184
+
185
+ #[ derive( Debug ) ]
186
+ struct CompositeFilterer {
187
+ filterers : Vec < Box < dyn watchexec:: filter:: Filterer > > ,
188
+ }
189
+
190
+ impl watchexec:: filter:: Filterer for CompositeFilterer {
191
+ fn check_event (
192
+ & self ,
193
+ event : & watchexec:: event:: Event ,
194
+ priority : watchexec:: event:: Priority ,
195
+ ) -> Result < bool , watchexec:: error:: RuntimeError > {
196
+ // We are interested in a change if _any_ component is interested in it
197
+ for f in & self . filterers {
198
+ if f. check_event ( event, priority) ? {
199
+ return Ok ( true ) ;
200
+ }
201
+ }
202
+ Ok ( false )
203
+ }
204
+ }
0 commit comments