@@ -7,6 +7,7 @@ use anyhow::Context;
77use async_trait:: async_trait;
88use spin_common:: ui:: quoted_path;
99use spin_manifest:: schema:: v2;
10+ use watchexec:: filter:: Filterer ;
1011
1112#[ async_trait]
1213pub ( crate ) trait FilterFactory : Send + Sync {
@@ -15,7 +16,7 @@ pub(crate) trait FilterFactory: Send + Sync {
1516 manifest_file : & Path ,
1617 manifest_dir : & Path ,
1718 manifest : & v2:: AppManifest ,
18- ) -> anyhow:: Result < Arc < watchexec_filterer_globset :: GlobsetFilterer > > ;
19+ ) -> anyhow:: Result < Arc < dyn Filterer > > ;
1920}
2021
2122pub ( crate ) struct ArtifactFilterFactory {
@@ -33,7 +34,7 @@ impl FilterFactory for ArtifactFilterFactory {
3334 manifest_file : & Path ,
3435 manifest_dir : & Path ,
3536 manifest : & v2:: AppManifest ,
36- ) -> anyhow:: Result < Arc < watchexec_filterer_globset :: GlobsetFilterer > > {
37+ ) -> anyhow:: Result < Arc < dyn Filterer > > {
3738 let manifest_glob = if self . skip_build {
3839 vec ! [ manifest_path_to_watch( manifest_file) ?]
3940 } else {
@@ -63,17 +64,9 @@ impl FilterFactory for ArtifactFilterFactory {
6364 . into_iter ( )
6465 . chain ( wasm_globs)
6566 . chain ( asset_globs)
66- . map ( |s| ( s, None ) )
6767 . collect :: < Vec < _ > > ( ) ;
6868
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 ?;
7770
7871 Ok ( Arc :: new ( filterer) )
7972 }
@@ -95,28 +88,22 @@ impl FilterFactory for BuildFilterFactory {
9588 manifest_file : & Path ,
9689 manifest_dir : & Path ,
9790 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 ) ;
10594
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 ?;
11197
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 } ;
120107
121108 Ok ( Arc :: new ( filterer) )
122109 }
@@ -152,22 +139,31 @@ impl FilterFactory for ManifestFilterFactory {
152139 manifest_file : & Path ,
153140 manifest_dir : & Path ,
154141 _: & v2:: AppManifest ,
155- ) -> anyhow:: Result < Arc < watchexec_filterer_globset :: GlobsetFilterer > > {
142+ ) -> anyhow:: Result < Arc < dyn Filterer > > {
156143 let manifest_glob = manifest_path_to_watch ( manifest_file) ?;
157144
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 ?;
166146
167147 Ok ( Arc :: new ( filterer) )
168148 }
169149}
170150
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+
171167// Although manifest dir must be absolute, and most things are safer with abs
172168// file paths, the manifest _path_ for the watchers must be relative to manifest dir
173169fn manifest_path_to_watch ( path : & Path ) -> anyhow:: Result < String > {
@@ -185,3 +181,24 @@ fn standard_ignores() -> Vec<(String, Option<PathBuf>)> {
185181 . map ( |pat| ( pat. to_owned ( ) , None ) )
186182 . collect ( )
187183}
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