Aur helper (#776)

* Arch Refactor

* Clippy
This commit is contained in:
Roey Darwish Dror
2021-10-25 22:03:57 +03:00
committed by GitHub
parent 6eb4cdd224
commit fb18af12ac
4 changed files with 198 additions and 94 deletions

View File

@@ -180,10 +180,20 @@ pub struct Brew {
greedy_cask: Option<bool>, greedy_cask: Option<bool>,
} }
#[derive(Debug, Deserialize, Clone, Copy)]
pub enum ArchPackageManager {
Autodetect,
Trizen,
Paru,
Yay,
Pacman,
}
#[derive(Deserialize, Default, Debug)] #[derive(Deserialize, Default, Debug)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Linux { pub struct Linux {
yay_arguments: Option<String>, yay_arguments: Option<String>,
arch_package_manager: Option<ArchPackageManager>,
trizen_arguments: Option<String>, trizen_arguments: Option<String>,
dnf_arguments: Option<String>, dnf_arguments: Option<String>,
apt_arguments: Option<String>, apt_arguments: Option<String>,
@@ -630,6 +640,16 @@ impl Config {
.unwrap_or("") .unwrap_or("")
} }
/// Extra yay arguments
#[allow(dead_code)]
pub fn arch_package_manager(&self) -> ArchPackageManager {
self.config_file
.linux
.as_ref()
.and_then(|s| s.arch_package_manager)
.unwrap_or(ArchPackageManager::Autodetect)
}
/// Extra yay arguments /// Extra yay arguments
#[allow(dead_code)] #[allow(dead_code)]
pub fn yay_arguments(&self) -> &str { pub fn yay_arguments(&self) -> &str {

173
src/steps/os/archlinux.rs Normal file
View File

@@ -0,0 +1,173 @@
use crate::config;
use crate::execution_context::ExecutionContext;
use crate::utils::which;
use anyhow::Result;
use std::env::var_os;
use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::process::Command;
fn get_execution_path() -> OsString {
let mut path = OsString::from("/usr/bin:");
path.push(var_os("PATH").unwrap());
path
}
pub trait ArchPackageManager {
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()>;
}
pub struct YayParu {
executable: PathBuf,
pacman: PathBuf,
}
impl ArchPackageManager for YayParu {
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
Command::new(&self.executable)
.arg("-Pw")
.spawn()
.and_then(|mut p| p.wait())
.ok();
let mut command = ctx.run_type().execute(&self.executable);
command
.arg("--pacman")
.arg(&self.pacman)
.arg("-Syu")
.args(ctx.config().yay_arguments().split_whitespace())
.env("PATH", get_execution_path());
if ctx.config().yes() {
command.arg("--noconfirm");
}
command.check_run()?;
if ctx.config().cleanup() {
let mut command = ctx.run_type().execute(&self.executable);
command.arg("--pacman").arg(&self.pacman).arg("-Scc");
if ctx.config().yes() {
command.arg("--noconfirm");
}
command.check_run()?;
}
Ok(())
}
}
impl YayParu {
fn get(exec_name: &str, pacman: &Path) -> Option<Self> {
Some(Self {
executable: which(exec_name)?,
pacman: pacman.to_owned(),
})
}
}
pub struct Trizen {
executable: PathBuf,
}
impl ArchPackageManager for Trizen {
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
let mut command = ctx.run_type().execute(&self.executable);
command
.arg("-Syu")
.args(ctx.config().trizen_arguments().split_whitespace())
.env("PATH", get_execution_path());
if ctx.config().yes() {
command.arg("--noconfirm");
}
command.check_run()?;
if ctx.config().cleanup() {
let mut command = ctx.run_type().execute(&self.executable);
command.arg("-Sc");
if ctx.config().yes() {
command.arg("--noconfirm");
}
command.check_run()?;
}
Ok(())
}
}
impl Trizen {
fn get() -> Option<Self> {
Some(Self {
executable: which("trizen")?,
})
}
}
pub struct Pacman {
sudo: PathBuf,
executable: PathBuf,
}
impl ArchPackageManager for Pacman {
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
let mut command = ctx.run_type().execute(&self.sudo);
command
.arg(&self.executable)
.arg("-Syu")
.env("PATH", get_execution_path());
if ctx.config().yes() {
command.arg("--noconfirm");
}
command.check_run()?;
if ctx.config().cleanup() {
let mut command = ctx.run_type().execute(&self.sudo);
command.arg(&self.executable).arg("-Scc");
if ctx.config().yes() {
command.arg("--noconfirm");
}
command.check_run()?;
}
Ok(())
}
}
impl Pacman {
pub fn get(ctx: &ExecutionContext) -> Option<Self> {
Some(Self {
executable: which("powerpill").unwrap_or_else(|| PathBuf::from("/usr/bin/pacman")),
sudo: ctx.sudo().to_owned()?,
})
}
}
fn box_pacakge_manager<P: 'static + ArchPackageManager>(package_manager: P) -> Box<dyn ArchPackageManager> {
Box::new(package_manager) as Box<dyn ArchPackageManager>
}
pub fn get_arch_package_manager(ctx: &ExecutionContext) -> Option<Box<dyn ArchPackageManager>> {
let pacman = which("powerpill").unwrap_or_else(|| PathBuf::from("/usr/bin/pacman"));
match ctx.config().arch_package_manager() {
config::ArchPackageManager::Autodetect => YayParu::get("paru", &pacman)
.map(box_pacakge_manager)
.or_else(|| YayParu::get("yay", &pacman).map(box_pacakge_manager))
.or_else(|| {
Trizen::get()
.map(box_pacakge_manager)
.or_else(|| Pacman::get(ctx).map(box_pacakge_manager))
}),
config::ArchPackageManager::Trizen => Trizen::get().map(box_pacakge_manager),
config::ArchPackageManager::Paru => YayParu::get("paru", &pacman).map(box_pacakge_manager),
config::ArchPackageManager::Yay => YayParu::get("yay", &pacman).map(box_pacakge_manager),
config::ArchPackageManager::Pacman => Pacman::get(ctx).map(box_pacakge_manager),
}
}
pub fn upgrade_arch_linux(ctx: &ExecutionContext) -> Result<()> {
let package_manager = get_arch_package_manager(ctx).unwrap();
package_manager.upgrade(ctx)
}

View File

@@ -1,14 +1,13 @@
use crate::error::{SkipStep, TopgradeError}; use crate::error::{SkipStep, TopgradeError};
use crate::execution_context::ExecutionContext; use crate::execution_context::ExecutionContext;
use crate::executor::{CommandExt, RunType}; use crate::executor::{CommandExt, RunType};
use crate::steps::os::archlinux;
use crate::terminal::{print_separator, print_warning}; use crate::terminal::{print_separator, print_warning};
use crate::utils::{require, require_option, which, PathExt}; use crate::utils::{require, require_option, which, PathExt};
use anyhow::Result; use anyhow::Result;
use ini::Ini; use ini::Ini;
use log::debug; use log::debug;
use serde::Deserialize; use serde::Deserialize;
use std::env::var_os;
use std::ffi::OsString;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use walkdir::WalkDir; use walkdir::WalkDir;
@@ -95,7 +94,7 @@ impl Distribution {
match self { match self {
Distribution::Alpine => upgrade_alpine_linux(ctx), Distribution::Alpine => upgrade_alpine_linux(ctx),
Distribution::Arch => upgrade_arch_linux(ctx), Distribution::Arch => archlinux::upgrade_arch_linux(ctx),
Distribution::CentOS | Distribution::Fedora => upgrade_redhat(ctx), Distribution::CentOS | Distribution::Fedora => upgrade_redhat(ctx),
Distribution::ClearLinux => upgrade_clearlinux(ctx), Distribution::ClearLinux => upgrade_clearlinux(ctx),
Distribution::Debian => upgrade_debian(ctx), Distribution::Debian => upgrade_debian(ctx),
@@ -155,97 +154,6 @@ fn upgrade_alpine_linux(ctx: &ExecutionContext) -> Result<()> {
ctx.run_type().execute(sudo).arg(&apk).arg("upgrade").check_run() ctx.run_type().execute(sudo).arg(&apk).arg("upgrade").check_run()
} }
fn upgrade_arch_linux(ctx: &ExecutionContext) -> Result<()> {
let pacman = which("powerpill").unwrap_or_else(|| PathBuf::from("/usr/bin/pacman"));
let yes = ctx.config().yes();
let sudo = ctx.sudo();
let run_type = ctx.run_type();
let cleanup = ctx.config().cleanup();
let path = {
let mut path = OsString::from("/usr/bin:");
path.push(var_os("PATH").unwrap());
path
};
debug!("Running Arch update with path: {:?}", path);
let yay = which("yay");
if let Some(yay) = &yay {
run_type
.execute(&yay)
.arg("-Pw")
.spawn()
.and_then(|mut p| p.wait())
.ok();
}
if let Some(yay) = yay.or_else(|| which("paru")) {
let mut command = run_type.execute(&yay);
command
.arg("--pacman")
.arg(&pacman)
.arg("-Syu")
.args(ctx.config().yay_arguments().split_whitespace())
.env("PATH", path);
if yes {
command.arg("--noconfirm");
}
command.check_run()?;
if cleanup {
let mut command = run_type.execute(&yay);
command.arg("--pacman").arg(&pacman).arg("-Scc");
if yes {
command.arg("--noconfirm");
}
command.check_run()?;
}
} else if let Some(trizen) = which("trizen") {
let mut command = run_type.execute(&trizen);
command
.arg("-Syu")
.args(ctx.config().trizen_arguments().split_whitespace())
.env("PATH", path);
if yes {
command.arg("--noconfirm");
}
command.check_run()?;
if cleanup {
let mut command = run_type.execute(&trizen);
command.arg("-Sc");
if yes {
command.arg("--noconfirm");
}
command.check_run()?;
}
} else if let Some(sudo) = &sudo {
let mut command = run_type.execute(&sudo);
command.arg(&pacman).arg("-Syu").env("PATH", path);
if yes {
command.arg("--noconfirm");
}
command.check_run()?;
if cleanup {
let mut command = run_type.execute(&sudo);
command.arg(&pacman).arg("-Scc");
if yes {
command.arg("--noconfirm");
}
command.check_run()?;
}
} else {
print_warning("Neither sudo nor yay detected. Skipping system upgrade");
}
Ok(())
}
fn upgrade_redhat(ctx: &ExecutionContext) -> Result<()> { fn upgrade_redhat(ctx: &ExecutionContext) -> Result<()> {
let _ = if let Some(ostree) = Path::new("/usr/bin/rpm-ostree").if_exists() { let _ = if let Some(ostree) = Path::new("/usr/bin/rpm-ostree").if_exists() {
if ctx.config().rpm_ostree() { if ctx.config().rpm_ostree() {
@@ -623,6 +531,7 @@ mod tests {
expected_distribution expected_distribution
); );
} }
#[test] #[test]
fn test_arch_linux() { fn test_arch_linux() {
test_template(include_str!("os_release/arch"), Distribution::Arch); test_template(include_str!("os_release/arch"), Distribution::Arch);

View File

@@ -1,5 +1,7 @@
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
pub mod android; pub mod android;
#[cfg(target_os = "linux")]
mod archlinux;
#[cfg(target_os = "dragonfly")] #[cfg(target_os = "dragonfly")]
pub mod dragonfly; pub mod dragonfly;
#[cfg(target_os = "freebsd")] #[cfg(target_os = "freebsd")]