forked from lix-project/lix-installer
Make shell profile locations chosen by planner (#375)
* Make shell profile locations chosen by planner * Fix mac * Fix fixture
This commit is contained in:
parent
f2c94e3578
commit
4856cff7b6
|
@ -6,6 +6,7 @@ use crate::{
|
|||
common::{ConfigureShellProfile, PlaceNixConfiguration},
|
||||
Action, ActionDescription, ActionError, ActionTag, StatefulAction,
|
||||
},
|
||||
planner::ShellProfileLocations,
|
||||
settings::{CommonSettings, SCRATCH_DIR},
|
||||
};
|
||||
|
||||
|
@ -23,18 +24,24 @@ pub struct ConfigureNix {
|
|||
|
||||
impl ConfigureNix {
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn plan(settings: &CommonSettings) -> Result<StatefulAction<Self>, ActionError> {
|
||||
pub async fn plan(
|
||||
shell_profile_locations: ShellProfileLocations,
|
||||
settings: &CommonSettings,
|
||||
) -> Result<StatefulAction<Self>, ActionError> {
|
||||
let setup_default_profile = SetupDefaultProfile::plan(PathBuf::from(SCRATCH_DIR))
|
||||
.await
|
||||
.map_err(|e| ActionError::Child(SetupDefaultProfile::action_tag(), Box::new(e)))?;
|
||||
|
||||
let configure_shell_profile = if settings.modify_profile {
|
||||
Some(
|
||||
ConfigureShellProfile::plan(settings.ssl_cert_file.clone())
|
||||
.await
|
||||
.map_err(|e| {
|
||||
ActionError::Child(ConfigureShellProfile::action_tag(), Box::new(e))
|
||||
})?,
|
||||
ConfigureShellProfile::plan(
|
||||
shell_profile_locations,
|
||||
settings.ssl_cert_file.clone(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
ActionError::Child(ConfigureShellProfile::action_tag(), Box::new(e))
|
||||
})?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -1,43 +1,12 @@
|
|||
use crate::action::base::{create_or_insert_into_file, CreateDirectory, CreateOrInsertIntoFile};
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionTag, StatefulAction};
|
||||
use crate::planner::ShellProfileLocations;
|
||||
|
||||
use nix::unistd::User;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tokio::task::JoinSet;
|
||||
use tracing::{span, Instrument, Span};
|
||||
|
||||
// Fish has different syntax than zsh/bash, treat it separate
|
||||
const PROFILE_FISH_VENDOR_CONFD_SUFFIX: &str = "vendor_conf.d/nix.fish";
|
||||
/**
|
||||
Each of these are common values of $__fish_vendor_confdir,
|
||||
under which Fish will look for a file named
|
||||
[`PROFILE_FISH_CONFD_SUFFIX`].
|
||||
|
||||
More info: https://fishshell.com/docs/3.3/index.html#configuration-files
|
||||
*/
|
||||
const PROFILE_FISH_VENDOR_CONFD_PREFIXES: &[&str] = &["/usr/share/fish/", "/usr/local/share/fish/"];
|
||||
|
||||
const PROFILE_FISH_CONFD_SUFFIX: &str = "conf.d/nix.fish";
|
||||
/**
|
||||
Each of these are common values of $__fish_sysconf_dir,
|
||||
under which Fish will look for a file named
|
||||
[`PROFILE_FISH_CONFD_PREFIXES`].
|
||||
*/
|
||||
const PROFILE_FISH_CONFD_PREFIXES: &[&str] = &[
|
||||
"/etc/fish", // standard
|
||||
"/usr/local/etc/fish", // their installer .pkg for macOS
|
||||
"/opt/homebrew/etc/fish", // homebrew
|
||||
"/opt/local/etc/fish", // macports
|
||||
];
|
||||
|
||||
const PROFILE_TARGETS: &[&str] = &[
|
||||
"/etc/bashrc",
|
||||
"/etc/profile.d/nix.sh",
|
||||
"/etc/bash.bashrc",
|
||||
// https://zsh.sourceforge.io/Intro/intro_3.html
|
||||
"/etc/zshrc",
|
||||
"/etc/zsh/zshrc",
|
||||
];
|
||||
const PROFILE_NIX_FILE_SHELL: &str = "/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh";
|
||||
const PROFILE_NIX_FILE_FISH: &str = "/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.fish";
|
||||
|
||||
|
@ -46,13 +15,17 @@ Configure any detected shell profiles to include Nix support
|
|||
*/
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct ConfigureShellProfile {
|
||||
locations: ShellProfileLocations,
|
||||
create_directories: Vec<StatefulAction<CreateDirectory>>,
|
||||
create_or_insert_into_files: Vec<StatefulAction<CreateOrInsertIntoFile>>,
|
||||
}
|
||||
|
||||
impl ConfigureShellProfile {
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn plan(ssl_cert_file: Option<PathBuf>) -> Result<StatefulAction<Self>, ActionError> {
|
||||
pub async fn plan(
|
||||
locations: ShellProfileLocations,
|
||||
ssl_cert_file: Option<PathBuf>,
|
||||
) -> Result<StatefulAction<Self>, ActionError> {
|
||||
let mut create_or_insert_files = Vec::default();
|
||||
let mut create_directories = Vec::default();
|
||||
|
||||
|
@ -78,12 +51,13 @@ impl ConfigureShellProfile {
|
|||
inde = " ", // indent
|
||||
);
|
||||
|
||||
for profile_target in PROFILE_TARGETS {
|
||||
for profile_target in locations.bash.iter().chain(locations.zsh.iter()) {
|
||||
let profile_target_path = Path::new(profile_target);
|
||||
if let Some(parent) = profile_target_path.parent() {
|
||||
if !parent.exists() {
|
||||
tracing::trace!(
|
||||
"Did not plan to edit `{profile_target}` as its parent folder does not exist."
|
||||
"Did not plan to edit `{}` as its parent folder does not exist.",
|
||||
profile_target.display(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
@ -113,7 +87,7 @@ impl ConfigureShellProfile {
|
|||
inde = " ", // indent
|
||||
);
|
||||
|
||||
for fish_prefix in PROFILE_FISH_CONFD_PREFIXES {
|
||||
for fish_prefix in &locations.fish.confd_prefixes {
|
||||
let fish_prefix_path = PathBuf::from(fish_prefix);
|
||||
|
||||
if !fish_prefix_path.exists() {
|
||||
|
@ -122,7 +96,7 @@ impl ConfigureShellProfile {
|
|||
}
|
||||
|
||||
let mut profile_target = fish_prefix_path;
|
||||
profile_target.push(PROFILE_FISH_CONFD_SUFFIX);
|
||||
profile_target.push(locations.fish.confd_suffix.clone());
|
||||
|
||||
if let Some(conf_d) = profile_target.parent() {
|
||||
create_directories.push(
|
||||
|
@ -142,7 +116,7 @@ impl ConfigureShellProfile {
|
|||
.await?,
|
||||
);
|
||||
}
|
||||
for fish_prefix in PROFILE_FISH_VENDOR_CONFD_PREFIXES {
|
||||
for fish_prefix in &locations.fish.vendor_confd_prefixes {
|
||||
let fish_prefix_path = PathBuf::from(fish_prefix);
|
||||
|
||||
if !fish_prefix_path.exists() {
|
||||
|
@ -151,7 +125,7 @@ impl ConfigureShellProfile {
|
|||
}
|
||||
|
||||
let mut profile_target = fish_prefix_path;
|
||||
profile_target.push(PROFILE_FISH_VENDOR_CONFD_SUFFIX);
|
||||
profile_target.push(locations.fish.vendor_confd_suffix.clone());
|
||||
|
||||
if let Some(conf_d) = profile_target.parent() {
|
||||
create_directories.push(
|
||||
|
@ -197,6 +171,7 @@ impl ConfigureShellProfile {
|
|||
}
|
||||
|
||||
Ok(Self {
|
||||
locations,
|
||||
create_directories,
|
||||
create_or_insert_into_files: create_or_insert_files,
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ use crate::{
|
|||
use std::{collections::HashMap, path::Path};
|
||||
use tokio::process::Command;
|
||||
|
||||
use super::ShellProfileLocations;
|
||||
|
||||
/// A planner for Linux installs
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[cfg_attr(feature = "cli", derive(clap::Parser))]
|
||||
|
@ -80,7 +82,7 @@ impl Planner for Linux {
|
|||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
ConfigureNix::plan(&self.settings)
|
||||
ConfigureNix::plan(ShellProfileLocations::default(), &self.settings)
|
||||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
|
|
|
@ -4,6 +4,8 @@ use std::{collections::HashMap, io::Cursor};
|
|||
use clap::ArgAction;
|
||||
use tokio::process::Command;
|
||||
|
||||
use super::ShellProfileLocations;
|
||||
|
||||
use crate::{
|
||||
action::{
|
||||
base::RemoveDirectory,
|
||||
|
@ -144,7 +146,7 @@ impl Planner for Macos {
|
|||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
ConfigureNix::plan(&self.settings)
|
||||
ConfigureNix::plan(ShellProfileLocations::default(), &self.settings)
|
||||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
|
|
|
@ -109,7 +109,9 @@ pub mod macos;
|
|||
#[cfg(target_os = "linux")]
|
||||
pub mod steam_deck;
|
||||
|
||||
use std::{collections::HashMap, string::FromUtf8Error};
|
||||
use std::{collections::HashMap, path::PathBuf, string::FromUtf8Error};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
action::{ActionError, StatefulAction},
|
||||
|
@ -278,6 +280,68 @@ impl BuiltinPlanner {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
|
||||
pub struct ShellProfileLocations {
|
||||
pub fish: FishShellProfileLocations,
|
||||
pub bash: Vec<PathBuf>,
|
||||
pub zsh: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for ShellProfileLocations {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
fish: FishShellProfileLocations::default(),
|
||||
bash: vec![
|
||||
"/etc/bashrc".into(),
|
||||
"/etc/profile.d/nix.sh".into(),
|
||||
"/etc/bash.bashrc".into(),
|
||||
],
|
||||
zsh: vec![
|
||||
// https://zsh.sourceforge.io/Intro/intro_3.html
|
||||
"/etc/zshrc".into(),
|
||||
"/etc/zsh/zshrc".into(),
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
|
||||
pub struct FishShellProfileLocations {
|
||||
pub confd_suffix: PathBuf,
|
||||
/**
|
||||
Each of these are common values of $__fish_sysconf_dir,
|
||||
under which Fish will look for the file named by
|
||||
`confd_suffix`.
|
||||
*/
|
||||
pub confd_prefixes: Vec<PathBuf>,
|
||||
/// Fish has different syntax than zsh/bash, treat it separate
|
||||
pub vendor_confd_suffix: PathBuf,
|
||||
/**
|
||||
Each of these are common values of $__fish_vendor_confdir,
|
||||
under which Fish will look for the file named by
|
||||
`confd_suffix`.
|
||||
|
||||
More info: <https://fishshell.com/docs/3.3/index.html#configuration-files>
|
||||
*/
|
||||
pub vendor_confd_prefixes: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for FishShellProfileLocations {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
confd_prefixes: vec![
|
||||
"/etc/fish".into(), // standard
|
||||
"/usr/local/etc/fish".into(), // their installer .pkg for macOS
|
||||
"/opt/homebrew/etc/fish".into(), // homebrew
|
||||
"/opt/local/etc/fish".into(), // macports
|
||||
],
|
||||
confd_suffix: "conf.d/nix.fish".into(),
|
||||
vendor_confd_prefixes: vec!["/usr/share/fish/".into(), "/usr/local/share/fish/".into()],
|
||||
vendor_confd_suffix: "vendor_conf.d/nix.fish".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An error originating from a [`Planner`]
|
||||
#[non_exhaustive]
|
||||
#[derive(thiserror::Error, Debug, strum::IntoStaticStr)]
|
||||
|
|
|
@ -73,6 +73,8 @@ use crate::{
|
|||
BuiltinPlanner,
|
||||
};
|
||||
|
||||
use super::ShellProfileLocations;
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[cfg_attr(feature = "cli", derive(clap::Parser))]
|
||||
pub struct SteamDeck {
|
||||
|
@ -205,6 +207,20 @@ impl Planner for SteamDeck {
|
|||
.await
|
||||
.map_err(PlannerError::Action)?;
|
||||
|
||||
// We need to remove this path since it's part of the read-only install.
|
||||
let mut shell_profile_locations = ShellProfileLocations::default();
|
||||
if let Some(index) = shell_profile_locations
|
||||
.fish
|
||||
.vendor_confd_prefixes
|
||||
.iter()
|
||||
.position(|v| *v == PathBuf::from("/usr/share/fish/"))
|
||||
{
|
||||
shell_profile_locations
|
||||
.fish
|
||||
.vendor_confd_prefixes
|
||||
.remove(index);
|
||||
}
|
||||
|
||||
Ok(vec![
|
||||
CreateDirectory::plan(&persistence, None, None, 0o0755, true)
|
||||
.await
|
||||
|
@ -221,7 +237,7 @@ impl Planner for SteamDeck {
|
|||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
ConfigureNix::plan(&self.settings)
|
||||
ConfigureNix::plan(shell_profile_locations, &self.settings)
|
||||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
|
|
25
tests/fixtures/linux/linux.json
vendored
25
tests/fixtures/linux/linux.json
vendored
|
@ -808,6 +808,31 @@
|
|||
},
|
||||
"configure_shell_profile": {
|
||||
"action": {
|
||||
"locations": {
|
||||
"fish": {
|
||||
"confd_suffix": "conf.d/nix.fish",
|
||||
"confd_prefixes": [
|
||||
"/etc/fish",
|
||||
"/usr/local/etc/fish",
|
||||
"/opt/homebrew/etc/fish",
|
||||
"/opt/local/etc/fish"
|
||||
],
|
||||
"vendor_confd_suffix": "vendor_conf.d/nix.fish",
|
||||
"vendor_confd_prefixes": [
|
||||
"/usr/share/fish/",
|
||||
"/usr/local/share/fish/"
|
||||
]
|
||||
},
|
||||
"bash": [
|
||||
"/etc/bashrc",
|
||||
"/etc/profile.d/nix.sh",
|
||||
"/etc/bash.bashrc"
|
||||
],
|
||||
"zsh": [
|
||||
"/etc/zshrc",
|
||||
"/etc/zsh/zshrc"
|
||||
]
|
||||
},
|
||||
"create_directories": [],
|
||||
"create_or_insert_into_files": [
|
||||
{
|
||||
|
|
24
tests/fixtures/linux/steam-deck.json
vendored
24
tests/fixtures/linux/steam-deck.json
vendored
|
@ -852,6 +852,30 @@
|
|||
},
|
||||
"configure_shell_profile": {
|
||||
"action": {
|
||||
"locations": {
|
||||
"fish": {
|
||||
"confd_suffix": "conf.d/nix.fish",
|
||||
"confd_prefixes": [
|
||||
"/etc/fish",
|
||||
"/usr/local/etc/fish",
|
||||
"/opt/homebrew/etc/fish",
|
||||
"/opt/local/etc/fish"
|
||||
],
|
||||
"vendor_confd_suffix": "vendor_conf.d/nix.fish",
|
||||
"vendor_confd_prefixes": [
|
||||
"/usr/local/share/fish/"
|
||||
]
|
||||
},
|
||||
"bash": [
|
||||
"/etc/bashrc",
|
||||
"/etc/profile.d/nix.sh",
|
||||
"/etc/bash.bashrc"
|
||||
],
|
||||
"zsh": [
|
||||
"/etc/zshrc",
|
||||
"/etc/zsh/zshrc"
|
||||
]
|
||||
},
|
||||
"create_directories": [],
|
||||
"create_or_insert_into_files": [
|
||||
{
|
||||
|
|
25
tests/fixtures/macos/macos.json
vendored
25
tests/fixtures/macos/macos.json
vendored
|
@ -888,6 +888,31 @@
|
|||
},
|
||||
"configure_shell_profile": {
|
||||
"action": {
|
||||
"locations": {
|
||||
"fish": {
|
||||
"confd_suffix": "conf.d/nix.fish",
|
||||
"confd_prefixes": [
|
||||
"/etc/fish",
|
||||
"/usr/local/etc/fish",
|
||||
"/opt/homebrew/etc/fish",
|
||||
"/opt/local/etc/fish"
|
||||
],
|
||||
"vendor_confd_suffix": "vendor_conf.d/nix.fish",
|
||||
"vendor_confd_prefixes": [
|
||||
"/usr/share/fish/",
|
||||
"/usr/local/share/fish/"
|
||||
]
|
||||
},
|
||||
"bash": [
|
||||
"/etc/bashrc",
|
||||
"/etc/profile.d/nix.sh",
|
||||
"/etc/bash.bashrc"
|
||||
],
|
||||
"zsh": [
|
||||
"/etc/zshrc",
|
||||
"/etc/zsh/zshrc"
|
||||
]
|
||||
},
|
||||
"create_directories": [],
|
||||
"create_or_insert_into_files": [
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue