From 184f86ebaea7264f906f1fb33b9bfc700c2eb203 Mon Sep 17 00:00:00 2001 From: steven-omaha <35634100+steven-omaha@users.noreply.github.com> Date: Mon, 27 Feb 2023 19:39:25 +0100 Subject: [PATCH] add python support --- TODO.md | 1 - crates/pacdef_core/src/backend/actual/mod.rs | 1 + .../pacdef_core/src/backend/actual/python.rs | 70 +++++++++++++++++++ crates/pacdef_core/src/backend/mod.rs | 1 + crates/pacdef_core/src/grouping/package.rs | 6 ++ crates/pacdef_core/src/review/strategy.rs | 6 +- 6 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 crates/pacdef_core/src/backend/actual/python.rs diff --git a/TODO.md b/TODO.md index d9a6502..4db956f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,3 @@ # To Do - tutorial -- support apt diff --git a/crates/pacdef_core/src/backend/actual/mod.rs b/crates/pacdef_core/src/backend/actual/mod.rs index 9e1cf5c..c714208 100644 --- a/crates/pacdef_core/src/backend/actual/mod.rs +++ b/crates/pacdef_core/src/backend/actual/mod.rs @@ -2,4 +2,5 @@ pub mod arch; #[cfg(feature = "debian")] pub mod debian; +pub mod python; pub mod rust; diff --git a/crates/pacdef_core/src/backend/actual/python.rs b/crates/pacdef_core/src/backend/actual/python.rs new file mode 100644 index 0000000..e1f2824 --- /dev/null +++ b/crates/pacdef_core/src/backend/actual/python.rs @@ -0,0 +1,70 @@ +use std::collections::HashSet; +use std::process::Command; +use std::process::ExitStatus; + +use anyhow::Context; +use anyhow::Result; +use serde_json::Value; + +use crate::backend::backend_trait::{Backend, Switches, Text}; +use crate::{impl_backend_constants, Group, Package}; + +#[derive(Debug, Clone)] +pub struct Python { + pub(crate) packages: HashSet, +} + +const BINARY: Text = "pip"; +const SECTION: Text = "python"; + +const SWITCHES_INFO: Switches = &["show"]; +const SWITCHES_INSTALL: Switches = &["install"]; +const SWITCHES_MAKE_DEPENDENCY: Switches = &[]; // not needed +const SWITCHES_REMOVE: Switches = &["uninstall"]; + +impl Backend for Python { + impl_backend_constants!(); + + fn get_all_installed_packages(&self) -> Result> { + let output = run_pip_command(&["list", "--format", "json", "--user"])?; + + extract_pacdef_packages(output) + } + + fn get_explicitly_installed_packages(&self) -> Result> { + let output = run_pip_command(&["list", "--format", "json", "--not-required", "--user"])?; + + extract_pacdef_packages(output) + } + + fn make_dependency(&self, _packages: &[Package]) -> Result { + todo!() + } +} + +fn run_pip_command(args: &[&str]) -> Result { + let mut cmd = Command::new(BINARY); + cmd.args(args); + let output = String::from_utf8(cmd.output()?.stdout)?; + let val: Value = serde_json::from_str(&output)?; + Ok(val) +} + +impl Python { + pub(crate) fn new() -> Self { + Self { + packages: HashSet::new(), + } + } +} + +fn extract_pacdef_packages(value: Value) -> Result> { + let result = value + .as_array() + .context("getting inner json array")? + .iter() + .map(|node| node["name"].as_str().unwrap()) + .map(Package::from) + .collect(); + Ok(result) +} diff --git a/crates/pacdef_core/src/backend/mod.rs b/crates/pacdef_core/src/backend/mod.rs index 7a25663..c8c10f1 100644 --- a/crates/pacdef_core/src/backend/mod.rs +++ b/crates/pacdef_core/src/backend/mod.rs @@ -16,5 +16,6 @@ pub enum Backends { Arch, #[cfg(feature = "debian")] Debian, + Python, Rust, } diff --git a/crates/pacdef_core/src/grouping/package.rs b/crates/pacdef_core/src/grouping/package.rs index c3fda26..19a0a73 100644 --- a/crates/pacdef_core/src/grouping/package.rs +++ b/crates/pacdef_core/src/grouping/package.rs @@ -24,6 +24,12 @@ impl From for Package { } } +impl From<&str> for Package { + fn from(value: &str) -> Self { + Self::from(value.to_string()) + } +} + impl Package { fn split_into_name_and_repo(s: &str) -> (String, Option) { let mut iter = s.split('/').rev(); diff --git a/crates/pacdef_core/src/review/strategy.rs b/crates/pacdef_core/src/review/strategy.rs index 57de1ec..395c9ed 100644 --- a/crates/pacdef_core/src/review/strategy.rs +++ b/crates/pacdef_core/src/review/strategy.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use anyhow::Result; +use anyhow::{ensure, Result}; use crate::backend::Backend; use crate::{Group, Package}; @@ -30,11 +30,11 @@ impl Strategy { pub(super) fn execute(self) -> Result<()> { if !self.delete.is_empty() { - self.backend.remove_packages(&self.delete)?; + ensure!(self.backend.remove_packages(&self.delete)?.success()); } if !self.as_dependency.is_empty() { - self.backend.make_dependency(&self.as_dependency)?; + ensure!(self.backend.make_dependency(&self.as_dependency)?.success()); } if !self.assign_group.is_empty() {