config/loader: drop ensure_location_supersets

Summary:
The config validation logic was migrated to Chef in D56651559.
Remove this function to unblock config layout refactoring.

Reviewed By: muirdm

Differential Revision: D56592494

fbshipit-source-id: 04a6a6f5bf4da7131f8aab45909467c8d74b5d1c
This commit is contained in:
Jun Wu 2024-04-29 13:21:09 -07:00 committed by Facebook GitHub Bot
parent d49f558773
commit 44ebe2309c
4 changed files with 1 additions and 238 deletions

View File

@ -10,7 +10,6 @@
//! Use `staticconfig::static_config!` to define static configs so they do not
//! have runtime parsing or hashmap insertion overhead.
use std::path::Path;
use std::sync::Arc;
use configmodel::Config;

View File

@ -90,8 +90,6 @@ pub trait ConfigSetHgExt {
/// Load a specified config file. Respect HGPLAIN environment variables.
/// Return errors parsing files.
fn load_hgrc(&mut self, path: impl AsRef<Path>, source: &'static str) -> Vec<Error>;
fn validate_dynamic(&mut self) -> Result<(), Error>;
}
/// Load config from specified "minimal repo", or global config if no path specified.
@ -389,7 +387,7 @@ impl ConfigSetHgExt for ConfigSet {
return Err(Errors(errors));
}
self.validate_dynamic().map_err(|err| Errors(vec![err]))
Ok(())
}
fn load_system(&mut self, opts: Options, ident: &Identity) -> Vec<Error> {
@ -630,31 +628,6 @@ impl ConfigSetHgExt for ConfigSet {
let opts = Options::new().source(source).process_hgplain();
self.load_path(path, &opts)
}
#[cfg(feature = "fb")]
fn validate_dynamic(&mut self) -> Result<(), Error> {
let allowed_locations: Option<Vec<String>> =
self.get_opt::<Vec<String>>("configs", "allowedlocations")?;
let allowed_configs: Option<Vec<String>> =
self.get_opt::<Vec<String>>("configs", "allowedconfigs")?;
Ok(self.ensure_location_supersets(
allowed_locations
.as_ref()
.map(|v| HashSet::from_iter(v.iter().map(|s| s.as_str()))),
allowed_configs.as_ref().map(|v| {
HashSet::from_iter(v.iter().map(|s| {
s.split_once('.')
.expect("allowed configs must contain dots")
}))
}),
))
}
#[cfg(not(feature = "fb"))]
fn validate_dynamic(&mut self) -> Result<(), Error> {
Ok(())
}
}
/// Read repo name from various places (remotefilelog.reponame, paths.default, .hg/reponame).

View File

@ -544,88 +544,6 @@ impl ConfigSet {
}
}
/// Drop configs from sources that are outside `allowed_locations` or
/// `allowed_configs`.
///
/// This function is being removed but we need logging to understand its
/// side-effect.
pub fn ensure_location_supersets(
&mut self,
allowed_locations: Option<HashSet<&str>>,
allowed_configs: Option<HashSet<(&str, &str)>>,
) {
for (sname, section) in self.sections.iter_mut() {
for (kname, values) in section.items.iter_mut() {
let values_copy = values.clone();
let mut removals = 0;
// value with a larger index takes precedence.
for (index, value) in values_copy.iter().enumerate() {
// Convert the index into the original index.
let index = index - removals;
// Get the filename of the value's rc location
let path: PathBuf = match value.location() {
None => continue,
Some((path, _)) => path,
};
let location: Option<String> = path
.file_name()
.and_then(|f| f.to_str())
.map(|s| s.to_string());
// If only certain locations are allowed, and this isn't one of them, remove
// it. If location is None, it came from inmemory, so don't filter it.
if let Some(location) = location {
if crate::builtin::get(location.as_str()).is_none()
&& allowed_locations
.as_ref()
.map(|a| a.contains(location.as_str()))
== Some(false)
&& allowed_configs
.as_ref()
.map(|a| a.contains(&(sname, kname)))
!= Some(true)
{
tracing::trace!(
target: "configset::validate",
"dropping {}.{} set by {} ({})",
sname.as_ref(),
kname.as_ref(),
path.display().to_string(),
value
.value()
.as_ref()
.map(|v| v.as_ref())
.unwrap_or_default(),
);
values.remove(index);
removals += 1;
continue;
}
}
}
// If the removal changes the config, log it as mismatched.
if let (Some(before_remove), Some(after_remove)) =
(values_copy.last(), values.last())
{
if before_remove.value != after_remove.value {
let source = match before_remove.location() {
None => before_remove.source().to_string(),
Some(l) => l.0.display().to_string(),
};
tracing::info!(
target: "config_mismatch",
config=&format!("{sname}.{kname}"),
expected=after_remove.value.clone().unwrap_or_default().as_ref(),
actual=before_remove.value.clone().unwrap_or_default().as_ref(),
source=source,
);
}
}
}
}
}
pub fn clear_unpinned(&mut self) {
self.sections.clear();
self.secondary = None;
@ -1161,61 +1079,6 @@ space_list=value1.a value1.b
assert_eq!(cfg.sections(), cfg2.sections());
}
#[test]
fn test_allowed_locations() {
let mut cfg = ConfigSet::new();
fn set(
cfg: &mut ConfigSet,
section: &'static str,
key: &'static str,
value: &'static str,
location: &'static str,
) {
cfg.set_internal(
Text::from_static(section),
Text::from_static(key),
Some(Text::from_static(value)),
Some(ValueLocation {
path: Arc::new(Path::new(location).to_owned()),
content: Text::from_static(""),
location: 0..1,
}),
&Options::new()
.source(Text::from_static("source"))
.pin(false),
);
}
set(&mut cfg, "section1", "key1", "value1", "subset1");
set(&mut cfg, "section2", "key2", "value2", "subset2");
let mut allow_list = HashSet::new();
allow_list.insert("subset1");
cfg.ensure_location_supersets(Some(allow_list.clone()), None);
assert_eq!(
cfg.get("section1", "key1"),
Some(Text::from_static("value1"))
);
assert_eq!(cfg.get("section2", "key2"), None);
// Check that allow_configs allows the config through, even if allow_locations did not.
let mut allow_configs = HashSet::new();
allow_configs.insert(("section2", "key2"));
set(&mut cfg, "section2", "key2", "value2", "subset2");
cfg.ensure_location_supersets(Some(allow_list), Some(allow_configs));
assert_eq!(
cfg.get("section1", "key1"),
Some(Text::from_static("value1"))
);
assert_eq!(
cfg.get("section2", "key2"),
Some(Text::from_static("value2"))
);
}
#[test]
fn test_secondary() {
let mut cfg1 = ConfigSet::new();
@ -1277,41 +1140,6 @@ x = 2
);
}
#[test]
fn test_verifier_removal() {
let mut cfg = ConfigSet::new();
fn set(
cfg: &mut ConfigSet,
section: &'static str,
key: &'static str,
value: &'static str,
location: &'static str,
) {
cfg.set_internal(
Text::from_static(section),
Text::from_static(key),
Some(Text::from_static(value)),
Some(ValueLocation {
path: Arc::new(Path::new(location).to_owned()),
content: Text::from_static(""),
location: 0..1,
}),
&Options::new().source(Text::from_static("source")),
);
}
// This test verifies that allowed location removal and subset removal interact nicely
// together.
set(&mut cfg, "section", "key", "value", "subset");
set(&mut cfg, "section", "key", "value2", "super");
let mut allowed_locations = HashSet::new();
allowed_locations.insert("super");
cfg.ensure_location_supersets(Some(allowed_locations), None);
}
#[test]
fn test_get_or() {
let mut cfg = ConfigSet::new();

View File

@ -168,43 +168,6 @@ Verify we don't regenerate configs if the Mercurial version hasn't changed
$ hg config section3.key3
value3
Verify configs.allowedlocations limits config loading to the allowed locations
$ cat >> .hg/hgrc <<EOF
> %include hgrc1
> %include hgrc2
> %include hgrc3
> EOF
$ cat >> .hg/hgrc1 <<EOF
> [zz_section]
> key=foo
> [zz_other_section]
> other_key=other_foo
> EOF
$ cat >> .hg/hgrc2 <<EOF
> [zz_section]
> key=bar
> [zz_other_section]
> other_key=other_bar
> EOF
$ hg config --debug | grep ': zz_'
$TESTTMP/shared_copy/.hg/hgrc2:2: zz_section.key=bar
$TESTTMP/shared_copy/.hg/hgrc2:4: zz_other_section.other_key=other_bar
$ hg config --debug --config "configs.allowedlocations=hgrc1 .hgrc" | grep ': zz_'
$TESTTMP/shared_copy/.hg/hgrc1:2: zz_section.key=foo
$TESTTMP/shared_copy/.hg/hgrc1:4: zz_other_section.other_key=other_foo
$ hg config --debug --config "configs.allowedlocations=hgrc2 .hgrc" | grep ': zz_'
$TESTTMP/shared_copy/.hg/hgrc2:2: zz_section.key=bar
$TESTTMP/shared_copy/.hg/hgrc2:4: zz_other_section.other_key=other_bar
$ hg config --debug --config "configs.allowedlocations=hgrc3 .hgrc" | grep ': zz_'
[1]
$ hg config --debug --config "configs.allowedlocations=hgrc3 .hgrc" --config "configs.allowedconfigs=zz_section.key .hgrc" | grep 'zz_section\.'
--config: configs.allowedconfigs=zz_section.key .hgrc
$TESTTMP/shared_copy/.hg/hgrc2:2: zz_section.key=bar
Verify we load internalconfig during clone
$ cd $TESTTMP
$ export HG_TEST_INTERNALCONFIG="$TESTTMP/test_hgrc"