Skip to content

Commit 7005f50

Browse files
committed
feat(cli): allow explicit extension names to override --baseline exclusion
When --extensions combines "all" with specific names (e.g. --extensions all,GL_ARB_texture_compression), the named extensions are treated as keep-alive pins that survive --baseline exclusion. New `keep` field on ExtensionFilter captures names listed alongside "all". The resolver checks this set before applying baseline exclusion. The `-` prefix exclusion remains unconditional and overrides keep. Precedence: -Foo (always excluded) > Foo (keep, survives baseline) > baseline (excluded unless kept). Signed-off-by: Steven Noonan <steven@uplinklabs.net>
1 parent 2ccfec7 commit 7005f50

2 files changed

Lines changed: 44 additions & 5 deletions

File tree

src/cli.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,18 @@ impl Cli {
138138
}
139139
}
140140

141-
let include = if include_all { None } else { Some(includes) };
141+
// When "all" is combined with explicit names, the explicit names act as
142+
// baseline-override pins — they survive --baseline exclusion even though
143+
// "all" means we don't use them for initial inclusion filtering.
144+
let (include, keep) = if include_all {
145+
(None, includes.into_iter().collect())
146+
} else {
147+
(Some(includes), HashSet::new())
148+
};
142149
Ok(ExtensionFilter {
143150
include,
144151
exclude: excludes,
152+
keep,
145153
})
146154
}
147155

@@ -166,10 +174,14 @@ impl Cli {
166174
/// `exclude` is always a set of names to unconditionally remove — applied as a
167175
/// final veto after all selection passes (explicit, dependency, promoted,
168176
/// predecessor, baseline).
177+
/// `keep` is a set of names that override baseline exclusion — used when the
178+
/// user writes `--extensions all,GL_ARB_foo` to pin specific extensions even
179+
/// if they'd otherwise be excluded by --baseline.
169180
#[derive(Debug)]
170181
pub struct ExtensionFilter {
171182
pub include: Option<Vec<String>>,
172183
pub exclude: HashSet<String>,
184+
pub keep: HashSet<String>,
173185
}
174186

175187
impl ExtensionFilter {
@@ -178,6 +190,7 @@ impl ExtensionFilter {
178190
Self {
179191
include: None,
180192
exclude: HashSet::new(),
193+
keep: HashSet::new(),
181194
}
182195
}
183196
}

src/resolve.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,14 +1134,40 @@ fn select_extensions<'a>(
11341134
}
11351135

11361136
// Build unified exclude set and apply.
1137-
let has_excludes = !explicit_excludes.is_empty() || !baseline_excludes.is_empty();
1138-
if has_excludes {
1137+
// Explicit includes override baseline exclusion — if you name an extension
1138+
// in --extensions (either as the sole include list, or alongside "all" as
1139+
// a keep-alive pin), you want it even if it's promoted into baseline.
1140+
// The `-` prefix exclusion is unconditional and overrides everything.
1141+
let explicit_keeps: HashSet<&str> = {
1142+
let mut keeps: HashSet<&str> = filter.keep.iter().map(String::as_str).collect();
1143+
// When include is Some (explicit list, no "all"), every listed name
1144+
// is an explicit request that should survive baseline exclusion.
1145+
if let Some(ref list) = filter.include {
1146+
keeps.extend(list.iter().map(String::as_str));
1147+
}
1148+
keeps
1149+
};
1150+
1151+
if !explicit_excludes.is_empty() || !baseline_excludes.is_empty() {
11391152
selected.retain(|e| {
1140-
!explicit_excludes.contains(e.raw.name.as_str())
1141-
&& !baseline_excludes.contains(&e.raw.name)
1153+
let name = e.raw.name.as_str();
1154+
// `-` prefix exclusions are unconditional.
1155+
if explicit_excludes.contains(name) {
1156+
return false;
1157+
}
1158+
// Baseline exclusions can be overridden by explicit inclusion.
1159+
if baseline_excludes.contains(&e.raw.name) && !explicit_keeps.contains(name) {
1160+
return false;
1161+
}
1162+
true
11421163
});
11431164
}
11441165

1166+
// Remove kept extensions from baseline_excludes for accurate reporting.
1167+
if !explicit_keeps.is_empty() {
1168+
baseline_excludes.retain(|name| !explicit_keeps.contains(name.as_str()));
1169+
}
1170+
11451171
// Collect the names that were actually excluded (intersection of what was
11461172
// selected before the veto with the exclude sets).
11471173
let excluded_explicit: Vec<String> = filter.exclude.iter().cloned().collect();

0 commit comments

Comments
 (0)