pacsea/logic/sandbox/
analyze.rs1use crate::logic::sandbox::parse::parse_pkgbuild_deps;
4use crate::logic::sandbox::parse::parse_srcinfo_deps;
5use crate::logic::sandbox::types::{DependencyDelta, SandboxInfo};
6use std::collections::HashSet;
7use std::process::{Command, Stdio};
8
9pub(super) fn analyze_package_from_srcinfo(
20 package_name: &str,
21 srcinfo_text: &str,
22 installed: &HashSet<String>,
23 provided: &HashSet<String>,
24) -> SandboxInfo {
25 let (depends, makedepends, checkdepends, optdepends) = parse_srcinfo_deps(srcinfo_text);
26
27 let depends_delta = analyze_dependencies(&depends, installed, provided);
29 let makedepends_delta = analyze_dependencies(&makedepends, installed, provided);
30 let checkdepends_delta = analyze_dependencies(&checkdepends, installed, provided);
31 let optdepends_delta = analyze_dependencies(&optdepends, installed, provided);
32
33 SandboxInfo {
34 package_name: package_name.to_string(),
35 depends: depends_delta,
36 makedepends: makedepends_delta,
37 checkdepends: checkdepends_delta,
38 optdepends: optdepends_delta,
39 }
40}
41
42pub(super) fn analyze_package_from_pkgbuild(
53 package_name: &str,
54 pkgbuild_text: &str,
55 installed: &HashSet<String>,
56 provided: &HashSet<String>,
57) -> SandboxInfo {
58 let (depends, makedepends, checkdepends, optdepends) = parse_pkgbuild_deps(pkgbuild_text);
59
60 let depends_delta = analyze_dependencies(&depends, installed, provided);
62 let makedepends_delta = analyze_dependencies(&makedepends, installed, provided);
63 let checkdepends_delta = analyze_dependencies(&checkdepends, installed, provided);
64 let optdepends_delta = analyze_dependencies(&optdepends, installed, provided);
65
66 SandboxInfo {
67 package_name: package_name.to_string(),
68 depends: depends_delta,
69 makedepends: makedepends_delta,
70 checkdepends: checkdepends_delta,
71 optdepends: optdepends_delta,
72 }
73}
74
75pub(super) fn analyze_dependencies(
87 deps: &[String],
88 installed: &HashSet<String>,
89 provided: &HashSet<String>,
90) -> Vec<DependencyDelta> {
91 deps.iter()
92 .filter_map(|dep_spec| {
93 let pkg_name = extract_package_name(dep_spec);
95 let is_installed = crate::logic::deps::is_package_installed_or_provided(
97 &pkg_name, installed, provided,
98 );
99
100 if is_installed && is_local_package(&pkg_name) {
102 return None;
103 }
104
105 let installed_version = if is_installed {
107 crate::logic::deps::get_installed_version(&pkg_name).ok()
108 } else {
109 None
110 };
111
112 let version_satisfied = installed_version
114 .as_ref()
115 .is_some_and(|version| crate::logic::deps::version_satisfies(version, dep_spec));
116
117 Some(DependencyDelta {
118 name: dep_spec.clone(),
119 is_installed,
120 installed_version,
121 version_satisfied,
122 })
123 })
124 .collect()
125}
126
127#[must_use]
135pub fn extract_package_name(dep_spec: &str) -> String {
136 let name = dep_spec
138 .find(':')
139 .map_or_else(|| dep_spec, |colon_pos| &dep_spec[..colon_pos]);
140
141 name.trim()
143 .split(">=")
144 .next()
145 .unwrap_or(name)
146 .split("<=")
147 .next()
148 .unwrap_or(name)
149 .split("==")
150 .next()
151 .unwrap_or(name)
152 .split('>')
153 .next()
154 .unwrap_or(name)
155 .split('<')
156 .next()
157 .unwrap_or(name)
158 .trim()
159 .to_string()
160}
161
162fn is_local_package(name: &str) -> bool {
170 let output = Command::new("pacman")
171 .args(["-Qi", name])
172 .env("LC_ALL", "C")
173 .env("LANG", "C")
174 .stdin(Stdio::null())
175 .stdout(Stdio::piped())
176 .stderr(Stdio::piped())
177 .output();
178
179 match output {
180 Ok(output) if output.status.success() => {
181 let text = String::from_utf8_lossy(&output.stdout);
182 for line in text.lines() {
184 if line.starts_with("Repository")
185 && let Some(colon_pos) = line.find(':')
186 {
187 let repo = line[colon_pos + 1..].trim().to_lowercase();
188 return repo == "local" || repo.is_empty();
189 }
190 }
191 }
192 _ => {
193 return false;
195 }
196 }
197
198 false
199}
200
201pub(super) fn get_installed_packages() -> std::collections::HashSet<String> {
209 crate::logic::deps::get_installed_packages()
210}