mirror of
https://github.com/openai/codex.git
synced 2026-10-21 17:48:44 +00:00
Fix shell filter override reporting
This commit is contained in:
@@ -616,6 +616,26 @@ fn value_at_path<'a>(root: &'a TomlValue, segments: &[String]) -> Option<&'a Tom
|
||||
Some(current)
|
||||
}
|
||||
|
||||
/// Looks up a path according to its config semantics.
|
||||
///
|
||||
/// Shell filter patterns compare case-insensitively and are normalized in the
|
||||
/// merged effective config, while raw layers preserve their original spelling.
|
||||
/// Match that path segment case-insensitively so equivalent raw and effective
|
||||
/// paths compare without changing ordinary TOML path semantics.
|
||||
fn value_at_semantic_path<'a>(root: &'a TomlValue, segments: &[String]) -> Option<&'a TomlValue> {
|
||||
let [policy, filters, pattern] = segments else {
|
||||
return value_at_path(root, segments);
|
||||
};
|
||||
if policy != "shell_environment_policy" || filters != "filters" {
|
||||
return value_at_path(root, segments);
|
||||
}
|
||||
|
||||
let filters = value_at_path(root, &segments[..2])?.as_table()?;
|
||||
filters
|
||||
.iter()
|
||||
.find_map(|(candidate, value)| candidate.eq_ignore_ascii_case(pattern).then_some(value))
|
||||
}
|
||||
|
||||
fn override_message(layer: &ConfigLayerSource) -> String {
|
||||
match layer {
|
||||
ConfigLayerSource::Mdm { domain, key: _ } => {
|
||||
@@ -653,10 +673,10 @@ fn compute_override_metadata(
|
||||
segments: &[String],
|
||||
) -> Option<OverriddenMetadata> {
|
||||
let user_value = match layers.get_active_user_layer() {
|
||||
Some(user_layer) => value_at_path(&user_layer.config, segments),
|
||||
Some(user_layer) => value_at_semantic_path(&user_layer.config, segments),
|
||||
None => return None,
|
||||
};
|
||||
let effective_value = value_at_path(effective, segments);
|
||||
let effective_value = value_at_semantic_path(effective, segments);
|
||||
|
||||
if user_value.is_some() && user_value == effective_value {
|
||||
return None;
|
||||
@@ -696,7 +716,9 @@ fn find_effective_layer(
|
||||
segments: &[String],
|
||||
) -> Option<ConfigLayerMetadata> {
|
||||
for layer in layers.layers_high_to_low() {
|
||||
if let Some(meta) = value_at_path(&layer.config, segments).map(|_| layer.metadata()) {
|
||||
if let Some(meta) =
|
||||
value_at_semantic_path(&layer.config, segments).map(|_| layer.metadata())
|
||||
{
|
||||
return Some(meta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -841,6 +841,68 @@ async fn write_value_reports_managed_override() {
|
||||
assert_eq!(overridden.effective_value, serde_json::json!("never"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn write_value_matches_shell_filter_paths_case_insensitively() -> Result<()> {
|
||||
let tmp = tempdir()?;
|
||||
let config_path = tmp.path().join(CONFIG_TOML_FILE);
|
||||
std::fs::write(&config_path, "")?;
|
||||
|
||||
let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());
|
||||
let result = service
|
||||
.write_value(ConfigValueWriteParams {
|
||||
file_path: Some(config_path.display().to_string()),
|
||||
key_path: "shell_environment_policy.filters.PATH".to_string(),
|
||||
value: serde_json::json!("include"),
|
||||
merge_strategy: MergeStrategy::Replace,
|
||||
expected_version: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
assert_eq!(result.status, WriteStatus::Ok);
|
||||
assert_eq!(result.overridden_metadata, None);
|
||||
assert!(std::fs::read_to_string(config_path)?.contains("PATH = \"include\""));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn write_value_reports_case_insensitive_shell_filter_override() -> Result<()> {
|
||||
let tmp = tempdir()?;
|
||||
let config_path = tmp.path().join(CONFIG_TOML_FILE);
|
||||
std::fs::write(&config_path, "")?;
|
||||
|
||||
let managed_path = tmp.path().join("managed_config.toml");
|
||||
std::fs::write(
|
||||
&managed_path,
|
||||
"[shell_environment_policy.filters]\npath = \"exclude\"\n",
|
||||
)?;
|
||||
let managed_file = AbsolutePathBuf::try_from(managed_path.clone())?;
|
||||
let service = ConfigManager::new_for_tests(
|
||||
tmp.path().to_path_buf(),
|
||||
vec![],
|
||||
LoaderOverrides::with_managed_config_path_for_tests(managed_path),
|
||||
CloudConfigBundleLoader::default(),
|
||||
);
|
||||
|
||||
let result = service
|
||||
.write_value(ConfigValueWriteParams {
|
||||
file_path: Some(config_path.display().to_string()),
|
||||
key_path: "shell_environment_policy.filters.PATH".to_string(),
|
||||
value: serde_json::json!("include"),
|
||||
merge_strategy: MergeStrategy::Replace,
|
||||
expected_version: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
assert_eq!(result.status, WriteStatus::OkOverridden);
|
||||
let overridden = result.overridden_metadata.expect("overridden metadata");
|
||||
assert_eq!(
|
||||
overridden.overriding_layer.name,
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromFile { file: managed_file }
|
||||
);
|
||||
assert_eq!(overridden.effective_value, serde_json::json!("exclude"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn upsert_merges_tables_replace_overwrites() -> Result<()> {
|
||||
let tmp = tempdir().expect("tempdir");
|
||||
|
||||
Reference in New Issue
Block a user