Skip to content

Commit

Permalink
Build CLI: Fix default shell in user configurations
Browse files Browse the repository at this point in the history
* Default shell is platform specific and they must not be shown
  on platform where are not supported (like `cmd` on Linux)
* Set default shell to `zsh` on MacOs.
* Default shell is installed by default and doesn't need an extra check,
  which can be faulty since `sh` doesn't provide a version argument
  • Loading branch information
AmmarAbouZor committed Oct 23, 2024
1 parent 328aed4 commit b662bc4
Showing 1 changed file with 38 additions and 32 deletions.
70 changes: 38 additions & 32 deletions cli/src/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,40 @@ use serde::{Deserialize, Serialize};

use crate::{cli_args::CargoCli, user_config::UserConfiguration};

#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
/// Represents the shell running by users providing method to create commands to run process
/// on the given shell.
pub enum UserShell {
#[cfg(unix)]
#[cfg_attr(all(unix, not(target_os = "macos")), default)]
Sh,

#[cfg(windows)]
#[default]
Cmd,

Bash,
#[cfg_attr(target_os = "macos", default)]
Zsh,
Fish,
NuShell,
Elvish,
Cmd,
PowerShell,
}

impl Default for UserShell {
fn default() -> Self {
if cfg!(windows) {
UserShell::Cmd
} else {
UserShell::Sh
}
}
}

impl Display for UserShell {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UserShell::Sh => write!(f, "SH"),
#[cfg(unix)]
UserShell::Sh => write!(f, "Sh"),
#[cfg(windows)]
UserShell::Cmd => write!(f, "Cmd"),
UserShell::Bash => write!(f, "Bash"),
UserShell::Zsh => write!(f, "ZSH"),
UserShell::Zsh => write!(f, "Zsh"),
UserShell::Fish => write!(f, "Fish"),
UserShell::NuShell => write!(f, "Nu Shell"),
UserShell::Elvish => write!(f, "Envish"),
UserShell::Cmd => write!(f, "Cmd"),
UserShell::PowerShell => write!(f, "Power Shell"),
}
}
Expand All @@ -70,51 +69,58 @@ impl UserShell {
/// Binary name for the shell
pub const fn bin(self) -> &'static str {
match self {
#[cfg(unix)]
UserShell::Sh => "sh",
#[cfg(windows)]
UserShell::Cmd => "cmd",
UserShell::Bash => "bash",
UserShell::Zsh => "zsh",
UserShell::Fish => "fish",
UserShell::NuShell => "nu",
UserShell::Elvish => "elvish",
UserShell::Cmd => "cmd",
UserShell::PowerShell => "pwsh",
}
}

/// Argument provided by each shell to run the provided process command and its arguments.
const fn arg(self) -> &'static str {
match self {
UserShell::Sh
| UserShell::Bash
#[cfg(unix)]
UserShell::Sh => "-c",
#[cfg(windows)]
UserShell::Cmd => "/C",
UserShell::Bash
| UserShell::Zsh
| UserShell::Fish
| UserShell::NuShell
| UserShell::Elvish => "-c",
UserShell::Cmd => "/C",
UserShell::PowerShell => "-Command",
}
}

/// Checks if the shell exist on the system by running it with the version argument.
pub fn exist(self) -> bool {
std::process::Command::new(self.bin())
.arg(self.version_arg())
.output()
.is_ok_and(|o| o.status.success())
}

/// Provides the argument to show the version of the given shell.
const fn version_arg(self) -> &'static str {
match self {
UserShell::Sh
| UserShell::Bash
// Default shell is always installed on their respecting operating system and doesn't need
// extra checks avoiding other potential problem because `sh` doesn't have a version
// argument.
let version_arg = match self {
#[cfg(unix)]
UserShell::Sh => return true,
#[cfg(windows)]
UserShell::Cmd => return true,
UserShell::Bash
| UserShell::Zsh
| UserShell::Fish
| UserShell::NuShell
| UserShell::Elvish => "--version",
UserShell::Cmd => "/? ",
UserShell::PowerShell => "-Version",
}
};

// Other wise run the shell with version argument to check if exists.
std::process::Command::new(self.bin())
.arg(version_arg)
.output()
.is_ok_and(|o| o.status.success())
}
}

Expand Down

0 comments on commit b662bc4

Please sign in to comment.