Support PowerShell core (fix #189)

This commit is contained in:
Roey Darwish Dror
2019-08-14 21:36:57 +03:00
parent 2fc42c8e9f
commit 4ae0263e0d
7 changed files with 95 additions and 87 deletions

View File

@@ -49,8 +49,6 @@ pub enum Step {
Sdkman,
/// Don't run remote Togprades
Remotes,
#[cfg(windows)]
/// Don't update Powershell modules
Powershell,
}

View File

@@ -2,6 +2,7 @@
use super::error::{Error, ErrorKind};
use super::utils::Check;
use failure::ResultExt;
use log::trace;
use std::ffi::{OsStr, OsString};
use std::path::Path;
use std::process::{Child, Command, ExitStatus};
@@ -208,6 +209,7 @@ pub trait CommandExt {
impl CommandExt for Command {
fn check_output(&mut self) -> Result<String, Error> {
let output = self.output().context(ErrorKind::ProcessExecution)?;
trace!("Output of {:?}: {:?}", self, output);
let status = output.status;
if !status.success() {
Err(ErrorKind::ProcessFailed(status))?

View File

@@ -124,10 +124,7 @@ fn run() -> Result<(), Error> {
}
}
#[cfg(windows)]
let powershell = windows::Powershell::new();
#[cfg(windows)]
let powershell = powershell::Powershell::new();
let should_run_powershell = powershell.profile().is_some() && config.should_run(Step::Powershell);
#[cfg(windows)]
@@ -232,12 +229,9 @@ fn run() -> Result<(), Error> {
git_repos.insert(base_dirs.config_dir().join("i3"));
}
#[cfg(windows)]
{
if let Some(profile) = powershell.profile() {
git_repos.insert(profile);
}
}
if config.should_run(Step::GitRepos) {
if let Some(custom_git_repos) = config.git_repos() {
@@ -253,8 +247,6 @@ fn run() -> Result<(), Error> {
)?;
}
#[cfg(windows)]
{
if should_run_powershell {
execute(
&mut report,
@@ -263,7 +255,6 @@ fn run() -> Result<(), Error> {
config.no_retry(),
)?;
}
}
#[cfg(unix)]
{

View File

@@ -3,6 +3,7 @@ pub mod generic;
pub mod git;
pub mod node;
pub mod os;
pub mod powershell;
#[cfg(unix)]
pub mod tmux;
pub mod vim;

View File

@@ -1,8 +1,7 @@
use crate::error::{Error, ErrorKind};
use crate::executor::{CommandExt, RunType};
use crate::terminal::{is_dumb, print_separator};
use crate::utils::{require, require_option, which, PathExt};
use std::path::PathBuf;
use crate::terminal::print_separator;
use crate::utils::require;
use std::process::Command;
pub fn run_chocolatey(run_type: RunType) -> Result<(), Error> {
@@ -21,67 +20,6 @@ pub fn run_scoop(run_type: RunType) -> Result<(), Error> {
run_type.execute(&scoop).args(&["update", "*"]).check_run()
}
pub struct Powershell {
path: Option<PathBuf>,
profile: Option<PathBuf>,
}
impl Powershell {
/// Returns a powershell instance.
///
/// If the powershell binary is not found, or the current terminal is dumb
/// then the instance of this struct will skip all the powershell steps.
pub fn new() -> Self {
let path = which("powershell").filter(|_| !is_dumb());
let profile = path.as_ref().and_then(|path| {
Command::new(path)
.args(&["-Command", "echo $profile"])
.check_output()
.map(|output| PathBuf::from(output.trim()))
.and_then(|p| p.require())
.ok()
});
Powershell { path, profile }
}
pub fn has_command(powershell: &PathBuf, command: &str) -> bool {
|| -> Result<(), Error> {
Command::new(&powershell)
.args(&["-Command", &format!("Get-Command {}", command)])
.check_output()?;
Ok(())
}()
.is_ok()
}
pub fn profile(&self) -> Option<&PathBuf> {
self.profile.as_ref()
}
pub fn update_modules(&self, run_type: RunType) -> Result<(), Error> {
let powershell = require_option(self.path.as_ref())?;
print_separator("Powershell Modules Update");
run_type.execute(&powershell).args(&["Update-Module", "-v"]).check_run()
}
pub fn windows_update(&self, run_type: RunType) -> Result<(), Error> {
let powershell = require_option(self.path.as_ref())?;
if !Self::has_command(&powershell, "Install-WindowsUpdate") {
Err(ErrorKind::SkipStep)?;
}
print_separator("Windows Update");
run_type
.execute(&powershell)
.args(&["-Command", "Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose"])
.check_run()
}
}
pub fn run_wsl_topgrade(run_type: RunType) -> Result<(), Error> {
let wsl = require("wsl")?;
let topgrade = Command::new(&wsl)

77
src/steps/powershell.rs Normal file
View File

@@ -0,0 +1,77 @@
use crate::error::Error;
#[cfg(windows)]
use crate::error::ErrorKind;
use crate::executor::{CommandExt, RunType};
use crate::terminal::{is_dumb, print_separator};
use crate::utils::{require_option, which, PathExt};
use std::path::PathBuf;
use std::process::Command;
pub struct Powershell {
path: Option<PathBuf>,
profile: Option<PathBuf>,
}
impl Powershell {
/// Returns a powershell instance.
///
/// If the powershell binary is not found, or the current terminal is dumb
/// then the instance of this struct will skip all the powershell steps.
pub fn new() -> Self {
let path = which("pwsh").or_else(|| which("powershell")).filter(|_| !is_dumb());
let profile = path.as_ref().and_then(|path| {
Command::new(path)
.args(&["-Command", "echo $profile"])
.check_output()
.map(|output| PathBuf::from(output.trim()))
.and_then(|p| p.require())
.ok()
});
Powershell { path, profile }
}
#[cfg(windows)]
pub fn has_module(powershell: &PathBuf, command: &str) -> bool {
|| -> Result<(), Error> {
Command::new(&powershell)
.args(&["-Command", &format!("Get-Module -ListAvailable {}", command)])
.check_output()?;
Ok(())
}()
.is_ok()
}
pub fn profile(&self) -> Option<&PathBuf> {
self.profile.as_ref()
}
pub fn update_modules(&self, run_type: RunType) -> Result<(), Error> {
let powershell = require_option(self.path.as_ref())?;
print_separator("Powershell Modules Update");
run_type
.execute(&powershell)
.args(&["-Command", "Update-Module", "-v"])
.check_run()
}
#[cfg(windows)]
pub fn windows_update(&self, run_type: RunType) -> Result<(), Error> {
let powershell = require_option(self.path.as_ref())?;
if !Self::has_module(&powershell, "PSWindowsUpdate") {
Err(ErrorKind::SkipStep)?;
}
print_separator("Windows Update");
run_type
.execute(&powershell)
.args(&[
"-Command",
"Import-Module PSWindowsUpdate; Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose",
])
.check_run()
}
}

View File

@@ -14,6 +14,8 @@ use std::os::windows::ffi::OsStrExt;
use std::process::Command;
use std::sync::Mutex;
#[cfg(windows)]
use which_crate::which;
#[cfg(windows)]
use winapi::um::wincon::SetConsoleTitleW;
lazy_static! {
@@ -27,7 +29,7 @@ fn shell() -> String {
#[cfg(windows)]
fn shell() -> &'static str {
"powershell"
which("pwsh").map(|_| "pwsh").unwrap_or("powershell")
}
pub fn run_shell() {
@@ -196,7 +198,6 @@ pub fn print_result<P: AsRef<str>>(key: P, succeeded: bool) {
TERMINAL.lock().unwrap().print_result(key, succeeded)
}
#[cfg(windows)]
/// Tells whether the terminal is dumb.
pub fn is_dumb() -> bool {
TERMINAL.lock().unwrap().width.is_none()