Only list changed plan settings in summary (#333)

* Only list changed plan settings in summary

* List all settings when `--explain`ing

* Sort the settings output
This commit is contained in:
Cole Helbling 2023-03-13 13:30:04 -07:00 committed by GitHub
parent c6abf95f02
commit 1861d48d59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 138 additions and 32 deletions

View file

@ -137,12 +137,31 @@ impl Planner for MyPlanner {
Ok(map) Ok(map)
} }
async fn configured_settings(
&self,
) -> Result<HashMap<String, serde_json::Value>, PlannerError> {
let default = Self::default().await?.settings()?;
let configured = self.settings()?;
let mut settings: HashMap<String, serde_json::Value> = HashMap::new();
for (key, value) in configured.iter() {
if default.get(key) != Some(value) {
settings.insert(key.clone(), value.clone());
}
}
Ok(settings)
}
#[cfg(feature = "diagnostics")] #[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<nix_installer::diagnostics::DiagnosticData, PlannerError> { async fn diagnostic_data(&self) -> Result<nix_installer::diagnostics::DiagnosticData, PlannerError> {
Ok(nix_installer::diagnostics::DiagnosticData::new( Ok(nix_installer::diagnostics::DiagnosticData::new(
self.common.diagnostic_endpoint.clone(), self.common.diagnostic_endpoint.clone(),
self.typetag_name().into(), self.typetag_name().into(),
self.configured_settings().await?, self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
)) ))
} }
} }

View file

@ -158,6 +158,7 @@ impl CommandExecute for Install {
match interaction::prompt( match interaction::prompt(
install_plan install_plan
.describe_install(currently_explaining) .describe_install(currently_explaining)
.await
.map_err(|e| eyre!(e))?, .map_err(|e| eyre!(e))?,
PromptChoice::Yes, PromptChoice::Yes,
currently_explaining, currently_explaining,

View file

@ -65,34 +65,55 @@ impl InstallPlan {
}) })
} }
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub fn describe_install(&self, explain: bool) -> Result<String, NixInstallerError> { pub async fn describe_install(&self, explain: bool) -> Result<String, NixInstallerError> {
let Self { let Self {
planner, planner,
actions, actions,
version, version,
.. ..
} = self; } = self;
let plan_settings = if explain {
// List all settings when explaining
planner.settings()?
} else {
// Otherwise, only list user-configured settings
planner.configured_settings().await?
};
let mut plan_settings = plan_settings
.into_iter()
.map(|(k, v)| format!("* {k}: {v}", k = k.bold()))
.collect::<Vec<_>>();
// Stabilize output order
plan_settings.sort();
let buf = format!( let buf = format!(
"\ "\
Nix install plan (v{version})\n\ Nix install plan (v{version})\n\
\n\ \n\
Planner: {planner}\n\ Planner: {planner}\n\
\n\ \n\
Planner settings:\n\ {maybe_plan_settings}\
\n\ \
{plan_settings}\n\
\n\
The following actions will be taken:\n\ The following actions will be taken:\n\
\n\ \n\
{actions}\n\ {actions}\n\
", ",
planner = planner.typetag_name(), planner = planner.typetag_name(),
plan_settings = planner maybe_plan_settings = if plan_settings.is_empty() {
.settings()? String::new()
.into_iter() } else {
.map(|(k, v)| format!("* {k}: {v}", k = k.bold())) // TODO: "Changed planner settings"?
.collect::<Vec<_>>() format!(
.join("\n"), "\
Planner settings:\n\
\n\
{plan_settings}\n\
\n\
",
plan_settings = plan_settings.join("\n")
)
},
actions = actions actions = actions
.iter() .iter()
.map(|v| v.describe_execute()) .map(|v| v.describe_execute())

View file

@ -105,12 +105,31 @@ impl Planner for Linux {
Ok(map) Ok(map)
} }
async fn configured_settings(
&self,
) -> Result<HashMap<String, serde_json::Value>, PlannerError> {
let default = Self::default().await?.settings()?;
let configured = self.settings()?;
let mut settings: HashMap<String, serde_json::Value> = HashMap::new();
for (key, value) in configured.iter() {
if default.get(key) != Some(value) {
settings.insert(key.clone(), value.clone());
}
}
Ok(settings)
}
#[cfg(feature = "diagnostics")] #[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> { async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> {
Ok(crate::diagnostics::DiagnosticData::new( Ok(crate::diagnostics::DiagnosticData::new(
self.settings.diagnostic_endpoint.clone(), self.settings.diagnostic_endpoint.clone(),
self.typetag_name().into(), self.typetag_name().into(),
self.configured_settings().await?, self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
)) ))
} }
} }

View file

@ -175,12 +175,31 @@ impl Planner for Macos {
Ok(map) Ok(map)
} }
async fn configured_settings(
&self,
) -> Result<HashMap<String, serde_json::Value>, PlannerError> {
let default = Self::default().await?.settings()?;
let configured = self.settings()?;
let mut settings: HashMap<String, serde_json::Value> = HashMap::new();
for (key, value) in configured.iter() {
if default.get(key) != Some(value) {
settings.insert(key.clone(), value.clone());
}
}
Ok(settings)
}
#[cfg(feature = "diagnostics")] #[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> { async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> {
Ok(crate::diagnostics::DiagnosticData::new( Ok(crate::diagnostics::DiagnosticData::new(
self.settings.diagnostic_endpoint.clone(), self.settings.diagnostic_endpoint.clone(),
self.typetag_name().into(), self.typetag_name().into(),
self.configured_settings().await?, self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
)) ))
} }
} }

View file

@ -53,12 +53,31 @@ impl Planner for MyPlanner {
Ok(map) Ok(map)
} }
async fn configured_settings(
&self,
) -> Result<HashMap<String, serde_json::Value>, PlannerError> {
let default = Self::default().await?.settings()?;
let configured = self.settings()?;
let mut settings: HashMap<String, serde_json::Value> = HashMap::new();
for (key, value) in configured.iter() {
if default.get(key) != Some(value) {
settings.insert(key.clone(), value.clone());
}
}
Ok(settings)
}
#[cfg(feature = "diagnostics")] #[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<nix_installer::diagnostics::DiagnosticData, PlannerError> { async fn diagnostic_data(&self) -> Result<nix_installer::diagnostics::DiagnosticData, PlannerError> {
Ok(nix_installer::diagnostics::DiagnosticData::new( Ok(nix_installer::diagnostics::DiagnosticData::new(
self.common.diagnostic_endpoint.clone(), self.common.diagnostic_endpoint.clone(),
self.typetag_name().into(), self.typetag_name().into(),
self.configured_settings().await?, self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
)) ))
} }
} }
@ -111,21 +130,8 @@ pub trait Planner: std::fmt::Debug + Send + Sync + dyn_clone::DynClone {
/// The settings being used by the planner /// The settings being used by the planner
fn settings(&self) -> Result<HashMap<String, serde_json::Value>, InstallSettingsError>; fn settings(&self) -> Result<HashMap<String, serde_json::Value>, InstallSettingsError>;
async fn configured_settings(&self) -> Result<Vec<String>, PlannerError> async fn configured_settings(&self)
where -> Result<HashMap<String, serde_json::Value>, PlannerError>;
Self: Sized,
{
let default = Self::default().await?.settings()?;
let configured = self.settings()?;
let mut keys: Vec<String> = Vec::new();
for (key, value) in configured.iter() {
if default.get(key) != Some(value) {
keys.push(key.clone())
}
}
Ok(keys)
}
/// A boxed, type erased planner /// A boxed, type erased planner
fn boxed(self) -> Box<dyn Planner> fn boxed(self) -> Box<dyn Planner>
@ -200,7 +206,9 @@ impl BuiltinPlanner {
Ok(built) Ok(built)
} }
pub async fn configured_settings(&self) -> Result<Vec<String>, PlannerError> { pub async fn configured_settings(
&self,
) -> Result<HashMap<String, serde_json::Value>, PlannerError> {
match self { match self {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
BuiltinPlanner::Linux(inner) => inner.configured_settings().await, BuiltinPlanner::Linux(inner) => inner.configured_settings().await,

View file

@ -257,12 +257,31 @@ impl Planner for SteamDeck {
Ok(map) Ok(map)
} }
async fn configured_settings(
&self,
) -> Result<HashMap<String, serde_json::Value>, PlannerError> {
let default = Self::default().await?.settings()?;
let configured = self.settings()?;
let mut settings: HashMap<String, serde_json::Value> = HashMap::new();
for (key, value) in configured.iter() {
if default.get(key) != Some(value) {
settings.insert(key.clone(), value.clone());
}
}
Ok(settings)
}
#[cfg(feature = "diagnostics")] #[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> { async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> {
Ok(crate::diagnostics::DiagnosticData::new( Ok(crate::diagnostics::DiagnosticData::new(
self.settings.diagnostic_endpoint.clone(), self.settings.diagnostic_endpoint.clone(),
self.typetag_name().into(), self.typetag_name().into(),
self.configured_settings().await?, self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
)) ))
} }
} }