mirror of
https://github.com/elladunbar/package-manager.git
synced 2025-11-05 12:29:54 -06:00
Add remote search for pacman and output
This commit is contained in:
parent
eac131ec71
commit
26506dbb28
3 changed files with 117 additions and 36 deletions
35
src/lib.rs
35
src/lib.rs
|
|
@ -1,4 +1,4 @@
|
|||
use std::ffi::OsString;
|
||||
use std::error::Error;
|
||||
|
||||
pub mod pacman;
|
||||
|
||||
|
|
@ -7,12 +7,35 @@ pub struct Package {
|
|||
pub name: String,
|
||||
pub version: String,
|
||||
pub description: Option<String>,
|
||||
pub installed: Option<bool>,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Package {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let end = "\x1b[0m";
|
||||
let bold = "\x1b[1m";
|
||||
let green = "\x1b[32m";
|
||||
let magenta = "\x1b[35m";
|
||||
let cyan = "\x1b[36m";
|
||||
|
||||
let installed = self.installed.unwrap_or(false);
|
||||
let installed_string = if installed { "[installed] " } else { "" };
|
||||
|
||||
let repository_string = self.repository.join(" / ");
|
||||
|
||||
let description_string = self
|
||||
.description
|
||||
.clone()
|
||||
.unwrap_or("No description provided".to_string());
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{bold}{} {green}{} {cyan}{}{magenta}{}{end}\n {}",
|
||||
self.name, self.version, installed_string, repository_string, description_string
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Manager {
|
||||
fn command_name(&self) -> OsString;
|
||||
fn test_command(&mut self) -> Result<(), String>
|
||||
where
|
||||
Self: Sized;
|
||||
fn remote_search(&self, query: &str) -> Result<Vec<Package>, &str>;
|
||||
fn remote_search(query: &str) -> Result<Vec<Package>, Box<dyn Error>>;
|
||||
}
|
||||
|
|
|
|||
11
src/main.rs
11
src/main.rs
|
|
@ -1,6 +1,11 @@
|
|||
use package_manager::{Manager, pacman::*};
|
||||
use package_manager::{Manager, pacman::Pacman};
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
let m = Pacman;
|
||||
print!("{:?}", m.manager_path().unwrap());
|
||||
let arg = env::args().nth(1).unwrap();
|
||||
let mut packages = Pacman::remote_search(&arg).unwrap();
|
||||
packages.sort_by(|p1, p2| p1.name.cmp(&p2.name));
|
||||
for package in packages {
|
||||
println!("{}", package);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,88 @@
|
|||
use crate::*;
|
||||
use std::str::FromStr;
|
||||
use std::{ffi::OsString, process::Command};
|
||||
use std::{collections::HashMap, process::Command};
|
||||
|
||||
pub struct Pacman {
|
||||
command_exists: bool,
|
||||
struct UnmergedPackage {
|
||||
repository: String,
|
||||
name: String,
|
||||
version: String,
|
||||
description: Option<String>,
|
||||
installed: Option<bool>,
|
||||
}
|
||||
|
||||
pub struct Pacman;
|
||||
|
||||
impl Manager for Pacman {
|
||||
fn command_name(&self) -> OsString {
|
||||
return OsString::from_str("pacman").unwrap();
|
||||
fn remote_search(query: &str) -> Result<Vec<Package>, Box<dyn Error>> {
|
||||
let output = Command::new("pacman").arg("-Ss").arg(query).output()?;
|
||||
let stdout = String::from_utf8(output.stdout)?;
|
||||
let lines: Vec<String> = stdout.lines().map(|s| s.to_string()).collect();
|
||||
|
||||
let mut unmerged_packages = Vec::new();
|
||||
let mut i = 0;
|
||||
while i + 1 < lines.len() {
|
||||
let start_line = &lines[i];
|
||||
let description_line = &lines[i + 1];
|
||||
|
||||
// split into repo + name, version, and install
|
||||
let parts: Vec<&str> = start_line.split_whitespace().collect();
|
||||
let repo_name = parts[0];
|
||||
let version = parts[1].to_string();
|
||||
let installed = Some((parts.len() > 2) && parts[2].starts_with("[installed"));
|
||||
|
||||
// split repo + name into repo and name
|
||||
let repo_name_parts: Vec<&str> = repo_name.split("/").collect();
|
||||
let repository = repo_name_parts[0].to_string();
|
||||
let name = repo_name_parts[1].to_string();
|
||||
|
||||
// strip description
|
||||
let description = Some(description_line.trim().to_string());
|
||||
|
||||
// create package
|
||||
let package = UnmergedPackage {
|
||||
repository,
|
||||
name,
|
||||
version,
|
||||
description,
|
||||
installed,
|
||||
};
|
||||
unmerged_packages.push(package);
|
||||
|
||||
i += 2;
|
||||
}
|
||||
fn test_command(&mut self) -> Result<(), String>
|
||||
where
|
||||
Self: Sized {
|
||||
if self.command_exists { return Ok(()); }
|
||||
let output = Command::new("which").arg(self.command_name()).output();
|
||||
match output {
|
||||
Ok(output) => {
|
||||
if output.status.success() {
|
||||
self.command_exists = true;
|
||||
return Ok(());
|
||||
} else {
|
||||
let err = format!("{} could not be found in path", self.command_name().to_string_lossy());
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
Err(_) => return Err("Existence check could not be run.".to_string()),
|
||||
}
|
||||
}
|
||||
fn remote_search(&self, query: &str) -> Result<Vec<Package>, &str> {
|
||||
if self.command_exists()
|
||||
let output = Command::new
|
||||
Ok(merge_packages(unmerged_packages))
|
||||
}
|
||||
}
|
||||
|
||||
fn process_version(version: &str) -> String {
|
||||
if version.ends_with(".1") {
|
||||
version[..version.len() - 2].to_string()
|
||||
} else {
|
||||
version.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_packages(unmerged: Vec<UnmergedPackage>) -> Vec<Package> {
|
||||
let mut groups: HashMap<String, Vec<UnmergedPackage>> = HashMap::new();
|
||||
for package in unmerged {
|
||||
groups
|
||||
.entry(package.name.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(package);
|
||||
}
|
||||
|
||||
let mut result = Vec::new();
|
||||
for (name, packages) in groups {
|
||||
let processed_version = process_version(&packages[0].version);
|
||||
let repositories: Vec<String> = packages.iter().map(|p| p.repository.clone()).collect();
|
||||
let description = packages[0].description.clone();
|
||||
let installed = packages[0].installed;
|
||||
result.push(Package {
|
||||
name,
|
||||
version: processed_version,
|
||||
repository: repositories,
|
||||
description,
|
||||
installed,
|
||||
});
|
||||
}
|
||||
result
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue