Skip to content

Commit dfcbfe2

Browse files
wan9chiclaude
andauthored
refactor(cache): introduce EnvMismatch as the canonical env-change shape (#437)
## Motivation `SpawnFingerprintChange` carried three env variants — `EnvAdded`, `EnvRemoved`, `EnvValueChanged` — that encoded the same concept three times over: an env var differing between a stored fingerprint and the current state. Every consumer had to spell out the same three-arm match, and the user-facing wording lived inline in `format_spawn_change`'s arms. This shape is about to be needed in more places. The runner-aware caching work (#430) detects env differences at two additional points — tool-tracked envs (`getEnv`) and env-glob match-sets (`getEnvs`) validated at cache lookup — and without a shared type each would re-invent the added/removed/changed triple plus its own formatting, with the wording drifting across three copies (the first draft of #430 had exactly that: an option-pair `{old: Option<Str>, new: Option<Str>}` with an impossible `(None, None)` state, a three-map `EnvGlobDiff`, and two hand-rolled renderers). ## Approach Introduce `EnvMismatch { Added, Removed, Changed }` next to the other mismatch vocabulary in `cache/`, with its `Display` impl as the single source of the user-facing wording. `SpawnFingerprintChange` folds its three variants into one `Env(EnvMismatch)`. No behavior change: detection logic, message strings, and snapshots are identical. #430 then reuses the enum for its post-run paths instead of defining parallel shapes. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 31fea5b commit dfcbfe2

2 files changed

Lines changed: 42 additions & 31 deletions

File tree

crates/vite_task/src/session/cache/display.rs

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,16 @@ use serde::{Deserialize, Serialize};
88
use vite_str::Str;
99
use vite_task_plan::cache_metadata::SpawnFingerprint;
1010

11-
use super::{CacheMiss, FingerprintMismatch, InputChangeKind, split_path};
11+
use super::{CacheMiss, EnvMismatch, FingerprintMismatch, InputChangeKind, split_path};
1212
use crate::session::event::CacheStatus;
1313

1414
/// Describes a single atomic change between two spawn fingerprints.
1515
///
1616
/// Used both for live cache status display and for persisted summary data.
1717
#[derive(Serialize, Deserialize)]
1818
pub enum SpawnFingerprintChange {
19-
// Environment variable changes
20-
/// Environment variable added
21-
EnvAdded { key: Str, value: Str },
22-
/// Environment variable removed
23-
EnvRemoved { key: Str, value: Str },
24-
/// Environment variable value changed
25-
EnvValueChanged { key: Str, old_value: Str, new_value: Str },
19+
/// A fingerprinted env var was added, removed, or changed value.
20+
Env(EnvMismatch),
2621

2722
// Untracked env config changes
2823
/// Untracked env pattern added
@@ -46,15 +41,7 @@ pub enum SpawnFingerprintChange {
4641
/// Used by both the live cache status display and the persisted summary rendering.
4742
pub fn format_spawn_change(change: &SpawnFingerprintChange) -> Str {
4843
match change {
49-
SpawnFingerprintChange::EnvAdded { key, value } => {
50-
vite_str::format!("env {key}={value} added")
51-
}
52-
SpawnFingerprintChange::EnvRemoved { key, value } => {
53-
vite_str::format!("env {key}={value} removed")
54-
}
55-
SpawnFingerprintChange::EnvValueChanged { key, old_value, new_value } => {
56-
vite_str::format!("env {key} value changed from '{old_value}' to '{new_value}'")
57-
}
44+
SpawnFingerprintChange::Env(mismatch) => vite_str::format!("{mismatch}"),
5845
SpawnFingerprintChange::UntrackedEnvAdded { name } => {
5946
vite_str::format!("untracked env '{name}' added")
6047
}
@@ -80,27 +67,27 @@ pub fn detect_spawn_fingerprint_changes(
8067
for (key, old_value) in &old_env.fingerprinted_envs {
8168
if let Some(new_value) = new_env.fingerprinted_envs.get(key) {
8269
if old_value != new_value {
83-
changes.push(SpawnFingerprintChange::EnvValueChanged {
84-
key: key.clone(),
70+
changes.push(SpawnFingerprintChange::Env(EnvMismatch::Changed {
71+
name: key.clone(),
8572
old_value: Str::from(old_value.as_ref()),
8673
new_value: Str::from(new_value.as_ref()),
87-
});
74+
}));
8875
}
8976
} else {
90-
changes.push(SpawnFingerprintChange::EnvRemoved {
91-
key: key.clone(),
77+
changes.push(SpawnFingerprintChange::Env(EnvMismatch::Removed {
78+
name: key.clone(),
9279
value: Str::from(old_value.as_ref()),
93-
});
80+
}));
9481
}
9582
}
9683

9784
// Check for added envs
9885
for (key, new_value) in &new_env.fingerprinted_envs {
9986
if !old_env.fingerprinted_envs.contains_key(key) {
100-
changes.push(SpawnFingerprintChange::EnvAdded {
101-
key: key.clone(),
87+
changes.push(SpawnFingerprintChange::Env(EnvMismatch::Added {
88+
name: key.clone(),
10289
value: Str::from(new_value.as_ref()),
103-
});
90+
}));
10491
}
10592
}
10693

@@ -158,11 +145,7 @@ pub fn format_cache_status_inline(cache_status: &CacheStatus) -> Option<Str> {
158145
FingerprintMismatch::SpawnFingerprint { old, new } => {
159146
let changes = detect_spawn_fingerprint_changes(old, new);
160147
match changes.first() {
161-
Some(
162-
SpawnFingerprintChange::EnvAdded { .. }
163-
| SpawnFingerprintChange::EnvRemoved { .. }
164-
| SpawnFingerprintChange::EnvValueChanged { .. },
165-
) => "envs changed",
148+
Some(SpawnFingerprintChange::Env(_)) => "envs changed",
166149
Some(
167150
SpawnFingerprintChange::UntrackedEnvAdded { .. }
168151
| SpawnFingerprintChange::UntrackedEnvRemoved { .. },

crates/vite_task/src/session/cache/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,34 @@ pub enum InputChangeKind {
139139
Removed,
140140
}
141141

142+
/// A single env var difference between a stored fingerprint and the current
143+
/// environment.
144+
///
145+
/// The canonical shape for an env change wherever one is detected and
146+
/// reported. The [`Display`] impl is the single source of the user-facing
147+
/// wording.
148+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
149+
pub enum EnvMismatch {
150+
/// Set now, but absent from the stored fingerprint.
151+
Added { name: Str, value: Str },
152+
/// In the stored fingerprint, but unset now.
153+
Removed { name: Str, value: Str },
154+
/// Present on both sides with different values.
155+
Changed { name: Str, old_value: Str, new_value: Str },
156+
}
157+
158+
impl Display for EnvMismatch {
159+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160+
match self {
161+
Self::Added { name, value } => write!(f, "env {name}={value} added"),
162+
Self::Removed { name, value } => write!(f, "env {name}={value} removed"),
163+
Self::Changed { name, old_value, new_value } => {
164+
write!(f, "env {name} value changed from '{old_value}' to '{new_value}'")
165+
}
166+
}
167+
}
168+
}
169+
142170
#[derive(Debug, Clone, Serialize, Deserialize)]
143171
pub enum FingerprintMismatch {
144172
/// Found a previous cache entry key for the same task, but the spawn fingerprint differs.

0 commit comments

Comments
 (0)