Skip to content

Commit

Permalink
ci: Remove homebrew from ci and fix tests (#29)
Browse files Browse the repository at this point in the history
* Update rust.yml

* test: Fixes to YUM tests

* test: escalate to sudo if needed (close #25)

* ci: elevate to sudo if permission

* chore: elevate sudo if needed
  • Loading branch information
dilawar authored Apr 6, 2024
1 parent 823aeb2 commit 5910f96
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 76 deletions.
11 changes: 8 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@ jobs:

steps:
- uses: actions/checkout@v3
- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master

- name: Install latest rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
default: true
override: true

- name: Build
run: cargo build --verbose
- name: Run tests
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn main() {
## Advanced usage
```rust

use mpm::{managers, verify::Verify, Cmd, Commands, PackageManager};
use mpm::{managers, verify::Verify, Cmd, PackageManagerCommands, PackageManager};

fn main() {
// creating a verified instance (package manager known to be in path/installed)
Expand Down
20 changes: 10 additions & 10 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::common::{Package, PackageManager};
/// line args.
pub struct Cli {
#[command(subcommand)]
command: MpmCommands,
command: MpmPackageManagerCommands,

/// Optionally specify a package manager that you want to use. If not given,
/// mpm will search for default package manager on this system.
Expand All @@ -31,7 +31,7 @@ pub struct Cli {
}

#[derive(Subcommand)]
pub enum MpmCommands {
pub enum MpmPackageManagerCommands {
#[command(about = "List supported package managers and display their availability")]
Managers,

Expand Down Expand Up @@ -88,29 +88,29 @@ pub fn execute(args: Cli) -> anyhow::Result<()> {
};

match args.command {
MpmCommands::Managers => crate::print::print_managers(),
MpmCommands::Search { string } => {
MpmPackageManagerCommands::Managers => crate::print::print_managers(),
MpmPackageManagerCommands::Search { string } => {
let pkgs = mpm.search(&string);
print_pkgs(&pkgs, args.json)?;
}
MpmCommands::List => {
MpmPackageManagerCommands::List => {
let pkgs = mpm.list_installed();
print_pkgs(&pkgs, args.json)?;
}
MpmCommands::Install { packages } => {
MpmPackageManagerCommands::Install { packages } => {
for pkg in packages {
let s = mpm.install(Package::from_str(&pkg)?);
anyhow::ensure!(s.success(), "Failed to install {pkg}");
}
}
MpmCommands::Uninstall { packages } => {
MpmPackageManagerCommands::Uninstall { packages } => {
for pkg in packages {
let s = mpm.uninstall(Package::from_str(&pkg)?);
anyhow::ensure!(s.success(), "Failed to uninstall pacakge {pkg}");
}
}

MpmCommands::Update { packages, all } => {
MpmPackageManagerCommands::Update { packages, all } => {
if all {
mpm.update_all();
} else {
Expand All @@ -120,10 +120,10 @@ pub fn execute(args: Cli) -> anyhow::Result<()> {
}
}
}
MpmCommands::Repo { repo } => {
MpmPackageManagerCommands::Repo { repo } => {
mpm.add_repo(&repo)?;
}
MpmCommands::Sync => {
MpmPackageManagerCommands::Sync => {
let s = mpm.sync();
anyhow::ensure!(s.success(), "Failed to sync repositories");
}
Expand Down
61 changes: 43 additions & 18 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const NO_VERSION: &str = "~";
///
/// Multiple package managers can be grouped together as dyn PackageManager.
#[ambassador::delegatable_trait]
pub trait PackageManager: Commands + std::fmt::Debug + std::fmt::Display {
pub trait PackageManager: PackageManagerCommands + std::fmt::Debug + std::fmt::Display {
/// Defines a delimeter to use while formatting package name and version
///
/// For example, HomeBrew supports `<name>@<version>` and APT supports
Expand Down Expand Up @@ -196,7 +196,7 @@ impl Error for RepoError {
/// Representation of a package manager command
///
/// All the variants are the type of commands that a type that imlements
/// [``Commands``] and [``PackageManager``] (should) support.
/// [``PackageManagerCommands``] and [``PackageManager``] (should) support.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Cmd {
Install,
Expand All @@ -211,12 +211,12 @@ pub enum Cmd {

/// Trait for defining package panager commands in one place
///
/// Only [``Commands::cmd``] and [``Commands::commands``] are required, the rest
/// are simply conviniece methods that internally call [``Commands::commands``].
/// The trait [``PackageManager``] depends on this to provide default
/// implementations.
/// Only [``PackageManagerCommands::cmd``] and [``Commands::commands``] are
/// required, the rest are simply conviniece methods that internally call
/// [``PackageManagerCommands::commands``]. The trait [``PackageManager``]
/// depends on this to provide default implementations.
#[ambassador::delegatable_trait]
pub trait Commands {
pub trait PackageManagerCommands {
/// Primary command of the package manager. For example, 'brew', 'apt', and
/// 'dnf', constructed with [``std::process::Command::new``].
fn cmd(&self) -> std::process::Command;
Expand Down Expand Up @@ -248,46 +248,71 @@ pub trait Commands {
commands.append(&mut self.get_flags(cmd));
commands
}

/// Run arbitrary commands against the package manager command and get
/// output
///
/// # Panics
/// This fn can panic when the defined [``Commands::cmd``] is not found in
/// path. This can be avoided by using [``verified::Verified``]
/// or manually ensuring that the [``Commands::cmd``] is valid.
/// This fn can panic when the defined [``PackageManagerCommands::cmd``] is
/// not found in path. This can be avoided by using
/// [``verified::Verified``] or manually ensuring that the
/// [``PackageManagerCommands::cmd``] is valid.
fn exec_cmds(&self, cmds: &[String]) -> std::process::Output {
tracing::info!("Executing {:?} with args {:?}", self.cmd(), cmds);
self.ensure_sudo();
self.cmd()
.args(cmds)
.output()
.expect("command executed without a prior check")
}

/// Run arbitrary commands against the package manager command and wait for
/// std::process::ExitStatus
///
/// # Panics
/// This fn can panic when the defined [``Commands::cmd``] is not found in
/// path. This can be avoided by using [``verified::Verified``]
/// or manually ensuring that the [``Commands::cmd``] is valid.
/// This fn can panic when the defined [``PackageManagerCommands::cmd``] is
/// not found in path. This can be avoided by using
/// [``verified::Verified``] or manually ensuring that the
/// [``PackageManagerCommands::cmd``] is valid.
fn exec_cmds_status<S: AsRef<str>>(&self, cmds: &[S]) -> std::process::ExitStatus {
self.ensure_sudo();
self.cmd()
.args(cmds.iter().map(AsRef::as_ref))
.status()
.expect("command executed without a prior check")
}

/// Run arbitrary commands against the package manager command and return
/// handle to the spawned process
///
/// # Panics
/// This fn can panic when the defined [``Commands::cmd``] is not found in
/// path. This can be avoided by using [``verified::Verified``]
/// or manually ensuring that the [``Commands::cmd``] is valid.
/// This fn can panic when the defined [``PackageManagerCommands::cmd``] is
/// not found in path. This can be avoided by using
/// [``verified::Verified``] or manually ensuring that the
/// [``PackageManagerCommands::cmd``] is valid.
fn exec_cmds_spawn(&self, cmds: &[String]) -> std::process::Child {
self.ensure_sudo();
self.cmd()
.args(cmds)
.spawn()
.expect("command executed without a prior check")
}

/// Ensure that we are in sudo mode.
fn ensure_sudo(&self) {
#[cfg(target_os = "linux")]
if let Err(e) = sudo::escalate_if_needed() {
tracing::warn!("Failed to elevate privileges: {e}.");
}
}

/// Check is package manager is available.
fn is_available(&self) -> bool {
match self.cmd().arg("--version").output() {
Err(_) => false,
Ok(output) => output.status.success(),
}
}
}

/// A representation of a package
Expand Down Expand Up @@ -381,8 +406,8 @@ pub enum Operation {
Update,
}

/// General purpose version of [``Commands::consolidated``] for consolidating
/// different types of arguments into a single Vec
/// General purpose version of [``PackageManagerCommands::consolidated``] for
/// consolidating different types of arguments into a single Vec
#[inline]
pub fn consolidate_args<'a>(cmds: &[&'a str], args: &[&'a str], flags: &[&'a str]) -> Vec<&'a str> {
let mut vec = Vec::with_capacity(cmds.len() + args.len() + flags.len());
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ mod tests {
str::FromStr,
};

use super::{Cmd, Commands};
use super::{Cmd, PackageManagerCommands};
use crate::{Package, PackageManager};

struct MockCommands;

impl Commands for MockCommands {
impl PackageManagerCommands for MockCommands {
fn cmd(&self) -> Command {
Command::new("")
}
Expand All @@ -84,7 +84,7 @@ mod tests {
}
}

impl Commands for MockPackageManager {
impl PackageManagerCommands for MockPackageManager {
fn cmd(&self) -> Command {
Command::new("")
}
Expand Down
9 changes: 6 additions & 3 deletions src/managers/apt.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fmt::Display, fs, io::Write, process::Command};

use crate::{common::Package, Cmd, Commands, PackageManager};
use crate::{common::Package, Cmd, PackageManager, PackageManagerCommands};

/// Wrapper for Advanced Pacakge Tool (APT), the default package management
/// user-facing utilities in Debian and Debian-based distributions.
Expand Down Expand Up @@ -60,7 +60,7 @@ impl Display for AdvancedPackageTool {
}
}

impl Commands for AdvancedPackageTool {
impl PackageManagerCommands for AdvancedPackageTool {
fn cmd(&self) -> Command {
Command::new("apt-get")
}
Expand Down Expand Up @@ -93,17 +93,20 @@ impl Commands for AdvancedPackageTool {
}

fn exec_cmds(&self, cmds: &[String]) -> std::process::Output {
self.ensure_sudo();
self.alt_cmd(cmds).args(cmds).output().unwrap()
}

fn exec_cmds_status<S: AsRef<str>>(&self, cmds: &[S]) -> std::process::ExitStatus {
self.ensure_sudo();
self.alt_cmd(cmds)
.args(cmds.iter().map(AsRef::as_ref))
.status()
.unwrap()
}

fn exec_cmds_spawn(&self, cmds: &[String]) -> std::process::Child {
self.ensure_sudo();
self.alt_cmd(cmds).args(cmds).spawn().unwrap()
}
}
Expand All @@ -113,7 +116,7 @@ mod tests {
use std::str::FromStr;

use super::AdvancedPackageTool;
use crate::{Cmd, Commands, Package, PackageManager};
use crate::{Cmd, Package, PackageManager, PackageManagerCommands};

#[test]
fn test_parse_pkg() {
Expand Down
4 changes: 2 additions & 2 deletions src/managers/brew.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fmt::Display, process::Command};

use crate::{Cmd, Commands, PackageManager};
use crate::{Cmd, PackageManager, PackageManagerCommands};

/// Wrapper for the Homebrew package manager.
///
Expand All @@ -14,7 +14,7 @@ impl PackageManager for Homebrew {
}
}

impl Commands for Homebrew {
impl PackageManagerCommands for Homebrew {
fn cmd(&self) -> Command {
Command::new("brew")
}
Expand Down
4 changes: 2 additions & 2 deletions src/managers/choco.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fmt::Display, process::Command};

use crate::{common::Package, Cmd, Commands, PackageManager};
use crate::{common::Package, Cmd, PackageManager, PackageManagerCommands};

/// Wrapper for the Chocolatey package manager for windows
///
Expand All @@ -21,7 +21,7 @@ impl PackageManager for Chocolatey {
}
}

impl Commands for Chocolatey {
impl PackageManagerCommands for Chocolatey {
fn cmd(&self) -> Command {
Command::new("choco")
}
Expand Down
4 changes: 2 additions & 2 deletions src/managers/dnf.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fmt::Display, process::Command};

use crate::{Cmd, Commands, Package, PackageManager};
use crate::{Cmd, Package, PackageManager, PackageManagerCommands};

/// Wrapper for DandifiedYUM or DNF, the next upcoming major version of YUM
///
Expand Down Expand Up @@ -49,7 +49,7 @@ impl Display for DandifiedYUM {
}
}

impl Commands for DandifiedYUM {
impl PackageManagerCommands for DandifiedYUM {
fn cmd(&self) -> Command {
Command::new("dnf")
}
Expand Down
Loading

0 comments on commit 5910f96

Please sign in to comment.