dar-backup 0.6.20.1__py3-none-any.whl → 0.7.1__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 CHANGED
@@ -1 +1,6 @@
1
- __version__ = "0.6.20.1"
1
+ __version__ = "0.7.1"
2
+
3
+ __license__ = '''Licensed under GNU GENERAL PUBLIC LICENSE v3, see the supplied file "LICENSE" for details.
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.
5
+ See section 15 and section 16 in the supplied "LICENSE" file.'''
6
+
dar_backup/clean_log.py CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env python3
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
+
2
4
  """
3
5
  clean-log.py source code is here: https://github.com/per2jensen/dar-backup/tree/main/v2/src/dar_backup/clean-log.py
4
6
  This script is part of dar-backup, a backup solution for Linux using dar and systemd.
dar_backup/cleanup.py CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env python3
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
2
3
 
3
4
  """
4
5
  cleanup.py source code is here: https://github.com/per2jensen/dar-backup
@@ -37,6 +38,7 @@ from dar_backup.util import setup_logging
37
38
  from dar_backup.util import get_logger
38
39
  from dar_backup.util import requirements
39
40
  from dar_backup.util import show_version
41
+ from dar_backup.util import get_invocation_command_line
40
42
  from dar_backup.util import print_aligned_settings
41
43
  from dar_backup.util import backup_definition_completer, list_archive_completer
42
44
 
@@ -222,6 +224,7 @@ def main():
222
224
  start_msgs.append(("cleanup.py:", about.__version__))
223
225
 
224
226
  logger.info(f"START TIME: {start_time}")
227
+ logger.debug(f"Command line: {get_invocation_command_line()}")
225
228
  logger.debug(f"`args`:\n{args}")
226
229
  logger.debug(f"`config_settings`:\n{config_settings}")
227
230
 
@@ -234,7 +237,7 @@ def main():
234
237
  args.verbose and start_msgs.append(("--cleanup-specific-archives:", args.cleanup_specific_archives))
235
238
 
236
239
  dangerous_keywords = ["--cleanup", "_FULL_"] # TODO: add more dangerous keywords
237
- print_aligned_settings(start_msgs, highlight_keywords=dangerous_keywords)
240
+ print_aligned_settings(start_msgs, highlight_keywords=dangerous_keywords, quiet=not args.verbose)
238
241
 
239
242
  # run PREREQ scripts
240
243
  requirements('PREREQ', config_settings)
@@ -1,3 +1,5 @@
1
+ # SPDX-License-Identifier: GPL-3.0-or-later
2
+
1
3
  import subprocess
2
4
  import logging
3
5
  import threading
@@ -1,3 +1,5 @@
1
+ # SPDX-License-Identifier: GPL-3.0-or-later
2
+
1
3
  import configparser
2
4
  from dataclasses import dataclass, field, fields
3
5
  from os.path import expandvars, expanduser
@@ -1,6 +1,8 @@
1
+ # SPDX-License-Identifier: GPL-3.0-or-later
2
+
1
3
  # This config file is intended to demo `dar-backup`.
2
4
  #
3
- # The `installer` puts it in ~/.config/dar-backup/dar-backup.conf
5
+ # The `demo` application puts this file in ~/.config/dar-backup/dar-backup.conf
4
6
 
5
7
  [MISC]
6
8
  LOGFILE_LOCATION = ~/dar-backup/dar-backup.log
@@ -13,7 +15,7 @@ NO_FILES_VERIFICATION = 5
13
15
  COMMAND_TIMEOUT_SECS = 86400
14
16
 
15
17
  [DIRECTORIES]
16
- BACKUP_DIR = ~/dar-backup/backups
18
+ BACKUP_DIR = @@BACKUP_DIR@@
17
19
  BACKUP.D_DIR = ~/.config/dar-backup/backup.d/
18
20
  TEST_RESTORE_DIR = ~/dar-backup/restore/
19
21
  # Optional parameter
@@ -0,0 +1,60 @@
1
+
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ # ------------------------------------------------------------------------
5
+ # Demo of a `dar-backup` configuration file
6
+ # This file was generated by dar-backup's `demo` program.
7
+ #
8
+ {%- if opts_dict | length > 0 %}
9
+ # Options given to the `demo` program:
10
+ {% endif %}
11
+ {%- if opts_dict.ROOT_DIR -%}
12
+ # --root-dir : {{ opts_dict.ROOT_DIR }}
13
+ {% endif %}
14
+ {%- if opts_dict.DIR_TO_BACKUP -%}
15
+ # --dir-to-backup : {{ opts_dict.DIR_TO_BACKUP }}
16
+ {% endif -%}
17
+ {%- if opts_dict.BACKUP_DIR -%}
18
+ # --backup-dir : {{ opts_dict.BACKUP_DIR }}
19
+ {% endif %}
20
+ #
21
+ # Variables used to generate this file:
22
+ # =====================================
23
+ {% for k,v in vars_map|dictsort %}# {{ k }} : {{ v }}
24
+ {% endfor -%}
25
+ # ------------------------------------------------------------------------
26
+
27
+ [MISC]
28
+ LOGFILE_LOCATION = {{ vars_map.DAR_BACKUP_DIR -}}/dar-backup.log
29
+ MAX_SIZE_VERIFICATION_MB = 2
30
+ MIN_SIZE_VERIFICATION_MB = 0
31
+ NO_FILES_VERIFICATION = 1
32
+ # timeout in seconds for backup, test, restore and par2 operations
33
+ # The author has such `dar` tasks running for 10-15 hours on the yearly backups, so a value of 24 hours is used.
34
+ # If a timeout is not specified when using the CommandRunner, a default timeout of 30 secs is used.
35
+ COMMAND_TIMEOUT_SECS = 86400
36
+
37
+ [DIRECTORIES]
38
+ BACKUP_DIR = {{ vars_map.BACKUP_DIR }}
39
+ BACKUP.D_DIR = {{ vars_map.BACKUP_D_DIR }}
40
+ TEST_RESTORE_DIR = {{ vars_map.TEST_RESTORE_DIR }}
41
+ # Optional parameter
42
+ # If you want to store the catalog database away from the BACKUP_DIR, use the MANAGER_DB_DIR variable.
43
+ #MANAGER_DB_DIR = /some/where/else/
44
+
45
+ [AGE]
46
+ # DIFF and INCR backups are kept for a configured number of days, then deleted by the `cleanuo`
47
+ # age settings are in days
48
+ DIFF_AGE = 100
49
+ INCR_AGE = 40
50
+
51
+ [PAR2]
52
+ ERROR_CORRECTION_PERCENT = 5
53
+ ENABLED = True
54
+
55
+ [PREREQ]
56
+ #SCRIPT_1 = <pre-script 1>
57
+
58
+ [POSTREQ]
59
+ #SCRIPT_1 = <post-script 1>
60
+
dar_backup/dar_backup.py CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python3
2
-
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
3
  """
4
4
  installer.py source code is here: https://github.com/per2jensen/dar-backup/tree/main/v2/src/dar_backup/installer.py
5
5
  This script is part of dar-backup, a backup solution for Linux using dar and systemd.
@@ -51,6 +51,7 @@ from dar_backup.util import BackupError
51
51
  from dar_backup.util import RestoreError
52
52
  from dar_backup.util import requirements
53
53
  from dar_backup.util import show_version
54
+ from dar_backup.util import get_invocation_command_line
54
55
  from dar_backup.util import get_binary_info
55
56
  from dar_backup.util import print_aligned_settings
56
57
  from dar_backup.util import backup_definition_completer, list_archive_completer
@@ -683,12 +684,29 @@ INCR back of a single backup definition in backup.d
683
684
 
684
685
 
685
686
  --selection
686
- --selection takes dar selection parameters between a pair of `"`.
687
687
 
688
- Example: select file names with this date in file names "2024-07-01" in the
689
- directory "path/to/a/dir" where the path is relative to root of the backup.
688
+ --selection takes dar file selection options inside a quoted string.
689
+
690
+ 💡 Shell quoting matters! Always wrap the entire selection string in double quotes to avoid shell splitting.
691
+
692
+ ✅ Use: --selection="-I '*.NEF'"
693
+ ❌ Avoid: --selection "-I '*.NEF'" → may break due to how your shell parses it.
694
+
695
+ Examples:
696
+ 1)
697
+ select file names with "Z50_" in file names:
698
+ python3 dar-backup.py --restore <name of dar archive> --selection="-I '*Z50_*'"
699
+ 2)
700
+ Filter out *.xmp files:
701
+ python3 dar-backup.py --restore <name of dar archive> --selection="-X '*.xmp'"
702
+
703
+ 3)
704
+ Include all files in a directory:
705
+ python3 dar-backup.py --restore <name of dar archive> --selection="-g 'path/to/a/dir'"
690
706
 
691
- python3 dar-backup.py --restore <name of dar archive> --selection "-I '*2024-07-01*' -g path/to/a/dir"
707
+ 4)
708
+ Exclude a directory:
709
+ python3 dar-backup.py --restore <name of dar archive> --selection="-P 'path/to/a/dir'"
692
710
 
693
711
  See dar documentation on file selection: http://dar.linux.free.fr/doc/man/dar.html#COMMANDS%20AND%20OPTIONS
694
712
  """
@@ -764,7 +782,7 @@ def main():
764
782
  parser.add_argument('--darrc', type=str, help='Optional path to .darrc')
765
783
  parser.add_argument('-l', '--list', action='store_true', help="List available archives.").completer = list_archive_completer
766
784
  parser.add_argument('--list-contents', help="List the contents of the specified archive.").completer = list_archive_completer
767
- parser.add_argument('--selection', help="dar file selection for listing/restoring specific files/directories.")
785
+ parser.add_argument('--selection', type=str, help="Selection string to pass to 'dar', e.g. --selection=\"-I '*.NEF'\"")
768
786
  # parser.add_argument('-r', '--restore', nargs=1, type=str, help="Restore specified archive.")
769
787
  parser.add_argument('-r', '--restore', type=str, help="Restore specified archive.").completer = list_archive_completer
770
788
  parser.add_argument('--restore-dir', type=str, help="Directory to restore files to.")
@@ -847,6 +865,7 @@ def main():
847
865
  start_time=int(time())
848
866
  start_msgs.append(('dar-backup.py:', about.__version__))
849
867
  logger.info(f"START TIME: {start_time}")
868
+ logger.debug(f"Command line: {get_invocation_command_line()}")
850
869
  logger.debug(f"{'`Args`:\n'}{args}")
851
870
  logger.debug(f"{'`Config_settings`:\n'}{config_settings}")
852
871
  dar_properties = get_binary_info(command='dar')
@@ -858,9 +877,9 @@ def main():
858
877
  start_msgs.append(('Config file:', os.path.abspath(args.config_file)))
859
878
  start_msgs.append((".darrc location:", args.darrc))
860
879
 
861
- args.verbose and args.full_backup and start_msgs.append(("Type of backup:", "FULL"))
862
- args.verbose and args.differential_backup and start_msgs.append(("Type of backup:", "DIFF"))
863
- args.verbose and args.incremental_backup and start_msgs.append(("Type of backup:", "INCR"))
880
+ args.full_backup and start_msgs.append(("Type of backup:", "FULL"))
881
+ args.differential_backup and start_msgs.append(("Type of backup:", "DIFF"))
882
+ args.incremental_backup and start_msgs.append(("Type of backup:", "INCR"))
864
883
  args.verbose and args.backup_definition and start_msgs.append(("Backup definition:", args.backup_definition))
865
884
  if args.alternate_reference_archive:
866
885
  args.verbose and start_msgs.append(("Alternate ref archive:", args.alternate_reference_archive))
@@ -874,8 +893,8 @@ def main():
874
893
  args.verbose and start_msgs.append(("PAR2 enabled:", config_settings.par2_enabled))
875
894
  args.verbose and start_msgs.append(("--do-not-compare:", args.do_not_compare))
876
895
 
877
- dangerous_keywords = ["--do-not", "alternate"] # TODO: add more dangerous keywords
878
- print_aligned_settings(start_msgs)
896
+ highlight_keywords = ["--do-not", "alternate"] # TODO: add more dangerous keywords
897
+ print_aligned_settings(start_msgs, quiet=not args.verbose, highlight_keywords=highlight_keywords)
879
898
 
880
899
  # sanity check
881
900
  if args.backup_definition and not os.path.exists(os.path.join(config_settings.backup_d_dir, args.backup_definition)):
@@ -1,3 +1,6 @@
1
+ #!/usr/bin/env python3
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
+
1
4
  from pathlib import Path
2
5
  import subprocess
3
6
  import argparse
dar_backup/demo.py CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env python3
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
+
2
4
  """
3
- installer.py source code is here: https://github.com/per2jensen/dar-backup/tree/main/v2/src/dar_backup/installer.py
5
+ demo.py source code is here: https://github.com/per2jensen/dar-backup/tree/main/v2/src/dar_backup/demo.py
4
6
  This script is part of dar-backup, a backup solution for Linux using dar and systemd.
5
7
 
6
8
  Licensed under GNU GENERAL PUBLIC LICENSE v3, see the supplied file "LICENSE" for details.
@@ -10,7 +12,9 @@ not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
12
  See section 15 and section 16 in the supplied "LICENSE" file
11
13
 
12
14
  This script can be used to configure dar-backup on your system.
13
- It is non-destructive and will not overwrite any existing files or directories.
15
+ It is non-destructive and will not overwrite any existing files or directories under --override is used.
16
+
17
+ User can set ROOT_DIR, DIR_TO_BACKUP and BACKUP_DIR (destination for backups) via optins to override defaults.
14
18
  """
15
19
 
16
20
  import argparse
@@ -19,120 +23,189 @@ import shutil
19
23
  import sys
20
24
 
21
25
  from . import __about__ as about
26
+ from . import util
27
+
28
+ from jinja2 import Environment, FileSystemLoader
22
29
  from pathlib import Path
30
+ from typing import Dict, Tuple
31
+
32
+
33
+ CONFIG_DIR = util.normalize_dir(util.expand_path("~/.config/dar-backup"))
34
+ DAR_BACKUP_DIR = util.normalize_dir(util.expand_path("~/dar-backup"))
35
+
23
36
 
24
- LICENSE = '''Licensed under GNU GENERAL PUBLIC LICENSE v3, see the supplied file "LICENSE" for details.
25
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW, not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26
- See section 15 and section 16 in the supplied "LICENSE" file.'''
27
37
 
28
- CONFIG_DIR = os.path.expanduser("~/.config/dar-backup")
29
- DAR_BACKUP_DIR = os.path.expanduser("~/dar-backup/")
38
+ def check_directories(args, vars_map: Dict[str,str]) -> bool:
39
+ """
40
+ Check if the directories exist and create them if they don't.
30
41
 
31
- BACKUP_DEFINITION = '''
32
- # Demo of a `dar-backup` definition file
33
- # This back definition file configures a backup of ~/.config/dar-backup
34
- # `dar-backup` puts the backups in ~/dar-backup/backups
35
- # ------------------------------------------------------------------------
42
+ Returns:
43
+ bool: True if the directories were created successfully, False otherwise.
44
+ """
45
+ result = True
46
+ for key in ("DAR_BACKUP_DIR","BACKUP_DIR","TEST_RESTORE_DIR","CONFIG_DIR","BACKUP_D_DIR"):
47
+ path = Path(vars_map[key])
48
+ if path.exists() and not args.override:
49
+ print(f"Directory '{path}' already exists")
50
+ result = False
51
+ return result
36
52
 
37
- # Switch to ordered selection mode, which means that the following options
38
- # will be considered top to bottom
39
- -am
40
53
 
41
- # Backup Root dir
42
- -R @@HOME_DIR@@
54
+ def generate_file(args, template: str, file_path: Path, vars_map: Dict[str, str], opts_dict: Dict[str, str]) -> bool:
55
+ """
56
+ Generate a file using a Jinja2 template.
43
57
 
44
- # Directories to backup below the Root dir
45
- -g .config/dar-backup
58
+ Args:
59
+ args: Command line arguments.
60
+ template (str): The name of the template file.
61
+ file_path (Path): The path where the generated file will be saved.
62
+ vars_map (Dict[str, str]): A dictionary containing variables for the template.
63
+ opts_dict (Dict[str, str]): A dictionary containing options given by user.
46
64
 
47
- # Examples of directories to exclude below the Root dir
48
- -P mnt
49
- -P .private
50
- -P .cache
65
+ Returns:
66
+ bool: True if the file was generated successfully, False otherwise.
67
+ """
68
+ current_script_dir = os.path.dirname(os.path.abspath(__file__))
69
+ env = Environment(loader=FileSystemLoader(current_script_dir))
70
+ tpl = env.get_template(template)
71
+ rendered = tpl.render(vars_map = vars_map, opts_dict = opts_dict)
72
+ if rendered is None:
73
+ print(f"Error: Template '{template}' could not be rendered.")
74
+ return False
75
+ if os.path.exists(file_path) and not args.override:
76
+ print(f"Error: File '{file_path}' already exists. Use --override to overwrite.")
77
+ return False
78
+ file_path.parent.mkdir(parents=True, exist_ok=True)
79
+ file_path.write_text(rendered)
80
+ print(f"File generated at '{file_path}'")
51
81
 
52
- # compression level
53
- -z5
54
82
 
55
- # no overwrite, if you rerun a backup, 'dar' halts and asks what to do
56
- -n
57
-
58
- # size of each slice in the archive
59
- --slice 10G
60
83
 
61
- # bypass directores marked as cache directories
62
- # http://dar.linux.free.fr/doc/Features.html
63
- --cache-directory-tagging
64
- '''
84
+ def setup_dicts(args, vars_map: Dict[str, str]) -> Tuple[Dict[str, str], Dict[str, str]]:
85
+ """
86
+ Override various entries in the dictionaries for jinja templating with user input.
87
+
88
+ Returns:
89
+ Tuple[Dict[str, str], Dict[str, str]]: A tuple containing the vars_map and opts_dict dictionaries.
90
+ """
91
+ opts_dict = {}
92
+ if args.root_dir:
93
+ opts_dict["ROOT_DIR"] = args.root_dir
94
+ if args.dir_to_backup:
95
+ opts_dict["DIR_TO_BACKUP"] = args.dir_to_backup
96
+ if args.backup_dir:
97
+ opts_dict["BACKUP_DIR"] = args.backup_dir
98
+
99
+ for key, value in opts_dict.items():
100
+ vars_map[key] = value
101
+
102
+ return vars_map, opts_dict
65
103
 
66
104
 
67
105
  def main():
68
106
  parser = argparse.ArgumentParser(
69
- description="Set up `dar-backup` on your system.",
107
+ description="Set up demo configuration for `dar-backup` on your system.",
70
108
  )
71
109
  parser.add_argument(
72
110
  "-i", "--install",
73
111
  action="store_true",
74
- help="Deploy a simple config file, use ~/dar-backup/ for log file, archives and restore tests."
112
+ help="Deploy demo config files and directories. Will not overwrite existing files or directories unless --override is used."
113
+ )
114
+ req = parser.add_argument_group(
115
+ 'These options must be used together'
116
+ )
117
+ req.add_argument(
118
+ "--root-dir",
119
+ type=str,
120
+ help="Specify the root directory for the backup."
121
+ )
122
+ req.add_argument(
123
+ "--dir-to-backup",
124
+ type=str,
125
+ help="Directory to backup, relative to the root directory."
126
+ )
127
+ parser.add_argument(
128
+ "--backup-dir",
129
+ type=str,
130
+ help="Directory where backups and redundancy files are put"
131
+ )
132
+ parser.add_argument(
133
+ "--override",
134
+ action="store_true",
135
+ help="By default, the script will not overwrite existing files or directories. Use this option to override this behavior."
75
136
  )
76
137
  parser.add_argument(
77
138
  "-v", "--version",
78
139
  action="version",
79
- version=f"%(prog)s version {about.__version__}, {LICENSE}"
140
+ version=f"%(prog)s version {about.__version__}, {about.__license__}"
141
+ )
142
+ parser.add_argument(
143
+ "-g", "--generate",
144
+ action="store_true",
145
+ help="Generate config files and put them in /tmp/."
80
146
  )
81
147
 
82
148
  args = parser.parse_args()
83
149
 
84
- if args.install:
85
- errors = []
86
- if os.path.exists(CONFIG_DIR):
87
- errors.append(f"Config directory '{CONFIG_DIR}' already exists.")
88
- if os.path.exists(DAR_BACKUP_DIR):
89
- errors.append(f"Directory '{DAR_BACKUP_DIR}' already exists.")
90
-
91
- if errors:
92
- for error in errors:
93
- print(f"Error: {error}")
150
+ group = [args.root_dir, args.dir_to_backup]
151
+ if any(group) and not all(group):
152
+ parser.error(
153
+ "Options --root-dir, --dir-to-backup must all be specified together."
154
+ )
155
+ exit(1)
156
+
157
+ args.root_dir = util.normalize_dir(util.expand_path(args.root_dir)) if args.root_dir else None
158
+ args.backup_dir = util.normalize_dir(util.expand_path(args.backup_dir)) if args.backup_dir else None
159
+ args.dir_to_backup = util.normalize_dir(util.expand_path(args.dir_to_backup)) if args.dir_to_backup else None
160
+
161
+
162
+
163
+ vars_map = {
164
+ # dar-backup.conf variables
165
+ "CONFIG_DIR" : CONFIG_DIR,
166
+ "DAR_BACKUP_DIR" : DAR_BACKUP_DIR,
167
+ "BACKUP_DIR" : os.path.join(DAR_BACKUP_DIR, "backups"),
168
+ "BACKUP_D_DIR" : os.path.join(CONFIG_DIR, "backup.d"),
169
+ "TEST_RESTORE_DIR" : os.path.join(DAR_BACKUP_DIR, "restore"),
170
+ # backup definition variables
171
+ "ROOT_DIR" : util.normalize_dir(util.expand_path("$HOME")),
172
+ "DIR_TO_BACKUP" : ".config/dar-backup",
173
+ }
174
+
175
+
176
+ vars_map, opts_dict = setup_dicts(args, vars_map)
177
+
178
+ if args.generate:
179
+ print("Generating backup definition file...")
180
+ vars_map["DAR_BACKUP_DIR"] = "/tmp"
181
+ args.override = True
182
+ generate_file(args, "demo_backup_def.j2", Path("/tmp/dar-backup/backup.d/demo"), vars_map, opts_dict)
183
+ vars_map["CONFIG_DIR"] = "/tmp"
184
+ generate_file(args, "dar-backup.conf.j2", Path("/tmp/dar-backup.conf"), vars_map, opts_dict)
185
+ elif args.install:
186
+ if not check_directories(args, vars_map):
187
+ print("Error: One or more directories already exist.\nSpecify non-existent directories or use --override to overwrite.")
94
188
  sys.exit(1)
95
189
 
96
- try:
97
- os.makedirs(DAR_BACKUP_DIR, exist_ok=False)
98
- os.makedirs(os.path.join(DAR_BACKUP_DIR, "backups"), exist_ok=False)
99
- os.makedirs(os.path.join(DAR_BACKUP_DIR, "restore"), exist_ok=False)
100
- os.makedirs(CONFIG_DIR, exist_ok=False)
101
- os.makedirs(os.path.join(CONFIG_DIR, "backup.d"), exist_ok=False)
102
- print(f"Directories created: `{DAR_BACKUP_DIR}` and `{CONFIG_DIR}`")
103
-
104
- script_dir = Path(__file__).parent
105
- source_file = script_dir / "dar-backup.conf"
106
- destination_file = Path(CONFIG_DIR) / "dar-backup.conf"
107
-
108
- try:
109
- shutil.copy2(source_file, destination_file)
110
- print(f"Config file deployed to {destination_file}")
111
- except Exception as e:
112
- print(f"Error: Could not copy config file: {e}")
113
- sys.exit(1)
114
-
115
-
116
- backup_definition = BACKUP_DEFINITION.replace("@@HOME_DIR@@", os.path.expanduser("~"))
117
-
118
- try:
119
- with open(os.path.join(CONFIG_DIR, "backup.d", "default"), "w") as f:
120
- f.write(backup_definition)
121
- print(f"Default backup definition file deployed to {os.path.join(CONFIG_DIR, 'backup.d', 'default')}")
122
- except Exception as e:
123
- print(f"Error: Could not write default backup definition: {e}")
124
- sys.exit(1)
125
- except Exception as e:
126
- print(f"Installation failed: {e}")
127
- sys.exit(1)
190
+ Path(vars_map["DAR_BACKUP_DIR"]).mkdir(parents=True, exist_ok=True)
191
+ Path(vars_map["BACKUP_DIR"]).mkdir(parents=True, exist_ok=True)
192
+ Path(vars_map["TEST_RESTORE_DIR"]).mkdir(parents=True, exist_ok=True)
193
+ Path(vars_map["CONFIG_DIR"]).mkdir(parents=True, exist_ok=True)
194
+ Path(vars_map["BACKUP_D_DIR"]).mkdir(parents=True, exist_ok=True)
195
+ print(f"Directories created.")
196
+
197
+ generate_file(args, "demo_backup_def.j2", Path(vars_map["BACKUP_D_DIR"]).joinpath("demo"), vars_map, opts_dict)
198
+ generate_file(args, "dar-backup.conf.j2", Path(vars_map["CONFIG_DIR"]).joinpath("dar-backup.conf"), vars_map, opts_dict)
128
199
 
129
- print("1. Now run `manager --create` to create the catalog database.")
200
+ print("1. Now run `manager --create-db` to create the catalog database.")
130
201
  print("2. Then you can run `dar-backup --full-backup` to create a backup.")
131
202
  print("3. List backups with `dar-backup --list`")
132
203
  print("4. List contents of a backup with `dar-backup --list-contents <backup-name>`")
204
+ else:
205
+ parser.print_help()
206
+ sys.exit(1)
133
207
 
134
208
  sys.exit(0)
135
209
 
136
-
137
210
  if __name__ == "__main__":
138
211
  main()
@@ -0,0 +1,62 @@
1
+
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ # ------------------------------------------------------------------------
5
+ # Demo of a `dar-backup` definition file
6
+ # This file was generated by dar-backup's `demo` program.
7
+ #
8
+ {%- if opts_dict | length > 0 %}
9
+ # Options given to the `demo` program:
10
+ {% endif %}
11
+ {%- if opts_dict.ROOT_DIR -%}
12
+ # --root-dir : {{ opts_dict.ROOT_DIR }}
13
+ {% endif %}
14
+ {%- if opts_dict.DIR_TO_BACKUP -%}
15
+ # --dir-to-backup : {{ opts_dict.DIR_TO_BACKUP }}
16
+ {% endif -%}
17
+ {%- if opts_dict.BACKUP_DIR -%}
18
+ # --backup-dir : {{ opts_dict.BACKUP_DIR }}
19
+ {% endif %}
20
+ #
21
+ # Variables used to generate this file:
22
+ # =====================================
23
+ {% for k,v in vars_map|dictsort %}# {{ k }} : {{ v }}
24
+ {% endfor -%}
25
+ # ------------------------------------------------------------------------
26
+
27
+ # Switch to ordered selection mode, which means that the following options
28
+ # will be considered top to bottom
29
+ -am
30
+
31
+ # Backup Root dir
32
+ {%- if vars_map.ROOT_DIR %}
33
+ -R {{ vars_map.ROOT_DIR }}
34
+ {% endif -%}
35
+
36
+ {% if vars_map.DIR_TO_BACKUP %}
37
+ # Directories to backup below the Root dir
38
+ -g {{ vars_map.DIR_TO_BACKUP }}
39
+
40
+ # This is an example of exclusion of a `.private` directory inside the
41
+ # directory that is backed up
42
+ -P {{ vars_map.DIR_TO_BACKUP }}/.private
43
+ {%- else %}
44
+ # Examples of directories to exclude below the Root dir
45
+ -P mnt
46
+ -P .cache
47
+ {% endif %}
48
+
49
+ # compression level
50
+ -z5
51
+
52
+ # no overwrite, if you rerun a backup, 'dar' halts and asks what to do
53
+ # as `dar-backup` gives the `-Q` option to `dar`, the net effect of `-n` and `-Q` is
54
+ # that `dar` will quit and not overwrite the existing backup
55
+ -n
56
+
57
+ # size of each slice in the archive (10G is 10 Gigabytes)
58
+ --slice 10G
59
+
60
+ # bypass directores marked as cache directories
61
+ # http://dar.linux.free.fr/doc/Features.html
62
+ --cache-directory-tagging
dar_backup/exceptions.py CHANGED
@@ -1,3 +1,5 @@
1
+ # SPDX-License-Identifier: GPL-3.0-or-later
2
+
1
3
  class ConfigSettingsError(Exception):
2
4
  """Raised when ConfigSettings encounters a critical error."""
3
5
  pass