Further documentation and overhaul of the help menu CLI
- Shields.io badges added to README.md with clarification on functionality present in pacwrap. - Stipulate the requirement for libalpm 14 or greater in README.md - Module documentation written in markdown located in /docs/ for filesystems and permissions modules - Help CLI refactored with format improvements and fixes. - Lock assert calls for container composition, creation, and remote sync - Added value opperand for process module in main frontend module
This commit is contained in:
parent
7d0942496e
commit
91b5c79c5a
26 changed files with 1476 additions and 762 deletions
15
README.md
15
README.md
|
@ -1,5 +1,10 @@
|
|||
# pacwrap
|
||||
|
||||
[![pacwrap](https://shields.io/aur/version/pacwrap?style=for-the-badge&color=599ffb&archlinux&label=pacwrap)](https://aur.archlinux.org/packages/pacwrap/)
|
||||
[![pacwrap-git](https://shields.io/aur/version/pacwrap-git?style=for-the-badge&color=599ffb&logo=archlinux&label=pacwrap-git)](https://aur.archlinux.org/packages/pacwrap-git/)
|
||||
[![License](https://shields.io/crates/l/pacwrap/0.8.0?style=for-the-badge&color=6dfb59)](https://spdx.org/licenses/GPL-3.0-only.html)
|
||||
![MSRV](https://shields.io/crates/msrv/pacwrap/0.8.0?style=for-the-badge&color=fba759)
|
||||
|
||||
<img align="left" src="./assets/logo.svg">
|
||||
|
||||
A package management front-end which utilises libalpm to facilitate the creation of unprivileged, userspace containers with parallelised, filesystem-agnostic deduplication. These containers are constructed via bubblewrap to execute package transactions and launch applications.
|
||||
|
@ -30,6 +35,12 @@ And finally, to install ```neovim``` inside of a fresh, aggregated container cal
|
|||
$ pacwrap -Syucat editor --dep=base neovim
|
||||
```
|
||||
|
||||
To update these containers just created in aggregate:
|
||||
|
||||
```
|
||||
$ pacwrap -Syu
|
||||
```
|
||||
|
||||
More advanced examples along with further documentation of configuration can be found further
|
||||
elaborated upon **[here](./docs/)**.
|
||||
|
||||
|
@ -45,7 +56,7 @@ If a feature you see here is not completed, feel free to submit a PR; or submit
|
|||
| Transaction Agent | Transact within a sandboxed runtime environment | ✅ |
|
||||
| Transaction CLI | Functional | ✅ |
|
||||
| Global Configuration | Functional | ✅ |
|
||||
| Dependency Resolution | Functional, but too liberal to compensate for a lack of conflict resolution | ⚠ |
|
||||
| Package Dependency Resolution | Utilizes a recursive first-depth search algorithm; resilient to cycling | ✅ |
|
||||
| Foreign Database Resolution | Populates foreign package database in aggregate containers | ✅ |
|
||||
| Foreign Database Resolution (Lazy) | Not yet implemented | ❌ |
|
||||
| Conflict Resolution | Not yet implemented | ❌ |
|
||||
|
@ -78,7 +89,7 @@ An online version of the user manual is viewable **[here](./docs/manual.md)**.
|
|||
|
||||
A minimum version of Rust 1.72 is required to build with the following libraries fulfilled by your distribution:
|
||||
```
|
||||
libalpm, libseccomp, libzstd
|
||||
libalpm>=14, libseccomp, libzstd
|
||||
```
|
||||
|
||||
## Packaging requirements
|
||||
|
|
13
docs/dbus/README.md
Normal file
13
docs/dbus/README.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Modules
|
||||
|
||||
This directory contains brief documentation along with examples for each permission module.
|
||||
|
||||
### Table of Contents
|
||||
|
||||
- [Devices](./dev.md)
|
||||
- [Display Servers](./display.md)
|
||||
- [Environment Variables](./env.md)
|
||||
- [Graphics Devices](./gpu.md)
|
||||
- [Networking](./gpu.md)
|
||||
- [Pipewire](./pipewire.md)
|
||||
- [PulseAudio](./pulseaudio.md)
|
10
docs/filesystems/README.md
Normal file
10
docs/filesystems/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Filesystem Modules
|
||||
|
||||
This directory contains brief documentation along with examples for each filesystem module.
|
||||
|
||||
### Table of Contents
|
||||
|
||||
- [Home](./home.md)
|
||||
- [Root](./root.md)
|
||||
- [Mount to root](./to_home.md)
|
||||
- [Mount to home](./to_root.md)
|
19
docs/filesystems/home.md
Normal file
19
docs/filesystems/home.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Mount home
|
||||
|
||||
Mount the container's home directory into the container.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
filesystems:
|
||||
- mount: home
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Provides the binding for the container's home directory. By default, this module
|
||||
will mount `~/.local/share/pacwrap/home/[container_name]` to `$HOME` inside the
|
||||
container at `/home/[container_name]`. Please refer to the [**to_home**](./to_home.md)
|
||||
module for more advanced options.
|
||||
|
||||
This module plays an important role in initializing the container's runtime environment.
|
19
docs/filesystems/root.md
Normal file
19
docs/filesystems/root.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Mount root
|
||||
|
||||
Mount the container's home directory into the container.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
filesystems:
|
||||
- mount: root
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Provides the binding for the container's root filesystem. By default, this module
|
||||
will bind the minimum required at `~/.local/share/pacwrap/root/[container_name]`
|
||||
to allow for a functional userspace inside of the container. Please refer to the
|
||||
[**to_root**](./to_root.md) module for more advanced options.
|
||||
|
||||
This module plays an important role in initializing the container's runtime environment.
|
27
docs/filesystems/to_home.md
Normal file
27
docs/filesystems/to_home.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Mount to home
|
||||
|
||||
Mount filesystem volumes to the container's root directory.
|
||||
|
||||
## Example
|
||||
|
||||
Mount `~/.config/fontconfig/ to the container's `$HOME` directory as read-only; then mount the
|
||||
`~/Downloads` to the container's `$HOME` directory with read-write permissions.
|
||||
|
||||
```
|
||||
filesystems:
|
||||
- mount: to_home
|
||||
volumes:
|
||||
- path: .config/fontconfig
|
||||
- permission: rw
|
||||
path: Downloads
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Mount filesystem volumes from the runtime user's `$HOME` into the container, in the container's `$HOME`
|
||||
directory, unless the destination is otherwise specified with `dest` variable. Pacwrap will terminate
|
||||
with an error condition if the file or directory is not found; or the user is otherwise not sufficiently
|
||||
privileged.
|
||||
|
||||
Specify read/write permissions with a string using the `permission` variable. Valid combinations are
|
||||
abbreviated as following: `ro` for read-only, and `rw` for read-write permissions.
|
28
docs/filesystems/to_root.md
Normal file
28
docs/filesystems/to_root.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Mount to root
|
||||
|
||||
Mount filesystem volumes to the container's root directory.
|
||||
|
||||
## Example
|
||||
|
||||
Mount `/usr/share/icons/`, and `/etc/fonts/`, as read-only to the container; then mount
|
||||
`/media/Storage/Games/Steam` to `/mnt/SteamLibrary`/ in the container with read-write permissions.
|
||||
|
||||
```
|
||||
filesystems:
|
||||
- mount: to_root
|
||||
volumes:
|
||||
- path: /usr/share/fonts
|
||||
- path: /etc/fonts
|
||||
- permission: rw
|
||||
path: /media/Storage/Games/Steam
|
||||
dest: /mnt/SteamLibrary
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Mount filesystem volumes from the host into the container, at the destination mirroring the host, unless
|
||||
the destination is otherwise specified with `dest` variable. Pacwrap will terminate with an error condition
|
||||
if the file or directory is not found; or the user is otherwise not sufficiently privileged.
|
||||
|
||||
Specify read/write permissions with a string using the `permission` variable. Valid value combinations are
|
||||
abbreviated as following: `ro` for read-only, and `rw` for read-write permissions.
|
|
@ -0,0 +1,13 @@
|
|||
# Modules
|
||||
|
||||
This directory contains brief documentation along with examples for each permission module.
|
||||
|
||||
### Table of Contents
|
||||
|
||||
- [Devices](./dev.md)
|
||||
- [Display Servers](./display.md)
|
||||
- [Environment Variables](./env.md)
|
||||
- [Graphics Devices](./gpu.md)
|
||||
- [Networking](./gpu.md)
|
||||
- [Pipewire](./pipewire.md)
|
||||
- [PulseAudio](./pulseaudio.md)
|
22
docs/modules/dev.md
Normal file
22
docs/modules/dev.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Device Module
|
||||
|
||||
Permiss access to devices from the `/dev/` sysfs.
|
||||
|
||||
## Example
|
||||
|
||||
Permiss access to the /dev/input device in the container environment.
|
||||
|
||||
```
|
||||
- module: dev
|
||||
devices:
|
||||
- input
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Mount a list of devices as specified in the `devices` array. Requires the user
|
||||
have unprivileged access to the device in question. Otherwise this module will
|
||||
terminate pacwrap with an error condition.
|
||||
|
||||
In most cases, the automatic permissions should be sufficient with the exception
|
||||
of some USB input devices for particular use cases.
|
14
docs/modules/display.md
Normal file
14
docs/modules/display.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Display Module
|
||||
|
||||
Provide access to display server sockets.
|
||||
|
||||
## Example
|
||||
```
|
||||
permissions:
|
||||
- module: display
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Use this module to automatically detect and bind available display server sockets to the container environment.
|
||||
If no sockets are available, this module will terminate pacwrap with an error condition.
|
25
docs/modules/env.md
Normal file
25
docs/modules/env.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Environment Variables Module
|
||||
|
||||
Set environment variables in the container environment.
|
||||
|
||||
## Example
|
||||
|
||||
Passthrough the environment variable `LANG`, and set the environment variable `QT_X11_NO_MITSHM`.
|
||||
|
||||
```
|
||||
permissions:
|
||||
- module: env
|
||||
variables:
|
||||
- var: LANG
|
||||
- var: QT_X11_NO_MITSHM
|
||||
set: '1'
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Use this module to passthrough or define environment variables in the container environment.
|
||||
When an environment variable is not available in the host environment, this module will
|
||||
provide warning and set a blank value in the target container.
|
||||
|
||||
By default pacwrap, will not passthrough environment variables from the host, unless specified
|
||||
otherwise by the user with the elidation of the `set` parameter when definining a `var`.
|
14
docs/modules/gpu.md
Normal file
14
docs/modules/gpu.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# GPU Module
|
||||
|
||||
Provide available GPUs to the container.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
permissions:
|
||||
- module: gpu
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Use this module to automatically detect and bind available GPUs to the container environment.
|
14
docs/modules/net.md
Normal file
14
docs/modules/net.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Networking Module
|
||||
|
||||
Provide host networking to the container.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
permissions:
|
||||
- module: net
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Use this module to bind all available host networking to the container environment.
|
14
docs/modules/pipewire.md
Normal file
14
docs/modules/pipewire.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Pipewire Module
|
||||
|
||||
Avail pipewire audio devices to the container.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
permissions:
|
||||
- module: pipewire
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Use this module to automatically detect and bind available pipewire sockets to the container environment.
|
14
docs/modules/pulseaudio.md
Normal file
14
docs/modules/pulseaudio.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# PulseAudio Module
|
||||
|
||||
Avail PulseAudio devices to the container.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
permissions:
|
||||
- module: pulseaudio
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Use this module to automatically detect and bind available PulseAudio sockets to the container environment.
|
|
@ -153,11 +153,10 @@ impl AlpmConfigData {
|
|||
|
||||
pub fn instantiate_alpm_agent(config: &Global, remotes: &AlpmConfigData) -> Alpm {
|
||||
let mut handle = Alpm::new("/mnt/fs", "/mnt/fs/var/lib/pacman/").unwrap();
|
||||
let hook_dirs = vec!["/mnt/fs/usr/share/libalpm/hooks/", "/mnt/fs/etc/pacman.d/hooks/"];
|
||||
|
||||
handle.set_logfile("/mnt/share/pacwrap.log").unwrap();
|
||||
handle
|
||||
.set_hookdirs(vec!["/mnt/fs/usr/share/libalpm/hooks/", "/mnt/fs/etc/pacman.d/hooks/"].iter())
|
||||
.unwrap();
|
||||
handle.set_hookdirs(hook_dirs.iter()).unwrap();
|
||||
handle.set_cachedirs(vec!["/mnt/share/cache"].iter()).unwrap();
|
||||
handle.set_gpgdir("/mnt/share/gnupg").unwrap();
|
||||
handle.set_logfile("/mnt/share/pacwrap.log").unwrap();
|
||||
|
@ -256,13 +255,15 @@ fn synchronize_database(cache: &ContainerCache, force: bool, lock: &Lock) -> Res
|
|||
}
|
||||
|
||||
Alpm::release(handle).unwrap();
|
||||
lock.assert()?;
|
||||
|
||||
for i in cache.registered().iter() {
|
||||
let ins: &ContainerHandle = cache.get_instance(i).unwrap();
|
||||
let ins: &ContainerHandle = cache.get_instance(i)?;
|
||||
|
||||
for repo in PACMAN_CONF.repos.iter() {
|
||||
let src = &format!("{}/pacman/sync/{}.db", *DATA_DIR, repo.name);
|
||||
let dest = &format!("{}/var/lib/pacman/sync/{}.db", ins.vars().root(), repo.name);
|
||||
|
||||
if let Err(error) = create_hard_link(src, dest).prepend(|| format!("Failed to hardlink db '{}'", dest)) {
|
||||
error.warn();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
# pacwrap
|
||||
|
||||
[![pacwrap](https://shields.io/aur/version/pacwrap?style=for-the-badge&color=599ffb&archlinux&label=pacwrap)](https://aur.archlinux.org/packages/pacwrap/)
|
||||
[![pacwrap-git](https://shields.io/aur/version/pacwrap-git?style=for-the-badge&color=599ffb&logo=archlinux&label=pacwrap-git)](https://aur.archlinux.org/packages/pacwrap-git/)
|
||||
[![License](https://shields.io/crates/l/pacwrap/0.8.0?style=for-the-badge&color=6dfb59)](https://spdx.org/licenses/GPL-3.0-only.html)
|
||||
![MSRV](https://shields.io/crates/msrv/pacwrap/0.8.0?style=for-the-badge&color=fba759)
|
||||
|
||||
<img align="left" src="../assets/logo.svg">
|
||||
|
||||
A package management front-end which utilises libalpm to facilitate the creation of unprivileged, userspace containers with parallelised, filesystem-agnostic deduplication. These containers are constructed via bubblewrap to execute package transactions and launch applications.
|
||||
|
@ -30,6 +35,12 @@ And finally, to install ```neovim``` inside of a fresh, aggregated container cal
|
|||
$ pacwrap -Syucat editor --dep=base neovim
|
||||
```
|
||||
|
||||
To update these containers just created in aggregate:
|
||||
|
||||
```
|
||||
$ pacwrap -Syu
|
||||
```
|
||||
|
||||
More advanced examples along with further documentation of configuration can be found further
|
||||
elaborated upon **[here](../docs/)**.
|
||||
|
||||
|
@ -45,7 +56,7 @@ If a feature you see here is not completed, feel free to submit a PR; or submit
|
|||
| Transaction Agent | Transact within a sandboxed runtime environment | ✅ |
|
||||
| Transaction CLI | Functional | ✅ |
|
||||
| Global Configuration | Functional | ✅ |
|
||||
| Dependency Resolution | Functional, but too liberal to compensate for a lack of conflict resolution | ⚠ |
|
||||
| Package Dependency Resolution | Utilizes a recursive first-depth search algorithm; resilient to cycling | ✅ |
|
||||
| Foreign Database Resolution | Populates foreign package database in aggregate containers | ✅ |
|
||||
| Foreign Database Resolution (Lazy) | Not yet implemented | ❌ |
|
||||
| Conflict Resolution | Not yet implemented | ❌ |
|
||||
|
@ -78,7 +89,7 @@ An online version of the user manual is viewable **[here](../docs/manual.md)**.
|
|||
|
||||
A minimum version of Rust 1.72 is required to build with the following libraries fulfilled by your distribution:
|
||||
```
|
||||
libalpm, libseccomp, libzstd
|
||||
libalpm>=14, libseccomp, libzstd
|
||||
```
|
||||
|
||||
## Packaging requirements
|
||||
|
|
|
@ -58,6 +58,7 @@ pub fn compose(args: &mut Arguments) -> Result<()> {
|
|||
|
||||
fn delete_containers<'a>(
|
||||
cache: &'a ContainerCache<'a>,
|
||||
lock: &'a Lock,
|
||||
logger: &mut Logger,
|
||||
delete: &Vec<&str>,
|
||||
flags: &TransactionFlags,
|
||||
|
@ -67,9 +68,9 @@ fn delete_containers<'a>(
|
|||
|
||||
if flags.contains(TransactionFlags::NO_CONFIRM) {
|
||||
println!("{} {}{}...{}", *BAR_GREEN, *BOLD, &message, *RESET);
|
||||
delete_roots(cache, logger, delete, force)?;
|
||||
delete_roots(cache, lock, logger, delete, force)?;
|
||||
} else if let Ok(_) = prompt_targets(&delete, &message, false) {
|
||||
delete_roots(cache, logger, delete, force)?;
|
||||
delete_roots(cache, lock, logger, delete, force)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -103,10 +104,12 @@ fn compose_handles<'a>(
|
|||
fn instantiate<'a>(
|
||||
composed: HashMap<&'a str, ContainerHandle<'a>>,
|
||||
mut cache: ContainerCache<'a>,
|
||||
lock: &'a Lock,
|
||||
logger: &mut Logger,
|
||||
) -> Result<ContainerCache<'a>> {
|
||||
lock.assert()?;
|
||||
println!("{} {}Instantiating container{}...{}", *BAR_GREEN, *BOLD, if composed.len() > 1 { "s" } else { "" }, *RESET);
|
||||
|
||||
|
||||
for (instance, handle) in composed {
|
||||
instantiate_container(&handle)?;
|
||||
|
||||
|
@ -220,10 +223,10 @@ fn engage_aggregator<'a>(args: &mut Arguments, lock: &'a Lock) -> Result<()> {
|
|||
}
|
||||
|
||||
if delete.len() > 0 {
|
||||
delete_containers(&cache, &mut logger, &delete, &flags, force)?;
|
||||
delete_containers(&cache, lock, &mut logger, &delete, &flags, force)?;
|
||||
}
|
||||
|
||||
cache = instantiate(compose_handles(&cache, compose)?, cache, &mut logger)?;
|
||||
cache = instantiate(compose_handles(&cache, compose)?, cache, lock, &mut logger)?;
|
||||
acquire_targets(&cache, &mut targets, &mut queue)?;
|
||||
Ok(TransactionAggregator::new(&cache, &mut logger, TransactionType::Upgrade(true, true, false))
|
||||
.assert_lock(lock)?
|
||||
|
|
306
pacwrap/src/help.rs
Normal file
306
pacwrap/src/help.rs
Normal file
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* pacwrap
|
||||
*
|
||||
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use indexmap::IndexSet;
|
||||
use lazy_static::lazy_static;
|
||||
use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||
|
||||
use pacwrap_core::{
|
||||
err,
|
||||
impl_error,
|
||||
utils::{arguments::Operand, is_color_terminal, Arguments},
|
||||
Error,
|
||||
ErrorTrait,
|
||||
};
|
||||
|
||||
mod manual;
|
||||
mod config;
|
||||
pub mod version;
|
||||
|
||||
pub use version::print_version;
|
||||
|
||||
lazy_static! {
|
||||
static ref HELP_ALL: Vec<HelpTopic> = [
|
||||
HelpTopic::Execute,
|
||||
HelpTopic::Sync,
|
||||
HelpTopic::Remove,
|
||||
HelpTopic::Compose,
|
||||
HelpTopic::Query,
|
||||
HelpTopic::Process,
|
||||
HelpTopic::Utils,
|
||||
HelpTopic::List,
|
||||
HelpTopic::Help,
|
||||
HelpTopic::Env,
|
||||
HelpTopic::Version,
|
||||
HelpTopic::Copyright
|
||||
]
|
||||
.into();
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ErrorKind {
|
||||
InvalidTopic(String),
|
||||
}
|
||||
|
||||
impl_error!(ErrorKind);
|
||||
|
||||
impl Display for ErrorKind {
|
||||
fn fmt(&self, fmter: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
Self::InvalidTopic(err) => write!(fmter, "Topic '{}' is not available.", err),
|
||||
}?;
|
||||
|
||||
write!(fmter, "\nTry 'pacwrap -h' for more information on valid operational parameters.")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn help(mut args: &mut Arguments) -> Result<(), Error> {
|
||||
let help = ascertain_help(&mut args)?;
|
||||
let mut buffer = String::new();
|
||||
|
||||
for topic in help.0 {
|
||||
topic.write(&mut buffer, help.1).unwrap();
|
||||
}
|
||||
|
||||
if let HelpLayout::Console = help.1 {
|
||||
print!("\x1b[?7l{}\x1b[?7h", buffer)
|
||||
} else {
|
||||
print!("{}", buffer)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ascertain_help<'a>(args: &'a mut Arguments) -> Result<(IndexSet<&'a HelpTopic>, &'a HelpLayout), Error> {
|
||||
let mut layout = match is_color_terminal() {
|
||||
true => &HelpLayout::Console,
|
||||
false => &HelpLayout::Dumb,
|
||||
};
|
||||
let mut topic: Vec<&HelpTopic> = vec![&HelpTopic::Default];
|
||||
let mut more = false;
|
||||
|
||||
while let Some(arg) = args.next() {
|
||||
match arg {
|
||||
Operand::Long("format") | Operand::Long("help") | Operand::Short('f') | Operand::Short('h') => continue,
|
||||
Operand::Short('m') | Operand::Long("more") => more = true,
|
||||
Operand::ShortPos('f', "man") | Operand::LongPos("format", "man") => layout = &HelpLayout::Man,
|
||||
Operand::ShortPos('f', "ansi") | Operand::LongPos("format", "ansi") => layout = &HelpLayout::Console,
|
||||
Operand::ShortPos('f', "dumb") | Operand::LongPos("format", "dumb") => layout = &HelpLayout::Dumb,
|
||||
Operand::ShortPos('f', "markdown") | Operand::LongPos("format", "markdown") => layout = &HelpLayout::Markdown,
|
||||
Operand::ShortPos('h', "all")
|
||||
| Operand::LongPos("help", "all")
|
||||
| Operand::Short('a')
|
||||
| Operand::Long("all")
|
||||
| Operand::Value("all") => topic.extend(HELP_ALL.iter()),
|
||||
Operand::ShortPos('h', value) | Operand::LongPos("help", value) | Operand::Value(value) =>
|
||||
topic.push(HelpTopic::from(value)?),
|
||||
_ => args.invalid_operand()?,
|
||||
}
|
||||
}
|
||||
|
||||
let len = topic.len();
|
||||
let start = if more || len == 1 || len > 7 { 0 } else { 1 };
|
||||
|
||||
args.set_index(1);
|
||||
Ok((topic.drain(start ..).collect(), layout))
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash)]
|
||||
enum HelpTopic {
|
||||
Sync,
|
||||
Remove,
|
||||
Compose,
|
||||
Execute,
|
||||
Default,
|
||||
Query,
|
||||
Utils,
|
||||
Process,
|
||||
List,
|
||||
Help,
|
||||
Env,
|
||||
Copyright,
|
||||
Version,
|
||||
PacwrapYml,
|
||||
}
|
||||
|
||||
impl HelpTopic {
|
||||
fn from(str: &str) -> Result<&Self, Error> {
|
||||
Ok(match str {
|
||||
"E" | "exec" | "run" => &HelpTopic::Execute,
|
||||
"S" | "sync" | "init" => &HelpTopic::Sync,
|
||||
"P" | "process" | "ps" => &HelpTopic::Process,
|
||||
"L" | "list" | "ls" => &HelpTopic::List,
|
||||
"U" | "utils" => &HelpTopic::Utils,
|
||||
"R" | "remove" => &HelpTopic::Remove,
|
||||
"C" | "compose" => &HelpTopic::Compose,
|
||||
"Q" | "query" => &HelpTopic::Query,
|
||||
"V" | "version" => &HelpTopic::Version,
|
||||
"h" | "help" => &HelpTopic::Help,
|
||||
"env" | "environment" => &HelpTopic::Env,
|
||||
"copyright" => &HelpTopic::Copyright,
|
||||
"synopsis" => &HelpTopic::Default,
|
||||
"pacwrap.yml" => &HelpTopic::PacwrapYml,
|
||||
_ => err!(ErrorKind::InvalidTopic(str.into()))?,
|
||||
})
|
||||
}
|
||||
|
||||
fn write(&self, buf: &mut String, layout: &HelpLayout) -> FmtResult {
|
||||
match self {
|
||||
Self::Default => manual::default(buf, layout),
|
||||
Self::Sync => manual::sync(buf, layout),
|
||||
Self::Remove => manual::remove(buf, layout),
|
||||
Self::Execute => manual::execute(buf, layout),
|
||||
Self::Process => manual::process(buf, layout),
|
||||
Self::Version => manual::version(buf, layout),
|
||||
Self::Env => manual::environment(buf, layout),
|
||||
Self::Compose => manual::compose(buf, layout),
|
||||
Self::Utils => manual::utils(buf, layout),
|
||||
Self::List => manual::list(buf, layout),
|
||||
Self::Help => manual::meta(buf, layout),
|
||||
Self::Query => manual::query(buf, layout),
|
||||
Self::Copyright => manual::copyright(buf, layout),
|
||||
Self::PacwrapYml => config::default(buf, layout),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum HelpLayout {
|
||||
Man,
|
||||
Dumb,
|
||||
Markdown,
|
||||
Console,
|
||||
}
|
||||
|
||||
impl HelpLayout {
|
||||
fn head(&self) -> &str {
|
||||
match self {
|
||||
Self::Console => "[1m",
|
||||
Self::Markdown => "## ",
|
||||
Self::Man => ".SH\n",
|
||||
Self::Dumb => "",
|
||||
}
|
||||
}
|
||||
|
||||
fn sub_bold(&self) -> &str {
|
||||
match self {
|
||||
Self::Console => " [37;1m",
|
||||
Self::Markdown => "#### **",
|
||||
Self::Man => ".TP\n\\fB",
|
||||
Self::Dumb => " ",
|
||||
}
|
||||
}
|
||||
|
||||
fn sub(&self) -> &str {
|
||||
match self {
|
||||
Self::Markdown => "#### ",
|
||||
Self::Man => ".TP\n",
|
||||
Self::Dumb | Self::Console => " ",
|
||||
}
|
||||
}
|
||||
|
||||
fn sub_section(&self) -> &str {
|
||||
match self {
|
||||
Self::Console => " [37;1m",
|
||||
Self::Markdown => "### **",
|
||||
Self::Man => ".SS\n",
|
||||
Self::Dumb => " ",
|
||||
}
|
||||
}
|
||||
|
||||
fn sub_paragraph(&self) -> &str {
|
||||
match self {
|
||||
Self::Console | Self::Dumb => " ",
|
||||
Self::Man => ".PP\n",
|
||||
Self::Markdown => "",
|
||||
}
|
||||
}
|
||||
|
||||
fn tab(&self) -> &str {
|
||||
match self {
|
||||
Self::Console | Self::Dumb => " ",
|
||||
Self::Markdown | Self::Man => "",
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn underline(&self) -> &str {
|
||||
match self {
|
||||
Self::Console => "[4m",
|
||||
Self::Man => "\n.I",
|
||||
Self::Markdown => "<ins>",
|
||||
Self::Dumb => "",
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn reset_underline(&self) -> &str {
|
||||
match self {
|
||||
Self::Console => "[0m",
|
||||
Self::Man => "\n.I",
|
||||
Self::Markdown => "</ins>",
|
||||
Self::Dumb => "",
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&self) -> &str {
|
||||
match self {
|
||||
Self::Console => "[0m",
|
||||
Self::Man => "\\fR",
|
||||
Self::Markdown | Self::Dumb => "",
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_bold(&self) -> &str {
|
||||
match self {
|
||||
Self::Console => "[0m",
|
||||
Self::Man => "\\fR",
|
||||
Self::Markdown => "**",
|
||||
Self::Dumb => "",
|
||||
}
|
||||
}
|
||||
|
||||
fn bold(&self) -> &str {
|
||||
match self {
|
||||
Self::Console => "[37;1m",
|
||||
Self::Man => "\\fB",
|
||||
Self::Markdown => "**",
|
||||
Self::Dumb => "",
|
||||
}
|
||||
}
|
||||
|
||||
fn code(&self) -> &str {
|
||||
match self {
|
||||
Self::Console | Self::Dumb | Self::Man => "",
|
||||
Self::Markdown => "```",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn version_string() -> String {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let release = env!("PACWRAP_BUILD");
|
||||
let head = env!("PACWRAP_BUILDHEAD");
|
||||
let date = env!("PACWRAP_BUILDSTAMP");
|
||||
|
||||
if head.is_empty() {
|
||||
format!("{version} ({date})")
|
||||
} else {
|
||||
format!("{version}-{head}-{release} ({date})")
|
||||
}
|
||||
}
|
160
pacwrap/src/help/config.rs
Normal file
160
pacwrap/src/help/config.rs
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* pacwrap
|
||||
*
|
||||
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::fmt::{Result as FmtResult, Write};
|
||||
|
||||
use crate::help::{version_string, HelpLayout};
|
||||
|
||||
pub fn default(buf: &mut String, layout: &HelpLayout) -> FmtResult {
|
||||
let head = layout.head();
|
||||
let tab = layout.tab();
|
||||
let bold = layout.bold();
|
||||
let sub_bold = layout.sub_bold();
|
||||
let sub_para = layout.sub_paragraph();
|
||||
let reset = layout.reset();
|
||||
let reset_bold = layout.reset_bold();
|
||||
let code = layout.code();
|
||||
let name = env!("CARGO_PKG_NAME");
|
||||
let date = env!("PACWRAP_BUILDSTAMP");
|
||||
|
||||
match layout {
|
||||
HelpLayout::Man => writeln!(
|
||||
buf,
|
||||
".nh\n.TH {name}.yml 2 \"{date}\" \"{name} version_string_placeholder\" \"Pacwrap Configuration Directives\"\n"
|
||||
)?,
|
||||
HelpLayout::Markdown => writeln!(
|
||||
buf,
|
||||
"# Pacwrap Configuration Directives
|
||||
|
||||
This document was generated by the {name} binary with version {} of the program.\n",
|
||||
version_string(),
|
||||
)?,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"{head}NAME{reset}
|
||||
{sub_bold}pacwrap.yml{reset_bold} - pacwrap configuration file.
|
||||
{sub_bold}repositories.conf{reset_bold} - pacman repository file.
|
||||
|
||||
{head}SYNOPSIS{reset}
|
||||
{sub_bold}~/.config/pacwrap/pacwrap.yml{reset_bold}
|
||||
{sub_bold}~/.config/pacwrap/repositories.conf{reset_bold}
|
||||
|
||||
{head}DESCRIPTION{reset}
|
||||
{tab}Pacwrap upon invocation will attempt to deserialise {bold}pacwrap.yml{reset_bold}(2) at the location specified herein
|
||||
{tab}compliant with the XDG Directory Specification. Upon activation of {bold}libalpm{reset_bold}(3), the repositories.conf
|
||||
{tab}file will be deserialised by the pacman_conf crate in order to faciliate the population of package
|
||||
{tab}repositories and mirrors.
|
||||
|
||||
{sub_para}Repository configuration is parsed using {bold}pacman.conf{reset_bold}(5)'s ini format. All other options related the
|
||||
{tab}{bold}libalpm{reset_bold}(3) as defined by {bold}pacman.conf{reset_bold}(5) therein are otherwise ignored. At present by default,
|
||||
{tab}the repository configuration, as defined, references the mirrorlist defined by your system.
|
||||
{tab}This ensures as smooth of an out-of-box experience as humanly possible.
|
||||
|
||||
{tab}Optionally you may specify environment variables, as specified in {bold}pacwrap{reset_bold}(1), to override
|
||||
{tab}these locations. These options are designated for experienced users only.
|
||||
|
||||
{head}EXAMPLE{reset}
|
||||
{code}
|
||||
{tab}config:
|
||||
{tab} logging: Basic
|
||||
{tab} summary: Table
|
||||
{tab} progress:
|
||||
{tab} transact: CondensedForeign
|
||||
{tab} download: CondensedForeign
|
||||
{tab}alpm:
|
||||
{tab} ignore_pkg:
|
||||
{tab} - nvidia-utils
|
||||
{tab} - lib32-nvidia-utils
|
||||
{code}
|
||||
|
||||
{head}SECTIONS{reset}
|
||||
{sub_bold}config:{reset_bold}
|
||||
{sub_para}{tab}Configuration pertaining to {bold}pacwrap{reset_bold}(1) are to be declared within this section.
|
||||
|
||||
{sub_bold}alpm:{reset_bold}
|
||||
{sub_para}{tab}Configuration pertaining to {bold}libalpm{reset_bold}(3) are to be declared within this section.
|
||||
|
||||
{head}CONFIG{reset}
|
||||
{sub_bold}logging{reset_bold}: Basic
|
||||
{tab}{tab}Logging verbosity specified here. Available options are {bold}Basic{reset_bold}, {bold}Verbose{bold}, and {bold}None{reset_bold}.
|
||||
|
||||
{sub_bold}summary{reset_bold}: Basic
|
||||
{tab}{tab}Transaction summary type. Available options are {bold}Basic{reset_bold}, {bold}BasicForeign{reset_bold}, {bold}Table{reset_bold}, and {bold}TableForeign{reset_bold}.
|
||||
|
||||
{tab}{tab}Each option suffixed with the {bold}Foreign{reset_bold} juxtaposition, will take effect only during the
|
||||
{tab}{tab}juxtaposed transaction type with otherwise the opposite effect.
|
||||
|
||||
{sub_bold}progress:{reset_bold}
|
||||
{tab}{tab}Progress types are declared within this subsection.
|
||||
|
||||
{head}PROGRESS{reset}
|
||||
{sub_bold}transact{reset_bold}: CondensedForeign
|
||||
{tab}{tab}Progress type for transaction progress is specified with this option. Available values are
|
||||
{tab}{tab}{bold}Basic{reset_bold}, {bold}Condensed{bold}, {bold}CondensedForeign{reset_bold}, {bold}CondensedLocal{reset_bold}, and {bold}Verbose{reset_bold}.
|
||||
|
||||
{tab}{tab}Each option suffixed with the {bold}Foreign{reset_bold} or {bold}Local{reset_bold} juxtaposition, will take effect only during
|
||||
{tab}{tab}the juxtaposed transaction type with otherwise the opposite effect.
|
||||
|
||||
{sub_bold}download{reset_bold}: Verbose
|
||||
{tab}{tab}Download type for download progress is specified with this option. Available values are
|
||||
{tab}{tab}{bold}Basic{reset_bold}, {bold}Condensed{bold}, {bold}CondensedForeign{reset_bold}, {bold}CondensedLocal{reset_bold}, and {bold}Verbose{reset_bold}.
|
||||
|
||||
{tab}{tab}Each option suffixed with the {bold}Foreign{reset_bold} or {bold}Local{reset_bold} juxtaposition, will take effect only during
|
||||
{tab}{tab}the juxtaposed transaction type with otherwise the opposite effect.
|
||||
|
||||
{head}ALPM{reset}
|
||||
{sub_bold}ignore_pkg:{reset_bold}
|
||||
{tab}{tab}Ignored package(s) are declared herein with a string array.
|
||||
|
||||
{sub_bold}hold_pkg:{reset_bold}
|
||||
{tab}{tab}Held package(s) are declared herein with a string array.
|
||||
|
||||
{sub_bold}sig_level{reset_bold}: Required DatabaseOptional
|
||||
{tab}{tab}Default global signature level - see {bold}pacman.conf{reset_bold}(5) for valid options. Options are declared
|
||||
{tab}{tab}as a singular string value.
|
||||
|
||||
{sub_bold}sig_level_local{reset_bold}: Optional
|
||||
{tab}{tab}Default local signature level - see {bold}pacman.conf{reset_bold}(5) for valid options. Options are declared
|
||||
{tab}{tab}as a single string value.
|
||||
|
||||
{sub_bold}check_space{reset_bold}: true
|
||||
{tab}{tab}Instructs {bold}libalpm{reset_bold}(3), where applicable, to check if there's available space on disk in order
|
||||
{tab}{tab}to facilitate a transaction. Value is declared with a {bold}bool{reset_bold}.
|
||||
|
||||
{sub_bold}download_timeout{reset_bold}: true
|
||||
{tab}{tab}Instructs {bold}libalpm{reset_bold}(3) to timeout downloads from unsatisfactory mirrors. Value is declared with
|
||||
{tab}{tab}a {bold}bool{reset_bold}.
|
||||
|
||||
{sub_bold}parallel_downloads{reset_bold}: 1
|
||||
{tab}{tab}Instructs {bold}libalpm{reset_bold}(3) to parallelise the download queue with a maximum queue amount. Specify an
|
||||
{tab}{tab}{bold}integer{reset_bold} to declare a maximum value.
|
||||
|
||||
{head}SEE ALSO{reset}
|
||||
{tab}{tab}{bold}pacman.conf{reset_bold}(5), {bold}libalpm{reset_bold}(3)
|
||||
|
||||
{head}COPYRIGHT{reset}
|
||||
{tab}Copyright (C) 2023-2024 Xavier R.M.
|
||||
|
||||
{sub_para}This program may be freely redistributed under the
|
||||
{tab}terms of the GNU General Public License v3 only.\n"
|
||||
)
|
||||
}
|
641
pacwrap/src/help/manual.rs
Normal file
641
pacwrap/src/help/manual.rs
Normal file
|
@ -0,0 +1,641 @@
|
|||
/*
|
||||
* pacwrap
|
||||
*
|
||||
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::fmt::{Result as FmtResult, Write};
|
||||
|
||||
use crate::help::{version_string, HelpLayout};
|
||||
|
||||
fn header(buf: &mut String, layout: &HelpLayout) -> FmtResult {
|
||||
let name = env!("CARGO_PKG_NAME");
|
||||
let date = env!("PACWRAP_BUILDSTAMP");
|
||||
|
||||
match layout {
|
||||
HelpLayout::Man => writeln!(buf, ".nh\n.TH {name} 1 \"{date}\" \"{name} version_string_placeholder\" \"User Manual\"\n"),
|
||||
HelpLayout::Markdown => writeln!(
|
||||
buf,
|
||||
"# Pacwrap User Manual
|
||||
|
||||
This document was generated by the {name} binary with version {} of the program.\n",
|
||||
version_string()
|
||||
),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default(buf: &mut String, layout: &HelpLayout) -> FmtResult {
|
||||
let head = layout.head();
|
||||
let tab = layout.tab();
|
||||
let sub_para = layout.sub_paragraph();
|
||||
let sub_bold = layout.sub_bold();
|
||||
let bold = layout.bold();
|
||||
let reset = layout.reset();
|
||||
let reset_bold = layout.reset_bold();
|
||||
|
||||
header(buf, layout)?;
|
||||
writeln!(
|
||||
buf,
|
||||
"{head}NAME{reset}
|
||||
{tab}pacwrap
|
||||
|
||||
{head}SYNOPSIS{reset}
|
||||
{tab}pacwrap [{bold}OPERATION{reset_bold} | {bold}COMMAND MODULE{reset_bold}] [{bold}ARGUMENTS{reset_bold}] [{bold}TARGETS{reset_bold}]
|
||||
|
||||
{head}DESCRIPTION{reset}
|
||||
{sub_para}A package management front-end which utilises libalpm to facilitate the creation of unprivileged,
|
||||
{tab}namespace containers with parallelised, filesystem-agnostic deduplication. These containers
|
||||
{tab}are constructed with bubblewrap to execute package transactions and launch applications.
|
||||
|
||||
{sub_para}This application is designed to allow for the creation and execution of secure, replicable
|
||||
{tab}containerised environments for general-purpose use. CLI and GUI applications are all supported.
|
||||
{tab}Once a container environment is configured, it can be re-established or replicated on any system.
|
||||
|
||||
{head}OPERATIONS{reset}
|
||||
{sub_bold}-S, --sync{reset_bold}
|
||||
{tab}{tab}Synchronize package databases and update packages in target containers.
|
||||
|
||||
{sub_bold}-R, --remove{reset_bold}
|
||||
{tab}{tab}Remove packages from target containers.
|
||||
|
||||
{sub_bold}-Q, --query{reset_bold}
|
||||
{tab}{tab}Query package information from target container.
|
||||
|
||||
{sub_bold}-C, --compose{reset_bold}
|
||||
{tab}{tab}Compose a container from configuration.
|
||||
|
||||
{sub_bold}-P, --process{reset_bold}
|
||||
{tab}{tab}Manage and show status of running container processes.
|
||||
|
||||
{sub_bold}-E, --execute{reset_bold}
|
||||
{tab}{tab}Executes application in target container using bubblewrap.
|
||||
|
||||
{sub_bold}-L, --list{reset_bold}
|
||||
{tab}{tab}List of available containers managed by pacwrap.
|
||||
|
||||
{sub_bold}-U, --utils{reset_bold}
|
||||
{tab}{tab}Invoke miscellaneous utilities to manage containers.
|
||||
|
||||
{sub_bold}-h, --help=<MODULE>{reset_bold}
|
||||
{tab}{tab}Invoke a printout of this manual to {bold}STDOUT{reset_bold}.
|
||||
|
||||
{sub_bold}-V, --version{reset_bold}
|
||||
{tab}{tab}Display version and copyright information in {bold}STDOUT{reset_bold}.\n"
|
||||
)
|
||||
}
|
||||
|
||||
pub fn execute(buf: &mut String, layout: &HelpLayout) -> FmtResult {
|
||||
let head = layout.head();
|
||||
let sub_bold = layout.sub_bold();
|
||||
let tab = layout.tab();
|
||||
let reset = layout.reset();
|
||||
let reset_bold = layout.reset_bold();
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"{head}EXECUTE{reset}
|
||||
{sub_bold}-r, --root{reset_bold}
|
||||
{tab}{tab}Execute operation with fakeroot and fakechroot. Facilitates a command with faked privileges.
|
||||
|
||||
{sub_bold}-s, --shell{reset_bold}
|
||||
{tab}{tab}Invoke a bash shell\n"
|
||||
)
|
||||
}
|
||||
|
||||
pub fn meta(buf: &mut String, layout: &HelpLayout) -> FmtResult {
|
||||
let head = layout.head();
|
||||
let bold = layout.bold();
|
||||
let sub_bold = layout.sub_bold();
|
||||
let reset = layout.reset();
|
||||
let reset_bold = layout.reset_bold();
|
||||
let tab = layout.tab();
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"{head}HELP{reset}
|
||||
{sub_bold}-m, --more{reset_bold}
|
||||
{tab}{tab}When specifying a topic to display, show the default topic in addition to specified options.
|
||||
|
||||
{sub_bold}-f, --format=FORMAT{reset_bold}
|
||||
{tab}{tab}Change output format of help in {bold}STDOUT{reset_bold}. Format options include: 'ansi', 'dumb', 'markdown', and 'man'.
|
||||
{tab}{tab}This option is for the express purposes of generating documentation at build time, and has little utility
|
||||
{tab}{tab}outside the context of package maintenance. 'man' option produces troff-formatted documents for man pages.
|
||||
|
||||
{sub_bold}-a, --all, --help=all{reset_bold}
|
||||
{tab}{tab}Display all help topics.\n"
|
||||
)
|
||||
}
|
||||
|
||||
pub fn sync(buf: &mut String, layout: &HelpLayout) -> FmtResult {
|
||||
let head = layout.head();
|
||||
let bold = layout.bold();
|
||||
let tab = layout.tab();
|
||||
let reset = layout.reset();
|
||||
let reset_bold = layout.reset_bold();
|
||||
let sub = layout.sub();
|
||||
let sub_bold = layout.sub_bold();
|
||||
let sub_sect = layout.sub_section();
|
||||
let sub_para = layout.sub_paragraph();
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"{head}SYNCHRONIZATION{reset}
|
||||
{sub_para}Provides the facilities required to be able to synchronize and create containers in aggregate.
|
||||
|
||||
{sub_bold}-y, --refresh{reset_bold}
|
||||
{tab}{tab}Synchronize remote package databases. Specify up to 2 times to force a refresh.
|
||||
|
||||
{sub_bold}-u, --upgrade{reset_bold}
|
||||
{tab}{tab}Execute aggregate upgrade routine on all or specified containers. Use {bold}-t, --target=<TARGET>{reset_bold} followed by
|
||||
{tab}{tab}a list of packages to specify package targets. Packages applicable to a target {bold}must{reset_bold} only be specified
|
||||
{tab}{tab}after the target operand.
|
||||
|
||||
{sub_bold}-f, --filesystem{reset_bold}
|
||||
{tab}{tab}Force execution of filesystem synchronization target on all or specified containers. In combination
|
||||
{tab}{tab}with {bold}-o/--target-only{reset_bold}, in addition to no other specified targets, filesystem slices will be synchronized
|
||||
{tab}{tab}without package synhcronization on on all applicable containers. This operation is useful for propagation
|
||||
{tab}{tab}of manual filesystem changes to all aggregate containers.
|
||||
|
||||
{sub_bold}-c, --create{reset_bold}
|
||||
{tab}{tab}Create a container with the first specified target. A container type argument is also required.
|
||||
|
||||
{sub_bold}-b, --base{reset_bold}
|
||||
{tab}{tab}Base container type. Specify alongside {bold}-c, --create{reset_bold} to assign this container type during creation.
|
||||
|
||||
{tab}{tab}This container type is used as the base layer for all downstream containers. Only one base container
|
||||
{tab}{tab}dependency per slice or aggregate is supported. Filesystem and package deduplication via slices and
|
||||
{tab}{tab}aggregate containers are recommended, but optional. This container type is not dependant.
|
||||
|
||||
{sub_bold}-s, --slice{reset_bold}
|
||||
{tab}{tab}Slice container type. Specify alongside {bold}-c, --create{reset_bold} to assign this container type during creation.
|
||||
{tab}{tab}Requires a base dependency, and optionally one or more sliced dependencies, to ascertain foreign
|
||||
{tab}{tab}packages and influence ordering of downstream synchronization target(s). Container slicing provides
|
||||
{tab}{tab}the ability to install packages in a lightweight, sliced filesytem, which aid in the deduplication
|
||||
{tab}{tab}of common downstream package and filesystem dependencies.
|
||||
|
||||
{tab}{tab}Useful for graphics drivers, graphical toolkits, fonts, etc.; these are not meant for applications.
|
||||
|
||||
{sub_bold}-a, --aggegrate{reset_bold}
|
||||
{tab}{tab}Aggregate container type. Specify alongside {bold}-c, --create{reset_bold} to this assign container type during creation.
|
||||
{tab}{tab}
|
||||
{tab}{tab}Requires a base dependency, and optionally one or more sliced dependencies, in order to acertain foreign
|
||||
{tab}{tab}packages and amalgamate the target. These containers are ideal for installing software with the aid of
|
||||
{tab}{tab}filesystem and package deduplication.
|
||||
{tab}{tab}
|
||||
{tab}{tab}Useful for all general purpose applications, browsers, e-mail clients, or even terminal user interface
|
||||
{tab}{tab}applications such as IRC clients. It is recommended to base your containers on aggregate type containers.
|
||||
|
||||
{sub_bold}-t, --target=TARGET{reset_bold}
|
||||
{tab}{tab}Specify a target container for the specified operation.
|
||||
|
||||
{sub_bold}-d, --dep=DEPEND{reset_bold}
|
||||
{tab}{tab}Specify a dependent container for the specified operation.
|
||||
|
||||
{sub_bold}-p, --preview{reset_bold}
|
||||
{tab}{tab}Perform a dryrun operation on existing containers to preview changes applicable or otherwise specified.
|
||||
{tab}{tab}Only applicable to
|
||||
|
||||
{sub_bold}-o, --target-only{reset_bold}
|
||||
{tab}{tab}Apply specified operation on the specified target(s) only.
|
||||
|
||||
{sub_bold}--force-foreign{reset_bold}
|
||||
{tab}{tab}Force synchronization of foreign packages on resident container. Useful for when installing
|
||||
{tab}{tab}a new package in an aggregate container without all the prerequisite foreign dependencies
|
||||
{tab}{tab}synchronized to this container's package database.
|
||||
|
||||
{sub_bold}--dbonly{reset_bold}
|
||||
{tab}{tab}Transact on resident containers with a database-only transaction.
|
||||
|
||||
{sub_bold}--noconfirm{reset_bold}
|
||||
{tab}{tab}Override confirmation prompts and confirm all operations.
|
||||
|
||||
{sub_sect}EXAMPLES{reset_bold}
|
||||
{sub}`$ pacwrap -Syucbt base`
|
||||
{tab}{tab}Create a base container named base with no additional packages
|
||||
|
||||
{sub}`$ pacwrap -Syucbt firefox firefox --dep=base,common,nvidia`
|
||||
{tab}{tab}Create aggregate container named firefox with firefox installed.
|
||||
|
||||
{sub}`$ pacwrap -Syut electron element-desktop -t mozilla firefox thunderbird`
|
||||
{tab}{tab}Synchronize package databases and upgrade all containers, as well as install element-desktop
|
||||
{tab}{tab}in the target electron, and install firefox and thunderbird in the target mozilla.
|
||||
|
||||
{sub}`$ pacwrap -Syucst common gtk3 qt6-base --dep=base -cst nvidia nvidia-utils --dep=base,common`
|
||||
{tab}{tab}Create two sliced containers, one named common with the packages gtk3, qt6-base, and another
|
||||
{tab}{tab}named nvidia with the package nvidia-utils.
|
||||
|
||||
{sub}`$ pacwrap -Sof`
|
||||
{tab}{tab}Synchronize filesystem state of all associated containers present in the data directory.\n")
|
||||
}
|
||||
|
||||
pub fn remove(buf: &mut String, layout: &HelpLayout) -> FmtResult {
|
||||
let head = layout.head();
|
||||
let tab = layout.tab();
|
||||
let sub = layout.sub();
|
||||
let bold = layout.bold();
|
||||
let sub_sect = layout.sub_section();
|
||||
let sub_bold = layout.sub_bold();
|
||||
let sub_para = layout.sub_paragraph();
|
||||
let reset = layout.reset();
|
||||
let reset_bold = layout.reset_bold();
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"{head}REMOVE{reset}
|
||||
{sub_para}Remove packages from specified containers.
|
||||
|
||||
{sub_bold}-s, --recursive{reset_bold}
|
||||
{tab}{tab}Recursively remove all target packages with the associated target container. This does
|
||||
{tab}{tab}not apply to packages upstream of a downstream container.
|
||||
|
||||
{sub_bold}-c, --cascade{reset_bold}
|
||||
{tab}{tab}Remove all target packages with the associated target container, including all their
|
||||
{tab}{tab}associated dependencies, provided they are not required by other packages, and are not
|
||||
{tab}{tab}marked as being upstream of the target container.
|
||||
|
||||
{sub_bold}-t, --target=TARGET{reset_bold}
|
||||
{tab}{tab}Specify a target container for the specified operation. At least one container target is
|
||||
{tab}{tab}is required for package removal operations.
|
||||
|
||||
{sub_bold}--force-foreign{reset_bold}
|
||||
{tab}{tab}Force the removal of foreign packages on target container. Useful for cleaning up
|
||||
{tab}{tab}the package database of foreign, upstream dependencies synchronized to the target
|
||||
{tab}{tab}container's package database.
|
||||
|
||||
{sub_bold}-m, --delete{reset_bold}
|
||||
{tab}{tab}Delete root filesystem(s) of specified targets. Shortcout to {bold}-Ur{reset_bold}.
|
||||
|
||||
{sub_bold}-p, --preview{reset_bold}
|
||||
{tab}{tab}Preview operation and perform no transaction.
|
||||
|
||||
{sub_bold}--dbonly{reset_bold}
|
||||
{tab}{tab}Transact on resident containers with a database-only transaction.
|
||||
|
||||
{sub_bold}--noconfirm{reset_bold}
|
||||
{tab}{tab}Override confirmation prompts and confirm all operations.
|
||||
|
||||
{sub_sect}EXAMPLES{reset_bold}
|
||||
{sub}`$ pacwrap -Rt firefox firefox`
|
||||
{tab}{tab}Remove the target package firefox from target container firefox.
|
||||
|
||||
{sub}`$ pacwrap rm firefox`
|
||||
{tab}{tab}Delete the root filesystem for the firefox container.
|
||||
\n"
|
||||
)
|
||||
}
|
||||
|
||||
pub fn compose(buf: &mut String, layout: &HelpLayout) -> FmtResult {
|
||||
let head = layout.head();
|
||||
let tab = layout.tab();
|
||||
let bold = layout.bold();
|
||||
let sub_bold = layout.sub_bold();
|
||||
let reset = layout.reset();
|
||||
let reset_bold = layout.reset_bold();
|
||||
let sub = layout.sub();
|
||||
let sub_sect = layout.sub_section();
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"{head}COMPOSE{reset}
|
||||
{tab}Compose containers from container configuration files. This functionality provides a way
|
||||
{tab}to deterministically compose containers from an established configuration.
|
||||
|
||||
{sub_bold}<FILE_PATH>{reset_bold}
|
||||
{tab}{tab}Compose a container from the specified configuration file on disk. Unless a target is
|
||||
{tab}{tab}otherwise specified, the container will be initialized with a name derived from the
|
||||
{tab}{tab}filename provided.
|
||||
|
||||
{sub_bold}-r, --reinitialize{reset_bold}
|
||||
{tab}{tab}Compose an available, existing container for composition. The pre-existing container root
|
||||
{tab}{tab}will be deleted and the container will be composited from the configuration data enumerated.
|
||||
|
||||
{tab}{tab}Reinitialize container
|
||||
|
||||
{sub_bold}-t, --target=TARGET{reset_bold}
|
||||
{tab}{tab}Specify a target container for the specified operation.
|
||||
|
||||
{sub_bold}-f, --force{reset_bold}
|
||||
{tab}{tab}Disable sanity checks and force removal of container filesystem(s).
|
||||
|
||||
{sub_bold}--reinitialize-all{reset_bold}
|
||||
{tab}{tab}Queues all available, existing containers for composition. All pre-existing container roots
|
||||
{tab}{tab}will be deleted and composited from the available configuration data enumerated.
|
||||
|
||||
{sub_bold}--from-config{reset_bold}
|
||||
{tab}{tab}Instruct pacwrap to populate configuration data from uninitialized containers. Under normal
|
||||
{tab}{tab}circumstances, configuration data will only be populated from containers with configuration
|
||||
{tab}{tab}data and an |