Skip to main content

metapac/backends/
xbps.rs

1use std::collections::{BTreeMap, BTreeSet};
2
3use color_eyre::Result;
4use color_eyre::eyre::eyre;
5use regex::Regex;
6use serde::{Deserialize, Serialize};
7
8use crate::cmd::{run_command, run_command_for_stdout};
9use crate::prelude::*;
10
11#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, derive_more::Display)]
12pub struct Xbps;
13
14#[derive(Debug, Serialize, Deserialize, Default)]
15#[serde(deny_unknown_fields)]
16pub struct XbpsConfig {}
17
18#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
19#[serde(deny_unknown_fields)]
20pub struct XbpsPackageOptions {}
21
22#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
23#[serde(deny_unknown_fields)]
24pub struct XbpsRepoOptions {}
25
26impl Backend for Xbps {
27    type Config = XbpsConfig;
28    type PackageOptions = XbpsPackageOptions;
29    type RepoOptions = XbpsRepoOptions;
30
31    fn invalid_package_help_text() -> String {
32        String::new()
33    }
34
35    fn is_valid_package_name(_: &str) -> Option<bool> {
36        None
37    }
38
39    fn get_all_packages(_: &Self::Config) -> Result<BTreeSet<String>> {
40        Err(eyre!("unimplemented"))
41    }
42
43    fn get_installed_packages(
44        config: &Self::Config,
45    ) -> Result<std::collections::BTreeMap<String, Self::PackageOptions>> {
46        if Self::version(config).is_err() {
47            return Ok(BTreeMap::new());
48        }
49
50        let stdout = run_command_for_stdout(
51            ["xbps-query", "--list-manual-pkgs"],
52            Perms::Same,
53            StdErr::Show,
54        )?;
55
56        // Removes the package version from output
57        let re = Regex::new(r"-[^-]*$")?;
58
59        let packages = stdout
60            .lines()
61            .map(|line| {
62                (
63                    re.replace_all(line, "").to_string(),
64                    Self::PackageOptions {},
65                )
66            })
67            .collect();
68
69        Ok(packages)
70    }
71
72    fn install_packages(
73        packages: &std::collections::BTreeMap<String, Self::PackageOptions>,
74        no_confirm: bool,
75        _: &Self::Config,
76    ) -> Result<()> {
77        if !packages.is_empty() {
78            run_command(
79                ["xbps-install", "--sync"]
80                    .into_iter()
81                    .chain(Some("--yes").filter(|_| no_confirm))
82                    .chain(packages.keys().map(String::as_str)),
83                Perms::Sudo,
84            )?;
85        }
86
87        Ok(())
88    }
89
90    fn uninstall_packages(
91        packages: &BTreeSet<String>,
92        no_confirm: bool,
93        _: &Self::Config,
94    ) -> Result<()> {
95        if !packages.is_empty() {
96            run_command(
97                ["xbps-remove", "--recursive"]
98                    .into_iter()
99                    .chain(Some("--yes").filter(|_| no_confirm))
100                    .chain(packages.iter().map(String::as_str)),
101                Perms::Sudo,
102            )?;
103        }
104
105        Ok(())
106    }
107
108    fn update_packages(
109        packages: &BTreeSet<String>,
110        no_confirm: bool,
111        _: &Self::Config,
112    ) -> Result<()> {
113        if !packages.is_empty() {
114            run_command(
115                ["xbps-install", "--sync", "--update"]
116                    .into_iter()
117                    .chain(Some("--yes").filter(|_| no_confirm))
118                    .chain(packages.iter().map(String::as_str)),
119                Perms::Sudo,
120            )?;
121        }
122
123        Ok(())
124    }
125
126    fn update_all_packages(no_confirm: bool, _: &Self::Config) -> Result<()> {
127        let update = || {
128            run_command(
129                ["xbps-install", "--sync", "--update"]
130                    .into_iter()
131                    .chain(Some("--yes").filter(|_| no_confirm)),
132                Perms::Sudo,
133            )
134        };
135
136        //has to be run twice to do a full update according to the docs:
137        //https://docs.voidlinux.org/xbps/index.html
138        update()?;
139        update()
140    }
141
142    fn clean_cache(config: &Self::Config) -> Result<()> {
143        Self::version(config).map_or(Ok(()), |_| {
144            run_command(
145                ["xbps-remove", "--clean-cache", "--remove-orphans"],
146                Perms::Sudo,
147            )
148        })
149    }
150
151    fn get_installed_repos(_: &Self::Config) -> Result<BTreeMap<String, Self::RepoOptions>> {
152        Ok(BTreeMap::new())
153    }
154
155    fn add_repos(
156        repos: &BTreeMap<String, Self::RepoOptions>,
157        _: bool,
158        _: &Self::Config,
159    ) -> Result<()> {
160        if repos.is_empty() {
161            Ok(())
162        } else {
163            Err(eyre!("unimplemented"))
164        }
165    }
166
167    fn remove_repos(repos: &BTreeSet<String>, _: bool, _: &Self::Config) -> Result<()> {
168        if repos.is_empty() {
169            Ok(())
170        } else {
171            Err(eyre!("unimplemented"))
172        }
173    }
174
175    fn version(_: &Self::Config) -> Result<String> {
176        run_command_for_stdout(["xbps-query", "--version"], Perms::Same, StdErr::Show)
177    }
178}