Compare commits
197 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 |
27 changed files with 1000 additions and 429 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
|
# snap-pac
|
||||||
# https://github.com/wesbarnett/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
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -20,11 +20,23 @@ PREFIX ?= /usr
|
||||||
|
|
||||||
SHARE_DIR = $(DESTDIR)$(PREFIX)/share
|
SHARE_DIR = $(DESTDIR)$(PREFIX)/share
|
||||||
|
|
||||||
.PHONY: install
|
.PHONY: install test docs
|
||||||
|
|
||||||
install:
|
install: man
|
||||||
@install -Dm755 scripts/* -t $(SHARE_DIR)/libalpm/scripts/
|
@install -Dm755 scripts/snap_pac.py $(SHARE_DIR)/libalpm/scripts/snap-pac
|
||||||
@install -Dm644 hooks/* -t $(SHARE_DIR)/libalpm/hooks/
|
@install -Dm644 hooks/* -t $(SHARE_DIR)/libalpm/hooks/
|
||||||
@install -Dm644 LICENSE -t $(SHARE_DIR)/licenses/$(PKGNAME)
|
@install -Dm644 LICENSE -t $(SHARE_DIR)/licenses/$(PKGNAME)/
|
||||||
@install -Dm644 man8/* -t $(SHARE_DIR)/man/man8
|
@install -Dm644 man8/* -t $(SHARE_DIR)/man/man8/
|
||||||
@install -Dm644 README -t $(SHARE_DIR)/doc/$(PKGNAME)
|
@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
|
||||||
|
|
|
||||||
28
README
28
README
|
|
@ -1,28 +0,0 @@
|
||||||
SYNOPSIS
|
|
||||||
|
|
||||||
This is a set of pacman hooks and script that automatically causes snapper to
|
|
||||||
perform a pre and post snapshot before and after pacman transactions, similar to
|
|
||||||
how YaST does with OpenSuse. This provides a simple way to undo changes to a
|
|
||||||
system after a pacman transaction.
|
|
||||||
|
|
||||||
INSTALLATION
|
|
||||||
|
|
||||||
Install the "snap-pac" package using pacman.
|
|
||||||
|
|
||||||
Alternatively download the latest release and signature from
|
|
||||||
https://github.com/wesbarnett/snap-pac/releases, verify the download, and then
|
|
||||||
run "make install".
|
|
||||||
|
|
||||||
I have signed the release tarball and commits with my PGP key. The key's
|
|
||||||
fingerprint is "8535CEF3F3C38EE69555BF67E4B5E45AA3B8C5C3".
|
|
||||||
|
|
||||||
DOCUMENTATION
|
|
||||||
|
|
||||||
See snap-pac(8) after installation.
|
|
||||||
|
|
||||||
TROUBLESHOOTING
|
|
||||||
|
|
||||||
After reviewing the man page, check the issues page and file a new issue if your
|
|
||||||
problem is not covered:
|
|
||||||
|
|
||||||
https://github.com/wesbarnett/snap-pac/issues
|
|
||||||
25
README.md
Normal file
25
README.md
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# snap-pac
|
||||||
|
|
||||||
|
## Synopsis
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Forked from Wes Barnett's solution for my own personal needs. Takes a single screenshot vs. the original's pre/post pair.
|
||||||
|
|
||||||
|
## [Installation](https://wesbarnett.github.io/snap-pac/installation.html)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Most likely, configuration is not needed. By default, the snapper configuration named `root` will have snapshots taken before every pacman transaction.
|
||||||
|
|
||||||
|
For more information on configuring snap-pac, see [the documentation](https://wesbarnett.github.io/snap-pac/configuration.html).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
See the [documentation here](https://wesbarnett.github.io/snap-pac/) or `man 8 snap-pac` after installation.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
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
|
# snap-pac
|
||||||
# https://github.com/wesbarnett/snap-pac
|
# https://github.com/wesbarnett/snap-pac
|
||||||
# Copyright (C) 2016, 2017 James W. Barnett
|
# Copyright (C) 2016, 2017, 2018 James W. Barnett
|
||||||
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -24,8 +24,9 @@ Type = Package
|
||||||
Target = *
|
Target = *
|
||||||
|
|
||||||
[Action]
|
[Action]
|
||||||
Description = Performing snapper pre snapshots for the following configurations...
|
Description = Taking snapper snapshot before installing...
|
||||||
Depends = snap-pac
|
Depends = snap-pac
|
||||||
When = PreTransaction
|
When = PreTransaction
|
||||||
Exec = /usr/share/libalpm/scripts/snap-pac pre
|
Exec = /usr/share/libalpm/scripts/snap-pac
|
||||||
|
NeedsTargets
|
||||||
AbortOnFail
|
AbortOnFail
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# snap-pac
|
# snap-pac
|
||||||
# https://github.com/wesbarnett/snap-pac
|
# https://github.com/wesbarnett/snap-pac
|
||||||
# Copyright (C) 2016, 2017 James W. Barnett
|
# Copyright (C) 2016, 2017, 2018 James W. Barnett
|
||||||
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
# snap-pac
|
|
||||||
# https://github.com/wesbarnett/snap-pac
|
|
||||||
# Copyright (C) 2016, 2017 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 for the following configurations...
|
|
||||||
Depends = snap-pac
|
|
||||||
When = PostTransaction
|
|
||||||
Exec = /usr/share/libalpm/scripts/snap-pac post
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
# snap-pac
|
|
||||||
# https://github.com/wesbarnett/snap-pac
|
|
||||||
# Copyright (C) 2016, 2017 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 = Install
|
|
||||||
Type = Package
|
|
||||||
Target = snap-pac
|
|
||||||
|
|
||||||
[Action]
|
|
||||||
Description = You are installing snap-pac, so no post transaction snapshots will be taken.
|
|
||||||
Depends = snap-pac
|
|
||||||
When = PostTransaction
|
|
||||||
Exec = /usr/bin/true
|
|
||||||
240
man8/snap-pac.8
240
man8/snap-pac.8
|
|
@ -1,240 +0,0 @@
|
||||||
'\" t
|
|
||||||
.TH SNAP-PAC 8 2017-02-04 SNAP-PAC
|
|
||||||
.SH NAME
|
|
||||||
snap-pac \- Pacman hooks that use snapper to create pre/post btrfs snapshots
|
|
||||||
like openSUSE's YaST
|
|
||||||
|
|
||||||
.SH DESCRIPTION
|
|
||||||
|
|
||||||
This is a set of \fIpacman\fR hooks and script that causes \fIsnapper\fR to
|
|
||||||
automatically take a pre and post snapshot before and after pacman transactions,
|
|
||||||
similar to how YaST 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.
|
|
||||||
|
|
||||||
To undo changes from a pacman transaction, use \fIsnapper undochange\fR. See
|
|
||||||
\fBsnapper\fR(8) 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 \fI/\fR. 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.
|
|
||||||
|
|
||||||
.SH CONFIGURATION
|
|
||||||
Configuration is done via the snapper configuration files, with extra variables
|
|
||||||
specific to these pacman hooks (see \fBsnapper-configs\fR(5)). The defaults
|
|
||||||
of the following should be suitable for most users.
|
|
||||||
|
|
||||||
The following are possible settings you can place in each snapper configuration
|
|
||||||
file (e.g., \fI/etc/snapper/configs/root\fR, etc.). Follow the pattern of other
|
|
||||||
variables in the configuration file (VAR=setting).
|
|
||||||
|
|
||||||
\fBPACMAN_PRE_POST=\fR\fB\fIyes\fR\fR\fB or \fR\fB\fIno\fR\fR
|
|
||||||
.RS 4
|
|
||||||
Perform pacman pre/post snapshots for this configuration.
|
|
||||||
|
|
||||||
Default is "no", except for the root configuration which is "yes".
|
|
||||||
.RE
|
|
||||||
|
|
||||||
.BR PACMAN_CLEANUP_ALGORITHM
|
|
||||||
.RS 4
|
|
||||||
Snapper algorithm used in cleaning up the pacman pre/post snapshots. See \fBsnapper\fR(8) for list of valid options.
|
|
||||||
|
|
||||||
Default is "number".
|
|
||||||
.RE
|
|
||||||
|
|
||||||
\fBPACMAN_PRE_DESCRIPTION=\fR\fB\fIstring\fR\fR
|
|
||||||
.RS 4
|
|
||||||
snapper description used for the pacman pre snapshot.
|
|
||||||
|
|
||||||
Default is the pacman command that called the snapshot.
|
|
||||||
.RE
|
|
||||||
|
|
||||||
\fBPACMAN_POST_DESCRIPTION=\fR\fB\fIstring\fR\fR
|
|
||||||
.RS 4
|
|
||||||
snapper description used for the pacman post snapshot.
|
|
||||||
|
|
||||||
Default is the pacman command that called the snapshot.
|
|
||||||
.RE
|
|
||||||
|
|
||||||
The following setting can be changed in the snapper configuration file
|
|
||||||
\fI/etc/conf.d/snapper\fR:
|
|
||||||
|
|
||||||
\fBPACMAN_ABORT_ON_FAIL=\fR\fB\fIyes\fR\fR\fB or \fR\fB\fIno\fR\fR
|
|
||||||
.RS 4
|
|
||||||
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.
|
|
||||||
|
|
||||||
Default is "no".
|
|
||||||
.RE
|
|
||||||
|
|
||||||
.SH EXAMPLE
|
|
||||||
|
|
||||||
Installing the nano package as normal:
|
|
||||||
|
|
||||||
.EX
|
|
||||||
|
|
||||||
# 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 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
|
|
||||||
|
|
||||||
.EE
|
|
||||||
|
|
||||||
The snapper snapshot number is given for each snapper configuration that is
|
|
||||||
used. Tip: this is also logged in pacman's log).
|
|
||||||
|
|
||||||
And here are the snapshots:
|
|
||||||
|
|
||||||
.EX
|
|
||||||
|
|
||||||
# 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 |
|
|
||||||
|
|
||||||
.EE
|
|
||||||
|
|
||||||
What changed?
|
|
||||||
|
|
||||||
.EX
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
.EE
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
.EX
|
|
||||||
|
|
||||||
# snapper -c root undochange 1033..1034
|
|
||||||
create:0 modify:3 delete:100
|
|
||||||
|
|
||||||
.EE
|
|
||||||
|
|
||||||
And nano is now gone, along with all the files it changed:
|
|
||||||
|
|
||||||
.EX
|
|
||||||
|
|
||||||
$ pacman -Qi nano
|
|
||||||
error: package 'nano' was not found
|
|
||||||
|
|
||||||
.EE
|
|
||||||
|
|
||||||
.SH TROUBLESHOOTING
|
|
||||||
|
|
||||||
.SS ERROR: \fI/etc/conf.d/snapper\fR does not exist!
|
|
||||||
snap-pac reads in the snapper configurations from \fI/etc/conf.d/snapper\fR. 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.
|
|
||||||
|
|
||||||
.SS WARNING: No snapper configurations found, so not taking any snapshots!
|
|
||||||
No snapper configurations were found in \fI/etc/conf.d/snapper\fR. This means you
|
|
||||||
haven't created any configurations yet using snapper create-config. See the
|
|
||||||
snapper manpage on how to do this.
|
|
||||||
|
|
||||||
.SS 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 configuration.
|
|
||||||
|
|
||||||
.SS 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.
|
|
||||||
|
|
||||||
.SS WARNING: Didn't find pacman running.
|
|
||||||
The script gets the description from the pacman command that was run. If you get
|
|
||||||
this warning it looks like you may have run the script directly instead of
|
|
||||||
letting it run through pacman's hooks.
|
|
||||||
|
|
||||||
.SS 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. Although snapper can be set up to
|
|
||||||
not need dbus, this is a simple way to check if one is in a chroot and avoid
|
|
||||||
attempting snapshots in it.
|
|
||||||
|
|
||||||
.SS After restoring snapshot from snap-pac, 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).
|
|
||||||
|
|
||||||
.SS snap-pac is only taking snapshots of the root configuration
|
|
||||||
That's the default behavior. See \fBCONFIGURATION\fR.
|
|
||||||
|
|
||||||
.SH FAQ
|
|
||||||
.SS Does snap-pac backup non-btrfs /boot partitions?
|
|
||||||
Nope. But you can add hook that does it for you. It would be something like the
|
|
||||||
following:
|
|
||||||
|
|
||||||
.EX
|
|
||||||
|
|
||||||
[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
|
|
||||||
|
|
||||||
.EE
|
|
||||||
|
|
||||||
.SH HOMEPAGE
|
|
||||||
https://github.com/wesbarnett
|
|
||||||
|
|
||||||
.SH AUTHORS
|
|
||||||
Wes Barnett <wes@wbarnett.us>
|
|
||||||
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR alpm-hooks (5),
|
|
||||||
.BR snapper (8),
|
|
||||||
.BR snapper-configs (5),
|
|
||||||
.BR pacman (8)
|
|
||||||
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# snap-pac
|
|
||||||
# https://github.com/wesbarnett/snap-pac
|
|
||||||
# Copyright (C) 2016, 2017 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.
|
|
||||||
|
|
||||||
declare -r SNAPPER_CONFIG_FILE=/etc/conf.d/snapper
|
|
||||||
declare -r DESC_LIMIT=48
|
|
||||||
declare -r name="snap-pac"
|
|
||||||
declare PACMAN_ABORT_ON_FAIL="no"
|
|
||||||
declare -r pacman_cmd="$(sed 's./usr/bin/pacman.pacman.g' <(ps -C pacman -o args=))"
|
|
||||||
declare -i x=0
|
|
||||||
declare -r pre_or_post=$1
|
|
||||||
|
|
||||||
out() { printf "$1 $2\n" "${@:3}"; }
|
|
||||||
error() { out "==> \033[00;31mERROR:\033[00m" "$@"; } >&2
|
|
||||||
warning() { out "==> \033[00;33mWARNING:\033[00m" "$@"; } >&2
|
|
||||||
die() {
|
|
||||||
error "$@"
|
|
||||||
[[ $PACMAN_ABORT_ON_FAIL == "no" ]] && exit 0
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
error_exit() { die "Aborted due to error."; }
|
|
||||||
kill_exit() { die "\nExited due to user intervention."; }
|
|
||||||
|
|
||||||
truncate_description() {
|
|
||||||
desc="$@"
|
|
||||||
if [[ "${#desc}" -gt $DESC_LIMIT ]]; then
|
|
||||||
echo "$(echo $desc | cut -c 1-$DESC_LIMIT)..."
|
|
||||||
else
|
|
||||||
echo $desc
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
set_defaults() {
|
|
||||||
PACMAN_PRE_POST="no"
|
|
||||||
[[ $CONFIG == "root" ]] && PACMAN_PRE_POST="yes"
|
|
||||||
PACMAN_PRE_DESCRIPTION="$pacman_cmd"
|
|
||||||
PACMAN_POST_DESCRIPTION="$pacman_cmd"
|
|
||||||
PACMAN_CLEANUP_ALGORITHM="number"
|
|
||||||
}
|
|
||||||
|
|
||||||
trap error_exit ERR
|
|
||||||
trap kill_exit SIGTERM SIGINT
|
|
||||||
|
|
||||||
[[ -z "$pacman_cmd" ]] && die "snap-pac should only be called via provided pacman hooks."
|
|
||||||
[[ ! -d /var/run/dbus ]] && die "No dbus available. Are you in a chroot environment?"
|
|
||||||
|
|
||||||
source "$SNAPPER_CONFIG_FILE"
|
|
||||||
|
|
||||||
for CONFIG in $SNAPPER_CONFIGS; do
|
|
||||||
|
|
||||||
set_defaults
|
|
||||||
source /etc/snapper/configs/"$CONFIG"
|
|
||||||
|
|
||||||
[[ $PACMAN_PRE_POST == "no" ]] && continue
|
|
||||||
|
|
||||||
prefile="/tmp/$name-pre_$CONFIG"
|
|
||||||
snapper_cmd="snapper --config $CONFIG create --type $pre_or_post --cleanup-algorithm $PACMAN_CLEANUP_ALGORITHM --print-number --description"
|
|
||||||
|
|
||||||
x=$((x+1))
|
|
||||||
|
|
||||||
if [[ "$pre_or_post" == "pre" ]]; then
|
|
||||||
printf "==> %s: $($snapper_cmd "$(truncate_description $PACMAN_PRE_DESCRIPTION)" | tee "$prefile")\n" "$CONFIG"
|
|
||||||
elif [[ -f $prefile && "$pre_or_post" == "post" ]]; then
|
|
||||||
printf "==> %s: $($snapper_cmd "$(truncate_description $PACMAN_POST_DESCRIPTION)" --pre-number "$(< "$prefile")")\n" "$CONFIG"
|
|
||||||
rm -f "$prefile"
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
[[ $x -eq 0 ]] && die "No snapper configurations are set up for snapshots to be taken."
|
|
||||||
|
|
||||||
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