dar-backup 0.6.18__py3-none-any.whl → 0.6.20__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/util.py CHANGED
@@ -9,6 +9,7 @@ See section 15 and section 16 in the supplied "LICENSE" file
9
9
  """
10
10
  import typing
11
11
  import locale
12
+ import configparser
12
13
  import logging
13
14
  import os
14
15
  import re
@@ -18,10 +19,17 @@ import shutil
18
19
  import sys
19
20
  import threading
20
21
  import traceback
22
+ from argcomplete.completers import ChoicesCompleter
21
23
  from datetime import datetime
22
24
  from dar_backup.config_settings import ConfigSettings
25
+ import dar_backup.__about__ as about
26
+
27
+ from rich.console import Console
28
+ from rich.text import Text
23
29
 
24
30
  from typing import NamedTuple, List
31
+ from typing import Tuple
32
+
25
33
 
26
34
  logger=None
27
35
  secondary_logger=None
@@ -72,11 +80,9 @@ def setup_logging(log_file: str, command_output_log_file: str, log_level: str =
72
80
  stdout_handler = logging.StreamHandler(sys.stdout)
73
81
  stdout_handler.setFormatter(formatter)
74
82
  logger.addHandler(stdout_handler)
75
- #secondary_logger.addHandler(stdout_handler)
76
83
 
77
84
  return logger
78
85
  except Exception as e:
79
- print("Logging initialization failed.")
80
86
  traceback.print_exc()
81
87
  sys.exit(1)
82
88
 
@@ -96,6 +102,72 @@ def get_logger(command_output_logger: bool = False) -> logging.Logger:
96
102
 
97
103
  return secondary_logger if command_output_logger else logger
98
104
 
105
+ def show_version():
106
+ script_name = os.path.basename(sys.argv[0])
107
+ print(f"{script_name} {about.__version__}")
108
+ print(f"{script_name} source code is here: https://github.com/per2jensen/dar-backup")
109
+ print('''Licensed under GNU GENERAL PUBLIC LICENSE v3, see the supplied file "LICENSE" for details.
110
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW, not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
111
+ See section 15 and section 16 in the supplied "LICENSE" file.''')
112
+
113
+ def extract_version(output):
114
+ match = re.search(r'(\d+\.\d+(\.\d+)?)', output)
115
+ return match.group(1) if match else "unknown"
116
+
117
+ def get_binary_info(command):
118
+ """
119
+ Return information about a binary command.
120
+ Args:
121
+ command (str): The command to check.
122
+ Returns:
123
+ dict: A dictionary containing the command, path, version, and full output.
124
+ Dict structure:
125
+ {
126
+ "command": str,
127
+ "path": str,
128
+ "version": str,
129
+ "full_output": str
130
+ }
131
+ Raises:
132
+ Exception: If there is an error running the command.
133
+ """
134
+ path = shutil.which(command)
135
+ if path is None:
136
+ return {
137
+ "command": command,
138
+ "path": "Not found",
139
+ "version": "unknown",
140
+ "full_output": ""
141
+ }
142
+
143
+ try:
144
+ result = subprocess.run(
145
+ [path, '--version'],
146
+ stdout=subprocess.PIPE,
147
+ stderr=subprocess.PIPE,
148
+ text=True
149
+ )
150
+
151
+ # Combine output regardless of return code
152
+ combined_output = (result.stdout + result.stderr).strip()
153
+
154
+ # Even if returncode != 0, the version info may still be valid
155
+ version = extract_version(combined_output)
156
+
157
+ return {
158
+ "command": command,
159
+ "path": path,
160
+ "version": version if version else "unknown",
161
+ "full_output": combined_output
162
+ }
163
+
164
+ except Exception as e:
165
+ return {
166
+ "command": command,
167
+ "path": path,
168
+ "version": "error",
169
+ "full_output": str(e)
170
+ }
99
171
 
100
172
 
101
173
  def requirements(type: str, config_setting: ConfigSettings):
@@ -155,7 +227,6 @@ class RestoreError(Exception):
155
227
  pass
156
228
 
157
229
 
158
-
159
230
  class CommandResult(NamedTuple):
160
231
  """
161
232
  The reult of the run_command() function.
@@ -238,4 +309,275 @@ def list_backups(backup_dir, backup_definition=None):
238
309
  print(f"{backup.ljust(max_name_length)} : {formatted_size.rjust(max_size_length)} MB")
239
310
 
240
311
 
312
+ def expand_path(path: str) -> str:
313
+ """
314
+ Expand ~ and environment variables like $HOME in a path.
315
+ """
316
+ return os.path.expanduser(os.path.expandvars(path))
317
+
318
+
319
+
320
+ def backup_definition_completer(prefix, parsed_args, **kwargs):
321
+ config_path = getattr(parsed_args, 'config_file', '~/.config/dar-backup/dar-backup.conf')
322
+ config_path = expand_path(config_path)
323
+ config_file = os.path.expanduser(config_path)
324
+ try:
325
+ config = ConfigSettings(config_file)
326
+ backup_d_dir = os.path.expanduser(config.backup_d_dir)
327
+ return [f for f in os.listdir(backup_d_dir) if f.startswith(prefix)]
328
+ except Exception:
329
+ return []
330
+
331
+
332
+ def extract_backup_definition_fallback() -> str:
333
+ """
334
+ Extracts --backup-definition or -d value directly from COMP_LINE.
335
+ This is needed because argcomplete doesn't always populate parsed_args fully.
336
+
337
+ Returns:
338
+ str: The value of the --backup-definition argument if found, else an empty string.
339
+ """
340
+ comp_line = os.environ.get("COMP_LINE", "")
341
+ # Match both "--backup-definition VALUE" and "-d VALUE"
342
+ match = re.search(r"(--backup-definition|-d)\s+([^\s]+)", comp_line)
343
+ if match:
344
+ return match.group(2)
345
+ return ""
346
+
347
+
348
+
349
+ def list_archive_completer(prefix, parsed_args, **kwargs):
350
+ import os
351
+ import configparser
352
+ from dar_backup.util import extract_backup_definition_fallback
353
+
354
+ backup_def = getattr(parsed_args, "backup_definition", None) or extract_backup_definition_fallback()
355
+ config_path = getattr(parsed_args, "config_file", None) or "~/.config/dar-backup/dar-backup.conf"
356
+
357
+ config_path = os.path.expanduser(os.path.expandvars(config_path))
358
+ if not os.path.exists(config_path):
359
+ return []
360
+
361
+ config = configparser.ConfigParser()
362
+ config.read(config_path)
363
+ backup_dir = config.get("DIRECTORIES", "BACKUP_DIR", fallback="")
364
+ backup_dir = os.path.expanduser(os.path.expandvars(backup_dir))
365
+
366
+ if not os.path.isdir(backup_dir):
367
+ return []
368
+
369
+ files = os.listdir(backup_dir)
370
+ archive_re = re.compile(rf"^{re.escape(backup_def)}_.+_\d{{4}}-\d{{2}}-\d{{2}}\.1\.dar$") if backup_def else re.compile(r".+_\d{4}-\d{2}-\d{2}\.1\.dar$")
371
+
372
+ return [
373
+ f.rsplit(".1.dar", 1)[0]
374
+ for f in files
375
+ if archive_re.match(f)
376
+ ]
377
+
378
+
379
+ def archive_content_completer(prefix, parsed_args, **kwargs):
380
+ """
381
+ Completes archive names from all available *.db files.
382
+ If --backup-def is given, only that one is used.
383
+ Only entries found in the catalog database (via `dar_manager --list`) are shown.
384
+ """
385
+
386
+ from dar_backup.config_settings import ConfigSettings
387
+ import subprocess
388
+ import re
389
+ import os
390
+ from datetime import datetime
391
+
392
+ # Expand config path
393
+ config_file = expand_path(getattr(parsed_args, "config_file", "~/.config/dar-backup/dar-backup.conf"))
394
+ config = ConfigSettings(config_file=config_file)
395
+ backup_dir = config.backup_dir
396
+
397
+ # Which db files to inspect?
398
+ backup_def = getattr(parsed_args, "backup_def", None)
399
+ db_files = (
400
+ [os.path.join(backup_dir, f"{backup_def}.db")]
401
+ if backup_def
402
+ else [os.path.join(backup_dir, f) for f in os.listdir(backup_dir) if f.endswith(".db")]
403
+ )
404
+
405
+ completions = []
406
+
407
+ for db_path in db_files:
408
+ if not os.path.exists(db_path):
409
+ continue
410
+
411
+ try:
412
+ result = subprocess.run(
413
+ ["dar_manager", "--base", db_path, "--list"],
414
+ stdout=subprocess.PIPE,
415
+ stderr=subprocess.DEVNULL,
416
+ text=True,
417
+ check=True
418
+ )
419
+ except subprocess.CalledProcessError:
420
+ continue
421
+
422
+ for line in result.stdout.splitlines():
423
+ parts = line.strip().split("\t")
424
+ if len(parts) >= 3:
425
+ archive = parts[2].strip()
426
+ if archive.startswith(prefix):
427
+ completions.append(archive)
428
+
429
+ # Sort: first by name (before first '_'), then by date (YYYY-MM-DD)
430
+ def sort_key(archive):
431
+ name_part = archive.split("_")[0]
432
+ date_match = re.search(r"\d{4}-\d{2}-\d{2}", archive)
433
+ date = datetime.strptime(date_match.group(0), "%Y-%m-%d") if date_match else datetime.min
434
+ return (name_part, date)
435
+
436
+ completions = sorted(set(completions), key=sort_key)
437
+ return completions or ["[no matching archives]"]
438
+
439
+
440
+
441
+ def add_specific_archive_completer(prefix, parsed_args, **kwargs):
442
+ """
443
+ Autocompletes archives that are present in the BACKUP_DIR
444
+ but not yet present in the <backup_def>.db catalog.
445
+ If --backup-def is provided, restrict suggestions to that.
446
+ """
447
+ from dar_backup.config_settings import ConfigSettings
448
+ import subprocess
449
+ import re
450
+ import os
451
+ from datetime import datetime
452
+
453
+ config_file = expand_path(getattr(parsed_args, "config_file", "~/.config/dar-backup/dar-backup.conf"))
454
+ config = ConfigSettings(config_file=config_file)
455
+ backup_dir = config.backup_dir
456
+ backup_def = getattr(parsed_args, "backup_def", None)
457
+
458
+ # Match pattern for archive base names: e.g. test_FULL_2025-04-01
459
+ dar_pattern = re.compile(r"^(.*?_(FULL|DIFF|INCR)_(\d{4}-\d{2}-\d{2}))\.1\.dar$")
460
+
461
+ # Step 1: scan backup_dir for .1.dar files
462
+ all_archives = set()
463
+ for fname in os.listdir(backup_dir):
464
+ match = dar_pattern.match(fname)
465
+ if match:
466
+ base = match.group(1)
467
+ if base.startswith(prefix):
468
+ if not backup_def or base.startswith(f"{backup_def}_"):
469
+ all_archives.add(base)
470
+
471
+ # Step 2: exclude ones already present in the .db
472
+ db_path = os.path.join(backup_dir, f"{backup_def}.db") if backup_def else None
473
+ existing = set()
474
+
475
+ if db_path and os.path.exists(db_path):
476
+ try:
477
+ result = subprocess.run(
478
+ ["dar_manager", "--base", db_path, "--list"],
479
+ stdout=subprocess.PIPE,
480
+ stderr=subprocess.DEVNULL,
481
+ text=True,
482
+ check=True
483
+ )
484
+ for line in result.stdout.splitlines():
485
+ parts = line.strip().split("\t")
486
+ if len(parts) >= 3:
487
+ existing.add(parts[2].strip())
488
+ except subprocess.CalledProcessError:
489
+ pass
490
+
491
+ # Step 3: return filtered list
492
+ candidates = sorted(archive for archive in all_archives if archive not in existing)
493
+ return candidates or ["[no new archives]"]
494
+
495
+
496
+
497
+
498
+ def patch_config_file(path: str, replacements: dict) -> None:
499
+ """
500
+ Replace specific key values in a config file in-place.
501
+
502
+ Args:
503
+ path: Path to the config file.
504
+ replacements: Dictionary of keys to new values, e.g., {"LOGFILE_LOCATION": "/tmp/logfile.log"}.
505
+ """
506
+ with open(path, 'r') as f:
507
+ lines = f.readlines()
508
+
509
+ with open(path, 'w') as f:
510
+ for line in lines:
511
+ key = line.split('=')[0].strip()
512
+ if key in replacements:
513
+ f.write(f"{key} = {replacements[key]}\n")
514
+ else:
515
+ f.write(line)
516
+
517
+
518
+
519
+
520
+ console = Console()
521
+
522
+ def print_aligned_settings(
523
+ settings: List[Tuple[str, str]],
524
+ log: bool = True,
525
+ header: str = "Startup Settings",
526
+ highlight_keywords: List[str] = None
527
+ ) -> None:
528
+ """
529
+ Print and optionally log settings nicely, using rich for color.
530
+ Highlights settings if dangerous keywords are found inside label or text,
531
+ but only if text is not None or empty.
532
+ """
533
+ if not settings:
534
+ return
535
+
536
+ settings = [(str(label), "" if text is None else str(text)) for label, text in settings]
537
+ logger = get_logger()
538
+
539
+ max_label_length = max(len(label) for label, _ in settings)
540
+
541
+ header_line = f"========== {header} =========="
542
+ footer_line = "=" * len(header_line)
543
+
544
+ console.print(f"[bold cyan]{header_line}[/bold cyan]")
545
+ if log and logger:
546
+ logger.info(header_line)
547
+
548
+ for label, text in settings:
549
+ padded_label = f"{label:<{max_label_length}}"
550
+
551
+ label_clean = label.rstrip(":").lower()
552
+ text_clean = text.lower()
553
+
554
+ # Skip highlighting if text is empty
555
+ if not text_clean.strip():
556
+ danger = False
557
+ else:
558
+ danger = False
559
+ if highlight_keywords:
560
+ combined_text = f"{label_clean} {text_clean}"
561
+ danger = any(keyword.lower() in combined_text for keyword in highlight_keywords)
562
+
563
+ # Build the line
564
+ line_text = Text()
565
+ line_text.append(padded_label, style="bold")
566
+ line_text.append(" ", style="none")
567
+
568
+ if danger:
569
+ line_text.append("[!]", style="bold red")
570
+ line_text.append(" ", style="none")
571
+
572
+ line_text.append(text, style="white")
573
+
574
+ console.print(line_text)
575
+
576
+ # Always log clean text (no [!] in log)
577
+ final_line_for_log = f"{padded_label} {text}"
578
+ if log and logger:
579
+ logger.info(final_line_for_log)
241
580
 
581
+ console.print(f"[bold cyan]{footer_line}[/bold cyan]")
582
+ if log and logger:
583
+ logger.info(footer_line)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dar-backup
3
- Version: 0.6.18
3
+ Version: 0.6.20
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
@@ -689,6 +689,7 @@ Classifier: Operating System :: POSIX :: Linux
689
689
  Classifier: Programming Language :: Python :: 3.9
690
690
  Classifier: Topic :: System :: Archiving :: Backup
691
691
  Requires-Python: >=3.9
692
+ Requires-Dist: argcomplete>=3.6.2
692
693
  Requires-Dist: inputimeout>=1.0.4
693
694
  Requires-Dist: rich>=13.0.0
694
695
  Description-Content-Type: text/markdown
@@ -697,12 +698,18 @@ Description-Content-Type: text/markdown
697
698
  # Full, differential or incremental backups using 'dar'
698
699
 
699
700
  [![codecov](https://codecov.io/gh/per2jensen/dar-backup/branch/main/graph/badge.svg)](https://codecov.io/gh/per2jensen/dar-backup)
701
+ [![PyPI monthly downloads](https://img.shields.io/pypi/dm/dar-backup)](https://pypi.org/project/dar-backup/)
702
+ [![Total Downloads](https://img.shields.io/badge/dynamic/json?color=blue&label=Total%20Downloads&query=total&url=https%3A%2F%2Fraw.githubusercontent.com%2Fper2jensen%2Fdar-backup%2Fmain%2Fdownloads.json)](https://pypi.org/project/dar-backup/)
700
703
 
701
704
  The wonderful 'dar' [Disk Archiver](https://github.com/Edrusb/DAR) is used for
702
705
  the heavy lifting, together with the par2 suite in these scripts.
703
706
 
704
707
  This is the `Python` based **version 2** of `dar-backup`.
705
708
 
709
+ ## TL;DR
710
+
711
+ `dar-backup` is a Python-powered CLI for creating and validating full, differential, and incremental backups using dar and par2. Designed for long-term restore integrity, even on user-space filesystems like FUSE.
712
+
706
713
  ## Table of Contents
707
714
 
708
715
  - [Full, differential or incremental backups using 'dar'](#full-differential-or-incremental-backups-using-dar)
@@ -728,6 +735,7 @@ This is the `Python` based **version 2** of `dar-backup`.
728
735
  - [Generate systemd files](#generate-systemd-files)
729
736
  - [Service: dar-back --incremental-backup](#service-dar-backup---incremental-backup)
730
737
  - [Timer: dar-back --incremental-backup](#timer-dar-backup---incremental-backup)
738
+ - [Systemd timer note](#systemd-timer-note)
731
739
  - [List contents of an archive](#list-contents-of-an-archive)
732
740
  - [dar file selection examples](#dar-file-selection-examples)
733
741
  - [Select a directory](#select-a-directory)
@@ -753,7 +761,9 @@ This is the `Python` based **version 2** of `dar-backup`.
753
761
  - [Skipping cache directories](#skipping-cache-directories)
754
762
  - [Progress bar + current directory](#progress-bar-and-current-directory)
755
763
  - [Todo](#todo)
764
+ - [Known Limitations / Edge Cases](#known-limitations--edge-cases)
756
765
  - [Reference](#reference)
766
+ - [CLI Tools Overview](#cli-tools-overview)
757
767
  - [Test coverage report](#test-coverage)
758
768
  - [dar-backup](#dar-backup-options)
759
769
  - [manager](#manager-options)
@@ -1346,6 +1356,10 @@ Persistent=true
1346
1356
  WantedBy=timers.target
1347
1357
  ````
1348
1358
 
1359
+ ## systemd timer note
1360
+
1361
+ 📅 OnCalendar syntax is flexible — you can tweak backup schedules easily. Run systemd-analyze calendar to preview timers.
1362
+
1349
1363
  ## list contents of an archive
1350
1364
 
1351
1365
  ```` bash
@@ -1636,8 +1650,27 @@ The indicators are not shown if dar-backup is run from systemd or if it is used
1636
1650
  - Look into a way to move the .par2 files away from the `dar` slices, to maximize chance of good redundancy.
1637
1651
  - Add option to dar-backup to use the `dar` option `--fsa-scope none`
1638
1652
 
1653
+ ## Known Limitations / Edge Cases
1654
+
1655
+ Does not currently encrypt data (by design — relies on encrypted storage)
1656
+
1657
+ One backup definition per file
1658
+
1659
+ .par2 files created for each slice (may be moved in future)
1660
+
1639
1661
  ## Reference
1640
1662
 
1663
+ ### CLI Tools Overview
1664
+
1665
+ | Command | Description |
1666
+ |-----------------------|-------------------------------------------|
1667
+ | `dar-backup` | Perform full, differential, or incremental backups with verification and restore testing |
1668
+ | `manager` | Maintain and query catalog databases for archives |
1669
+ | `cleanup` | Remove outdated DIFF/INCR archives (and optionally FULLs) |
1670
+ | `clean-log` | Clean up excessive log output from dar command logs |
1671
+ | `installer` | Set up required directories and default config files |
1672
+ | `dar-backup-systemd` | Generate (and optionally install) systemd timers and services for automated backups |
1673
+
1641
1674
  ### test coverage
1642
1675
 
1643
1676
  Running
@@ -1646,23 +1679,26 @@ Running
1646
1679
  pytest --cov=dar_backup tests/
1647
1680
  ````
1648
1681
 
1649
- results for version 0.6.17 in this report:
1682
+ results for a dev version 0.6.19 in this report:
1650
1683
 
1651
1684
  ```` code
1652
1685
  ---------- coverage: platform linux, python 3.12.3-final-0 -----------
1653
- Name Stmts Miss Cover
1654
- -------------------------------------------------------------------------------------
1655
- venv/lib/python3.12/site-packages/dar_backup/__about__.py 1 0 100%
1656
- venv/lib/python3.12/site-packages/dar_backup/__init__.py 0 0 100%
1657
- venv/lib/python3.12/site-packages/dar_backup/clean_log.py 68 14 79%
1658
- venv/lib/python3.12/site-packages/dar_backup/cleanup.py 196 53 73%
1659
- venv/lib/python3.12/site-packages/dar_backup/config_settings.py 66 8 88%
1660
- venv/lib/python3.12/site-packages/dar_backup/dar_backup.py 464 99 79%
1661
- venv/lib/python3.12/site-packages/dar_backup/installer.py 46 46 0%
1662
- venv/lib/python3.12/site-packages/dar_backup/manager.py 316 72 77%
1663
- venv/lib/python3.12/site-packages/dar_backup/util.py 162 34 79%
1664
- -------------------------------------------------------------------------------------
1665
- TOTAL 1319 326 75%
1686
+ Name Stmts Miss Cover
1687
+ ----------------------------------------------------------
1688
+ src/dar_backup/__about__.py 1 0 100%
1689
+ src/dar_backup/__init__.py 0 0 100%
1690
+ src/dar_backup/clean_log.py 68 13 81%
1691
+ src/dar_backup/cleanup.py 193 17 91%
1692
+ src/dar_backup/command_runner.py 73 1 99%
1693
+ src/dar_backup/config_settings.py 66 8 88%
1694
+ src/dar_backup/dar_backup.py 535 56 90%
1695
+ src/dar_backup/dar_backup_systemd.py 56 7 88%
1696
+ src/dar_backup/installer.py 59 6 90%
1697
+ src/dar_backup/manager.py 351 56 84%
1698
+ src/dar_backup/rich_progress.py 70 7 90%
1699
+ src/dar_backup/util.py 130 15 88%
1700
+ ----------------------------------------------------------
1701
+ TOTAL 1602 186 88%
1666
1702
  ````
1667
1703
 
1668
1704
  ### dar-backup options
@@ -0,0 +1,23 @@
1
+ dar_backup/.darrc,sha256=-aerqivZmOsW_XBCh9IfbYTUvw0GkzDSr3Vx4GcNB1g,2113
2
+ dar_backup/Changelog.md,sha256=hFz5NoZyezxgKza9i4VBv57aPnCuzhIQM9yK_2cxAZ8,9107
3
+ dar_backup/README.md,sha256=PcZQRaBw9i_GbRoA786OFKI0PwY87E7D30UzovWqEQQ,44902
4
+ dar_backup/__about__.py,sha256=bhh1JgaMOqVsHTPoLk0PdjZxyDSXmYzOzEaRGXYuakc,22
5
+ dar_backup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ dar_backup/clean_log.py,sha256=uQ_9HomK7RRkskXrgMPbAC84RgNlCFJ8RHL9KHeAMvc,5447
7
+ dar_backup/cleanup.py,sha256=4IG736gdmvjurcQQ_DC-B5CoA3Ix9u5C3WfwmMmFIpc,12500
8
+ dar_backup/command_runner.py,sha256=PQA968EXssSGjSs_16psFkdxRZi9-YK4TrBKFz0ss3k,4455
9
+ dar_backup/config_settings.py,sha256=8HhIDVtFk7D3VqJlYcveOlAaSEJwIaO3MICz-rN3tVY,5260
10
+ dar_backup/dar-backup.conf,sha256=WWNrysjQ1ii2jpab8jxgWCw3IkNxLBYVOW8fxWbO_9g,1155
11
+ dar_backup/dar_backup.py,sha256=x0at94NeQzu8tv2ohg3YKAt6j76gQUS2387wh5Z4B78,41856
12
+ dar_backup/dar_backup_systemd.py,sha256=oehD_t9CFu0CsMgDWRH-Gt74Ynl1m29yqQEh5Kxv7aw,3807
13
+ dar_backup/demo.py,sha256=fl2LHHWxuXRT814M_zuZh_YqqLk6nuNg9BI9HpLzdUU,4841
14
+ dar_backup/exceptions.py,sha256=6fpHpnhkbtFcFZVDMqCsdESg-kQNCjF40EROGKeq8yU,113
15
+ dar_backup/installer.py,sha256=gISJ3inz1uTjM5235gNtwjDUG-Fq6b3OZzMQuJl5eRg,2252
16
+ dar_backup/manager.py,sha256=UyEcm9ydkok47slgSlpPEKP_mAdkvcwCghLCXdNlGpc,26622
17
+ dar_backup/rich_progress.py,sha256=jTwM-4VlqHHzKqIfyXjL1pWEriobSJwCdN3YXzXzRdo,3105
18
+ dar_backup/util.py,sha256=2Uwd1bf3N-AEzIvc69gvwEnGXNYNzZ-RqxUfbvmOUAc,20079
19
+ dar_backup-0.6.20.dist-info/METADATA,sha256=dO6-9MvI9M_munyvCVFGNrq33NBbDDxn6UAIRLwVb5U,86624
20
+ dar_backup-0.6.20.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
21
+ dar_backup-0.6.20.dist-info/entry_points.txt,sha256=jFMqGdvGO8NeHrmcB0pxY7__PCSQAWRCFzsschMXsec,248
22
+ dar_backup-0.6.20.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
23
+ dar_backup-0.6.20.dist-info/RECORD,,
@@ -3,5 +3,5 @@ clean-log = dar_backup.clean_log:main
3
3
  cleanup = dar_backup.cleanup:main
4
4
  dar-backup = dar_backup.dar_backup:main
5
5
  dar-backup-systemd = dar_backup.dar_backup_systemd:main
6
- installer = dar_backup.installer:main
6
+ demo = dar_backup.demo:main
7
7
  manager = dar_backup.manager:main
@@ -1,21 +0,0 @@
1
- dar_backup/.darrc,sha256=-aerqivZmOsW_XBCh9IfbYTUvw0GkzDSr3Vx4GcNB1g,2113
2
- dar_backup/Changelog.md,sha256=ZRK03WnSbNWkMQAVNvfflKs06TGmkB4wBOm0Lp4ft1c,7830
3
- dar_backup/README.md,sha256=b4eoXh8fo7Li1mJqMKbrW-SrI2gDYkczCtL8G9-KoFE,43261
4
- dar_backup/__about__.py,sha256=g-mDk6iCtdmWAx2-NGjdBzw-GF98McMHGx0wkhbKFM4,22
5
- dar_backup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- dar_backup/clean_log.py,sha256=cGhtKYnQJ2ceNQfw5XcCln_WNBasbmlfhO3kRydjDNk,5196
7
- dar_backup/cleanup.py,sha256=BAiztBL0Dpr3fs6WZU_9oR5jUWumHua4dS37JtSxi-Q,12499
8
- dar_backup/command_runner.py,sha256=74Fsylz1NN-dn8lbdRhkL6LA1r527QJeojBlniGrPuo,2708
9
- dar_backup/config_settings.py,sha256=Rh4T35-w_5tpRAViMfv3YP3GBpG4mQy7Do8cNBzYAR0,4912
10
- dar_backup/dar-backup.conf,sha256=64O3bGlzqupneT2gVeaETJ1qS6-3Exet9Zto27jgwPQ,897
11
- dar_backup/dar_backup.py,sha256=THZmKZgOWxtYo9HaysU38GZ1hnpTcziJ45sPQ4HvJoE,41003
12
- dar_backup/dar_backup_systemd.py,sha256=oehD_t9CFu0CsMgDWRH-Gt74Ynl1m29yqQEh5Kxv7aw,3807
13
- dar_backup/installer.py,sha256=fl2LHHWxuXRT814M_zuZh_YqqLk6nuNg9BI9HpLzdUU,4841
14
- dar_backup/manager.py,sha256=HRuWeDB1sd14HwMEM6dk6OVqpj2KDTk6y55OKw7vUHE,22420
15
- dar_backup/rich_progress.py,sha256=jTwM-4VlqHHzKqIfyXjL1pWEriobSJwCdN3YXzXzRdo,3105
16
- dar_backup/util.py,sha256=2V4ONpoGh_W6wFv2RbJoUIEDxcY6_ot4frtzEBWsu7U,8798
17
- dar_backup-0.6.18.dist-info/METADATA,sha256=My1Utkqgj1iYhfC4OfWXzzzrU2bPasbWl9usZqS_7bw,84949
18
- dar_backup-0.6.18.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
19
- dar_backup-0.6.18.dist-info/entry_points.txt,sha256=NSCYoG5Dvh1UhvKWOQPgcHdFv4--R4Sre3d9FwJra3E,258
20
- dar_backup-0.6.18.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
21
- dar_backup-0.6.18.dist-info/RECORD,,