Compare commits
433 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 | ||
|
|
c208cbe7e9 | ||
|
|
5b2a17c94b | ||
|
|
2bb4081773 | ||
|
|
946f0df093 | ||
|
|
97dfcebeeb | ||
|
|
9625951a11 | ||
|
|
5417160503 | ||
|
|
47f124dec6 | ||
|
|
9237b519f7 | ||
|
|
5ef0091d9b | ||
|
|
a7b017b326 | ||
|
|
c6e5f06691 | ||
|
|
be873061bd | ||
|
|
a7429f8838 | ||
|
|
a34fd38af5 | ||
|
|
71ee66826e | ||
|
|
43ae966afa | ||
|
|
1f26d4247f | ||
|
|
ec81615379 | ||
|
|
797d27521b | ||
|
|
3a4e052d7b | ||
|
|
47da90f66f | ||
|
|
f5b9ce68e1 | ||
|
|
26e72a4272 | ||
|
|
c29edbc4bd | ||
|
|
9de30a8075 | ||
|
|
14b9e99d04 | ||
|
|
53b096836e | ||
|
|
162a2cf60a | ||
|
|
b9e6572092 | ||
|
|
dd35f89c37 | ||
|
|
f0e35d5e6f | ||
|
|
0630806061 | ||
|
|
efd9dc781d | ||
|
|
8cea1d9528 | ||
|
|
df0f4549a2 | ||
|
|
6d9cca05fa | ||
|
|
a692215033 | ||
|
|
4b84410780 | ||
|
|
519be40dc0 | ||
|
|
67a81829cf | ||
|
|
eee0134ed2 | ||
|
|
e08a0aca24 | ||
|
|
a4bf9641ab | ||
|
|
87913d022c | ||
|
|
e945e3ffc3 | ||
|
|
06c61fa5b4 | ||
|
|
fd3780aedb | ||
|
|
ae5c332c8a | ||
|
|
e981f3c729 | ||
|
|
d4cf0fa183 | ||
|
|
ea654087df | ||
|
|
268256123e | ||
|
|
b4fa01786d | ||
|
|
7017e68087 | ||
|
|
78130b2e06 | ||
|
|
1113b8882c | ||
|
|
f503d7a233 | ||
|
|
243d1d6ee9 | ||
|
|
0b2b465b6f | ||
|
|
5738263134 | ||
|
|
4571e2890b | ||
|
|
bef769fd04 | ||
|
|
be35509864 | ||
|
|
525f0602d9 | ||
|
|
01390f4873 | ||
|
|
4986dc60ec | ||
|
|
adda3341d3 | ||
|
|
acbdda794f | ||
|
|
ffdd26f055 | ||
|
|
0b724a5fcf | ||
|
|
44bef72930 | ||
|
|
e7844991a0 | ||
|
|
b22224f150 | ||
|
|
9c67dcec57 | ||
|
|
9e6a9de678 | ||
|
|
fbb7c5ae81 | ||
|
|
deb7d862ed | ||
|
|
825bbf89a7 | ||
|
|
2fb18c78f0 | ||
|
|
8a0c325ee2 | ||
|
|
cfda6a90b7 | ||
|
|
a13a5ab706 | ||
|
|
d5e7860fb3 | ||
|
|
1467c59874 | ||
|
|
088c4a630a | ||
|
|
769673531a | ||
|
|
5187adb9e5 | ||
|
|
376355538e | ||
|
|
5e92c178a3 | ||
|
|
17506c3b43 | ||
|
|
d392bf411b | ||
|
|
8f5989df84 | ||
|
|
dd4307f6b5 | ||
|
|
6d57ff8c16 | ||
|
|
68b92700c9 | ||
|
|
f8731f2b38 | ||
|
|
4f25ac388f | ||
|
|
96b282e4fa | ||
|
|
cef3d00b01 | ||
|
|
1cffe0260a | ||
|
|
7ad490c283 | ||
|
|
3a9aaadb1f | ||
|
|
35e62cc8b2 | ||
|
|
2e364c802f | ||
|
|
48469cbbc3 | ||
|
|
34da5c923f | ||
|
|
1c71f3d185 | ||
|
|
60eed78f0c | ||
|
|
fbbe552550 | ||
|
|
b6f8c322d4 | ||
|
|
32306e37f8 | ||
|
|
33efa4484d | ||
|
|
8194b4ac7b | ||
|
|
31a76ca665 | ||
|
|
a0659fdae0 | ||
|
|
7213a5ad1c | ||
|
|
16d26fe55f | ||
|
|
6e12136abc | ||
|
|
976d440616 | ||
|
|
02a37e8289 | ||
|
|
14b4fd127a | ||
|
|
c39458f224 | ||
|
|
4f6de57707 | ||
|
|
b6f25d7685 | ||
|
|
081ed10675 | ||
|
|
92b1ccc3bb | ||
|
|
f5094e5616 | ||
|
|
fcc7763c45 | ||
|
|
3f8ea86897 | ||
|
|
54eec76bc8 | ||
|
|
7cdb6ba28e | ||
|
|
6bae9c0044 | ||
|
|
3244efa1f9 | ||
|
|
1f0b93bbb8 | ||
|
|
9074bc6237 | ||
|
|
4e8b0aac98 | ||
|
|
e6b0a6a6e5 | ||
|
|
fd4c92de01 | ||
|
|
137875b568 | ||
|
|
d3afa0b201 | ||
|
|
4fcff3de03 | ||
|
|
b96cd99707 | ||
|
|
bc1050ddfc | ||
|
|
e7739b0542 | ||
|
|
c390946261 | ||
|
|
c310e4f02a | ||
|
|
ff74d7cb68 | ||
|
|
fff40e3ec9 | ||
|
|
cb1b080f98 | ||
|
|
4dca29d2e6 | ||
|
|
a54835d7ff | ||
|
|
e8f1671853 | ||
|
|
eef77c8ded | ||
|
|
cfaab80706 | ||
|
|
9a3e96d579 | ||
|
|
b4d78e7ce7 | ||
|
|
a596a458a4 | ||
|
|
bbedb6b505 | ||
|
|
7ce9dabd69 | ||
|
|
2132f71cde | ||
|
|
ccc295d8c7 | ||
|
|
d0f31ca36d | ||
|
|
ca536be860 | ||
|
|
4f06537ceb | ||
|
|
82a62f5966 | ||
|
|
d490b01fe4 | ||
|
|
a9df03a623 | ||
|
|
1451753571 | ||
|
|
c38a46b2ba | ||
|
|
f872136ba2 | ||
|
|
916cfa86ba | ||
|
|
2bc20147a9 |
26 changed files with 1072 additions and 43 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
|
||||
42
Makefile
Normal file
42
Makefile
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# snap-pac
|
||||
# https://github.com/wesbarnett/snap-pac
|
||||
# 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
|
||||
# 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.,
|
||||
|
||||
PKGNAME = snap-pac
|
||||
PREFIX ?= /usr
|
||||
|
||||
SHARE_DIR = $(DESTDIR)$(PREFIX)/share
|
||||
|
||||
.PHONY: install test docs
|
||||
|
||||
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
|
||||
27
README.md
27
README.md
|
|
@ -1,10 +1,25 @@
|
|||
# snap-pac
|
||||
|
||||
These are used for Arch Linux's pacman, so that snapper automatically takes a
|
||||
pre and post snapshot before and after pacman transactions. There's no need to
|
||||
create aliases, etc. See `man alpm-hooks` and `man snapper` for more
|
||||
information.
|
||||
## Synopsis
|
||||
|
||||
## Installation
|
||||
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.
|
||||
|
||||
Install [the package from the AUR](https://aur.archlinux.org/packages/snap-pac/).
|
||||
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
|
||||
32
hooks/05-snap-pac.hook
Normal file
32
hooks/05-snap-pac.hook
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# snap-pac
|
||||
# https://github.com/wesbarnett/snap-pac
|
||||
# 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
|
||||
# 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 = Taking snapper snapshot before installing...
|
||||
Depends = snap-pac
|
||||
When = PreTransaction
|
||||
Exec = /usr/share/libalpm/scripts/snap-pac
|
||||
NeedsTargets
|
||||
AbortOnFail
|
||||
28
hooks/10-snap-pac-removal.hook
Normal file
28
hooks/10-snap-pac-removal.hook
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# snap-pac
|
||||
# https://github.com/wesbarnett/snap-pac
|
||||
# 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
|
||||
# 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 = Remove
|
||||
Type = Package
|
||||
Target = snap-pac
|
||||
|
||||
[Action]
|
||||
Description = You are removing snap-pac. No post transaction snapshots will be taken.
|
||||
Depends = snap-pac
|
||||
When = PreTransaction
|
||||
Exec = /usr/bin/bash -c "rm -f /tmp/snap-pac-pre_*"
|
||||
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}")
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
PREFILE=/etc/snapper/.snap-pac-pre
|
||||
if [ -f $PREFILE ]; then
|
||||
SNAPPERPACPRE=$(cat $PREFILE)
|
||||
snapper --config root create --type post --pre-number $SNAPPERPACPRE --description "pacman posttransaction"
|
||||
rm $PREFILE
|
||||
else
|
||||
echo "WARNING: $PREFILE does not exist, so not performing post snapshot. If you are initially installing snap-pac, this is normal."
|
||||
fi
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
snapper --config root create --type pre --print-number --description "pacman pretransaction" > /etc/snapper/.snap-pac-pre
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
[Trigger]
|
||||
Operation = Upgrade
|
||||
Operation = Install
|
||||
Operation = Remove
|
||||
Type = Package
|
||||
Target = *
|
||||
|
||||
[Action]
|
||||
Description = Snapper snapshot after a transaction
|
||||
Depends = snapper
|
||||
When = PostTransaction
|
||||
Exec = /usr/bin/snapper-pac-post
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
[Trigger]
|
||||
Operation = Upgrade
|
||||
Operation = Install
|
||||
Operation = Remove
|
||||
Type = Package
|
||||
Target = *
|
||||
|
||||
[Action]
|
||||
Description = Snapper snapshot before a transaction
|
||||
Depends = snapper
|
||||
When = PreTransaction
|
||||
Exec = /usr/bin/snapper-pac-pre
|
||||
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