use crate::{command, os, packages::Package};
use anyhow::{format_err, Error};
use std::ffi::OsStr;
use std::io;
#[derive(Debug)]
pub struct Pip {
command: command::Command<'static>,
}
impl Pip {
pub fn new(name: &'static str) -> Self {
Pip {
command: command::Command::new(os::command(name)),
}
}
pub fn test(&self) -> Result<bool, Error> {
match self.command.run(&["--version"]) {
Ok(output) => Ok(output.status.success()),
Err(e) => match e.kind() {
io::ErrorKind::NotFound => Ok(false),
_ => Err(Error::from(e)),
},
}
}
pub fn list_installed(&self) -> Result<Vec<Package>, Error> {
let mut out = Vec::new();
let args = &["list", "--format=columns"];
for line in self.command.run_lines(args)? {
let line = line.trim();
if line == "" {
continue;
}
let mut it = line.split(' ');
let name = it
.next()
.ok_or_else(|| format_err!("expected package name"))?;
out.push(Package {
name: name.to_string(),
});
}
Ok(out)
}
pub fn install_packages<S>(&self, packages: impl IntoIterator<Item = S>) -> Result<(), Error>
where
S: AsRef<OsStr>,
{
let packages = packages.into_iter().collect::<Vec<_>>();
let mut args = Vec::new();
args.push(OsStr::new("install"));
args.push(OsStr::new("--user"));
args.extend(packages.iter().map(AsRef::as_ref));
self.command.run(args)?;
Ok(())
}
}
#[derive(Debug)]
pub struct PackageManager {
name: &'static str,
pip: Pip,
}
impl PackageManager {
pub fn new(name: &'static str) -> Self {
PackageManager {
name,
pip: Pip::new(name),
}
}
}
impl super::PackageManager for PackageManager {
fn primary(&self) -> bool {
true
}
fn name(&self) -> &str {
self.name
}
fn test(&self) -> Result<bool, Error> {
self.pip.test()
}
fn list_packages(&self) -> Result<Vec<Package>, Error> {
self.pip.list_installed()
}
fn install_packages(&self, packages: &[String]) -> Result<(), Error> {
self.pip.install_packages(packages)
}
}