Files
topgrade/src/steps/os/archlinux.rs
Thomas Schönauer ab630cfbc6 v10.2.5 release (#330)
* Don't show desktop notification on error (if `skip_notify = true`) (#275)

* Use ─ (U+2500) to draw borders (#282)

* Adds Pclinuxos support (#283)

* Add Devkitpro Pacman support (#291)

* Added support for Neovim package manager lazy.nvim (#293)

* Added support for lazy.nvim

From https://github.com/folke/lazy.nvim
Authored-by: Jacob Lane Ledbetter <jledbetter460@gmail.com>

* Make garuda-update update AUR packages by default (#296)

* fix(#298): Don't throw error if no Helm repository found (#305)

* Skip .NET when `dotnet tool list` is not successful (#302)

* feat(pacstall): add `-y` flag variant (#312)

* Add openSUSE MicroOS support (#315)

* Adds notify-send timeout of 10s (#318)

* Don't run yum when rpm-ostree is available (#313)

* don't run yum when rpm-ostree is available

* Clippy fix

* rpm-ostree: set default value to true

* Fixes if loop error

* Fixes gem update --system requires sudo now (#317)

* Fixes gem update --system requires sudo now

* rubygem: Adds arg -EH to sudo

* Use fixed nala path instead of which(nala) (#314)

* Adds notify-send bug warning when topgrade is run (#324)

* Adds notify-send bug warning when topgrade is run

* fix typo + clippy

* notify-send warning respects skip_notify flag

* nix: Adds additional arguments support (#325)

* Adds pip-review and pipupgrade support (#316)

* Adds pip-review and pipupgrade support

* Python: fixes pip_review and pipupgrade

* v10.2.5 patch (#329)

* WSL: Adds new wsl --update flags (#327)

* wsl: Updates available flags

* Clippy fix

* Add WslUpdate runner

* wsl: Code Typo

* wsl: Code Typos

* wsl: Code Typos

* wsl: Code Typo

* Adds AM Package Manager (#328)

* Adds AM Package Manager

* Clippy fixes

* Cargo fmt

* Moves am to linux only in main file

---------

Co-authored-by: Guilherme Silva <626206+guihkx@users.noreply.github.com>
Co-authored-by: Gabriel Augendre <gabriel@augendre.info>
Co-authored-by: Cat Core <34719527+arthurbambou@users.noreply.github.com>
Co-authored-by: Hugo Haas <hugoh@hugoh.net>
Co-authored-by: Baptiste <32563450+BapRx@users.noreply.github.com>
Co-authored-by: bbx0 <39773919+bbx0@users.noreply.github.com>
Co-authored-by: Sourajyoti Basak <wiz28@protonmail.com>
2023-01-29 19:19:27 +00:00

365 lines
10 KiB
Rust

use std::env::var_os;
use std::ffi::OsString;
use std::path::{Path, PathBuf};
use color_eyre::eyre;
use color_eyre::eyre::Result;
use walkdir::WalkDir;
use crate::command::CommandExt;
use crate::error::TopgradeError;
use crate::execution_context::ExecutionContext;
use crate::sudo::Sudo;
use crate::utils::which;
use crate::{config, Step};
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<()> {
if ctx.config().show_arch_news() {
ctx.run_type()
.execute(&self.executable)
.arg("-Pw")
.status_checked_with_codes(&[1, 0])?;
}
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(Step::System) {
command.arg("--noconfirm");
}
command.status_checked()?;
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(Step::System) {
command.arg("--noconfirm");
}
command.status_checked()?;
}
Ok(())
}
}
impl YayParu {
fn get(exec_name: &str, pacman: &Path) -> Option<Self> {
Some(Self {
executable: which(exec_name)?,
pacman: pacman.to_owned(),
})
}
}
pub struct GarudaUpdate {
executable: PathBuf,
}
impl ArchPackageManager for GarudaUpdate {
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
let mut command = ctx.run_type().execute(&self.executable);
command
.env("PATH", get_execution_path())
.env("UPDATE_AUR", "1")
.env("SKIP_MIRRORLIST", "1");
if ctx.config().yes(Step::System) {
command.env("PACMAN_NOCONFIRM", "1");
}
command.args(ctx.config().garuda_update_arguments().split_whitespace());
command.status_checked()?;
Ok(())
}
}
impl GarudaUpdate {
fn get() -> Option<Self> {
Some(Self {
executable: which("garuda-update")?,
})
}
}
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(Step::System) {
command.arg("--noconfirm");
}
command.status_checked()?;
if ctx.config().cleanup() {
let mut command = ctx.run_type().execute(&self.executable);
command.arg("-Sc");
if ctx.config().yes(Step::System) {
command.arg("--noconfirm");
}
command.status_checked()?;
}
Ok(())
}
}
impl Trizen {
fn get() -> Option<Self> {
Some(Self {
executable: which("trizen")?,
})
}
}
pub struct Pacman {
sudo: Sudo,
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(Step::System) {
command.arg("--noconfirm");
}
command.status_checked()?;
if ctx.config().cleanup() {
let mut command = ctx.run_type().execute(&self.sudo);
command.arg(&self.executable).arg("-Scc");
if ctx.config().yes(Step::System) {
command.arg("--noconfirm");
}
command.status_checked()?;
}
Ok(())
}
}
impl Pacman {
pub fn get(ctx: &ExecutionContext) -> Option<Self> {
Some(Self {
executable: which("powerpill").unwrap_or_else(|| PathBuf::from("pacman")),
sudo: ctx.sudo().to_owned()?,
})
}
}
pub struct Pikaur {
executable: PathBuf,
}
impl Pikaur {
fn get() -> Option<Self> {
Some(Self {
executable: which("pikaur")?,
})
}
}
impl ArchPackageManager for Pikaur {
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
let mut command = ctx.run_type().execute(&self.executable);
command
.arg("-Syu")
.args(ctx.config().pikaur_arguments().split_whitespace())
.env("PATH", get_execution_path());
if ctx.config().yes(Step::System) {
command.arg("--noconfirm");
}
command.status_checked()?;
if ctx.config().cleanup() {
let mut command = ctx.run_type().execute(&self.executable);
command.arg("-Sc");
if ctx.config().yes(Step::System) {
command.arg("--noconfirm");
}
command.status_checked()?;
}
Ok(())
}
}
pub struct Pamac {
executable: PathBuf,
}
impl Pamac {
fn get() -> Option<Self> {
Some(Self {
executable: which("pamac")?,
})
}
}
impl ArchPackageManager for Pamac {
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
let mut command = ctx.run_type().execute(&self.executable);
command
.arg("upgrade")
.args(ctx.config().pamac_arguments().split_whitespace())
.env("PATH", get_execution_path());
if ctx.config().yes(Step::System) {
command.arg("--no-confirm");
}
command.status_checked()?;
if ctx.config().cleanup() {
let mut command = ctx.run_type().execute(&self.executable);
command.arg("clean");
if ctx.config().yes(Step::System) {
command.arg("--no-confirm");
}
command.status_checked()?;
}
Ok(())
}
}
pub struct Aura {
executable: PathBuf,
sudo: Sudo,
}
impl Aura {
fn get(ctx: &ExecutionContext) -> Option<Self> {
Some(Self {
executable: which("aura")?,
sudo: ctx.sudo().to_owned()?,
})
}
}
impl ArchPackageManager for Aura {
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
let sudo = which("sudo").unwrap_or_else(PathBuf::new);
let mut aur_update = ctx.run_type().execute(&sudo);
if sudo.ends_with("sudo") {
aur_update
.arg(&self.executable)
.arg("-Au")
.args(ctx.config().aura_aur_arguments().split_whitespace());
if ctx.config().yes(Step::System) {
aur_update.arg("--noconfirm");
}
aur_update.status_checked()?;
} else {
println!("Aura requires sudo installed to work with AUR packages")
}
let mut pacman_update = ctx.run_type().execute(&self.sudo);
pacman_update
.arg(&self.executable)
.arg("-Syu")
.args(ctx.config().aura_pacman_arguments().split_whitespace());
if ctx.config().yes(Step::System) {
pacman_update.arg("--noconfirm");
}
pacman_update.status_checked()?;
Ok(())
}
}
fn box_package_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("pacman"));
match ctx.config().arch_package_manager() {
config::ArchPackageManager::Autodetect => GarudaUpdate::get()
.map(box_package_manager)
.or_else(|| YayParu::get("paru", &pacman).map(box_package_manager))
.or_else(|| YayParu::get("yay", &pacman).map(box_package_manager))
.or_else(|| Trizen::get().map(box_package_manager))
.or_else(|| Pikaur::get().map(box_package_manager))
.or_else(|| Pamac::get().map(box_package_manager))
.or_else(|| Pacman::get(ctx).map(box_package_manager))
.or_else(|| Aura::get(ctx).map(box_package_manager)),
config::ArchPackageManager::GarudaUpdate => GarudaUpdate::get().map(box_package_manager),
config::ArchPackageManager::Trizen => Trizen::get().map(box_package_manager),
config::ArchPackageManager::Paru => YayParu::get("paru", &pacman).map(box_package_manager),
config::ArchPackageManager::Yay => YayParu::get("yay", &pacman).map(box_package_manager),
config::ArchPackageManager::Pacman => Pacman::get(ctx).map(box_package_manager),
config::ArchPackageManager::Pikaur => Pikaur::get().map(box_package_manager),
config::ArchPackageManager::Pamac => Pamac::get().map(box_package_manager),
config::ArchPackageManager::Aura => Aura::get(ctx).map(box_package_manager),
}
}
pub fn upgrade_arch_linux(ctx: &ExecutionContext) -> Result<()> {
let package_manager =
get_arch_package_manager(ctx).ok_or_else(|| eyre::Report::from(TopgradeError::FailedGettingPackageManager))?;
package_manager.upgrade(ctx)
}
pub fn show_pacnew() {
let mut iter = WalkDir::new("/etc")
.into_iter()
.filter_map(Result::ok)
.filter(|f| {
f.path()
.extension()
.filter(|ext| ext == &"pacnew" || ext == &"pacsave")
.is_some()
})
.peekable();
if iter.peek().is_some() {
println!("\nPacman backup configuration files found:");
for entry in iter {
println!("{}", entry.path().display());
}
}
}