@@ -24,6 +24,13 @@ use crate::{
2424 session:: cache:: { EnvMismatch , InputChangeKind } ,
2525} ;
2626
27+ #[ derive(
28+ SchemaWrite , SchemaRead , Debug , Clone , PartialEq , Eq , PartialOrd , Ord , Serialize , Deserialize ,
29+ ) ]
30+ pub enum TrackedEnvQuery {
31+ Glob ( Str ) ,
32+ }
33+
2734/// Path read access info
2835#[ derive( Debug , Clone , Copy ) ]
2936pub struct PathRead {
@@ -44,18 +51,18 @@ pub struct PostRunFingerprint {
4451 /// context that served the original request.
4552 pub tracked_envs : BTreeMap < Str , Option < EnvValueHash > > ,
4653
47- /// Glob-pattern env queries (`getEnvs`) made with `tracked: true`.
48- /// Outer key is the glob pattern , inner map is the match-set at execution
49- /// time (name -> value hash). Validated at cache lookup by re-matching
50- /// against the current env context and comparing the resulting set.
54+ /// Bulk env queries (`getEnvs`) made with `tracked: true`.
55+ /// Outer key is the query , inner map is the match-set at execution time
56+ /// (name -> value hash). Validated at cache lookup by re-matching against
57+ /// the current env context and comparing the resulting set.
5158 ///
5259 /// Non-UTF-8 env names are never matched, saved, or treated as errors:
5360 /// they are not returned to the client, so their existence cannot affect
5461 /// task behavior. Values are stricter. A matched env must have a UTF-8
5562 /// value; the JS client errors when querying a matched non-UTF-8 value,
5663 /// and cache-hit validation treats a currently matched non-UTF-8 value as
5764 /// a changed mismatch so stale cached output is not replayed.
58- pub tracked_env_globs : BTreeMap < Str , BTreeMap < Str , EnvValueHash > > ,
65+ pub tracked_env_queries : BTreeMap < TrackedEnvQuery , BTreeMap < Str , EnvValueHash > > ,
5966}
6067
6168/// A mismatch between the stored post-run fingerprint and the current state.
@@ -65,9 +72,9 @@ pub enum PostRunMismatch {
6572 Input { kind : InputChangeKind , path : RelativePathBuf } ,
6673 /// A tool-tracked env var changed value, appeared, or disappeared.
6774 TrackedEnv ( EnvMismatch ) ,
68- /// A tool-tracked env glob 's match-set changed between runs. Carries the
69- /// first differing entry in env-name order.
70- TrackedEnvGlob { pattern : Str , mismatch : EnvMismatch } ,
75+ /// A tool-tracked bulk env query 's match-set changed between runs. Carries
76+ /// the first differing entry in env-name order.
77+ TrackedEnvQuery { query : TrackedEnvQuery , mismatch : EnvMismatch } ,
7178}
7279
7380/// Fingerprint for a single path (file or directory)
@@ -107,14 +114,14 @@ impl PostRunFingerprint {
107114 /// * `base_dir` - Workspace root for resolving relative paths
108115 /// * `globbed_inputs` - Prerun glob fingerprint; paths here are skipped
109116 /// * `tracked_envs` - Tool-requested env vars (name -> value hash), validated on lookup
110- /// * `tracked_env_globs ` - Tool-requested env globs (pattern -> match-set hashes)
117+ /// * `tracked_env_queries ` - Tool-requested bulk env queries (query -> match-set hashes)
111118 #[ tracing:: instrument( level = "debug" , skip_all, name = "create_post_run_fingerprint" ) ]
112119 pub fn create (
113120 inferred_path_reads : & HashMap < RelativePathBuf , PathRead > ,
114121 base_dir : & AbsolutePath ,
115122 globbed_inputs : & BTreeMap < RelativePathBuf , u64 > ,
116123 tracked_envs : BTreeMap < Str , Option < EnvValueHash > > ,
117- tracked_env_globs : BTreeMap < Str , BTreeMap < Str , EnvValueHash > > ,
124+ tracked_env_queries : BTreeMap < TrackedEnvQuery , BTreeMap < Str , EnvValueHash > > ,
118125 ) -> anyhow:: Result < Self > {
119126 let inferred_inputs = inferred_path_reads
120127 . par_iter ( )
@@ -126,7 +133,7 @@ impl PostRunFingerprint {
126133 } )
127134 . collect :: < anyhow:: Result < HashMap < _ , _ > > > ( ) ?;
128135
129- Ok ( Self { inferred_inputs, tracked_envs, tracked_env_globs } )
136+ Ok ( Self { inferred_inputs, tracked_envs, tracked_env_queries } )
130137 }
131138
132139 /// Validates the fingerprint against current filesystem state and the
@@ -194,19 +201,19 @@ impl PostRunFingerprint {
194201 }
195202 }
196203
197- for ( pattern , stored_matches) in & self . tracked_env_globs {
198- let current_matches = match match_env_glob ( pattern . as_str ( ) , unfiltered_envs) ? {
199- EnvGlobValidation :: Matches ( matches) => matches,
200- EnvGlobValidation :: NonUtf8Value ( mismatch) => {
201- return Ok ( Some ( PostRunMismatch :: TrackedEnvGlob {
202- pattern : pattern . clone ( ) ,
204+ for ( query , stored_matches) in & self . tracked_env_queries {
205+ let current_matches = match match_env_query ( query , unfiltered_envs) ? {
206+ EnvQueryValidation :: Matches ( matches) => matches,
207+ EnvQueryValidation :: NonUtf8Value ( mismatch) => {
208+ return Ok ( Some ( PostRunMismatch :: TrackedEnvQuery {
209+ query : query . clone ( ) ,
203210 mismatch,
204211 } ) ) ;
205212 }
206213 } ;
207214 if let Some ( mismatch) = first_env_glob_mismatch ( stored_matches, & current_matches) {
208- return Ok ( Some ( PostRunMismatch :: TrackedEnvGlob {
209- pattern : pattern . clone ( ) ,
215+ return Ok ( Some ( PostRunMismatch :: TrackedEnvQuery {
216+ query : query . clone ( ) ,
210217 mismatch,
211218 } ) ) ;
212219 }
@@ -216,34 +223,41 @@ impl PostRunFingerprint {
216223 }
217224}
218225
219- /// Build the current match-set for `pattern` by enumerating the given env
220- /// snapshot and keeping UTF-8 names whose representation matches the glob. If
221- /// a matching env has a non-UTF-8 value, return a changed mismatch so the stale
222- /// cache entry is not replayed.
223- fn match_env_glob (
224- pattern : & str ,
226+ /// Build the current match-set for `query` by enumerating the given env
227+ /// snapshot and keeping matching UTF-8 names. If a matching env has a non-UTF-8
228+ /// value, return a changed mismatch so the stale cache entry is not replayed.
229+ fn match_env_query (
230+ query : & TrackedEnvQuery ,
231+ envs : & FxHashMap < Arc < OsStr > , Arc < OsStr > > ,
232+ ) -> anyhow:: Result < EnvQueryValidation > {
233+ let TrackedEnvQuery :: Glob ( pattern) = query;
234+ let glob = vite_glob:: env:: EnvGlob :: new ( pattern. as_str ( ) ) ?;
235+ Ok ( collect_matching_envs ( envs, |name| glob. is_match ( name) ) )
236+ }
237+
238+ fn collect_matching_envs (
225239 envs : & FxHashMap < Arc < OsStr > , Arc < OsStr > > ,
226- ) -> anyhow :: Result < EnvGlobValidation > {
227- let glob = vite_glob :: env :: EnvGlob :: new ( pattern ) ? ;
240+ is_match : impl Fn ( & str ) -> bool ,
241+ ) -> EnvQueryValidation {
228242 let mut matches = BTreeMap :: new ( ) ;
229243 for ( name, value) in envs {
230244 let Some ( name_str) = name. to_str ( ) else {
231245 continue ;
232246 } ;
233- if !glob . is_match ( name_str) {
247+ if !is_match ( name_str) {
234248 continue ;
235249 }
236250 let Some ( value_str) = value. to_str ( ) else {
237- return Ok ( EnvGlobValidation :: NonUtf8Value ( EnvMismatch :: Changed {
251+ return EnvQueryValidation :: NonUtf8Value ( EnvMismatch :: Changed {
238252 name : Str :: from ( name_str) ,
239- } ) ) ;
253+ } ) ;
240254 } ;
241255 matches. insert ( Str :: from ( name_str) , EnvValueHash :: new ( value_str) ) ;
242256 }
243- Ok ( EnvGlobValidation :: Matches ( matches) )
257+ EnvQueryValidation :: Matches ( matches)
244258}
245259
246- enum EnvGlobValidation {
260+ enum EnvQueryValidation {
247261 Matches ( BTreeMap < Str , EnvValueHash > ) ,
248262 NonUtf8Value ( EnvMismatch ) ,
249263}
@@ -516,9 +530,10 @@ mod tests {
516530
517531 #[ test]
518532 fn validate_reports_current_non_utf8_tracked_env_glob_value_as_changed ( ) {
519- let mut tracked_env_globs = BTreeMap :: new ( ) ;
520- tracked_env_globs. insert ( Str :: from ( "PROBE_*" ) , BTreeMap :: new ( ) ) ;
521- let fingerprint = PostRunFingerprint { tracked_env_globs, ..PostRunFingerprint :: default ( ) } ;
533+ let mut tracked_env_queries = BTreeMap :: new ( ) ;
534+ tracked_env_queries. insert ( TrackedEnvQuery :: Glob ( Str :: from ( "PROBE_*" ) ) , BTreeMap :: new ( ) ) ;
535+ let fingerprint =
536+ PostRunFingerprint { tracked_env_queries, ..PostRunFingerprint :: default ( ) } ;
522537
523538 let mut unfiltered_envs = FxHashMap :: default ( ) ;
524539 unfiltered_envs. insert (
@@ -531,22 +546,23 @@ mod tests {
531546 fingerprint. validate ( & workspace_root, & unfiltered_envs) . expect ( "validation succeeds" ) ;
532547
533548 match mismatch {
534- Some ( PostRunMismatch :: TrackedEnvGlob {
535- pattern ,
549+ Some ( PostRunMismatch :: TrackedEnvQuery {
550+ query ,
536551 mismatch : EnvMismatch :: Changed { name } ,
537552 } ) => {
538- assert_eq ! ( pattern . as_str ( ) , "PROBE_*" ) ;
553+ assert_eq ! ( query , TrackedEnvQuery :: Glob ( Str :: from ( "PROBE_*" ) ) ) ;
539554 assert_eq ! ( name. as_str( ) , "PROBE_BAD" ) ;
540555 }
541- other => panic ! ( "expected changed tracked env glob mismatch, got {other:?}" ) ,
556+ other => panic ! ( "expected changed tracked env query mismatch, got {other:?}" ) ,
542557 }
543558 }
544559
545560 #[ test]
546561 fn validate_ignores_non_utf8_tracked_env_glob_names ( ) {
547- let mut tracked_env_globs = BTreeMap :: new ( ) ;
548- tracked_env_globs. insert ( Str :: from ( "PROBE_*" ) , BTreeMap :: new ( ) ) ;
549- let fingerprint = PostRunFingerprint { tracked_env_globs, ..PostRunFingerprint :: default ( ) } ;
562+ let mut tracked_env_queries = BTreeMap :: new ( ) ;
563+ tracked_env_queries. insert ( TrackedEnvQuery :: Glob ( Str :: from ( "PROBE_*" ) ) , BTreeMap :: new ( ) ) ;
564+ let fingerprint =
565+ PostRunFingerprint { tracked_env_queries, ..PostRunFingerprint :: default ( ) } ;
550566
551567 let mut unfiltered_envs = FxHashMap :: default ( ) ;
552568 unfiltered_envs. insert (
0 commit comments