dar-backup 1.0.1__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dar_backup/__about__.py +1 -2
- dar_backup/clean_log.py +102 -63
- dar_backup/cleanup.py +139 -107
- dar_backup/command_runner.py +123 -15
- dar_backup/config_settings.py +25 -12
- dar_backup/dar-backup.conf +7 -0
- dar_backup/dar-backup.conf.j2 +3 -1
- dar_backup/dar_backup.py +529 -102
- dar_backup/dar_backup_systemd.py +1 -1
- dar_backup/demo.py +19 -11
- dar_backup/installer.py +18 -1
- dar_backup/manager.py +1085 -96
- dar_backup/util.py +128 -19
- {dar_backup-1.0.1.dist-info → dar_backup-1.1.0.dist-info}/METADATA +320 -42
- dar_backup-1.1.0.dist-info/RECORD +23 -0
- dar_backup/Changelog.md +0 -401
- dar_backup/README.md +0 -2045
- dar_backup-1.0.1.dist-info/RECORD +0 -25
- {dar_backup-1.0.1.dist-info → dar_backup-1.1.0.dist-info}/WHEEL +0 -0
- {dar_backup-1.0.1.dist-info → dar_backup-1.1.0.dist-info}/entry_points.txt +0 -0
- {dar_backup-1.0.1.dist-info → dar_backup-1.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dar-backup
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: A script to do full, differential and incremental backups using dar. Some files are restored from the backups during verification, after which par2 redundancy files are created. The script also has a cleanup feature to remove old backups and par2 files.
|
|
5
5
|
Project-URL: GPG Public Key, https://keys.openpgp.org/search?q=dar-backup@pm.me
|
|
6
6
|
Project-URL: Homepage, https://github.com/per2jensen/dar-backup/tree/main/v2
|
|
@@ -686,27 +686,30 @@ Classifier: Development Status :: 5 - Production/Stable
|
|
|
686
686
|
Classifier: Intended Audience :: End Users/Desktop
|
|
687
687
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
688
688
|
Classifier: Operating System :: POSIX :: Linux
|
|
689
|
-
Classifier: Programming Language :: Python :: 3.
|
|
689
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
690
690
|
Classifier: Topic :: System :: Archiving :: Backup
|
|
691
|
-
Requires-Python: >=3.
|
|
691
|
+
Requires-Python: >=3.11
|
|
692
692
|
Requires-Dist: argcomplete>=3.6.2
|
|
693
|
+
Requires-Dist: dateparser>=1.2.0
|
|
693
694
|
Requires-Dist: inputimeout>=1.0.4
|
|
694
695
|
Requires-Dist: jinja2>=3.1.6
|
|
695
696
|
Requires-Dist: rich>=13.0.0
|
|
696
697
|
Provides-Extra: dev
|
|
697
698
|
Requires-Dist: anyio>=4.4.0; extra == 'dev'
|
|
698
|
-
Requires-Dist: black>=25.1.0; extra == 'dev'
|
|
699
699
|
Requires-Dist: coverage>=7.8.2; extra == 'dev'
|
|
700
700
|
Requires-Dist: h11>=0.16.0; extra == 'dev'
|
|
701
701
|
Requires-Dist: httpcore>=0.17.3; extra == 'dev'
|
|
702
702
|
Requires-Dist: matplotlib>=3.10.3; extra == 'dev'
|
|
703
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
703
704
|
Requires-Dist: pandas>=2.3.0; extra == 'dev'
|
|
704
705
|
Requires-Dist: psutil>=7.0.0; extra == 'dev'
|
|
705
|
-
Requires-Dist: pytest; extra == 'dev'
|
|
706
706
|
Requires-Dist: pytest-cov>=6.1.1; extra == 'dev'
|
|
707
|
+
Requires-Dist: pytest-json-report; extra == 'dev'
|
|
708
|
+
Requires-Dist: pytest-mock; extra == 'dev'
|
|
707
709
|
Requires-Dist: pytest-timeout>=2.4.0; extra == 'dev'
|
|
708
710
|
Requires-Dist: pytest>=8.4.0; extra == 'dev'
|
|
709
711
|
Requires-Dist: requests>=2.32.2; extra == 'dev'
|
|
712
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
710
713
|
Requires-Dist: wheel>=0.45.1; extra == 'dev'
|
|
711
714
|
Requires-Dist: zipp>=3.19.1; extra == 'dev'
|
|
712
715
|
Provides-Extra: packaging
|
|
@@ -742,6 +745,18 @@ You can see the [v2 Changelog](v2/Changelog.md) for details on features and prog
|
|
|
742
745
|
|
|
743
746
|
Version **1.0.0** was reached on October 9, 2025.
|
|
744
747
|
|
|
748
|
+
**High-level flow**
|
|
749
|
+
|
|
750
|
+
[](#dar-backup-principles)
|
|
751
|
+
|
|
752
|
+
**Quick links**
|
|
753
|
+
|
|
754
|
+
- [Quick Guide](#quick-guide)
|
|
755
|
+
- [Redundancy to fix bitrot](#par2)
|
|
756
|
+
- [Point In Time Recovery](#point-in-time-recovery-pitr)
|
|
757
|
+
- [550+ unit tests & integration tests](#test-coverage)
|
|
758
|
+
- par2 bitrot repair proof, full/diff/incr with restore, PITR verifications, ...
|
|
759
|
+
|
|
745
760
|
## Table of Contents
|
|
746
761
|
|
|
747
762
|
- [`dar-backup`](#dar-backup)
|
|
@@ -785,6 +800,7 @@ Version **1.0.0** was reached on October 9, 2025.
|
|
|
785
800
|
- [select a directory](#select-a-directory)
|
|
786
801
|
- [select files with "Z50" in the file name and exclude .xmp files](#select-files-with-z50-in-the-file-name-and-exclude-xmp-files)
|
|
787
802
|
- [Restoring](#restoring)
|
|
803
|
+
- [Point-in-Time Recovery (PITR)](#point-in-time-recovery-pitr)
|
|
788
804
|
- [default location for restores](#default-location-for-restores)
|
|
789
805
|
- [--restore-dir option](#--restore-dir-option)
|
|
790
806
|
- [a single file](#a-single-file)
|
|
@@ -813,8 +829,8 @@ Version **1.0.0** was reached on October 9, 2025.
|
|
|
813
829
|
- [Performance tip due to par2](#performance-tip-due-to-par2)
|
|
814
830
|
- [.darrc sets -vd -vf (since v0.6.4)](#darrc-sets--vd--vf-since-v064)
|
|
815
831
|
- [Separate log file for command output](#separate-log-file-for-command-output)
|
|
832
|
+
- [Trace Logging (Debug details)](#trace-logging-debug-details)
|
|
816
833
|
- [Skipping cache directories](#skipping-cache-directories)
|
|
817
|
-
- [Progress bar and current directory](#progress-bar-and-current-directory)
|
|
818
834
|
- [Shell autocompletion](#shell-autocompletion)
|
|
819
835
|
- [Use it](#use-it)
|
|
820
836
|
- [Archive name completion (smart, context-aware)](#archive-name-completion-smart-context-aware)
|
|
@@ -826,7 +842,10 @@ Version **1.0.0** was reached on October 9, 2025.
|
|
|
826
842
|
- [Projects these scripts benefit from](#projects-these-scripts-benefit-from)
|
|
827
843
|
- [Reference](#reference)
|
|
828
844
|
- [CLI Tools Overview](#cli-tools-overview)
|
|
829
|
-
- [
|
|
845
|
+
- [Test coverage](#test-coverage)
|
|
846
|
+
- [Test selection with markers](#test-selection-with-markers)
|
|
847
|
+
- [Common runs](#common-runs)
|
|
848
|
+
- [Run all tests](#run-all-tests)
|
|
830
849
|
- [Dar-backup options](#dar-backup-options)
|
|
831
850
|
- [Dar-backup exit codes](#dar-backup-exit-codes)
|
|
832
851
|
- [Dar-backup env vars](#dar-backup-env-vars)
|
|
@@ -841,6 +860,10 @@ Version **1.0.0** was reached on October 9, 2025.
|
|
|
841
860
|
- [DISCORD WEBHOOK](#discord-webhook)
|
|
842
861
|
- [Restore test config](#restore-test-config)
|
|
843
862
|
- [Par2](#par2-1)
|
|
863
|
+
- [1.0.2](#102)
|
|
864
|
+
- [Trace Logging](#trace-logging)
|
|
865
|
+
- [Command output Capture](#command-output-capture)
|
|
866
|
+
- [1.1.0](#110)
|
|
844
867
|
|
|
845
868
|
## My use case
|
|
846
869
|
|
|
@@ -1487,6 +1510,7 @@ NO_FILES_VERIFICATION = 5
|
|
|
1487
1510
|
# timeout in seconds for backup, test, restore and par2 operations
|
|
1488
1511
|
# The author has such `dar` tasks running for 10-15 hours on the yearly backups, so a value of 24 hours is used.
|
|
1489
1512
|
# If a timeout is not specified when using the util.run_command(), a default timeout of 30 secs is used.
|
|
1513
|
+
# Use -1 to disable timeouts.
|
|
1490
1514
|
COMMAND_TIMEOUT_SECS = 86400
|
|
1491
1515
|
|
|
1492
1516
|
[DIRECTORIES]
|
|
@@ -1509,7 +1533,6 @@ ERROR_CORRECTION_PERCENT = 5
|
|
|
1509
1533
|
ENABLED = True
|
|
1510
1534
|
# Optional PAR2 configuration
|
|
1511
1535
|
# PAR2_DIR = /path/to/par2-store
|
|
1512
|
-
# PAR2_MODE = per-slice
|
|
1513
1536
|
# PAR2_RATIO_FULL = 10
|
|
1514
1537
|
# PAR2_RATIO_DIFF = 5
|
|
1515
1538
|
# PAR2_RATIO_INCR = 5
|
|
@@ -1518,7 +1541,6 @@ ENABLED = True
|
|
|
1518
1541
|
# Optional per-backup overrides (section name = backup definition)
|
|
1519
1542
|
[media-files]
|
|
1520
1543
|
PAR2_DIR = /mnt/par2/media-files
|
|
1521
|
-
PAR2_MODE = per-archive
|
|
1522
1544
|
PAR2_RATIO_FULL = 10
|
|
1523
1545
|
|
|
1524
1546
|
# scripts to run before the backup to setup the environment
|
|
@@ -1536,6 +1558,7 @@ PAR2 notes:
|
|
|
1536
1558
|
- If `PAR2_DIR` is unset, par2 files are created next to the archive slices (legacy behavior) and no manifest is written
|
|
1537
1559
|
- When `PAR2_DIR` is set, dar-backup writes a manifest next to the par2 set:
|
|
1538
1560
|
`archive_base.par2.manifest.ini`
|
|
1561
|
+
- When generating a par2 set, par2 reads all archive slices before writing any output files; for large backups, this initial read can take hours
|
|
1539
1562
|
- Verify or repair using:
|
|
1540
1563
|
`par2 verify -B <archive_dir> <par2_set.par2>`
|
|
1541
1564
|
`par2 repair -B <archive_dir> <par2_set.par2>`
|
|
@@ -1861,6 +1884,25 @@ This happens when the shell splits the quoted string or interprets globs before
|
|
|
1861
1884
|
|
|
1862
1885
|
> 💡 **Tip:** See [dar's documentation](http://dar.linux.free.fr/doc/man/dar.html#COMMANDS%20AND%20OPTIONS)
|
|
1863
1886
|
|
|
1887
|
+
>
|
|
1888
|
+
> 💡💡 **Tip:** To filter all the empty directories away that `dar` emits when listing contents, append this grep:
|
|
1889
|
+
>
|
|
1890
|
+
> ```bash
|
|
1891
|
+
> |grep -vE '\s+d[rwx-]{9}\s'
|
|
1892
|
+
>```
|
|
1893
|
+
>
|
|
1894
|
+
>Example using the grep to discard directory noise from `dar's` output:
|
|
1895
|
+
>
|
|
1896
|
+
> ```bash
|
|
1897
|
+
> dar-backup --list-contents media-files_INCR_2025-05-10 --selection="-I '*Z50*' -X '*.xmp'" | grep -vE '\s+d[rwx-]{9}\s'
|
|
1898
|
+
>[Saved][ ] [-L-][ 0%][X] -rw-rw-r-- user user 26 Mio Fri May 9 11:26:16 2025 home/user/data/2025/2025-05-09-Roskilde-Nordisk-udstilling/Z50_0633.NEF
|
|
1899
|
+
>[Saved][ ] [-L-][ 0%][X] -rw-rw-r-- user user 26 Mio Fri May 9 11:26:16 2025 home/user/data/2025/2025-05-09-Roskilde-Nordisk-udstilling/Z50_0632.NEF
|
|
1900
|
+
>[Saved][ ] [-L-][ 0%][X] -rw-rw-r-- user user 28 Mio Fri May 9 11:09:04 2025 home/user/data/2025/2025-05-09-Roskilde-Nordisk-udstilling/Z50_0631.NEF
|
|
1901
|
+
>[Saved][ ] [-L-][ 0%][X] -rw-rw-r-- user user 29 Mio Fri May 9 11:09:03 2025 home/user/data/2025/2025-05-09-Roskilde-Nordisk-udstilling/Z50_0630.NEF
|
|
1902
|
+
>[Saved][ ] [-L-][ 0%][X] -rw-rw-r-- user user 29 Mio Fri May 9 11:09:03 2025 home/user/data/2025/2025-05-09-Roskilde-Nordisk-udstilling/Z50_0629.NEF
|
|
1903
|
+
>...
|
|
1904
|
+
>```
|
|
1905
|
+
|
|
1864
1906
|
### select a directory
|
|
1865
1907
|
|
|
1866
1908
|
Select files and sub directories in `home/user/data/2025/2025-05-09-Roskilde-Nordisk-udstilling`
|
|
@@ -1909,6 +1951,97 @@ gives something like
|
|
|
1909
1951
|
|
|
1910
1952
|
## Restoring
|
|
1911
1953
|
|
|
1954
|
+
### Point-in-Time Recovery (PITR)
|
|
1955
|
+
|
|
1956
|
+
Use the `manager` CLI to restore files as they existed at a specific time:
|
|
1957
|
+
|
|
1958
|
+
```bash
|
|
1959
|
+
. <the virtual env>/bin/activate
|
|
1960
|
+
manager --config-file <dar-backup.conf> \
|
|
1961
|
+
--backup-def <definition> \
|
|
1962
|
+
--restore-path tmp/path/to/file.txt \
|
|
1963
|
+
--when "2026-01-29 15:00:39" \
|
|
1964
|
+
--target /tmp/restore_pitr \
|
|
1965
|
+
--log-stdout --verbose
|
|
1966
|
+
deactivate
|
|
1967
|
+
```
|
|
1968
|
+
|
|
1969
|
+
Restore a directory (same idea, but the path is a directory):
|
|
1970
|
+
|
|
1971
|
+
```bash
|
|
1972
|
+
. <the virtual env>/bin/activate
|
|
1973
|
+
manager --config-file <dar-backup.conf> \
|
|
1974
|
+
--backup-def <definition> \
|
|
1975
|
+
--restore-path tmp/path/to/directory/ \
|
|
1976
|
+
--when "2026-01-29 15:00:39" \
|
|
1977
|
+
--target /tmp/restore_pitr \
|
|
1978
|
+
--log-stdout --verbose
|
|
1979
|
+
deactivate
|
|
1980
|
+
```
|
|
1981
|
+
|
|
1982
|
+
Dry-run the archive chain selection before restoring:
|
|
1983
|
+
|
|
1984
|
+
```bash
|
|
1985
|
+
. <the virtual env>/bin/activate
|
|
1986
|
+
manager --config-file <dar-backup.conf> \
|
|
1987
|
+
--backup-def <definition> \
|
|
1988
|
+
--restore-path tmp/path/to/directory \
|
|
1989
|
+
--when "2026-01-29 15:00:39" \
|
|
1990
|
+
--pitr-report \
|
|
1991
|
+
--log-stdout --verbose
|
|
1992
|
+
deactivate
|
|
1993
|
+
```
|
|
1994
|
+
|
|
1995
|
+
**Notes**:
|
|
1996
|
+
- `--restore-path` must be a relative path as stored in the catalog (no leading slash).
|
|
1997
|
+
- If a restore path is a **directory** and its name has no file extension, add a trailing `/` to make the intent explicit (e.g., `photos/2026/01/`). This avoids ambiguity with file paths that also lack extensions.
|
|
1998
|
+
- Example (directory name has no extension):
|
|
1999
|
+
- `manager --backup-def <definition> --restore-path "Automatic Upload/Per - iPhone/2026/01/" --when "now" --target /tmp/restore_pitr`
|
|
2000
|
+
- `--target` is required to avoid accidental restores into the current working directory.
|
|
2001
|
+
- Protected targets are blocked (e.g., `/etc`, `/usr`, `/bin`, `/var`, `/root`, `/boot`, `/lib`, `/proc`, `/sys`, `/dev`).
|
|
2002
|
+
- `--pitr-report` does a **dry-run** chain selection; if it reports missing archives, a restore will fail until the catalog is rebuilt or missing archives are restored.
|
|
2003
|
+
- `--pitr-report-first` runs the same chain report before a restore and aborts if any archive is missing (useful as a safety preflight).
|
|
2004
|
+
- `--when` accepts natural-language date expressions via `dateparser`. Examples:
|
|
2005
|
+
- `"now"`
|
|
2006
|
+
- `"2 weeks ago"`
|
|
2007
|
+
- `"2025-10-05 14:30"`
|
|
2008
|
+
- `yesterday 23:00`
|
|
2009
|
+
- PITR restores use the catalog to select the correct archive chain (FULL → DIFF → INCR) and then restore **directly with `dar`** in that order.
|
|
2010
|
+
- This avoids interactive `dar_manager` prompts (e.g., non‑monotonic mtimes often seen on pCloud/FUSE).
|
|
2011
|
+
- Directories can get a **new mtime** when files inside them are added/removed; the chain restore ensures the correct tree is rebuilt even if mtimes look “too new”.
|
|
2012
|
+
- Missing archives:
|
|
2013
|
+
- PITR uses the latest FULL, the latest DIFF after that FULL, and the latest INCR after that DIFF.
|
|
2014
|
+
- If any archive slice in that chain is missing on disk, PITR restore **fails** and logs which archive slices are missing.
|
|
2015
|
+
- A short Discord notice is sent (if configured) so missing archives are visible immediately.
|
|
2016
|
+
- Relocating archive paths in the catalog:
|
|
2017
|
+
- The catalog stores **absolute archive paths**. If archives move (or a mountpoint changes), the catalog will still point to the old path.
|
|
2018
|
+
- This can happen when manager DBs are moved to another disk and the archives are re-added from a different mountpoint.
|
|
2019
|
+
- Use the built-in relocate command to rewrite a path prefix in-place:
|
|
2020
|
+
- Dry run:
|
|
2021
|
+
- `manager --relocate-archive-path /old/path /new/path --relocate-archive-path-dry-run --backup-def <definition>`
|
|
2022
|
+
- Apply:
|
|
2023
|
+
- `manager --relocate-archive-path /old/path /new/path --backup-def <definition>`
|
|
2024
|
+
- Example (move `/home/pj/mnt/dar` to `/mnt/dar`):
|
|
2025
|
+
- `manager --relocate-archive-path /home/pj/mnt/dar /mnt/dar --backup-def pCloudDrive`
|
|
2026
|
+
- Alternative quick fix: create a symlink from the old path to the new path.
|
|
2027
|
+
- Rebuilding a catalog after archive loss:
|
|
2028
|
+
- If PITR fails due to missing archives, the catalog may no longer match what is actually on disk.
|
|
2029
|
+
- You can rebuild the catalog from the remaining archives and then retry PITR (with the understanding that older restore points may no longer be possible).
|
|
2030
|
+
- Example:
|
|
2031
|
+
- `manager --create-db --config-file <dar-backup.conf>`
|
|
2032
|
+
- `manager --add-dir <backup_dir> --backup-def <definition> --config-file <dar-backup.conf>`
|
|
2033
|
+
- Or add individual archives:
|
|
2034
|
+
- `manager --add-specific-archive <path/to/archive> --config-file <dar-backup.conf>`
|
|
2035
|
+
|
|
2036
|
+
Example of the issue:
|
|
2037
|
+
1) FULL backup at 10:00 with `/data/photos/`
|
|
2038
|
+
2) You add files at 11:00 (directory mtime updates)
|
|
2039
|
+
3) DIFF backup at 11:05
|
|
2040
|
+
4) You request PITR restore of `/data/photos/` at 10:30
|
|
2041
|
+
|
|
2042
|
+
`dar_manager -w` may say “directory did not exist before that time” because the directory mtime is now 11:00+.
|
|
2043
|
+
The fallback still restores the correct tree as of 10:30 by applying the archive chain.
|
|
2044
|
+
|
|
1912
2045
|
### default location for restores
|
|
1913
2046
|
|
|
1914
2047
|
dar-backup will use the TEST_RESTORE_DIR location as the Root for restores, if the --restore-dir option has not been supplied.
|
|
@@ -2217,23 +2350,29 @@ In order to not clutter that log file with the output of commands being run, a n
|
|
|
2217
2350
|
|
|
2218
2351
|
The secondary log file can get quite cluttered, if you want to remove the clutter, run the `clean-log`script with the `--file` option, or simply delete it.
|
|
2219
2352
|
|
|
2220
|
-
###
|
|
2353
|
+
### Trace Logging (Debug details)
|
|
2221
2354
|
|
|
2222
|
-
|
|
2355
|
+
To keep the main log file clean while preserving essential debugging information, `dar-backup` creates a separate trace log file (e.g., `dar-backup.trace.log`) alongside the main log.
|
|
2223
2356
|
|
|
2224
|
-
|
|
2357
|
+
- **Main Log (`dar-backup.log`)**: Contains clean, human-readable INFO/ERROR messages. Stack traces are suppressed here.
|
|
2358
|
+
- **Trace Log (`dar-backup.trace.log`)**: Captures ALL messages at `DEBUG` level, including full exception stack traces. Use this file for debugging crashes or unexpected behavior.
|
|
2225
2359
|
|
|
2226
|
-
|
|
2360
|
+
You can configure the rotation of this file in `[MISC]`:
|
|
2227
2361
|
|
|
2228
|
-
|
|
2362
|
+
```ini
|
|
2363
|
+
[MISC]
|
|
2364
|
+
# ... other settings ...
|
|
2365
|
+
TRACE_LOG_MAX_BYTES = 10485760 # 10 MB default
|
|
2366
|
+
TRACE_LOG_BACKUP_COUNT = 1 # Keep 1 old trace file (default)
|
|
2367
|
+
```
|
|
2229
2368
|
|
|
2230
|
-
|
|
2231
|
-
dar-backup displays 2 visual artifacts to show progress.
|
|
2369
|
+
### Skipping cache directories
|
|
2232
2370
|
|
|
2233
|
-
|
|
2234
|
-
2. a status line showing the directory being backed up. If the directory is big and takes time to backup, the line is not changing, but you will probably know there is a lot to backup.
|
|
2371
|
+
The author uses the `--cache-directory-tagging` option in his [backup definitions](#backup-definition-example).
|
|
2235
2372
|
|
|
2236
|
-
The
|
|
2373
|
+
The effect is that directories with the [CACHEDIR.TAG](https://bford.info/cachedir/) file are not backed up. Those directories contain content fetched from the net, which is of an ephemeral nature and probably not what you want to back up.
|
|
2374
|
+
|
|
2375
|
+
If the option is not in the backup definition, the cache directories are backed up as any other.
|
|
2237
2376
|
|
|
2238
2377
|
### Shell autocompletion
|
|
2239
2378
|
|
|
@@ -2418,7 +2557,6 @@ pytest # run the test suite
|
|
|
2418
2557
|
|
|
2419
2558
|
- Perhaps look into pre-processing backup definitions. As `dar` does not expand env vars
|
|
2420
2559
|
`dar-backup` could do so and feed the result to `dar`.
|
|
2421
|
-
- When run interactively, a progress bar during test and par2 generation would be nice.
|
|
2422
2560
|
- Look into a way to move the .par2 files away from the `dar` slices, to maximize chance of good redundancy.
|
|
2423
2561
|
- Add option to dar-backup to use the `dar` option `--fsa-scope none`
|
|
2424
2562
|
|
|
@@ -2453,40 +2591,135 @@ One backup definition per file
|
|
|
2453
2591
|
| [installer](#installer-options) | Set up directories and optionally create catalog databases according to a config file |
|
|
2454
2592
|
| [demo](#demo-options) | Set up required directories and config files for a demo|
|
|
2455
2593
|
|
|
2456
|
-
###
|
|
2594
|
+
### Test coverage
|
|
2595
|
+
|
|
2596
|
+
#### Test selection with markers
|
|
2597
|
+
|
|
2598
|
+
The test suite is annotated with these markers:
|
|
2599
|
+
|
|
2600
|
+
- `unit` (fast, pure logic)
|
|
2601
|
+
- `component` (subprocess boundary with mocks/lightweight commands)
|
|
2602
|
+
- `integration` (end-to-end workflows; external tools)
|
|
2603
|
+
- `slow` (long-running/heavier integration)
|
|
2604
|
+
- `live_discord` (sends real webhook messages; opt-in only)
|
|
2605
|
+
|
|
2606
|
+
#### Common runs
|
|
2607
|
+
|
|
2608
|
+
```bash
|
|
2609
|
+
# Fast local loop (unit + component)
|
|
2610
|
+
pytest -m "unit or component"
|
|
2611
|
+
|
|
2612
|
+
# Integration (exclude slow + live webhook)
|
|
2613
|
+
pytest -m "integration and not slow and not live_discord"
|
|
2614
|
+
|
|
2615
|
+
# Slow-only
|
|
2616
|
+
pytest -m slow
|
|
2457
2617
|
|
|
2458
|
-
|
|
2618
|
+
# Full suite (default pytest.ini already excludes live_discord)
|
|
2619
|
+
pytest -m "not live_discord"
|
|
2620
|
+
|
|
2621
|
+
# Live webhook (requires DAR_BACKUP_DISCORD_WEBHOOK_URL)
|
|
2622
|
+
pytest -m live_discord
|
|
2623
|
+
```
|
|
2624
|
+
|
|
2625
|
+
#### Run all tests
|
|
2459
2626
|
|
|
2460
2627
|
```bash
|
|
2461
|
-
pytest
|
|
2628
|
+
pytest
|
|
2462
2629
|
```
|
|
2463
2630
|
|
|
2464
|
-
Results for version 1.
|
|
2631
|
+
Results for version 1.1.0 (pre-release, Feb 1, 2026) in this report:
|
|
2465
2632
|
|
|
2466
2633
|
```text
|
|
2467
|
-
|
|
2468
|
-
|
|
2634
|
+
===================================== test session starts =====================================
|
|
2635
|
+
platform linux -- Python 3.12.3, pytest-8.4.0, pluggy-1.6.0
|
|
2636
|
+
rootdir: /home/pj/git/dar-backup/v2
|
|
2637
|
+
configfile: pytest.ini
|
|
2638
|
+
testpaths: tests
|
|
2639
|
+
plugins: anyio-4.9.0, timeout-2.4.0, cov-6.1.1, mock-3.15.1
|
|
2640
|
+
timeout: 1800.0s
|
|
2641
|
+
timeout method: signal
|
|
2642
|
+
timeout func_only: False
|
|
2643
|
+
collected 559 items / 1 deselected / 558 selected
|
|
2644
|
+
|
|
2645
|
+
tests/test_add_old_archive_confirmation.py .... [ 0%]
|
|
2646
|
+
tests/test_alternate_reference_archive.py ... [ 1%]
|
|
2647
|
+
tests/test_autocompletion_install.py ... [ 1%]
|
|
2648
|
+
tests/test_binary_info.py ...... [ 2%]
|
|
2649
|
+
tests/test_bitrot.py .. [ 3%]
|
|
2650
|
+
tests/test_clean_log.py .................... [ 6%]
|
|
2651
|
+
tests/test_cleanup.py ............................... [ 12%]
|
|
2652
|
+
tests/test_command_runner.py ......................................... [ 19%]
|
|
2653
|
+
tests/test_config_comments.py . [ 19%]
|
|
2654
|
+
tests/test_config_settings.py .............. [ 22%]
|
|
2655
|
+
tests/test_create_backup_command.py ... [ 22%]
|
|
2656
|
+
tests/test_create_full_diff_incr_backup.py .......... [ 24%]
|
|
2657
|
+
tests/test_dar_backup.py ....................................................... [ 34%]
|
|
2658
|
+
tests/test_dar_backup_additional_coverage.py ....................... [ 38%]
|
|
2659
|
+
tests/test_dar_backup_startup.py .. [ 39%]
|
|
2660
|
+
tests/test_darrc.py .. [ 39%]
|
|
2661
|
+
tests/test_demo.py ............. [ 41%]
|
|
2662
|
+
tests/test_discord_webhook.py .. [ 42%]
|
|
2663
|
+
tests/test_filter_darrc_file.py . [ 42%]
|
|
2664
|
+
tests/test_generic_backup_command_execution.py . [ 42%]
|
|
2665
|
+
tests/test_get_config_file.py ....... [ 43%]
|
|
2666
|
+
tests/test_gpt_file_compression.py . [ 43%]
|
|
2667
|
+
tests/test_gpt_tests.py ....... [ 45%]
|
|
2668
|
+
tests/test_installer.py .................. [ 48%]
|
|
2669
|
+
tests/test_links.py . [ 48%]
|
|
2670
|
+
tests/test_list_definitions.py . [ 48%]
|
|
2671
|
+
tests/test_listing.py ... [ 49%]
|
|
2672
|
+
tests/test_logging_trace.py .. [ 49%]
|
|
2673
|
+
tests/test_manager.py ................................................................. [ 61%]
|
|
2674
|
+
[ 61%]
|
|
2675
|
+
tests/test_manager_coverage.py .................................. [ 67%]
|
|
2676
|
+
tests/test_par2.py . [ 67%]
|
|
2677
|
+
tests/test_par2_manifest.py . [ 67%]
|
|
2678
|
+
tests/test_par2_multi_definitions.py . [ 67%]
|
|
2679
|
+
tests/test_par2_overrides.py . [ 68%]
|
|
2680
|
+
tests/test_pitr.py .............................................. [ 76%]
|
|
2681
|
+
tests/test_pitr_integration.py ..... [ 77%]
|
|
2682
|
+
tests/test_postreq.py . [ 77%]
|
|
2683
|
+
tests/test_preflight.py ... [ 77%]
|
|
2684
|
+
tests/test_prereq.py . [ 78%]
|
|
2685
|
+
tests/test_readme_changelog.py .......... [ 79%]
|
|
2686
|
+
tests/test_restore.py .... [ 80%]
|
|
2687
|
+
tests/test_run_command.py ......s [ 81%]
|
|
2688
|
+
tests/test_sanity_checks.py ................. [ 84%]
|
|
2689
|
+
tests/test_space_definition.py . [ 85%]
|
|
2690
|
+
tests/test_startup_cleanup.py ....... [ 86%]
|
|
2691
|
+
tests/test_status_indicators.py ....... [ 87%]
|
|
2692
|
+
tests/test_stress.py . [ 87%]
|
|
2693
|
+
tests/test_systemd_unit_generation.py .......... [ 89%]
|
|
2694
|
+
tests/test_trace_logging.py .. [ 89%]
|
|
2695
|
+
tests/test_util.py .......................................... [ 97%]
|
|
2696
|
+
tests/test_util_completers.py .......... [ 99%]
|
|
2697
|
+
tests/test_verbose.py ... [ 99%]
|
|
2698
|
+
tests/test_verify_cleanup.py . [100%]
|
|
2699
|
+
|
|
2700
|
+
======================================= tests coverage ========================================
|
|
2701
|
+
_______________________ coverage: platform linux, python 3.12.3-final-0 _______________________
|
|
2469
2702
|
|
|
2470
2703
|
Name Stmts Miss Branch BrPart Cover
|
|
2471
2704
|
------------------------------------------------------------------------
|
|
2472
|
-
src/dar_backup/__about__.py
|
|
2705
|
+
src/dar_backup/__about__.py 3 0 0 0 100%
|
|
2473
2706
|
src/dar_backup/__init__.py 0 0 0 0 100%
|
|
2474
|
-
src/dar_backup/clean_log.py
|
|
2475
|
-
src/dar_backup/cleanup.py
|
|
2476
|
-
src/dar_backup/command_runner.py
|
|
2477
|
-
src/dar_backup/config_settings.py
|
|
2478
|
-
src/dar_backup/dar_backup.py
|
|
2479
|
-
src/dar_backup/dar_backup_systemd.py 56
|
|
2480
|
-
src/dar_backup/demo.py
|
|
2707
|
+
src/dar_backup/clean_log.py 114 10 46 2 91%
|
|
2708
|
+
src/dar_backup/cleanup.py 294 42 100 9 87%
|
|
2709
|
+
src/dar_backup/command_runner.py 231 20 82 10 90%
|
|
2710
|
+
src/dar_backup/config_settings.py 162 9 62 10 92%
|
|
2711
|
+
src/dar_backup/dar_backup.py 1027 55 420 49 92%
|
|
2712
|
+
src/dar_backup/dar_backup_systemd.py 56 1 10 1 97%
|
|
2713
|
+
src/dar_backup/demo.py 100 1 34 2 98%
|
|
2481
2714
|
src/dar_backup/exceptions.py 2 0 0 0 100%
|
|
2482
|
-
src/dar_backup/installer.py
|
|
2483
|
-
src/dar_backup/manager.py
|
|
2484
|
-
src/dar_backup/rich_progress.py 70
|
|
2485
|
-
src/dar_backup/util.py
|
|
2715
|
+
src/dar_backup/installer.py 120 4 54 4 95%
|
|
2716
|
+
src/dar_backup/manager.py 1105 91 454 38 91%
|
|
2717
|
+
src/dar_backup/rich_progress.py 70 2 30 3 95%
|
|
2718
|
+
src/dar_backup/util.py 521 43 142 24 90%
|
|
2486
2719
|
------------------------------------------------------------------------
|
|
2487
|
-
TOTAL
|
|
2488
|
-
Coverage XML written to file coverage.xml
|
|
2489
|
-
|
|
2720
|
+
TOTAL 3805 278 1434 152 91%
|
|
2721
|
+
Coverage XML written to file /tmp/coverage.xml
|
|
2722
|
+
================== 557 passed, 1 skipped, 1 deselected in 409.66s (0:06:49) ===================
|
|
2490
2723
|
```
|
|
2491
2724
|
|
|
2492
2725
|
### Dar-backup options
|
|
@@ -2558,6 +2791,13 @@ Available options:
|
|
|
2558
2791
|
-l, --list-catalogs List catalogs in databases for all backup definitions.
|
|
2559
2792
|
--list-archive-contents <archive> List the contents of an archive’s catalog by archive name.
|
|
2560
2793
|
--find-file <file> Search catalogs for a specific file.
|
|
2794
|
+
--restore-path <path> [<path> ...] Restore specific path(s) (Point-in-Time Recovery).
|
|
2795
|
+
--when <timestamp> Date/time for restoration (used with --restore-path).
|
|
2796
|
+
--target <path> Target directory for restoration (default: current dir).
|
|
2797
|
+
--pitr-report Report PITR archive chain for --restore-path/--when without restoring.
|
|
2798
|
+
--pitr-report-first Run PITR chain report before restore and abort if missing archives.
|
|
2799
|
+
--relocate-archive-path <old> <new> Rewrite archive path prefix in the catalog DB (requires --backup-def).
|
|
2800
|
+
--relocate-archive-path-dry-run Show archive path changes without applying them (use with --relocate-archive-path).
|
|
2561
2801
|
--verbose Enable verbose output.
|
|
2562
2802
|
--log-level <level> Set log level (`debug` or `trace`, default is `info`).
|
|
2563
2803
|
|
|
@@ -2754,10 +2994,48 @@ PAR2_RUN_VERIFY = true
|
|
|
2754
2994
|
#
|
|
2755
2995
|
#[etc]
|
|
2756
2996
|
# Keep global PAR2 settings but tweak ratios for this backup definition
|
|
2757
|
-
# RATIO is
|
|
2997
|
+
# RATIO is given in percent (%)
|
|
2758
2998
|
#PAR2_RATIO_FULL = 15
|
|
2759
2999
|
#PAR2_RATIO_DIFF = 8
|
|
2760
3000
|
#PAR2_RATIO_INCR = 8
|
|
2761
3001
|
```
|
|
2762
3002
|
|
|
2763
3003
|
[Per-backup override test case: `tests/test_par2_overrides.py`](v2/tests/test_par2_overrides.py)
|
|
3004
|
+
|
|
3005
|
+
#### 1.0.2
|
|
3006
|
+
|
|
3007
|
+
##### Trace Logging
|
|
3008
|
+
|
|
3009
|
+
To support debugging without cluttering the main log file, a secondary trace log is now created (e.g., `dar-backup.trace.log`).
|
|
3010
|
+
This file captures all `DEBUG` level messages and full exception stack traces.
|
|
3011
|
+
|
|
3012
|
+
You can configure its rotation in the `[MISC]` section:
|
|
3013
|
+
|
|
3014
|
+
- `TRACE_LOG_MAX_BYTES`: Max size of the trace log file in bytes. Default is `10485760` (10 MB).
|
|
3015
|
+
- `TRACE_LOG_BACKUP_COUNT`: Number of rotated trace log files to keep. Default is `1`.
|
|
3016
|
+
|
|
3017
|
+
Example:
|
|
3018
|
+
|
|
3019
|
+
```ini
|
|
3020
|
+
[MISC]
|
|
3021
|
+
TRACE_LOG_MAX_BYTES = 10485760
|
|
3022
|
+
TRACE_LOG_BACKUP_COUNT = 1
|
|
3023
|
+
```
|
|
3024
|
+
|
|
3025
|
+
##### Command output Capture
|
|
3026
|
+
|
|
3027
|
+
- New optional `[MISC]` setting: `COMMAND_CAPTURE_MAX_BYTES` (default 102400).
|
|
3028
|
+
- Limits how much stdout/stderr is kept in memory per command while still logging full output.
|
|
3029
|
+
- Set to `0` to disable buffering entirely. Command output is still streamed to dar-backup-commands.log
|
|
3030
|
+
- If set to `0`, the calling function cannot rely on output from the executed command. The exit value is the only result provided.
|
|
3031
|
+
|
|
3032
|
+
Example:
|
|
3033
|
+
|
|
3034
|
+
```ini
|
|
3035
|
+
[MISC]
|
|
3036
|
+
COMMAND_CAPTURE_MAX_BYTES = 102400
|
|
3037
|
+
```
|
|
3038
|
+
|
|
3039
|
+
#### 1.1.0
|
|
3040
|
+
|
|
3041
|
+
COMMAND_TIMEOUT_SECS=-1 now disables timeout for commands executed.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
dar_backup/.darrc,sha256=-aerqivZmOsW_XBCh9IfbYTUvw0GkzDSr3Vx4GcNB1g,2113
|
|
2
|
+
dar_backup/__about__.py,sha256=DYQe7Z3Iqf23m_tT6w_2w8TNZxvVTYCEbt1HJwr0C4M,370
|
|
3
|
+
dar_backup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
dar_backup/clean_log.py,sha256=Uf6MjpS_v1IVZdfx7ogRo6j5EIscdxjLImn8GKZo_rc,7038
|
|
5
|
+
dar_backup/cleanup.py,sha256=Hds6q-3w5RAg69280JmofaoPtuSVLoOJTvTX_i8Veyw,19106
|
|
6
|
+
dar_backup/command_runner.py,sha256=tqOwm-eaghS5jkwlwbaN1Wl9bO1WNlqk-zrIRdnp2Rs,15067
|
|
7
|
+
dar_backup/config_settings.py,sha256=t3lFbYZ6XCnvKIU2EEpqJUW7OAz3rNb5iuCisW3D2mg,12698
|
|
8
|
+
dar_backup/dar-backup.conf,sha256=ejucmhEbSdqFU4JEVfrWbFj9H6U87TWSnhex3LraEUY,2124
|
|
9
|
+
dar_backup/dar-backup.conf.j2,sha256=kD13msmP2IXLjnJ9lZmqtLTnsUZq1EkPZAI1LlOkYXo,3852
|
|
10
|
+
dar_backup/dar_backup.py,sha256=ai4miv7S3W2sE5NwN6A-OaHifp2wRvJyMbGcYKPngXM,71183
|
|
11
|
+
dar_backup/dar_backup_systemd.py,sha256=BWy5tvjq4Gex1YleQhQH57b_nFhSVhKUF_cLvSlDMkw,3874
|
|
12
|
+
dar_backup/demo.py,sha256=DONTzskD5lq6CSeHQUf_kOQ5ntekn6t-keOszgtUocI,8228
|
|
13
|
+
dar_backup/demo_backup_def.j2,sha256=hQW2Glp0QGV3Kt8cwjS0mpOCdyzjVlpgbgL6LpXTKJA,1793
|
|
14
|
+
dar_backup/exceptions.py,sha256=dBQwgKUilgfb1Tnlm_m1Dl1IqoY75L0n1uRkm0DBVTk,158
|
|
15
|
+
dar_backup/installer.py,sha256=yJ0xXi24C1Vo6gnj2BlhV1X55ZIG5t21t8tNKTYSclM,7616
|
|
16
|
+
dar_backup/manager.py,sha256=g-EzgAZiDLgDPmpLi30Ss5gkKytiLTx-WiN4R4cKHuM,65924
|
|
17
|
+
dar_backup/rich_progress.py,sha256=SfwFxebBl6jnDQMUQr4McknkW1yQWaJVo1Ju1OD3okA,3221
|
|
18
|
+
dar_backup/util.py,sha256=pq-SIAI_Tt4C9LiFfHxwTWmSAAkhgdE5QtS4IgYjqdY,38594
|
|
19
|
+
dar_backup-1.1.0.dist-info/METADATA,sha256=-reQRtVee46ypbaT8Rhm5icV29y74GficyFzh7GVqr8,133833
|
|
20
|
+
dar_backup-1.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
21
|
+
dar_backup-1.1.0.dist-info/entry_points.txt,sha256=pOK9M8cHeAcGIatrYzkm_1O89kPk0enyYONALYjFBx4,286
|
|
22
|
+
dar_backup-1.1.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
23
|
+
dar_backup-1.1.0.dist-info/RECORD,,
|