config: prompt user for flakes

This commit is contained in:
Kate Temkin 2024-05-05 16:48:16 -06:00
parent 83960c7814
commit 7c36a83a86
9 changed files with 83 additions and 8 deletions

View file

@ -37,7 +37,7 @@ impl CreateGroup {
}, },
} }
// Ensure group does not exists // Ensure group does not exist
if let Some(group) = Group::from_name(name.as_str()) if let Some(group) = Group::from_name(name.as_str())
.map_err(|e| ActionErrorKind::GettingGroupId(name.clone(), e)) .map_err(|e| ActionErrorKind::GettingGroupId(name.clone(), e))
.map_err(Self::error)? .map_err(Self::error)?

View file

@ -17,7 +17,7 @@ use crate::action::{
/// The `nix.conf` configuration names that are safe to merge. /// The `nix.conf` configuration names that are safe to merge.
// FIXME(@cole-h): make configurable by downstream users? // FIXME(@cole-h): make configurable by downstream users?
const MERGEABLE_CONF_NAMES: &[&str] = &["experimental-features"]; const MERGEABLE_CONF_NAMES: &[&str] = &["experimental-features", "substituters", "trusted-public-keys"];
const NIX_CONF_MODE: u32 = 0o664; const NIX_CONF_MODE: u32 = 0o664;
const NIX_CONF_COMMENT_CHAR: char = '#'; const NIX_CONF_COMMENT_CHAR: char = '#';

View file

@ -46,6 +46,7 @@ impl ConfigureNix {
settings.proxy.clone(), settings.proxy.clone(),
settings.ssl_cert_file.clone(), settings.ssl_cert_file.clone(),
settings.extra_conf.clone(), settings.extra_conf.clone(),
settings.enable_flakes,
settings.force, settings.force,
) )
.await .await

View file

@ -30,6 +30,7 @@ impl PlaceNixConfiguration {
proxy: Option<Url>, proxy: Option<Url>,
ssl_cert_file: Option<PathBuf>, ssl_cert_file: Option<PathBuf>,
extra_conf: Vec<UrlOrPathOrString>, extra_conf: Vec<UrlOrPathOrString>,
enable_flakes: bool,
force: bool, force: bool,
) -> Result<StatefulAction<Self>, ActionError> { ) -> Result<StatefulAction<Self>, ActionError> {
let mut extra_conf_text = vec![]; let mut extra_conf_text = vec![];
@ -91,7 +92,13 @@ impl PlaceNixConfiguration {
let settings = nix_config.settings_mut(); let settings = nix_config.settings_mut();
settings.insert("build-users-group".to_string(), nix_build_group_name); settings.insert("build-users-group".to_string(), nix_build_group_name);
let experimental_features = ["nix-command", "flakes", "repl-flake"]; let mut experimental_features = vec!["nix-command"];
// Enable flakes if desired.
if enable_flakes {
experimental_features.push("flakes");
}
match settings.entry("experimental-features".to_string()) { match settings.entry("experimental-features".to_string()) {
Entry::Occupied(mut slot) => { Entry::Occupied(mut slot) => {
let slot_mut = slot.get_mut(); let slot_mut = slot.get_mut();
@ -125,10 +132,24 @@ impl PlaceNixConfiguration {
ssl_cert_file_canonical.display().to_string(), ssl_cert_file_canonical.display().to_string(),
); );
} }
// Set up our substituters.
settings.insert(
"substituters".to_string(),
"https://cache.nixos.org https://cache.lix.systems".to_string(),
);
settings.insert(
"trusted-public-keys".to_string(),
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o=".to_string()
);
if enable_flakes {
settings.insert( settings.insert(
"extra-nix-path".to_string(), "extra-nix-path".to_string(),
"nixpkgs=flake:nixpkgs".to_string(), "nixpkgs=flake:nixpkgs".to_string(),
); );
}
let create_directory = CreateDirectory::plan(NIX_CONF_FOLDER, None, None, 0o0755, force) let create_directory = CreateDirectory::plan(NIX_CONF_FOLDER, None, None, 0o0755, force)
.await .await
.map_err(Self::error)?; .map_err(Self::error)?;

View file

@ -16,6 +16,7 @@ pub enum PromptChoice {
// The below method was adopted from Rustup at https://github.com/rust-lang/rustup/blob/3331f34c01474bf216c99a1b1706725708833de1/src/cli/term2.rs#L37 // The below method was adopted from Rustup at https://github.com/rust-lang/rustup/blob/3331f34c01474bf216c99a1b1706725708833de1/src/cli/term2.rs#L37
pub(crate) async fn prompt( pub(crate) async fn prompt(
question: impl AsRef<str>, question: impl AsRef<str>,
prompt_text: impl AsRef<str>,
default: PromptChoice, default: PromptChoice,
currently_explaining: bool, currently_explaining: bool,
) -> eyre::Result<PromptChoice> { ) -> eyre::Result<PromptChoice> {
@ -29,7 +30,7 @@ pub(crate) async fn prompt(
{are_you_sure} ({yes}/{no}{maybe_explain}): \ {are_you_sure} ({yes}/{no}{maybe_explain}): \
", ",
question = question.as_ref(), question = question.as_ref(),
are_you_sure = "Proceed?".bold(), are_you_sure = prompt_text.as_ref().bold(),
no = if default == PromptChoice::No { no = if default == PromptChoice::No {
"[N]o" "[N]o"
} else { } else {

View file

@ -92,7 +92,7 @@ pub fn ensure_root() -> eyre::Result<()> {
if !is_root() { if !is_root() {
eprintln!( eprintln!(
"{}", "{}",
"`nix-installer` needs to run as `root`, attempting to escalate now via `sudo`..." "`lix-installer` needs to run as `root`, attempting to escalate now via `sudo`..."
.yellow() .yellow()
.dimmed() .dimmed()
); );

View file

@ -170,7 +170,39 @@ impl CommandExecute for Install {
serde_json::from_str(&install_plan_string)? serde_json::from_str(&install_plan_string)?
}, },
(None, None) => { (None, None) => {
let builtin_planner = BuiltinPlanner::from_common_settings(settings.clone()) let mut settings_to_apply = settings.clone();
if !no_confirm {
// Say hello.
let mut term = term.expect("Internal consistency: term should have been None checked already!");
let hello_message = format!("{}{}", "\n\nWelcome to the Lix installer!".bold(), " Just a couple of quick questions.\n\n");
term.write_all(hello_message.as_bytes())?;
term.flush()?;
// Ask about flakes.
match interaction::prompt(
"Flakes are an experimental feature, but widely used in the community.\nYou can change this later in `/etc/nix/nix.conf`.",
"Enable flakes?",
PromptChoice::Yes,
true,
)
.await?
{
PromptChoice::Yes => settings_to_apply.enable_flakes = true,
PromptChoice::Explain => panic!("This prompt has no explanation."),
PromptChoice::No => settings_to_apply.enable_flakes = false,
}
// Notify the user about the nix command.
let nixcmd_message = format!("{}{}{}{}{}",
"\nQUICK NOTE:".bold().yellow(), " we've enabled the experimental", " nix ".bold(), "command for you!\n",
"Be aware that commands starting with `nix ` such as `nix build` may change syntax.\n\n".green());
term.write_all(nixcmd_message.as_bytes())?;
term.flush()?;
}
let builtin_planner = BuiltinPlanner::from_common_settings(settings_to_apply)
.await .await
.map_err(|e| eyre::eyre!(e))?; .map_err(|e| eyre::eyre!(e))?;
@ -236,6 +268,7 @@ impl CommandExecute for Install {
.describe_install(currently_explaining) .describe_install(currently_explaining)
.await .await
.map_err(|e| eyre!(e))?, .map_err(|e| eyre!(e))?,
"Proceed?",
PromptChoice::Yes, PromptChoice::Yes,
currently_explaining, currently_explaining,
) )
@ -276,6 +309,7 @@ impl CommandExecute for Install {
.describe_uninstall(currently_explaining) .describe_uninstall(currently_explaining)
.await .await
.map_err(|e| eyre!(e))?, .map_err(|e| eyre!(e))?,
"Proceed?",
PromptChoice::Yes, PromptChoice::Yes,
currently_explaining, currently_explaining,
) )

View file

@ -169,6 +169,7 @@ impl CommandExecute for Uninstall {
plan.describe_uninstall(currently_explaining) plan.describe_uninstall(currently_explaining)
.await .await
.map_err(|e| eyre!(e))?, .map_err(|e| eyre!(e))?,
"Proceed?",
PromptChoice::Yes, PromptChoice::Yes,
currently_explaining, currently_explaining,
) )

View file

@ -203,6 +203,20 @@ pub struct CommonSettings {
) )
)] )]
pub force: bool, pub force: bool,
/// If `nix-installer` should enable flakes.
#[cfg_attr(
feature = "cli",
clap(
long,
action(ArgAction::SetFalse),
default_value = "true",
global = true,
env = "NIX_INSTALLER_ENABLE_FLAKES"
)
)]
pub enable_flakes: bool,
} }
impl CommonSettings { impl CommonSettings {
@ -270,6 +284,7 @@ impl CommonSettings {
proxy: Default::default(), proxy: Default::default(),
extra_conf: Default::default(), extra_conf: Default::default(),
force: false, force: false,
enable_flakes: true,
ssl_cert_file: Default::default(), ssl_cert_file: Default::default(),
}) })
} }
@ -287,6 +302,7 @@ impl CommonSettings {
proxy, proxy,
extra_conf, extra_conf,
force, force,
enable_flakes,
ssl_cert_file, ssl_cert_file,
} = self; } = self;
let mut map = HashMap::default(); let mut map = HashMap::default();
@ -322,6 +338,7 @@ impl CommonSettings {
map.insert("proxy".into(), serde_json::to_value(proxy)?); map.insert("proxy".into(), serde_json::to_value(proxy)?);
map.insert("ssl_cert_file".into(), serde_json::to_value(ssl_cert_file)?); map.insert("ssl_cert_file".into(), serde_json::to_value(ssl_cert_file)?);
map.insert("extra_conf".into(), serde_json::to_value(extra_conf)?); map.insert("extra_conf".into(), serde_json::to_value(extra_conf)?);
map.insert("enable_flakes".into(), serde_json::to_value(enable_flakes)?);
map.insert("force".into(), serde_json::to_value(force)?); map.insert("force".into(), serde_json::to_value(force)?);
Ok(map) Ok(map)
} }