Compare commits
260 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7208cd3f26 | ||
|
|
e54405822f | ||
|
|
74a055dfe6 | ||
|
|
d58d047d2a | ||
|
|
959bf2b102 | ||
|
|
c79d73fdc0 | ||
|
|
6423f59848 | ||
|
|
6cfaa46fff | ||
|
|
759a2cc84c | ||
|
|
6dc564314c | ||
|
|
fad8cd676c | ||
|
|
6ae4bbb810 | ||
|
|
121f744ac6 | ||
|
|
f38f7aa9e6 | ||
|
|
b6cb6c0ef7 | ||
|
|
2f39f46ac0 | ||
|
|
08af0963d2 | ||
|
|
d78781f771 | ||
|
|
1159296a8a | ||
|
|
e913d70b95 | ||
|
|
2ab106c200 | ||
|
|
f4f8fd8a7f | ||
|
|
95ad2669f6 | ||
|
|
4ebfa0eaa6 | ||
|
|
9b459dc49d | ||
|
|
138717d269 | ||
|
|
abb1e2beb8 | ||
|
|
5271109cc4 | ||
|
|
ecd19a6705 | ||
|
|
e8a8c6c096 | ||
|
|
98d4286157 | ||
|
|
ef889e198e | ||
|
|
3288517395 | ||
|
|
ea778aa380 | ||
|
|
3da59ac9d3 | ||
|
|
c01ba154d0 | ||
|
|
53b5a34c18 | ||
|
|
22751b7d95 | ||
|
|
38c93b1ad5 | ||
|
|
d81f6f1f6f | ||
|
|
7734706157 | ||
|
|
73f683533f | ||
|
|
559a8d7b54 | ||
|
|
a2704e5eda | ||
|
|
2aad72fb1a | ||
|
|
ec959799b8 | ||
|
|
b65cc3d261 | ||
|
|
a455240b60 | ||
|
|
573559e250 | ||
|
|
c0224aed25 | ||
|
|
0636c02438 | ||
|
|
c382fbdbf8 | ||
|
|
135e5a91d0 | ||
|
|
0f86de6ade | ||
|
|
b66665a35e | ||
|
|
c7d6f9b88c | ||
|
|
0c6f8f769e | ||
|
|
cb47d1907d | ||
|
|
2428ee46ca | ||
|
|
da67ac9ac9 | ||
|
|
d8c8ae9b66 | ||
|
|
1ef50ddd42 | ||
|
|
292f1713ad | ||
|
|
a78e7b6d71 | ||
|
|
bf541e667d | ||
|
|
8ca92a0bb4 | ||
|
|
7eb7081012 | ||
|
|
733f915ac0 | ||
|
|
9ab0a7833d | ||
|
|
8dfba55e07 | ||
|
|
e5ea12d060 | ||
|
|
fad08ebe29 | ||
|
|
d81070c898 | ||
|
|
287c1eacac | ||
|
|
796b0f790d | ||
|
|
fdda143014 | ||
|
|
1e6629aa08 | ||
|
|
95dce2a22d | ||
|
|
081a8bf1f2 | ||
|
|
651ee7402a | ||
|
|
eeb376a54c | ||
|
|
edd388092f | ||
|
|
5b5643001a | ||
|
|
1716654236 | ||
|
|
de9ef06efa | ||
|
|
630354ac30 | ||
|
|
ca9746fd6b | ||
|
|
bd0527e003 | ||
|
|
830f0fb084 | ||
|
|
abdecad935 | ||
|
|
0a3d49a940 | ||
|
|
1ccdebdcb2 | ||
|
|
7e99ee19c3 | ||
|
|
baf8fce9c6 | ||
|
|
18ec7c1232 | ||
|
|
47ca26cdeb | ||
|
|
6be6cab827 | ||
|
|
b44d46d6bc | ||
|
|
1f746a22d9 | ||
|
|
bd2f9bb6e1 | ||
|
|
e6724de4c8 | ||
|
|
da71fe8bb8 | ||
|
|
57438e11c9 | ||
|
|
0dc86a06ac | ||
|
|
8ceb5ef133 | ||
|
|
cfd636401e | ||
|
|
e5121d4e28 | ||
|
|
481cb47bd0 | ||
|
|
0aff4920b4 | ||
|
|
61981ab4f9 | ||
|
|
1ff1f66b8d | ||
|
|
82472f513a | ||
|
|
6e4d05a4f4 | ||
|
|
2bd088c576 | ||
|
|
6e326592c3 | ||
|
|
0bd23edb67 | ||
|
|
8e0268a1b2 | ||
|
|
8af8c526bc | ||
|
|
189fb58044 | ||
|
|
e1a4b527bc | ||
|
|
a2ba2aa201 | ||
|
|
905ed72380 | ||
|
|
18a26d36e8 | ||
|
|
6e6ea87c1b | ||
|
|
d97065a2e4 | ||
|
|
5dac095982 | ||
|
|
1dabe290b6 | ||
|
|
39dee2be1f | ||
|
|
42f12d216f | ||
|
|
24891dfce3 | ||
|
|
9a796f490b | ||
|
|
561551ba53 | ||
|
|
0fb43271be | ||
|
|
4e671baf51 | ||
|
|
8edd181ab7 | ||
|
|
ff3bdf1e2d | ||
|
|
a868836031 | ||
|
|
2112224e9d | ||
|
|
da977e108c | ||
|
|
dee6ff6a08 | ||
|
|
a0d0a823f1 | ||
|
|
8d11628592 | ||
|
|
d9ce4c5d8e | ||
|
|
ca7bfe6663 | ||
|
|
94a78681b7 | ||
|
|
32cba7c5a3 | ||
|
|
cf160c21f5 | ||
|
|
ff5554d304 | ||
|
|
7bff82da28 | ||
|
|
a94895c9ee | ||
|
|
2a33eafc7c | ||
|
|
8b738b92f5 | ||
|
|
5db7eb1468 | ||
|
|
8e1cde3f01 | ||
|
|
d4813a7fdc | ||
|
|
65fdd716e0 | ||
|
|
f9b2c62ab7 | ||
|
|
1d02860306 | ||
|
|
4f5ce6554a | ||
|
|
a60e16f8e1 | ||
|
|
d8ef209911 | ||
|
|
9530dd9a1b | ||
|
|
41919ab4ad | ||
|
|
4ec3acfee5 | ||
|
|
c0f92f1cfb | ||
|
|
f21b4998a4 | ||
|
|
a6e0cd3287 | ||
|
|
1135776e93 | ||
|
|
3a904dac0e | ||
|
|
311e2d9a75 | ||
|
|
9ebba032da | ||
|
|
e6d48a89ad | ||
|
|
6ad1c1f571 | ||
|
|
76c4151814 | ||
|
|
38c0c29605 | ||
|
|
a368582080 | ||
|
|
7b39fb5d1b | ||
|
|
2f7c44ba21 | ||
|
|
edc4e89368 | ||
|
|
3bbd2a3152 | ||
|
|
9f8816b103 | ||
|
|
a238bd40f5 | ||
|
|
ce7516c681 | ||
|
|
67a89013cd | ||
|
|
f67d8dab2c | ||
|
|
9a8e7ac65f | ||
|
|
d5d7fe5956 | ||
|
|
bc059a3f04 | ||
|
|
d3d4a40992 | ||
|
|
4151fcb35c | ||
|
|
d92c259b70 | ||
|
|
a2048588af | ||
|
|
05e10dcff3 | ||
|
|
335745bd8b | ||
|
|
325c8f45c3 | ||
|
|
a54039effe | ||
|
|
c41c294dba | ||
|
|
613a1a3552 | ||
|
|
59eb91c5f8 | ||
|
|
1eebf453e0 | ||
|
|
6efd9d6fc7 | ||
|
|
923d232f8e | ||
|
|
9a8c20ce1a | ||
|
|
39bc6ea222 | ||
|
|
89db1fcfe7 | ||
|
|
29be92e46a | ||
|
|
b14f923a09 | ||
|
|
b5220f2a5d | ||
|
|
eabc759750 | ||
|
|
c8d14e43d5 | ||
|
|
267a497f4e | ||
|
|
123e33e162 | ||
|
|
83e578369d | ||
|
|
02770cffc6 | ||
|
|
505d62a80d | ||
|
|
e9a5cf31af | ||
|
|
ea299e2b8a | ||
|
|
1969e5bd15 | ||
|
|
591a0730c6 | ||
|
|
e3537fab43 | ||
|
|
d162241a1b | ||
|
|
6105acf78b | ||
|
|
2edea865b0 | ||
|
|
5011637263 | ||
|
|
f7bf18e85c | ||
|
|
51cee6cf6c | ||
|
|
d99b2a759f | ||
|
|
eee3dec43e | ||
|
|
9f8918a30e | ||
|
|
83509c2fe4 | ||
|
|
ffca5484e9 | ||
|
|
59ea13fd11 | ||
|
|
b6082ceaed | ||
|
|
2c62cce12c | ||
|
|
76eff16127 | ||
|
|
039c0ae70d | ||
|
|
730abde329 | ||
|
|
f2a7e7b189 | ||
|
|
2478a189d8 | ||
|
|
b97cf5bf04 | ||
|
|
03792597b0 | ||
|
|
8f10395a88 | ||
|
|
e6ec6a7c8f | ||
|
|
70859e84a2 | ||
|
|
b737252a4e | ||
|
|
5afd92ddfb | ||
|
|
42b8a93292 | ||
|
|
54df716ec1 | ||
|
|
f0ddb4ee29 | ||
|
|
7d981ff6fd | ||
|
|
439f925abf | ||
|
|
8ef411732e | ||
|
|
c5b822c2dd | ||
|
|
ac28d14ed8 | ||
|
|
7f1e35b20a | ||
|
|
04bf81ab05 | ||
|
|
6594945ecf | ||
|
|
01d4af9e3e | ||
|
|
509cfb0540 | ||
|
|
33d2617bbb |
25 changed files with 987 additions and 479 deletions
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
- [ ] Closes #xxxx
|
||||
- [ ] Tests added / passed
|
||||
- [ ] All linting tests pass
|
||||
28
.github/workflows/docs.yml
vendored
Normal file
28
.github/workflows/docs.yml
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
name: Docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install dependencies
|
||||
run: python -m pip install --upgrade pip sphinx
|
||||
- name: Build docs
|
||||
run: sphinx-build -a docs/source docs/build
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs/build
|
||||
publish_branch: gh-pages
|
||||
24
.github/workflows/tests.yml
vendored
Normal file
24
.github/workflows/tests.yml
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
name: Tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install dependencies
|
||||
run: python -m pip install --upgrade pip pytest flake8
|
||||
- name: Run linter
|
||||
run: flake8 --max-line-length=120 scripts/
|
||||
- name: Run tests
|
||||
run: python -m pytest -v
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
__pycache__
|
||||
venv
|
||||
docs/build
|
||||
man8
|
||||
26
Makefile
26
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
# snap-pac
|
||||
# https://github.com/wesbarnett/snap-pac
|
||||
# Copyright (C) 2016 James W. Barnett
|
||||
# Copyright (C) 2016-2021 James W. Barnett
|
||||
|
||||
# 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
|
||||
|
|
@ -20,9 +20,23 @@ PREFIX ?= /usr
|
|||
|
||||
SHARE_DIR = $(DESTDIR)$(PREFIX)/share
|
||||
|
||||
.PHONY: install
|
||||
.PHONY: install test docs
|
||||
|
||||
install:
|
||||
@install -Dm755 scripts/* -t $(SHARE_DIR)/libalpm/scripts/
|
||||
@install -Dm644 hooks/* -t $(SHARE_DIR)/libalpm/hooks/
|
||||
@install -Dm644 LICENSE -t $(SHARE_DIR)/licenses/$(PKGNAME)
|
||||
install: man
|
||||
@install -Dm755 scripts/snap_pac.py $(SHARE_DIR)/libalpm/scripts/snap-pac
|
||||
@install -Dm644 hooks/* -t $(SHARE_DIR)/libalpm/hooks/
|
||||
@install -Dm644 LICENSE -t $(SHARE_DIR)/licenses/$(PKGNAME)/
|
||||
@install -Dm644 man8/* -t $(SHARE_DIR)/man/man8/
|
||||
@install -Dm644 README.md -t $(SHARE_DIR)/doc/$(PKGNAME)/
|
||||
@install -Dm644 extra/snap-pac.ini $(DESTDIR)/etc/snap-pac.ini
|
||||
|
||||
test:
|
||||
@python -m pytest -v .
|
||||
|
||||
man:
|
||||
@cd docs && make man
|
||||
@mkdir -p man8
|
||||
@awk 'NR==33{print ".SH DESCRIPTION"}7' docs/build/man/snap-pac.8 > man8/snap-pac.8
|
||||
|
||||
docs: man
|
||||
@sphinx-build -a docs/source docs/build
|
||||
|
|
|
|||
248
README.md
248
README.md
|
|
@ -1,253 +1,25 @@
|
|||
# snap-pac
|
||||
|
||||
[](https://aur.archlinux.org/packages/snap-pac/)
|
||||
[](https://github.com/wesbarnett/snap-pac/blob/master/LICENSE)
|
||||
[](https://aur.archlinux.org/packages/snap-pac/)
|
||||
## Synopsis
|
||||
|
||||
This causes Arch Linux's pacman to use
|
||||
[snapper](https://wiki.archlinux.org/index.php/Snapper) to automatically take a
|
||||
pre and post snapshot before and after pacman transactions using pacman's hooks
|
||||
feature, similar to how YaST does with OpenSuse. This provides a simple way to
|
||||
undo changes to a system after a pacman transaction.
|
||||
This is a set of [pacman](https://wiki.archlinux.org/index.php/Pacman) hooks and scripts that automatically cause [snapper](http://snapper.io/) to perform a snapshot before pacman transactions.
|
||||
|
||||
* [Installation](#installation)
|
||||
* [Configuration](#configuration)
|
||||
* [Usage](#usage)
|
||||
* [Example](#example)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* [License](#license)
|
||||
* [FAQ](#faq)
|
||||
* [See also](#see-also)
|
||||
* [Did you like this project?](#did-you-like-this-project)
|
||||
Forked from Wes Barnett's solution for my own personal needs. Takes a single screenshot vs. the original's pre/post pair.
|
||||
|
||||
## Installation
|
||||
|
||||
Install [the package from the
|
||||
AUR](https://aur.archlinux.org/packages/snap-pac/).
|
||||
|
||||
### PGP Key
|
||||
|
||||
I have signed the release tarball with my PGP key. You must import my public key
|
||||
to verify the signature if you are using the PKGBUILD in the AUR. This can be
|
||||
done via:
|
||||
|
||||
$ gpg --keyserver hkp://pgp.mit.edu --recv-keys 0xE4B5E45AA3B8C5C3
|
||||
|
||||
The key's fingerprint is `8535CEF3F3C38EE69555BF67E4B5E45AA3B8C5C3`.
|
||||
## [Installation](https://wesbarnett.github.io/snap-pac/installation.html)
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration is done via the snapper configuration files, with extra variables
|
||||
specific to these pacman hooks. The defaults should be suitable for most users,
|
||||
so you shouldn't need to change anything.
|
||||
Most likely, configuration is not needed. By default, the snapper configuration named `root` will have snapshots taken before every pacman transaction.
|
||||
|
||||
The following are possible settings you can place in each snapper configuration
|
||||
file (*e.g.*, `/etc/snapper/configs/root`, etc.):
|
||||
For more information on configuring snap-pac, see [the documentation](https://wesbarnett.github.io/snap-pac/configuration.html).
|
||||
|
||||
* `PACMAN_PRE_POST` - perform pacman pre/post snapshots for this configuration.
|
||||
Default is `"no"` for all configurations, except for the `root` configuration
|
||||
which is `"yes"`.
|
||||
* `PACMAN_CLEANUP_ALGORITHM` - snapper algorithm used in cleaning up the pacman pre/post
|
||||
snapshots. Default is `"number"`.
|
||||
* `PACMAN_PRE_DESCRIPTION` - snapper description used for the pacman pre snapshot.
|
||||
Default is the pacman command that called the snapshot.
|
||||
* `PACMAN_POST_DESCRIPTION` - snapper description used for the pacman post snapshot.
|
||||
Default is the pacman command that called the snapshot.
|
||||
## Documentation
|
||||
|
||||
The following setting can be changed in the snapper configuration file
|
||||
`/etc/conf.d/snapper`:
|
||||
|
||||
* `PACMAN_ABORT_ON_FAIL` - By default this is set to `"no"`. When set to `"yes"`
|
||||
this causes pacman to abort a transaction if the snap-pac pre hook fails. This
|
||||
prevents an upgrade/installation/removal from occurring if a pre snapshot cannot be
|
||||
performed.
|
||||
|
||||
## Usage
|
||||
|
||||
### Taking snapshots
|
||||
|
||||
**Use pacman—and AUR helpers—as normal and watch snapper do its thing.** No
|
||||
bash scripts for you to call. No bash aliases to setup.
|
||||
|
||||
Because these are pacman hooks, it doesn't matter how you call pacman—whether
|
||||
directly, through an AUR helper, or using an alias—snapper will create the
|
||||
snapshots when pacman installs, upgrades, or removes a package. The
|
||||
pacman command used is logged in the snapper description for the
|
||||
snapshots. Additionally the snapshot numbers are output to the screen and to the
|
||||
pacman log for each snapper configuration during the pacman transaction.
|
||||
|
||||
### Undoing a transaction
|
||||
|
||||
To undo changes from a pacman transaction, use `snapper undochange`. See the
|
||||
snapper manpage and the following example.
|
||||
|
||||
If you have severe breakage—like snapper is gone for some reason and you can't
|
||||
get it back—you'll have to resort to more extreme methods, such as taking a
|
||||
snapshot of the pre snapshot and making it the default subvolume or mounting it
|
||||
as `/`. Most likely you'll need to use a live USB to get into a chroot
|
||||
environment to do any of these things. Snapper has a `snapper rollback` feature,
|
||||
but your setup has to be properly configured to use it. The exact procedure
|
||||
depends on your specific setup. Be careful.
|
||||
|
||||
## Example
|
||||
|
||||
Installing the `nano` package as normal:
|
||||
|
||||
# pacman -S nano
|
||||
resolving dependencies...
|
||||
looking for conflicting packages...
|
||||
|
||||
Packages (1) nano-2.5.3-1
|
||||
|
||||
Total Installed Size: 2.14 MiB
|
||||
|
||||
:: Proceed with installation? [Y/n] Y
|
||||
(1/1) checking keys in keyring [######################################] 100%
|
||||
(1/1) checking package integrity [######################################] 100%
|
||||
(1/1) loading package files [######################################] 100%
|
||||
(1/1) checking for file conflicts [######################################] 100%
|
||||
(1/1) checking available disk space [######################################] 100%
|
||||
:: Running pre-transaction hooks...
|
||||
(1/1) Performing snapper pre snapshots...
|
||||
home N/A
|
||||
root 1033 ✓
|
||||
:: Processing package changes...
|
||||
(1/1) installing nano [######################################] 100%
|
||||
:: Running post-transaction hooks...
|
||||
(1/1) Performing snapper post snapshots...
|
||||
home N/A
|
||||
root 1034 ✓
|
||||
|
||||
The snapper snapshot number is given for each snapper configuration that is
|
||||
used (tip: this is also logged in pacman's log). "N/A" means that configuration
|
||||
is not set up for snap-pac (see above).
|
||||
|
||||
And here are the snapshots:
|
||||
|
||||
# snapper -c root list -t pre-post | tail -n 1
|
||||
1033 | 1034 | Fri 22 Apr 2016 01:54:13 PM CDT | Fri 22 Apr 2016 01:54:14 PM CDT | pacman -S nano |
|
||||
|
||||
What changed?
|
||||
|
||||
# snapper -c root status 1033..1034
|
||||
+..... /etc/nanorc
|
||||
c..... /etc/snapper/.snap-pac-pre
|
||||
+..... /usr/bin/nano
|
||||
+..... /usr/bin/rnano
|
||||
+..... /usr/share/doc/nano
|
||||
+..... /usr/share/doc/nano/faq.html
|
||||
+..... /usr/share/doc/nano/fr
|
||||
+..... /usr/share/doc/nano/fr/nano.1.html
|
||||
+..... /usr/share/doc/nano/fr/nanorc.5.html
|
||||
+..... /usr/share/doc/nano/fr/rnano.1.html
|
||||
|
||||
|
||||
I truncated the above output, but it continues. See the manpage for snapper to
|
||||
see what each symbol means. You can also do `snapper diff` in the same
|
||||
way—I'll spare you that one.
|
||||
|
||||
To undo the upgrade:
|
||||
|
||||
# snapper -c root undochange 1033..1034
|
||||
create:0 modify:3 delete:100
|
||||
|
||||
And `nano` is now gone, along with all the files it changed:
|
||||
|
||||
$ pacman -Qi nano
|
||||
error: package 'nano' was not found
|
||||
See the [documentation here](https://wesbarnett.github.io/snap-pac/) or `man 8 snap-pac` after installation.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**==> ERROR: One or more PGP signatures could not be verified!**
|
||||
|
||||
See [PGP Key](#pgp-key) on how to import my PGP key.
|
||||
|
||||
**ERROR: /etc/conf.d/snapper does not exist!**
|
||||
|
||||
*snap-pac* reads in the snapper configurations from `/etc/conf.d/snapper`. It
|
||||
can't do that if the file doesn't exist. I'm not sure what you've done to not
|
||||
have it exist in the default location.
|
||||
|
||||
**WARNING: No snapper configurations found, so not taking any snapshots!**
|
||||
|
||||
No snapper configurations were found in `/etc/conf.d/snapper`. This means you
|
||||
haven't created any configurations yet using `snapper create-config`. See the
|
||||
snapper manpage on how to do this.
|
||||
|
||||
**WARNING: No snapper configurations are set up for snapshots to be taken!**
|
||||
|
||||
Although you seem to have created at least one snapper configuration, none of
|
||||
them are set up for *snap-pac*'s pacman hooks. By default *snap-pac* will take
|
||||
snapshots for the `root` configuration and any other configuration which has
|
||||
`PACMAN_PRE_POST` set to `yes` in its configuration file. This message means you
|
||||
don't have a snapper configuration named `root` (or `PACMAN_PRE_POST` is set to
|
||||
`no` for it) and no other configuration is set up for snapshots. See the
|
||||
configuration section above.
|
||||
|
||||
**WARNING: *prefile* does not exist, so no post snapshot will be taken. If you are initially installing snap-pac, this is normal.**
|
||||
|
||||
*snap-pac* saves the pre snapshot's number in a temporary file. Somehow it got
|
||||
removed before the post snapshot could be taken. When you initially install
|
||||
*snap-pac* the post hook is run, but the pre hook never was, so this message
|
||||
will show up then as well and is safe to ignore in that circumstance.
|
||||
|
||||
**ERROR: Unable to use snapper without dbus. Are you in a chroot environment?**
|
||||
|
||||
Snapper requires dbus. If you chroot into another environment, dbus will not be
|
||||
available, so snapper can't take snapshots.
|
||||
|
||||
**"N/A" next to one of the snapper configurations in the hook's output**
|
||||
|
||||
*snap-pac* lists all snapper configurations it finds and tells you which ones it
|
||||
took a snapshot of along with the snapshot number. "N/A" means the configuration
|
||||
is not set up for snap-pac, so no snapshot was taken for that snapper
|
||||
configuration. See [configuration](#configuration).
|
||||
|
||||
**Other problems**
|
||||
|
||||
If you have a problem not listed here, check the [open
|
||||
issues](https://github.com/wesbarnett/snap-pac/issues) and file new issue if
|
||||
your problem is not listed.
|
||||
|
||||
## FAQ
|
||||
|
||||
**Does snap-pac backup non-btrfs `/boot` partitions?**
|
||||
|
||||
Nope. See
|
||||
[here](https://github.com/wesbarnett/snap-pac/issues/7#issuecomment-245593818)
|
||||
for an example on how to set this up.
|
||||
|
||||
## License
|
||||
|
||||
snap-pac
|
||||
|
||||
Copyright (C) 2016 James W. Barnett
|
||||
|
||||
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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
## See also
|
||||
|
||||
* [ArchWiki Btrfs article](https://wiki.archlinux.org/index.php/Btrfs)
|
||||
* [ArchWiki Snapper article](https://wiki.archlinux.org/index.php/Snapper)
|
||||
* [Btrfs homepage](https://wiki.archlinux.org/index.php/Btrfs)
|
||||
* [snapper homepage](http://snapper.io/)
|
||||
* `man alpm-hooks`
|
||||
* `man btrfs`
|
||||
* `man snapper`
|
||||
|
||||
## Did you like this project?
|
||||
|
||||
If you like this project, send me a Bitcoin tip: `1PZziQoUJfhMKZC8gXQZtS5ebHWMba3Geb`
|
||||
After reviewing the documentation, [check the issues page] and file a new issue if your problem is not covered.
|
||||
|
||||
[check the issues page]: https://codeberg.org/ak95/snap-pac/issues
|
||||
|
|
|
|||
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
65
docs/source/conf.py
Normal file
65
docs/source/conf.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'snap-pac'
|
||||
copyright = '2021, Wes Barnett, PhD'
|
||||
author = 'Wes Barnett, PhD'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'alabaster'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
html_theme_options = {
|
||||
'badge_branch': 'main',
|
||||
'description': 'pacman hooks that use snapper to create pre/post btrfs snapshots',
|
||||
'fixed_sidebar': True,
|
||||
'github_banner': True,
|
||||
'github_user': 'wesbarnett',
|
||||
'github_repo': 'snap-pac',
|
||||
'github_type': 'star'
|
||||
}
|
||||
|
||||
man_pages = [("index", "snap-pac", "Pacman hooks that use snapper to create pre/post btrfs snapshots like openSUSE's YaST", "Wes Barnett", "8")]
|
||||
manpages_url = 'https://man.archlinux.org/man/{page}.{section}'
|
||||
99
docs/source/configuration.rst
Normal file
99
docs/source/configuration.rst
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
Configuration
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
Configuration is done via Python ini configuration files. The defaults
|
||||
should be suitable for most users, so you may not need to do any configuration at all.
|
||||
By default only the ``root`` snapper configuration is snapshotted.
|
||||
|
||||
A commented example configuration files is located at ``/etc/snap-pac.ini``.
|
||||
|
||||
Edit with your favorite editor. The file is commented and should be
|
||||
self-explanatory.
|
||||
|
||||
Each section corresponds with a snapper configuration. Add additional sections to add
|
||||
other snapper configurations to be snapshotted. By default, only the root configuration
|
||||
is snapshotted. Additionally you can add a section named ``DEFAULT`` with options that
|
||||
apply to all snapper configurations unless overridden in a later section.
|
||||
|
||||
Each section can have the following entries:
|
||||
|
||||
* ``desc_limit`` - integer; maximum length of description string before being truncated.
|
||||
Default: 72
|
||||
* ``important_packages`` - list of strings; names of packages that if involved in a pacman
|
||||
transaction will add ``important=yes`` to the snapper userdata for the pair of
|
||||
snapshots. Default: []
|
||||
* ``important_commands`` - list of strings; parent commands that will add
|
||||
``important=yes`` to the snapper userdata for the pair of snapshots. Default: []
|
||||
* ``pre_description`` - string; description for the pre snapshot. Default: the parent
|
||||
command that called the pacman hook.
|
||||
* ``post_description`` - string; description for the post snapshot. Default: space
|
||||
separated list of packages that were installed, upgraded, or removed.
|
||||
* ``snapshot`` - boolean; whether or not to snapshot the configuration. Default: True for
|
||||
``root`` configuration; False otherwise.
|
||||
* ``userdata`` - list of strings; key-value pairs that will be added to the userdata for
|
||||
the pair of snapshots. Default: []
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Turn off snapshots for ``root`` configuration and turn on for ``home`` configuration:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[root]
|
||||
snapshot = False
|
||||
|
||||
[home]
|
||||
snapshot = True
|
||||
|
||||
|
||||
Set the snapper to add the userdata ``important=yes`` for every snapshot in the ``root``
|
||||
configuration when a system upgrade is performed:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[root]
|
||||
important_commands = ["pacman -Syu"]
|
||||
|
||||
Set the snapper to add the userdata ``important=yes`` for every snapshot in the ``root``
|
||||
configuration when a pacman transaction handles the packages ``linux`` and ``linux-lts``:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[root]
|
||||
important_packages = ["linux", "linux-lts"]
|
||||
|
||||
Here's a fuller example, with several options set for different configurations. In this
|
||||
case the ``root`` configuration snapshot will have ``important=yes`` when ``linux`` and
|
||||
``linux-lts`` packages are part of the transaction. Additionally when full system
|
||||
upgrades are performed ``root`` snapshots will be marked ``important=yes``. Note that
|
||||
you don't have to add ``snapshot = True`` for the ``root`` configuration since that is
|
||||
the default.
|
||||
|
||||
This file also turns one snapshots for the ``home`` snapper configuration and adds the
|
||||
userdata ``requestid=42,user=arthur`` to all snapshots for that configuration.
|
||||
Additionally the post snapshot description is overridden.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[root]
|
||||
important_packages = ["linux", "linux-lts"]
|
||||
important_commands = ["pacman -Syu"]
|
||||
|
||||
[home]
|
||||
snapshot = True
|
||||
userdata = ["requestid=42", "user=arthur"]
|
||||
post_description = "pacman transaction post snapshot"
|
||||
|
||||
Environment Variables
|
||||
=====================
|
||||
|
||||
To temporarily prevent snapshots from being performed for a single pacman
|
||||
command, set the environment variable ``SNAP_PAC_SKIP``. For example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo SNAP_PAC_SKIP=y pacman -Syu
|
||||
91
docs/source/examples.rst
Normal file
91
docs/source/examples.rst
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
Example
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
Here is an example of how the snapshots are created and how to rollback and pacman
|
||||
transaction. Here the nano package is installed:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pacman -S nano
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
resolving dependencies...
|
||||
looking for conflicting packages...
|
||||
|
||||
Packages (1) nano-2.5.3-1
|
||||
|
||||
Total Installed Size: 2.14 MiB
|
||||
|
||||
:: Proceed with installation? [Y/n] Y
|
||||
(1/1) checking keys in keyring [######################################] 100%
|
||||
(1/1) checking package integrity [######################################] 100%
|
||||
(1/1) loading package files [######################################] 100%
|
||||
(1/1) checking for file conflicts [######################################] 100%
|
||||
(1/1) checking available disk space [######################################] 100%
|
||||
:: Running pre-transaction hooks...
|
||||
(1/1) Performing snapper pre snapshots for the following configurations...
|
||||
=> root: 1033
|
||||
:: Processing package changes...
|
||||
(1/1) installing nano [######################################] 100%
|
||||
:: Running post-transaction hooks...
|
||||
(1/1) Performing snapper post snapshots for the following configurations...
|
||||
=> root: 1034
|
||||
|
||||
The snapper snapshot number is given for each snapper configuration that is used. This
|
||||
is also logged in pacman's log.
|
||||
|
||||
Here are the snapshots created before and after the pacman transaction:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
snapper -c root list -t pre-post | tail -n 1
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
1033 | 1034 | Fri 22 Apr 2016 01:54:13 PM CDT | Fri 22 Apr 2016 01:54:14 PM CDT | pacman -S nano |
|
||||
|
||||
Here is what changed during the transaction:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
snapper -c root status 1033..1034
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
+..... /etc/nanorc
|
||||
c..... /etc/snapper/.snap-pac-pre
|
||||
+..... /usr/bin/nano
|
||||
+..... /usr/bin/rnano
|
||||
+..... /usr/share/doc/nano
|
||||
+..... /usr/share/doc/nano/faq.html
|
||||
+..... /usr/share/doc/nano/fr
|
||||
+..... /usr/share/doc/nano/fr/nano.1.html
|
||||
+..... /usr/share/doc/nano/fr/nanorc.5.html
|
||||
+..... /usr/share/doc/nano/fr/rnano.1.html
|
||||
|
||||
The above output is truncated, but it continues. See :manpage:`snapper(8)` to for what each
|
||||
symbol means. You can also do ``snapper diff`` in the same way.
|
||||
|
||||
Then, to undo the pacman transaction:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
snapper -c root undochange 1033..1034
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
create:0 modify:3 delete:100
|
||||
|
||||
Now nano is no longer installed, along with all the files it changed:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pacman -Qi nano
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
error: package 'nano' was not found
|
||||
47
docs/source/faq.rst
Normal file
47
docs/source/faq.rst
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
FAQ
|
||||
===
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
**Does snap-pac backup non-btrfs /boot partitions?**
|
||||
|
||||
No, but you can add a hook that does it for you. It would be something like the following:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[Trigger]
|
||||
Operation = Upgrade
|
||||
Operation = Install
|
||||
Operation = Remove
|
||||
Type = Package
|
||||
Target = linux
|
||||
|
||||
[Action]
|
||||
Description = Backing up /boot...
|
||||
When = PreTransaction
|
||||
Exec = /usr/bin/rsync -avzq --delete /boot /.bootbackup
|
||||
|
||||
Note that you will probably want to name the file with a numbered prefix less than
|
||||
``05`` so that it is run before the snap-pac pre snapshot takes place. That will ensure
|
||||
that the snapshot taken will have the boot partition back-up corresponding with the
|
||||
state of the system. For example, you could name it ``04-backupboot.hook``.
|
||||
|
||||
|
||||
**How do I link old kernel modules automatically when the kernel is upgraded?**
|
||||
|
||||
This behavior is no longer a part of this package. Use a pacman hook like the following:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[Trigger]
|
||||
Operation = Upgrade
|
||||
Operation = Install
|
||||
Operation = Remove
|
||||
Type = Package
|
||||
Target = linux
|
||||
|
||||
[Action]
|
||||
Description = Symlinking old kernel modules...
|
||||
When = PostTransaction
|
||||
Exec = /usr/bin/bash -c "find /usr/lib/modules -xtype l -delete; ln -sv /.snapshots/$(snapper -c root list | awk 'END{print $1}')/snapshot/usr/lib/modules/$(uname -r) /usr/lib/modules/"
|
||||
79
docs/source/index.rst
Normal file
79
docs/source/index.rst
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
.. snap-pac documentation master file, created by
|
||||
sphinx-quickstart on Thu Mar 11 19:49:12 2021.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
snap-pac
|
||||
========
|
||||
|
||||
This is a set of `pacman <https://archlinux.org/pacman/>`_ hooks and script that causes
|
||||
`snapper <http://snapper.io/>`_ to automatically take a pre and post snapshot before and
|
||||
after pacman transactions, similar to how `YaST <https://yast.opensuse.org/>`_ does with
|
||||
OpenSuse. This provides a simple way to undo changes to a system after a pacman
|
||||
transaction.
|
||||
|
||||
Because these are pacman hooks, it doesn't matter how you call pacman—whether
|
||||
directly, through an AUR helper, or using an alias—snapper will create the snapshots
|
||||
when pacman installs, upgrades, or removes a package. The pacman command used is
|
||||
logged in the snapper description for the snapshots. Additionally the snapshot numbers
|
||||
are output to the screen and to the pacman log for each snapper configuration during the
|
||||
pacman transaction, so that the user can easily find which changes he or she may want to
|
||||
revert.
|
||||
|
||||
.. code-block:: none
|
||||
:caption: When you run pacman, the snapper pre/post snapshots are created automatically. For a fuller example see :doc:`examples`.
|
||||
:emphasize-lines: 17,18,25,26
|
||||
|
||||
$ sudo pacman -S vim
|
||||
resolving dependencies...
|
||||
looking for conflicting packages...
|
||||
|
||||
Packages (1) vim-8.2.2489-1
|
||||
|
||||
Total Installed Size: 3.79 MiB
|
||||
Net Upgrade Size: 0.00 MiB
|
||||
|
||||
:: Proceed with installation? [Y/n]
|
||||
(1/1) checking keys in keyring [############] 100%
|
||||
(1/1) checking package integrity [############] 100%
|
||||
(1/1) loading package files [############] 100%
|
||||
(1/1) checking for file conflicts [############] 100%
|
||||
(1/1) checking available disk space [############] 100%
|
||||
:: Running pre-transaction hooks...
|
||||
(1/1) Performing snapper pre snapshots for the following configurations...
|
||||
==> root: 7394
|
||||
:: Processing package changes...
|
||||
(1/1) installing vim [############] 100%
|
||||
:: Running post-transaction hooks...
|
||||
(1/4) Arming ConditionNeedsUpdate...
|
||||
(2/4) Updating icon theme caches...
|
||||
(3/4) Updating the desktop file MIME type cache...
|
||||
(4/4) Performing snapper post snapshots for the following configurations...
|
||||
==> root: 7395
|
||||
|
||||
|
||||
To undo changes from a pacman transaction, use ``snapper undochange``. See the :manpage:`snapper(8)`
|
||||
for more details as well as examples.
|
||||
|
||||
If you have severe breakage—like snapper is gone for some reason and you can't get it
|
||||
back—you'll have to resort to more extreme methods, such as taking a snapshot of the pre
|
||||
snapshot and making it the default subvolume or mounting it as /. Most likely you'll
|
||||
need to use a live USB to get into a chroot environment to do any of these things.
|
||||
Snapper has a ``snapper rollback`` feature, but your setup has to be properly configured to
|
||||
use it. The exact procedure depends on your specific setup. Be careful.
|
||||
|
||||
Note that the pre transaction hooks occur before the pacman transaction but after the
|
||||
pacman database is synced, if applicable. In other words, if you run `pacman -Syu` and
|
||||
roll back the upgrade according to the above instructions, you will not have rolled back
|
||||
the pacman database to the previous state. Thus, if, after upgrading and rolling back
|
||||
the upgrade, you then install a package, it will possibly be a partial upgrade, which is
|
||||
unsupported.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
installation
|
||||
configuration
|
||||
examples
|
||||
troubleshooting
|
||||
faq
|
||||
66
docs/source/installation.rst
Normal file
66
docs/source/installation.rst
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
Installation
|
||||
============
|
||||
|
||||
Install the ``snap-pac`` package using pacman:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pacman -S snap-pac
|
||||
|
||||
Alternatively download the `latest release and signature
|
||||
<https://github.com/wesbarnett/snap-pac/releases>`_. Then, verify the download:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
gpg --verify snap-pac-<version>.tar.gz.sig
|
||||
|
||||
where ``<version>`` is the version number you downloaded.
|
||||
|
||||
Finally, run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make install
|
||||
|
||||
I have signed the release tarball and commits with my PGP key. Starting with release
|
||||
2.2, the tarballs are signed with my key with fingerprint
|
||||
``F7B28C61944FE30DABEEB0B01070BCC98C18BD66``.
|
||||
|
||||
For previous releases, the key's fingerprint was
|
||||
``8535CEF3F3C38EE69555BF67E4B5E45AA3B8C5C3``.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
``python``, ``pacman``, and ``snapper`` are all required.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
For testing, ``pytest`` is required. To run the tests do:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make test
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Typically, you will not need to build the documentation on your own and can simply
|
||||
access it by visiting the `online documentation
|
||||
<https://wesbarnett.github.io/snap-pac/>`_ or by accessing the manpage:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
man 8 snap-pac
|
||||
|
||||
To build the documentation, ``sphinx`` is required. To build the documentation you can
|
||||
do:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make docs
|
||||
|
||||
The resulting html documentation will then be located at ``docs/build/index.html``.
|
||||
Additionally, this generates the manpage which will be located under ``man8``.
|
||||
23
docs/source/troubleshooting.rst
Normal file
23
docs/source/troubleshooting.rst
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Troubleshooting
|
||||
===============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
**snap-pac is only taking snapshots of the root configuration.**
|
||||
|
||||
That's the default behavior. See :doc:`configuration`.
|
||||
|
||||
**No snapshots are being taken when I run pacman.**
|
||||
|
||||
No snapper configurations are set up for snap-pac's pacman hooks. By default snap-pac
|
||||
will take snapshots for the root configuration and any other configuration which has
|
||||
SNAPSHOT set to yes in its configuration file. See :doc:`configuration`.
|
||||
|
||||
**After restoring snapshot from snap-pac, the pacman database is locked.**
|
||||
|
||||
The pre/post snaphots are taken while pacman is running, so this is expected. Follow
|
||||
the instructions pacman gives you (*e.g.*, removing the lock file). You can add the
|
||||
database lock file to a snapper filter so that snapper won't consider it when
|
||||
performing snapper diff, snapper status, snapper undochange, etc. See the Filters
|
||||
section in :manpage:`snapper(8)` for more information.
|
||||
38
extra/snap-pac.ini
Normal file
38
extra/snap-pac.ini
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# snap-pac example configuration file
|
||||
# see snap-pac(8) for more details
|
||||
|
||||
# Each section corresponds with a snapper configuration. Add additional sections to add
|
||||
# other configurations to be snapshotted. By default, only the root configuration is snapshotted.
|
||||
# Create a section named [DEFAULT] to have a setting apply for all snapper configurations
|
||||
|
||||
## Uncomment to set parameters for snapper configuration named root
|
||||
#[root]
|
||||
|
||||
## How many characters to limit the description for snapper.
|
||||
## Default is 72
|
||||
#desc_limit = 72
|
||||
|
||||
## Whether or not to take snapshots of this snapper configuration
|
||||
## Default is True for root configuration and False for all other configurations
|
||||
#snapshot = True
|
||||
|
||||
## What snapper cleanup algorithm to use
|
||||
## Default is number
|
||||
#cleanup_algorithm = number
|
||||
|
||||
## Uncomment to add "important=yes" to userdata for snapshots referring to these packages
|
||||
## Default is []
|
||||
#important_packages = ["linux", "linux-lts"]
|
||||
|
||||
## Uncomment to add "important=yes" to userdata for snapshots that were created with the following commands
|
||||
## Default is []
|
||||
#important_commands = ["pacman -Syu"]
|
||||
|
||||
## Add custom userdata. Each key-value pair should be an item in the list
|
||||
## Default is []
|
||||
#userdata = ["key=value","foo=bar"]
|
||||
|
||||
## Example for another snapper configuration named "home"
|
||||
# [home]
|
||||
## Default is False
|
||||
# snapshot = True
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# snap-pac
|
||||
# https://github.com/wesbarnett/snap-pac
|
||||
# Copyright (C) 2016 James W. Barnett
|
||||
# Copyright (C) 2016, 2017, 2018 James W. Barnett
|
||||
|
||||
# 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
|
||||
|
|
@ -24,8 +24,9 @@ Type = Package
|
|||
Target = *
|
||||
|
||||
[Action]
|
||||
Description = Performing snapper pre snapshots...
|
||||
Description = Taking snapper snapshot before installing...
|
||||
Depends = snap-pac
|
||||
When = PreTransaction
|
||||
Exec = /usr/share/libalpm/scripts/snap-pac pre
|
||||
AbortOnFail
|
||||
Exec = /usr/share/libalpm/scripts/snap-pac
|
||||
NeedsTargets
|
||||
AbortOnFail
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# snap-pac
|
||||
# https://github.com/wesbarnett/snap-pac
|
||||
# Copyright (C) 2016 James W. Barnett
|
||||
# Copyright (C) 2016, 2017, 2018 James W. Barnett
|
||||
|
||||
# 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
|
||||
|
|
@ -22,7 +22,7 @@ Type = Package
|
|||
Target = snap-pac
|
||||
|
||||
[Action]
|
||||
Description = NOTE: You are removing snap-pac. No post transaction snapshots will be taken.
|
||||
Description = You are removing snap-pac. No post transaction snapshots will be taken.
|
||||
Depends = snap-pac
|
||||
When = PreTransaction
|
||||
Exec = /usr/share/libalpm/scripts/snap-pac-remove
|
||||
Exec = /usr/bin/bash -c "rm -f /tmp/snap-pac-pre_*"
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
# snap-pac
|
||||
# https://github.com/wesbarnett/snap-pac
|
||||
# Copyright (C) 2016 James W. Barnett
|
||||
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
[Trigger]
|
||||
Operation = Upgrade
|
||||
Operation = Install
|
||||
Operation = Remove
|
||||
Type = Package
|
||||
Target = *
|
||||
|
||||
[Action]
|
||||
Description = Performing snapper post snapshots...
|
||||
Depends = snap-pac
|
||||
When = PostTransaction
|
||||
Exec = /usr/share/libalpm/scripts/snap-pac post
|
||||
149
scripts/snap-pac
149
scripts/snap-pac
|
|
@ -1,149 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# snap-pac
|
||||
# https://github.com/wesbarnett/snap-pac
|
||||
# Copyright (C) 2016 James W. Barnett
|
||||
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# Main script.
|
||||
|
||||
set -e
|
||||
|
||||
SNAPPER_CONFIG_FILE=/etc/conf.d/snapper
|
||||
|
||||
ERRORMSG=" \033[00;31mERROR:\033[00m"
|
||||
WARNINGMSG=" \033[00;33mWARNING:\033[00m"
|
||||
|
||||
PACMAN_ABORT_ON_FAIL="no"
|
||||
|
||||
# Virtual console fonts don't have the unicode checkmark
|
||||
if [[ "$TERM" == "linux" ]]; then
|
||||
checkmark="done"
|
||||
else
|
||||
checkmark="✓"
|
||||
fi
|
||||
|
||||
if [[ -f "$SNAPPER_CONFIG_FILE" ]]; then
|
||||
source "$SNAPPER_CONFIG_FILE"
|
||||
else
|
||||
echo -e "$ERRORMSG $SNAPPER_CONFIG_FILE does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo -e "$ERRORMSG Script must be run as root."
|
||||
if [[ $PACMAN_ABORT_ON_FAIL == "yes" ]]; then
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -d /var/run/dbus ]]; then
|
||||
echo -e "$ERRORMSG Unable to use snapper without dbus. Are you in a chroot environment?"
|
||||
if [[ $PACMAN_ABORT_ON_FAIL == "yes" ]]; then
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo -e "$ERRORMSG Only one argument should be passed to this script."
|
||||
if [[ $PACMAN_ABORT_ON_FAIL == "yes" ]]; then
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $1 != "pre" ]] && [[ $1 != "post" ]]; then
|
||||
echo -e "$ERRORMSG First argument should either be 'pre' or 'post'."
|
||||
if [[ $PACMAN_ABORT_ON_FAIL == "yes" ]]; then
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$SNAPPER_CONFIGS" ]]; then
|
||||
echo -e "$ERRORMSG No snapper configurations found, so not taking any snapshots!"
|
||||
if [[ $PACMAN_ABORT_ON_FAIL == "yes" ]]; then
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
declare -r pre_or_post=$1
|
||||
declare pacman_cmd
|
||||
pacman_cmd="$(sed 's./usr/bin/pacman.pacman.g' <(ps -C pacman -o args=))"
|
||||
|
||||
declare -i x=0
|
||||
for CONFIG in $SNAPPER_CONFIGS; do
|
||||
|
||||
# Set defaults
|
||||
PACMAN_PRE_POST="no"
|
||||
if [[ $CONFIG == "root" ]]; then
|
||||
PACMAN_PRE_POST="yes"
|
||||
fi
|
||||
PACMAN_PRE_DESCRIPTION="$pacman_cmd"
|
||||
PACMAN_POST_DESCRIPTION="$pacman_cmd"
|
||||
PACMAN_CLEANUP_ALGORITHM="number"
|
||||
|
||||
# Source snapper configuration to override defaults
|
||||
source /etc/snapper/configs/"$CONFIG"
|
||||
|
||||
echo -n " $CONFIG "
|
||||
|
||||
if [[ $PACMAN_PRE_POST == "yes" ]]; then
|
||||
|
||||
prefile="/tmp/snap-pac-pre_$CONFIG"
|
||||
snapper_cmd="snapper --config $CONFIG create --type $pre_or_post --cleanup-algorithm $PACMAN_CLEANUP_ALGORITHM"
|
||||
|
||||
x=$((x+1))
|
||||
|
||||
if [[ "$pre_or_post" == "pre" ]]; then
|
||||
$snapper_cmd --description "$PACMAN_PRE_DESCRIPTION" --print-number > "$prefile"
|
||||
echo -n "$(< "$prefile") "
|
||||
echo "$checkmark"
|
||||
elif [[ -f $prefile ]]; then
|
||||
postnum=$($snapper_cmd --description "$PACMAN_POST_DESCRIPTION" --print-number --pre-number "$(< "$prefile")")
|
||||
echo -n "$postnum "
|
||||
echo "$checkmark"
|
||||
rm "$prefile"
|
||||
else
|
||||
echo -e "$WARNINGMSG $prefile does not exist, so no post snapshot will be taken. If you are initially installing snap-pac, this is normal."
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
echo "N/A"
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if [[ $x -eq 0 ]]; then
|
||||
echo -e "$ERRORMSG No snapper configurations are set up for snapshots to be taken!"
|
||||
if [[ $PACMAN_ABORT_ON_FAIL == "yes" ]]; then
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# snap-pac
|
||||
# https://github.com/wesbarnett/snap-pac
|
||||
# Copyright (C) 2016 James W. Barnett
|
||||
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# Removes file that stores pre number when snap-pac is removed.
|
||||
|
||||
set -e
|
||||
|
||||
SNAPPER_CONFIG_FILE=/etc/conf.d/snapper
|
||||
|
||||
ERRORMSG="\033[00;31mERROR:\033[00m"
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo -e "$ERRORMSG Script must be run as root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -f "$SNAPPER_CONFIG_FILE" ]]; then
|
||||
source "$SNAPPER_CONFIG_FILE"
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for CONFIG in $SNAPPER_CONFIGS; do
|
||||
|
||||
prefile="/tmp/snap-pac-pre_$CONFIG"
|
||||
if [[ -f "$prefile" ]]; then
|
||||
rm "$prefile"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
exit 0
|
||||
161
scripts/snap_pac.py
Executable file
161
scripts/snap_pac.py
Executable file
|
|
@ -0,0 +1,161 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright (C) 2021 Wes Barnett
|
||||
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
"""Script for taking snapshots; run from pacman hooks."""
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from configparser import ConfigParser
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
||||
logging.basicConfig(format="%(message)s", level=logging.INFO)
|
||||
|
||||
|
||||
class SnapperCmd:
|
||||
|
||||
def __init__(self, config, cleanup_algorithm, description="", nodbus=False, userdata=""):
|
||||
self.cmd = ["snapper"]
|
||||
if nodbus:
|
||||
self.cmd.append("--no-dbus")
|
||||
self.cmd.extend([
|
||||
f"--config {config} create",
|
||||
f"--cleanup-algorithm {cleanup_algorithm}",
|
||||
"--print-number"
|
||||
])
|
||||
self.cmd.append("--read-write")
|
||||
if description:
|
||||
self.cmd.append(f"--description \"{description}\"")
|
||||
if userdata:
|
||||
self.cmd.append(f"--userdata \"{userdata}\"")
|
||||
|
||||
def __call__(self):
|
||||
return os.popen(self.__str__()).read().rstrip("\n")
|
||||
|
||||
def __str__(self):
|
||||
return " ".join(self.cmd)
|
||||
|
||||
|
||||
class ConfigProcessor:
|
||||
|
||||
def __init__(self, ini_file, parent_cmd=None, packages=None):
|
||||
"""Set up defaults for snap-pac configuration."""
|
||||
|
||||
if parent_cmd is None:
|
||||
self.parent_cmd = os.popen(f"ps -p {os.getppid()} -o args=").read().strip()
|
||||
else:
|
||||
self.parent_cmd = parent_cmd
|
||||
|
||||
if packages is None:
|
||||
self.packages = [line.rstrip("\n") for line in sys.stdin]
|
||||
else:
|
||||
self.packages = packages
|
||||
|
||||
self.config = ConfigParser()
|
||||
self.config["DEFAULT"] = {
|
||||
"snapshot": False,
|
||||
"cleanup_algorithm": "number",
|
||||
"description": self.parent_cmd,
|
||||
"desc_limit": 72,
|
||||
"important_packages": [],
|
||||
"important_commands": [],
|
||||
"userdata": []
|
||||
}
|
||||
self.config["root"] = {
|
||||
"snapshot": True
|
||||
}
|
||||
self.config.read(ini_file)
|
||||
|
||||
def get_cleanup_algorithm(self, section):
|
||||
return self.config.get(section, "cleanup_algorithm")
|
||||
|
||||
def get_description(self, section):
|
||||
desc_limit = self.config.getint(section, "desc_limit")
|
||||
return self.config.get(section, "description")[:desc_limit]
|
||||
|
||||
def check_important_commands(self, section):
|
||||
return self.parent_cmd in json.loads(self.config.get(section, "important_commands"))
|
||||
|
||||
def check_important_packages(self, section):
|
||||
important_packages = json.loads(self.config.get(section, "important_packages"))
|
||||
return any(x in important_packages for x in self.packages)
|
||||
|
||||
def check_important(self, section):
|
||||
return (self.check_important_commands(section) or
|
||||
self.check_important_packages(section))
|
||||
|
||||
def get_userdata(self, section):
|
||||
userdata = set(json.loads(self.config.get(section, "userdata")))
|
||||
if self.check_important(section):
|
||||
userdata.add("important=yes")
|
||||
return ",".join(sorted(list(userdata)))
|
||||
|
||||
def __call__(self, section):
|
||||
if section not in self.config:
|
||||
self.config.add_section(section)
|
||||
return {
|
||||
"description": self.get_description(section),
|
||||
"cleanup_algorithm": self.get_cleanup_algorithm(section),
|
||||
"userdata": self.get_userdata(section),
|
||||
"snapshot": self.config.getboolean(section, "snapshot")
|
||||
}
|
||||
|
||||
|
||||
def get_snapper_configs(conf_file):
|
||||
"""Get the snapper configurations."""
|
||||
for line in conf_file.read_text().split("\n"):
|
||||
if line.startswith("SNAPPER_CONFIGS"):
|
||||
line = line.rstrip("\n").rstrip("\"").split("=")
|
||||
return line[1].lstrip("\"").split()
|
||||
|
||||
|
||||
def check_skip():
|
||||
return os.getenv("SNAP_PAC_SKIP", "n").lower() in ["y", "yes", "true", "1"]
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = ArgumentParser(description="Script for taking snapper snapshots. Used with pacman hooks.")
|
||||
parser.add_argument(
|
||||
"--ini", dest="snap_pac_ini", type=Path,
|
||||
default=Path("/etc/snap-pac.ini"), help="snap-pac ini file path"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--conf", dest="snapper_conf_file", type=Path,
|
||||
default=Path("/etc/conf.d/snapper"), help="snapper configuration file path"
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
if check_skip():
|
||||
logging.warning("snapper snapshots skipped")
|
||||
quit()
|
||||
|
||||
args = parse_args()
|
||||
config_processor = ConfigProcessor(args.snap_pac_ini)
|
||||
chroot = os.stat("/") != os.stat("/proc/1/root/.")
|
||||
|
||||
for snapper_config in get_snapper_configs(args.snapper_conf_file):
|
||||
|
||||
data = config_processor(snapper_config)
|
||||
if data["snapshot"]:
|
||||
num = SnapperCmd(snapper_config, data["cleanup_algorithm"], data["description"], chroot, data["userdata"])()
|
||||
logging.info(f"==> {snapper_config}: {num}")
|
||||
122
tests/test_script.py
Normal file
122
tests/test_script.py
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
import tempfile
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from scripts.snap_pac import check_skip, ConfigProcessor, get_snapper_configs, Prefile, SnapperCmd
|
||||
|
||||
|
||||
@pytest.mark.parametrize("snapper_cmd, actual_cmd", [
|
||||
(
|
||||
SnapperCmd("root", "pre", "number", "foo"),
|
||||
"snapper --config root create --cleanup-algorithm number --print-number --description \"foo\" --type pre"
|
||||
),
|
||||
(
|
||||
SnapperCmd("root", "post", "number", "bar", False, 1234),
|
||||
"snapper --config root create --cleanup-algorithm number --print-number"
|
||||
" --description \"bar\" --pre-number 1234 --type post"
|
||||
),
|
||||
(
|
||||
SnapperCmd("root", "post", "number", "bar", True, 1234),
|
||||
"snapper --no-dbus --config root create --cleanup-algorithm number --print-number"
|
||||
" --description \"bar\" --pre-number 1234 --type post"
|
||||
),
|
||||
(
|
||||
SnapperCmd("root", "post", "number", "bar", False, 1234, "important=yes"),
|
||||
"snapper --config root create --cleanup-algorithm number --print-number"
|
||||
" --description \"bar\" --userdata \"important=yes\" --pre-number 1234 --type post"
|
||||
),
|
||||
(
|
||||
SnapperCmd("root", "post", "number", "bar", False, 1234, "foo=bar,important=yes"),
|
||||
"snapper --config root create --cleanup-algorithm number --print-number"
|
||||
" --description \"bar\" --userdata \"foo=bar,important=yes\" --pre-number 1234 --type post"
|
||||
),
|
||||
(
|
||||
SnapperCmd("root", "post", "number", "bar", False, None, "foo=bar,important=yes"),
|
||||
"snapper --config root create --cleanup-algorithm number --print-number"
|
||||
" --description \"bar\" --userdata \"foo=bar,important=yes\" --type single"
|
||||
)
|
||||
])
|
||||
def test_snapper_cmd(snapper_cmd, actual_cmd):
|
||||
assert str(snapper_cmd) == actual_cmd
|
||||
|
||||
|
||||
def test_get_snapper_configs():
|
||||
with tempfile.NamedTemporaryFile("w", delete=False) as f:
|
||||
f.write("## Path: System/Snapper\n")
|
||||
f.write("\n")
|
||||
f.write("## Type: string\n")
|
||||
f.write("## Default: \"\"\n")
|
||||
f.write("# List of snapper configurations.\n")
|
||||
f.write("SNAPPER_CONFIGS=\"home root foo bar\"\n")
|
||||
name = f.name
|
||||
assert get_snapper_configs(Path(name)) == ["home", "root", "foo", "bar"]
|
||||
|
||||
|
||||
def test_skip_snap_pac():
|
||||
os.environ["SNAP_PAC_SKIP"] = "y"
|
||||
assert check_skip() is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize("section, command, packages, snapshot_type, result", [
|
||||
(
|
||||
"root", "foo", ["bar"], "pre",
|
||||
{"description": "foo", "cleanup_algorithm": "number", "userdata": "", "snapshot": True}
|
||||
),
|
||||
(
|
||||
"root", "pacman -Syu", [], "pre",
|
||||
{"description": "pacman -Syu", "cleanup_algorithm": "number", "userdata": "important=yes", "snapshot": True}
|
||||
),
|
||||
(
|
||||
"mail", "pacman -Syu", [], "pre",
|
||||
{"description": "pacman -Syu", "cleanup_algorithm": "number", "userdata": "", "snapshot": False}
|
||||
),
|
||||
(
|
||||
"home", "pacman -Syu", [], "pre",
|
||||
{"description": "pac", "cleanup_algorithm": "number", "userdata": "foo=bar,requestid=42", "snapshot": True}
|
||||
),
|
||||
(
|
||||
"home", "pacman -Syu", [], "post",
|
||||
{"description": "a r", "cleanup_algorithm": "number", "userdata": "foo=bar,requestid=42", "snapshot": True}
|
||||
),
|
||||
(
|
||||
"myconfig", "pacman -S linux", ["linux"], "post",
|
||||
{"description": "linux", "cleanup_algorithm": "timeline",
|
||||
"userdata": "foo=bar,important=yes,requestid=42", "snapshot": True}
|
||||
),
|
||||
])
|
||||
def test_config_processor(section, command, packages, snapshot_type, result):
|
||||
with tempfile.NamedTemporaryFile("w", delete=False) as f:
|
||||
f.write("[root]\n")
|
||||
f.write("important_commands = [\"pacman -Syu\"]\n\n")
|
||||
f.write("[home]\n")
|
||||
f.write("snapshot = True\n")
|
||||
f.write("desc_limit = 3\n")
|
||||
f.write("post_description = a really long description\n")
|
||||
f.write("userdata = [\"foo=bar\", \"requestid=42\"]\n\n")
|
||||
f.write("[myconfig]\n")
|
||||
f.write("snapshot = True\n")
|
||||
f.write("cleanup_algorithm = timeline\n")
|
||||
f.write("important_packages = [\"linux\", \"linux-lts\"]\n")
|
||||
f.write("userdata = [\"foo=bar\", \"requestid=42\"]\n")
|
||||
name = f.name
|
||||
config_processor = ConfigProcessor(name, snapshot_type, command, packages)
|
||||
assert config_processor(section) == result
|
||||
|
||||
|
||||
def test_prefile_read_none():
|
||||
prefile = Prefile("root", "pre")
|
||||
assert prefile.read() is None
|
||||
|
||||
|
||||
def test_prefile_read():
|
||||
prefile = Prefile("root", "pre")
|
||||
prefile.write("1234")
|
||||
prefile = Prefile("root", "post")
|
||||
assert prefile.read() == "1234"
|
||||
|
||||
|
||||
def test_no_prefile():
|
||||
prefile = Prefile("foo-pre-file-not-found", "post")
|
||||
assert prefile.read() is None
|
||||
Loading…
Add table
Reference in a new issue