dar-backup 0.7.2__tar.gz → 0.8.1__tar.gz
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-0.7.2/src/dar_backup → dar_backup-0.8.1}/Changelog.md +18 -1
- {dar_backup-0.7.2 → dar_backup-0.8.1}/PKG-INFO +4 -2
- {dar_backup-0.7.2 → dar_backup-0.8.1}/README.md +1 -1
- {dar_backup-0.7.2 → dar_backup-0.8.1}/doc/badges/badge_clones.json +1 -1
- dar_backup-0.8.1/doc/badges/milestone_1000.txt +1 -0
- dar_backup-0.8.1/doc/badges/milestone_badge.json +6 -0
- dar_backup-0.8.1/doc/clones.json +385 -0
- dar_backup-0.8.1/doc/weekly_clones.png +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/pyproject.toml +2 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1/src/dar_backup}/Changelog.md +18 -1
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/README.md +1 -1
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/__about__.py +1 -1
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/clean_log.py +12 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/command_runner.py +49 -15
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/contourpy-1.3.2.dist-info/LICENSE +29 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/cycler-0.12.1.dist-info/LICENSE +27 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/fonttools-4.58.2.dist-info/licenses/LICENSE +21 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/kiwisolver-1.4.8.dist-info/LICENSE +71 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/matplotlib-3.10.3.dist-info/LICENSE +99 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/numpy/ma/LICENSE +24 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/pandas-2.3.0.dist-info/LICENSE +1250 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/pillow-11.2.1.dist-info/licenses/LICENSE +998 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/pyparsing-3.2.3.dist-info/LICENSE +18 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/LICENSE +54 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/LICENSE +18 -0
- dar_backup-0.8.1/venv/lib/python3.12/site-packages/tzdata-2025.2.dist-info/licenses/LICENSE +15 -0
- dar_backup-0.7.2/doc/badges/milestone_badge.json +0 -6
- dar_backup-0.7.2/doc/clones.json +0 -190
- dar_backup-0.7.2/doc/weekly_clones.png +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/.gitignore +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/doc/badges/README.md +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/doc/badges/milestone_500.txt +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/doc/dev.md +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/doc/doc.md +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/packages/deb/README.md +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/.darrc +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/__init__.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/cleanup.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/config_settings.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/dar-backup.conf +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/dar-backup.conf.j2 +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/dar_backup.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/dar_backup_systemd.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/demo.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/demo_backup_def.j2 +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/exceptions.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/installer.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/manager.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/rich_progress.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/src/dar_backup/util.py +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/SecretStorage-3.3.3.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/black-25.1.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/blib2to3/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/build-1.2.2.post1.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/certifi-2025.4.26.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/cffi-1.17.1.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/charset_normalizer-3.4.2.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/cryptography-45.0.3.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2/venv/lib/python3.12/site-packages/dar_backup-0.7.2.dist-info → dar_backup-0.8.1/venv/lib/python3.12/site-packages/dar_backup-0.8.1.dist-info}/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/filelock-3.18.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/hyperlink-21.0.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/id-1.5.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/iniconfig-2.1.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/jaraco.classes-3.4.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/jaraco.context-6.0.1.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/jaraco.functools-4.1.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/jeepney-0.9.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/keyring-25.6.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/markdown_it_py-3.0.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/mdurl-0.1.2.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/more_itertools-10.7.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/mypy_extensions-1.1.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/nh3-0.2.21.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/packaging-25.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/pathspec-0.12.1.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/platformdirs-4.3.8.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/psutil-7.0.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/ptyprocess-0.7.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/pycparser-2.22.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/pygments-2.19.1.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/pyproject_hooks-1.2.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/pytest-8.4.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/pytest_cov-6.1.1.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/pytest_timeout-2.4.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/readme_renderer-44.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/requests_toolbelt-1.0.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/rfc3986-2.0.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/rich-14.0.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/shellingham-1.5.4.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/tomli_w-1.2.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/tomlkit-0.13.2.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/trove_classifiers-2025.5.9.12.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/twine-6.1.0.dist-info/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/typing_extensions-4.14.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/virtualenv-20.31.2.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/wheel/vendored/packaging/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/zipp-3.22.0.dist-info/licenses/LICENSE +0 -0
- {dar_backup-0.7.2 → dar_backup-0.8.1}/venv/lib/python3.12/site-packages/zstandard-0.23.0.dist-info/LICENSE +0 -0
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
<!-- markdownlint-disable MD024 -->
|
|
2
2
|
# dar-backup Changelog
|
|
3
3
|
|
|
4
|
+
## v2-beta-0.8.1 - 2025-07-16
|
|
5
|
+
|
|
6
|
+
Github link: [v2-beta-0.8.1](https://github.com/per2jensen/dar-backup/tree/v2-beta-0.8.1/v2)
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- FIX: runner now logs an error and fills more data into the returned CommandResult.
|
|
11
|
+
|
|
12
|
+
## v2-beta-0.8.0 - 2025-06-13
|
|
13
|
+
|
|
14
|
+
Github link: [v2-beta-0.8.0](https://github.com/per2jensen/dar-backup/tree/v2-beta-0.8.0/v2)
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Modified clone dashboard generator to produce easier to read dashboard and be more robust.
|
|
19
|
+
- Dir_traversal sanitation: clean_log.py now only accepts files in configured log directory to `--file` option.
|
|
20
|
+
|
|
4
21
|
## v2-beta-0.7.2 - 2025-06-07
|
|
5
22
|
|
|
6
23
|
Github link: [v2-beta-0.7.2](https://github.com/per2jensen/dar-backup/tree/v2-beta-0.7.2/v2)
|
|
@@ -16,7 +33,7 @@ Github link: [v2-beta-0.7.2](https://github.com/per2jensen/dar-backup/tree/v2-be
|
|
|
16
33
|
- Enrolling into [Snyk code checker](https://snyk.io/code-checker/) and learning how to work with it.
|
|
17
34
|
|
|
18
35
|
- Snyk helped pointing out vulnerable versions of some packages used.
|
|
19
|
-
- Input
|
|
36
|
+
- Input sanitation started, there is room for improvement.
|
|
20
37
|
|
|
21
38
|
## v2-beta-0.7.1 - 2025-05-22
|
|
22
39
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dar-backup
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.1
|
|
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
|
|
@@ -699,6 +699,8 @@ 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
|
+
Requires-Dist: matplotlib>=3.10.3; extra == 'dev'
|
|
703
|
+
Requires-Dist: pandas>=2.3.0; extra == 'dev'
|
|
702
704
|
Requires-Dist: psutil>=7.0.0; extra == 'dev'
|
|
703
705
|
Requires-Dist: pytest; extra == 'dev'
|
|
704
706
|
Requires-Dist: pytest-cov>=6.1.1; extra == 'dev'
|
|
@@ -725,7 +727,7 @@ Description-Content-Type: text/markdown
|
|
|
725
727
|
[](https://pypi.org/project/dar-backup/)
|
|
726
728
|
[](https://pypi.org/project/dar-backup/)
|
|
727
729
|
[](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
|
|
728
|
-
[](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
|
|
730
|
+
[](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png) <sub>🎯 Stats powered by [ClonePulse](https://github.com/per2jensen/clonepulse)</sub>
|
|
729
731
|
|
|
730
732
|
The wonderful 'dar' [Disk Archiver](https://github.com/Edrusb/DAR) is used for
|
|
731
733
|
the heavy lifting, together with the [parchive](https://github.com/Parchive/par2cmdline) suite in these scripts.
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://pypi.org/project/dar-backup/)
|
|
10
10
|
[](https://pypi.org/project/dar-backup/)
|
|
11
11
|
[](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
|
|
12
|
-
[](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
|
|
12
|
+
[](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png) <sub>🎯 Stats powered by [ClonePulse](https://github.com/per2jensen/clonepulse)</sub>
|
|
13
13
|
|
|
14
14
|
The wonderful 'dar' [Disk Archiver](https://github.com/Edrusb/DAR) is used for
|
|
15
15
|
the heavy lifting, together with the [parchive](https://github.com/Parchive/par2cmdline) suite in these scripts.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Reached 1000 clones on 2025-06-13T02:51:59.728578+00:00Z
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
{
|
|
2
|
+
"annotations": [
|
|
3
|
+
{
|
|
4
|
+
"date": "2025-05-17",
|
|
5
|
+
"label": "LinkedIn"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"date": "2025-05-04",
|
|
9
|
+
"label": "r/linuxadmin"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"date": "2025-05-20",
|
|
13
|
+
"label": "Daily max: 124"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"total_clones": 1453,
|
|
17
|
+
"unique_clones": 824,
|
|
18
|
+
"daily": [
|
|
19
|
+
{
|
|
20
|
+
"timestamp": "2025-05-04T00:00:00Z",
|
|
21
|
+
"count": 30,
|
|
22
|
+
"uniques": 15
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"timestamp": "2025-05-05T00:00:00Z",
|
|
26
|
+
"count": 7,
|
|
27
|
+
"uniques": 5
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"timestamp": "2025-05-06T00:00:00Z",
|
|
31
|
+
"count": 7,
|
|
32
|
+
"uniques": 5
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"timestamp": "2025-05-07T00:00:00Z",
|
|
36
|
+
"count": 2,
|
|
37
|
+
"uniques": 2
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"timestamp": "2025-05-08T00:00:00Z",
|
|
41
|
+
"count": 10,
|
|
42
|
+
"uniques": 7
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"timestamp": "2025-05-09T00:00:00Z",
|
|
46
|
+
"count": 10,
|
|
47
|
+
"uniques": 5
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"timestamp": "2025-05-10T00:00:00Z",
|
|
51
|
+
"count": 8,
|
|
52
|
+
"uniques": 6
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"timestamp": "2025-05-11T00:00:00Z",
|
|
56
|
+
"count": 7,
|
|
57
|
+
"uniques": 5
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"timestamp": "2025-05-12T00:00:00Z",
|
|
61
|
+
"count": 11,
|
|
62
|
+
"uniques": 5
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"timestamp": "2025-05-13T00:00:00Z",
|
|
66
|
+
"count": 25,
|
|
67
|
+
"uniques": 13
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"timestamp": "2025-05-14T00:00:00Z",
|
|
71
|
+
"count": 22,
|
|
72
|
+
"uniques": 12
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"timestamp": "2025-05-15T00:00:00Z",
|
|
76
|
+
"count": 13,
|
|
77
|
+
"uniques": 8
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"timestamp": "2025-05-16T00:00:00Z",
|
|
81
|
+
"count": 8,
|
|
82
|
+
"uniques": 4
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"timestamp": "2025-05-17T00:00:00Z",
|
|
86
|
+
"count": 14,
|
|
87
|
+
"uniques": 7
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"timestamp": "2025-05-18T00:00:00Z",
|
|
91
|
+
"count": 53,
|
|
92
|
+
"uniques": 23
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"timestamp": "2025-05-19T00:00:00Z",
|
|
96
|
+
"count": 31,
|
|
97
|
+
"uniques": 13
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"timestamp": "2025-05-20T00:00:00Z",
|
|
101
|
+
"count": 124,
|
|
102
|
+
"uniques": 44
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"timestamp": "2025-05-21T00:00:00Z",
|
|
106
|
+
"count": 40,
|
|
107
|
+
"uniques": 18
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"timestamp": "2025-05-22T00:00:00Z",
|
|
111
|
+
"count": 19,
|
|
112
|
+
"uniques": 12
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"timestamp": "2025-05-23T00:00:00Z",
|
|
116
|
+
"count": 9,
|
|
117
|
+
"uniques": 5
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"timestamp": "2025-05-24T00:00:00Z",
|
|
121
|
+
"count": 8,
|
|
122
|
+
"uniques": 6
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"timestamp": "2025-05-25T00:00:00Z",
|
|
126
|
+
"count": 63,
|
|
127
|
+
"uniques": 23
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"timestamp": "2025-05-26T00:00:00Z",
|
|
131
|
+
"count": 13,
|
|
132
|
+
"uniques": 7
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"timestamp": "2025-05-27T00:00:00Z",
|
|
136
|
+
"count": 9,
|
|
137
|
+
"uniques": 7
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"timestamp": "2025-05-28T00:00:00Z",
|
|
141
|
+
"count": 5,
|
|
142
|
+
"uniques": 3
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"timestamp": "2025-05-29T00:00:00Z",
|
|
146
|
+
"count": 13,
|
|
147
|
+
"uniques": 6
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"timestamp": "2025-05-30T00:00:00Z",
|
|
151
|
+
"count": 7,
|
|
152
|
+
"uniques": 3
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"timestamp": "2025-05-31T00:00:00Z",
|
|
156
|
+
"count": 8,
|
|
157
|
+
"uniques": 5
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"timestamp": "2025-06-01T00:00:00Z",
|
|
161
|
+
"count": 25,
|
|
162
|
+
"uniques": 15
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"timestamp": "2025-06-02T00:00:00Z",
|
|
166
|
+
"count": 15,
|
|
167
|
+
"uniques": 7
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"timestamp": "2025-06-03T00:00:00Z",
|
|
171
|
+
"count": 57,
|
|
172
|
+
"uniques": 31
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"timestamp": "2025-06-04T00:00:00Z",
|
|
176
|
+
"count": 35,
|
|
177
|
+
"uniques": 22
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"timestamp": "2025-06-05T00:00:00Z",
|
|
181
|
+
"count": 15,
|
|
182
|
+
"uniques": 12
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"timestamp": "2025-06-06T00:00:00Z",
|
|
186
|
+
"count": 33,
|
|
187
|
+
"uniques": 18
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"timestamp": "2025-06-07T00:00:00Z",
|
|
191
|
+
"count": 49,
|
|
192
|
+
"uniques": 20
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"timestamp": "2025-06-08T00:00:00Z",
|
|
196
|
+
"count": 33,
|
|
197
|
+
"uniques": 19
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"timestamp": "2025-06-09T00:00:00Z",
|
|
201
|
+
"count": 18,
|
|
202
|
+
"uniques": 12
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"timestamp": "2025-06-10T00:00:00Z",
|
|
206
|
+
"count": 26,
|
|
207
|
+
"uniques": 16
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"timestamp": "2025-06-11T00:00:00Z",
|
|
211
|
+
"count": 9,
|
|
212
|
+
"uniques": 6
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"timestamp": "2025-06-12T00:00:00Z",
|
|
216
|
+
"count": 10,
|
|
217
|
+
"uniques": 8
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"timestamp": "2025-06-13T00:00:00Z",
|
|
221
|
+
"count": 48,
|
|
222
|
+
"uniques": 18
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"timestamp": "2025-06-14T00:00:00Z",
|
|
226
|
+
"count": 11,
|
|
227
|
+
"uniques": 9
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"timestamp": "2025-06-15T00:00:00Z",
|
|
231
|
+
"count": 10,
|
|
232
|
+
"uniques": 8
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"timestamp": "2025-06-16T00:00:00Z",
|
|
236
|
+
"count": 18,
|
|
237
|
+
"uniques": 11
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"timestamp": "2025-06-17T00:00:00Z",
|
|
241
|
+
"count": 11,
|
|
242
|
+
"uniques": 9
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"timestamp": "2025-06-18T00:00:00Z",
|
|
246
|
+
"count": 9,
|
|
247
|
+
"uniques": 7
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"timestamp": "2025-06-19T00:00:00Z",
|
|
251
|
+
"count": 10,
|
|
252
|
+
"uniques": 8
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"timestamp": "2025-06-20T00:00:00Z",
|
|
256
|
+
"count": 25,
|
|
257
|
+
"uniques": 18
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"timestamp": "2025-06-21T00:00:00Z",
|
|
261
|
+
"count": 8,
|
|
262
|
+
"uniques": 6
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"timestamp": "2025-06-22T00:00:00Z",
|
|
266
|
+
"count": 8,
|
|
267
|
+
"uniques": 6
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"timestamp": "2025-06-23T00:00:00Z",
|
|
271
|
+
"count": 19,
|
|
272
|
+
"uniques": 14
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"timestamp": "2025-06-24T00:00:00Z",
|
|
276
|
+
"count": 8,
|
|
277
|
+
"uniques": 6
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"timestamp": "2025-06-25T00:00:00Z",
|
|
281
|
+
"count": 11,
|
|
282
|
+
"uniques": 8
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"timestamp": "2025-06-26T00:00:00Z",
|
|
286
|
+
"count": 6,
|
|
287
|
+
"uniques": 5
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"timestamp": "2025-06-27T00:00:00Z",
|
|
291
|
+
"count": 11,
|
|
292
|
+
"uniques": 7
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"timestamp": "2025-06-28T00:00:00Z",
|
|
296
|
+
"count": 12,
|
|
297
|
+
"uniques": 9
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"timestamp": "2025-06-29T00:00:00Z",
|
|
301
|
+
"count": 10,
|
|
302
|
+
"uniques": 7
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"timestamp": "2025-06-30T00:00:00Z",
|
|
306
|
+
"count": 20,
|
|
307
|
+
"uniques": 13
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"timestamp": "2025-07-01T00:00:00Z",
|
|
311
|
+
"count": 12,
|
|
312
|
+
"uniques": 10
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"timestamp": "2025-07-02T00:00:00Z",
|
|
316
|
+
"count": 12,
|
|
317
|
+
"uniques": 10
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"timestamp": "2025-07-03T00:00:00Z",
|
|
321
|
+
"count": 20,
|
|
322
|
+
"uniques": 14
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"timestamp": "2025-07-04T00:00:00Z",
|
|
326
|
+
"count": 18,
|
|
327
|
+
"uniques": 9
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"timestamp": "2025-07-05T00:00:00Z",
|
|
331
|
+
"count": 21,
|
|
332
|
+
"uniques": 14
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"timestamp": "2025-07-06T00:00:00Z",
|
|
336
|
+
"count": 20,
|
|
337
|
+
"uniques": 15
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"timestamp": "2025-07-07T00:00:00Z",
|
|
341
|
+
"count": 26,
|
|
342
|
+
"uniques": 17
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"timestamp": "2025-07-08T00:00:00Z",
|
|
346
|
+
"count": 14,
|
|
347
|
+
"uniques": 9
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
"timestamp": "2025-07-09T00:00:00Z",
|
|
351
|
+
"count": 19,
|
|
352
|
+
"uniques": 13
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"timestamp": "2025-07-10T00:00:00Z",
|
|
356
|
+
"count": 18,
|
|
357
|
+
"uniques": 13
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
"timestamp": "2025-07-11T00:00:00Z",
|
|
361
|
+
"count": 22,
|
|
362
|
+
"uniques": 13
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"timestamp": "2025-07-12T00:00:00Z",
|
|
366
|
+
"count": 19,
|
|
367
|
+
"uniques": 12
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
"timestamp": "2025-07-13T00:00:00Z",
|
|
371
|
+
"count": 20,
|
|
372
|
+
"uniques": 13
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"timestamp": "2025-07-14T00:00:00Z",
|
|
376
|
+
"count": 38,
|
|
377
|
+
"uniques": 21
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"timestamp": "2025-07-15T00:00:00Z",
|
|
381
|
+
"count": 18,
|
|
382
|
+
"uniques": 12
|
|
383
|
+
}
|
|
384
|
+
]
|
|
385
|
+
}
|
|
Binary file
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
<!-- markdownlint-disable MD024 -->
|
|
2
2
|
# dar-backup Changelog
|
|
3
3
|
|
|
4
|
+
## v2-beta-0.8.1 - 2025-07-16
|
|
5
|
+
|
|
6
|
+
Github link: [v2-beta-0.8.1](https://github.com/per2jensen/dar-backup/tree/v2-beta-0.8.1/v2)
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- FIX: runner now logs an error and fills more data into the returned CommandResult.
|
|
11
|
+
|
|
12
|
+
## v2-beta-0.8.0 - 2025-06-13
|
|
13
|
+
|
|
14
|
+
Github link: [v2-beta-0.8.0](https://github.com/per2jensen/dar-backup/tree/v2-beta-0.8.0/v2)
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Modified clone dashboard generator to produce easier to read dashboard and be more robust.
|
|
19
|
+
- Dir_traversal sanitation: clean_log.py now only accepts files in configured log directory to `--file` option.
|
|
20
|
+
|
|
4
21
|
## v2-beta-0.7.2 - 2025-06-07
|
|
5
22
|
|
|
6
23
|
Github link: [v2-beta-0.7.2](https://github.com/per2jensen/dar-backup/tree/v2-beta-0.7.2/v2)
|
|
@@ -16,7 +33,7 @@ Github link: [v2-beta-0.7.2](https://github.com/per2jensen/dar-backup/tree/v2-be
|
|
|
16
33
|
- Enrolling into [Snyk code checker](https://snyk.io/code-checker/) and learning how to work with it.
|
|
17
34
|
|
|
18
35
|
- Snyk helped pointing out vulnerable versions of some packages used.
|
|
19
|
-
- Input
|
|
36
|
+
- Input sanitation started, there is room for improvement.
|
|
20
37
|
|
|
21
38
|
## v2-beta-0.7.1 - 2025-05-22
|
|
22
39
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://pypi.org/project/dar-backup/)
|
|
10
10
|
[](https://pypi.org/project/dar-backup/)
|
|
11
11
|
[](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
|
|
12
|
-
[](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
|
|
12
|
+
[](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png) <sub>🎯 Stats powered by [ClonePulse](https://github.com/per2jensen/clonepulse)</sub>
|
|
13
13
|
|
|
14
14
|
The wonderful 'dar' [Disk Archiver](https://github.com/Edrusb/DAR) is used for
|
|
15
15
|
the heavy lifting, together with the [parchive](https://github.com/Parchive/par2cmdline) suite in these scripts.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.8.1"
|
|
2
2
|
|
|
3
3
|
__license__ = '''Licensed under GNU GENERAL PUBLIC LICENSE v3, see the supplied file "LICENSE" for details.
|
|
4
4
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW, not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
@@ -138,6 +138,18 @@ def main():
|
|
|
138
138
|
|
|
139
139
|
for file_path in args.file:
|
|
140
140
|
|
|
141
|
+
if ".." in os.path.normpath(file_path).split(os.sep):
|
|
142
|
+
print(f"Error: Path traversal is not allowed: '{file_path}'")
|
|
143
|
+
sys.exit(1)
|
|
144
|
+
|
|
145
|
+
logfile_dir = os.path.dirname(os.path.realpath(config_settings.logfile_location))
|
|
146
|
+
resolved_path = os.path.realpath(file_path)
|
|
147
|
+
|
|
148
|
+
if not resolved_path.startswith(logfile_dir + os.sep):
|
|
149
|
+
print(f"Error: File is outside allowed directory: '{file_path}'")
|
|
150
|
+
sys.exit(1)
|
|
151
|
+
|
|
152
|
+
# Validate the file path type and existence
|
|
141
153
|
if not isinstance(file_path, (str, bytes, os.PathLike)):
|
|
142
154
|
print(f"Error: Invalid file path type: {file_path}")
|
|
143
155
|
sys.exit(1)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import subprocess
|
|
4
4
|
import logging
|
|
5
|
+
import traceback
|
|
5
6
|
import threading
|
|
6
7
|
import os
|
|
7
8
|
import sys
|
|
@@ -12,14 +13,24 @@ from dar_backup.util import get_logger
|
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class CommandResult:
|
|
15
|
-
def __init__(self, returncode: int, stdout: str, stderr: str):
|
|
16
|
+
def __init__(self, returncode: int, stdout: str, stderr: str, stack: str = None):
|
|
16
17
|
self.returncode = returncode
|
|
17
18
|
self.stdout = stdout
|
|
18
19
|
self.stderr = stderr
|
|
20
|
+
self.stack = stack
|
|
19
21
|
|
|
20
22
|
def __repr__(self):
|
|
21
|
-
return f"<CommandResult returncode={self.returncode}>"
|
|
22
|
-
|
|
23
|
+
return f"<CommandResult returncode={self.returncode}\nstdout={self.stdout}\nstderr={self.stderr}\nstack={self.stack}>"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def __str__(self):
|
|
27
|
+
return (
|
|
28
|
+
f"CommandResult:\n"
|
|
29
|
+
f" Return code: {self.returncode}\n"
|
|
30
|
+
f" STDOUT:\n{self.stdout}\n"
|
|
31
|
+
f" STDERR:\n{self.stderr}\n"
|
|
32
|
+
f" Stacktrace:\n{self.stack if self.stack else '<none>'}"
|
|
33
|
+
)
|
|
23
34
|
|
|
24
35
|
class CommandRunner:
|
|
25
36
|
def __init__(
|
|
@@ -74,22 +85,29 @@ class CommandRunner:
|
|
|
74
85
|
) -> CommandResult:
|
|
75
86
|
timeout = timeout or self.default_timeout
|
|
76
87
|
|
|
77
|
-
#log the command to be executed
|
|
78
88
|
command = f"Executing command: {' '.join(cmd)} (timeout={timeout}s)"
|
|
79
|
-
self.command_logger.info(command)
|
|
80
|
-
self.logger.debug(command)
|
|
81
|
-
|
|
82
|
-
process = subprocess.Popen(
|
|
83
|
-
cmd,
|
|
84
|
-
stdout=subprocess.PIPE if capture_output else None,
|
|
85
|
-
stderr=subprocess.PIPE if capture_output else None,
|
|
86
|
-
text=False,
|
|
87
|
-
bufsize=-1
|
|
88
|
-
)
|
|
89
|
+
self.command_logger.info(command)
|
|
90
|
+
self.logger.debug(command)
|
|
89
91
|
|
|
90
92
|
stdout_lines = []
|
|
91
93
|
stderr_lines = []
|
|
92
94
|
|
|
95
|
+
try:
|
|
96
|
+
process = subprocess.Popen(
|
|
97
|
+
cmd,
|
|
98
|
+
stdout=subprocess.PIPE if capture_output else None,
|
|
99
|
+
stderr=subprocess.PIPE if capture_output else None,
|
|
100
|
+
text=False,
|
|
101
|
+
bufsize=-1
|
|
102
|
+
)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
stack = traceback.format_exc()
|
|
105
|
+
return CommandResult(
|
|
106
|
+
returncode=-1,
|
|
107
|
+
stdout='',
|
|
108
|
+
stderr=str(e),
|
|
109
|
+
stack=stack
|
|
110
|
+
)
|
|
93
111
|
|
|
94
112
|
def stream_output(stream, lines, level):
|
|
95
113
|
try:
|
|
@@ -123,11 +141,27 @@ class CommandRunner:
|
|
|
123
141
|
process.kill()
|
|
124
142
|
self.logger.error(f"Command timed out: {' '.join(cmd)}")
|
|
125
143
|
return CommandResult(-1, ''.join(stdout_lines), ''.join(stderr_lines))
|
|
144
|
+
except Exception as e:
|
|
145
|
+
stack = traceback.format_exc()
|
|
146
|
+
self.logger.error(f"Command execution failed: {' '.join(cmd)} with error: {e}")
|
|
147
|
+
return CommandResult(-1, ''.join(stdout_lines), ''.join(stderr_lines), stack)
|
|
126
148
|
|
|
127
149
|
for t in threads:
|
|
128
150
|
t.join()
|
|
129
151
|
|
|
152
|
+
|
|
130
153
|
if check and process.returncode != 0:
|
|
131
154
|
self.logger.error(f"Command failed with exit code {process.returncode}")
|
|
155
|
+
return CommandResult(
|
|
156
|
+
process.returncode,
|
|
157
|
+
''.join(stdout_lines),
|
|
158
|
+
''.join(stderr_lines),
|
|
159
|
+
stack=traceback.format_stack()
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
return CommandResult(
|
|
163
|
+
process.returncode,
|
|
164
|
+
''.join(stdout_lines),
|
|
165
|
+
''.join(stderr_lines),
|
|
166
|
+
)
|
|
132
167
|
|
|
133
|
-
return CommandResult(process.returncode, ''.join(stdout_lines), ''.join(stderr_lines))
|