dar-backup 0.6.2__py3-none-any.whl → 0.6.3__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 -1
- dar_backup/manager.py +237 -24
- {dar_backup-0.6.2.dist-info → dar_backup-0.6.3.dist-info}/METADATA +1 -1
- {dar_backup-0.6.2.dist-info → dar_backup-0.6.3.dist-info}/RECORD +7 -7
- {dar_backup-0.6.2.dist-info → dar_backup-0.6.3.dist-info}/WHEEL +0 -0
- {dar_backup-0.6.2.dist-info → dar_backup-0.6.3.dist-info}/entry_points.txt +0 -0
- {dar_backup-0.6.2.dist-info → dar_backup-0.6.3.dist-info}/licenses/LICENSE +0 -0
dar_backup/__about__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.6.
|
|
1
|
+
__version__ = "0.6.3"
|
dar_backup/manager.py
CHANGED
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
import os
|
|
25
24
|
import argparse
|
|
25
|
+
import os
|
|
26
|
+
import re
|
|
26
27
|
import sys
|
|
27
28
|
|
|
28
29
|
|
|
@@ -30,7 +31,9 @@ from . import __about__ as about
|
|
|
30
31
|
from dar_backup.config_settings import ConfigSettings
|
|
31
32
|
from dar_backup.util import run_command
|
|
32
33
|
from dar_backup.util import setup_logging
|
|
34
|
+
from datetime import datetime
|
|
33
35
|
from time import time
|
|
36
|
+
from typing import Dict, List, NamedTuple
|
|
34
37
|
|
|
35
38
|
# Constants
|
|
36
39
|
SCRIPTNAME = os.path.basename(__file__)
|
|
@@ -70,9 +73,20 @@ def create_db(backup_def: str, config_settings: ConfigSettings):
|
|
|
70
73
|
logger.error(f"stderr: {stderr}")
|
|
71
74
|
logger.error(f"stdout: {stdout}")
|
|
72
75
|
|
|
76
|
+
return process.returncode
|
|
73
77
|
|
|
74
78
|
|
|
75
|
-
def
|
|
79
|
+
def list_catalogs(backup_def: str, config_settings: ConfigSettings) -> NamedTuple:
|
|
80
|
+
"""
|
|
81
|
+
Returns:
|
|
82
|
+
a typing.NamedTuple of class dar-backup.util.CommandResult with the following properties:
|
|
83
|
+
- process: of type subprocess.CompletedProcess: The result of the command execution.
|
|
84
|
+
- stdout: of type str: The standard output of the command.
|
|
85
|
+
- stderr: of type str: The standard error of the command.
|
|
86
|
+
- returncode: of type int: The return code of the command.
|
|
87
|
+
- timeout: of type int: The timeout value in seconds used to run the command.
|
|
88
|
+
- command: of type list[str): The command executed.
|
|
89
|
+
"""
|
|
76
90
|
database = f"{backup_def}{DB_SUFFIX}"
|
|
77
91
|
database_path = os.path.join(config_settings.backup_dir, database)
|
|
78
92
|
if not os.path.exists(database_path):
|
|
@@ -87,27 +101,101 @@ def list_db(backup_def: str, config_settings: ConfigSettings):
|
|
|
87
101
|
logger.error(f"stdout: {stdout}")
|
|
88
102
|
else:
|
|
89
103
|
print(stdout)
|
|
90
|
-
|
|
104
|
+
return process
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def cat_no_for_name(archive: str, config_settings: ConfigSettings) -> int:
|
|
108
|
+
"""
|
|
109
|
+
Find the catalog number for the given archive name
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
- the found number, if the archive catalog is present in the database
|
|
113
|
+
- "-1" if the archive is not found
|
|
114
|
+
"""
|
|
115
|
+
backup_def = backup_def_from_archive(archive)
|
|
116
|
+
process = list_catalogs(backup_def, config_settings)
|
|
117
|
+
if process.returncode != 0:
|
|
118
|
+
logger.error(f"Error listing catalogs for backup def: '{backup_def}'")
|
|
119
|
+
return -1
|
|
120
|
+
line_no = 1
|
|
121
|
+
for line in process.stdout.splitlines():
|
|
122
|
+
#print(f"{line_no}: {line}")
|
|
123
|
+
line_no += 1
|
|
124
|
+
search = re.search(f"\s+(\d+)\s+.*?({archive}).*", line)
|
|
125
|
+
if search:
|
|
126
|
+
#print("FOUND")
|
|
127
|
+
logger.info(f"Found archive: '{archive}', catalog #: '{search.group(1)}'")
|
|
128
|
+
return int(search.group(1))
|
|
129
|
+
return -1
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def list_catalog_contents(catalog_number: int, backup_def: str, config_settings: ConfigSettings):
|
|
136
|
+
"""
|
|
137
|
+
List the contents of catalog # in catalog database for given backup definition
|
|
138
|
+
"""
|
|
139
|
+
database = f"{backup_def}{DB_SUFFIX}"
|
|
140
|
+
database_path = os.path.join(config_settings.backup_dir, database)
|
|
141
|
+
if not os.path.exists(database_path):
|
|
142
|
+
logger.error(f'Database not found: "{database_path}"')
|
|
143
|
+
return 1
|
|
144
|
+
command = ['dar_manager', '--base', database_path, '-u', f"{catalog_number}"]
|
|
145
|
+
process = run_command(command)
|
|
146
|
+
stdout, stderr = process.stdout, process.stderr
|
|
147
|
+
if process.returncode != 0:
|
|
148
|
+
logger.error(f'Error listing catalogs for: "{database_path}"')
|
|
149
|
+
logger.error(f"stderr: {stderr}")
|
|
150
|
+
logger.error(f"stdout: {stdout}")
|
|
151
|
+
else:
|
|
152
|
+
print(stdout)
|
|
153
|
+
return process.returncode
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def find_file(file, backup_def, config_settings):
|
|
157
|
+
"""
|
|
158
|
+
Find a specific file
|
|
159
|
+
"""
|
|
160
|
+
database = f"{backup_def}{DB_SUFFIX}"
|
|
161
|
+
database_path = os.path.join(config_settings.backup_dir, database)
|
|
162
|
+
if not os.path.exists(database_path):
|
|
163
|
+
logger.error(f'Database not found: "{database_path}"')
|
|
164
|
+
return 1
|
|
165
|
+
command = ['dar_manager', '--base', database_path, '-f', f"{file}"]
|
|
166
|
+
process = run_command(command)
|
|
167
|
+
stdout, stderr = process.stdout, process.stderr
|
|
168
|
+
if process.returncode != 0:
|
|
169
|
+
logger.error(f'Error finding file: {file} in: "{database_path}"')
|
|
170
|
+
logger.error(f"stderr: {stderr}")
|
|
171
|
+
logger.error(f"stdout: {stdout}")
|
|
172
|
+
else:
|
|
173
|
+
print(stdout)
|
|
174
|
+
return process.returncode
|
|
91
175
|
|
|
92
176
|
|
|
93
|
-
def add_specific_archive(archive: str, config_settings: ConfigSettings):
|
|
177
|
+
def add_specific_archive(archive: str, config_settings: ConfigSettings, directory: str =None) -> int:
|
|
94
178
|
# sanity check - does dar backup exist?
|
|
179
|
+
if not directory:
|
|
180
|
+
directory = config_settings.backup_dir
|
|
95
181
|
archive = os.path.basename(archive) # remove path if it was given
|
|
96
|
-
archive_path = os.path.join(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
182
|
+
archive_path = os.path.join(directory, f'{archive}')
|
|
183
|
+
|
|
184
|
+
archive_test_path = os.path.join(directory, f'{archive}.1.dar')
|
|
185
|
+
if not os.path.exists(archive_test_path):
|
|
186
|
+
logger.error(f'dar backup: "{archive_test_path}" not found, exiting')
|
|
187
|
+
return 1
|
|
100
188
|
|
|
101
189
|
# sanity check - does backup definition exist?
|
|
102
190
|
backup_definition = archive.split('_')[0]
|
|
103
191
|
backup_def_path = os.path.join(config_settings.backup_d_dir, backup_definition)
|
|
104
192
|
if not os.path.exists(backup_def_path):
|
|
105
193
|
logger.error(f'backup definition "{backup_definition}" not found (--add-specific-archive option probably not correct), exiting')
|
|
106
|
-
|
|
194
|
+
return 1
|
|
107
195
|
|
|
108
196
|
database = f"{backup_definition}{DB_SUFFIX}"
|
|
109
197
|
database_path = os.path.realpath(os.path.join(config_settings.backup_dir, database))
|
|
110
|
-
logger.info(f'Add "{archive_path}" to catalog "{database}"')
|
|
198
|
+
logger.info(f'Add "{archive_path}" to catalog: "{database}"')
|
|
111
199
|
|
|
112
200
|
command = ['dar_manager', '--base', database_path, "--add", archive_path, "-ai", "-Q"]
|
|
113
201
|
process = run_command(command)
|
|
@@ -122,7 +210,99 @@ def add_specific_archive(archive: str, config_settings: ConfigSettings):
|
|
|
122
210
|
logger.error(f"stderr: {stderr}")
|
|
123
211
|
logger.error(f"stdout: {stdout}")
|
|
124
212
|
|
|
125
|
-
|
|
213
|
+
return process.returncode
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def add_directory(args: argparse.ArgumentParser, config_settings: ConfigSettings) -> None:
|
|
218
|
+
"""
|
|
219
|
+
Loop over the DAR archives in the given directory args.add_dir in increasing order by date and add them to their catalog database.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
args (argparse.ArgumentParser): The command-line arguments object containing the add_dir attribute.
|
|
223
|
+
config_settings (ConfigSettings): The configuration settings object.
|
|
224
|
+
|
|
225
|
+
This function performs the following steps:
|
|
226
|
+
1. Checks if the specified directory exists. If not, raises a RuntimeError.
|
|
227
|
+
2. Uses a regular expression to match DAR archive files with base names in the format <string>_{FULL, DIFF, INCR}_YYYY-MM-DD.
|
|
228
|
+
3. Lists the DAR archives in the specified directory and extracts their base names and dates.
|
|
229
|
+
4. Sorts the DAR archives by date.
|
|
230
|
+
5. Loops over the sorted DAR archives and adds each archive to its catalog database using the add_specific_archive function.
|
|
231
|
+
|
|
232
|
+
Example:
|
|
233
|
+
args = argparse.ArgumentParser()
|
|
234
|
+
args.add_dir = '/path/to/dar/archives'
|
|
235
|
+
config_settings = ConfigSettings()
|
|
236
|
+
add_directory(args, config_settings)
|
|
237
|
+
"""
|
|
238
|
+
if not os.path.exists(args.add_dir):
|
|
239
|
+
raise RuntimeError(f"Directory {args.add_dir} does not exist")
|
|
240
|
+
|
|
241
|
+
# Regular expression to match DAR archive files with base name and date in the format <string>_{FULL, DIFF, INCR}_YYYY-MM-DD
|
|
242
|
+
#dar_pattern = re.compile(r'^(.*?_(FULL|DIFF|INCR)_(\d{4}-\d{2}-\d{2}))\.\d+\.dar$')
|
|
243
|
+
dar_pattern = re.compile(r'^(.*?_(FULL|DIFF|INCR)_(\d{4}-\d{2}-\d{2}))\.1.dar$') # just read slice #1 of an archive
|
|
244
|
+
# List of DAR archives with their dates and base names
|
|
245
|
+
dar_archives = []
|
|
246
|
+
|
|
247
|
+
for filename in os.listdir(args.add_dir):
|
|
248
|
+
logger.debug(f"check if '{filename}' is a dar archive slice #1?")
|
|
249
|
+
match = dar_pattern.match(filename)
|
|
250
|
+
if match:
|
|
251
|
+
base_name = match.group(1)
|
|
252
|
+
date_str = match.group(3)
|
|
253
|
+
date_obj = datetime.strptime(date_str, '%Y-%m-%d')
|
|
254
|
+
dar_archives.append((date_obj, base_name))
|
|
255
|
+
logger.debug(f" -> yes: base name: {base_name}, date: {date_str}")
|
|
256
|
+
|
|
257
|
+
if not dar_archives or len(dar_archives) == 0:
|
|
258
|
+
logger.info(f"No 'dar' archives found in directory {args.add_dir}")
|
|
259
|
+
return
|
|
260
|
+
|
|
261
|
+
# Sort the DAR archives by date
|
|
262
|
+
dar_archives.sort()
|
|
263
|
+
|
|
264
|
+
# Loop over the sorted DAR archives and process them
|
|
265
|
+
result: List[Dict] = []
|
|
266
|
+
for date_obj, base_name in dar_archives:
|
|
267
|
+
logger.info(f"Adding dar archive: '{base_name}' to it's catalog database")
|
|
268
|
+
result_archive = add_specific_archive(base_name, config_settings, args.add_dir)
|
|
269
|
+
result.append({ f"{base_name}" : result_archive})
|
|
270
|
+
if result_archive != 0:
|
|
271
|
+
logger.error(f"Something went wrong added {base_name} to it's catalog")
|
|
272
|
+
|
|
273
|
+
logger.debug(f"Results adding archives found in: '{args.add_dir}': result")
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def backup_def_from_archive(archive: str) -> str:
|
|
277
|
+
"""
|
|
278
|
+
return the backup definition from archive name
|
|
279
|
+
"""
|
|
280
|
+
search = re.search("(.*?)_", archive)
|
|
281
|
+
backup_def = search.group(1)
|
|
282
|
+
logger.debug(f"backup definition: '{backup_def}' from given archive '{archive}'")
|
|
283
|
+
return backup_def
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def remove_specific_archive(archive: str, config_settings: ConfigSettings) -> int:
|
|
288
|
+
backup_def = backup_def_from_archive(archive)
|
|
289
|
+
database_path = os.path.join(config_settings.backup_dir, f"{backup_def}{DB_SUFFIX}")
|
|
290
|
+
cat_no = cat_no_for_name(archive, config_settings)
|
|
291
|
+
if cat_no > 0:
|
|
292
|
+
command = ['dar_manager', '--base', database_path, "--delete", str(cat_no)]
|
|
293
|
+
process = run_command(command)
|
|
294
|
+
else:
|
|
295
|
+
logger.error(f"archive: '{archive}' not found in in't catalog database: {database_path}")
|
|
296
|
+
return cat_no
|
|
297
|
+
|
|
298
|
+
if process.returncode == 0:
|
|
299
|
+
logger.info(f"'{archive}' removed from it's catalog")
|
|
300
|
+
else:
|
|
301
|
+
logger.error(process.stdout)
|
|
302
|
+
logger.error(process.sterr)
|
|
303
|
+
|
|
304
|
+
return process.returncode
|
|
305
|
+
|
|
126
306
|
|
|
127
307
|
|
|
128
308
|
|
|
@@ -142,7 +322,9 @@ def main():
|
|
|
142
322
|
parser.add_argument('-d', '--backup-def', type=str, help='Restrict to work only on this backup definition')
|
|
143
323
|
parser.add_argument('--add-specific-archive', type=str, help='Add this archive to catalog database')
|
|
144
324
|
parser.add_argument('--remove-specific-archive', type=str, help='Remove this archive from catalog database')
|
|
145
|
-
parser.add_argument('--list-
|
|
325
|
+
parser.add_argument('--list-catalog', action='store_true', help='List catalogs in databases for all backup definitions')
|
|
326
|
+
parser.add_argument('--list-catalog-contents', type=int, help="List contents of a catalog. Argument is the 'archive #', '-d <definition>' argument is also required")
|
|
327
|
+
parser.add_argument('--find-file', type=str, help="List catalogs containing <path>/file. '-d <definition>' argument is also required")
|
|
146
328
|
parser.add_argument('--verbose', action='store_true', help='Be more verbose')
|
|
147
329
|
parser.add_argument('--log-level', type=str, help="`debug` or `trace`, default is `info`", default="info")
|
|
148
330
|
parser.add_argument('--log-stdout', action='store_true', help='also print log messages to stdout')
|
|
@@ -196,6 +378,13 @@ See section 15 and section 16 in the supplied "LICENSE" file.''')
|
|
|
196
378
|
logger.error("you can't add and remove archives in the same operation, exiting")
|
|
197
379
|
sys.exit(1)
|
|
198
380
|
|
|
381
|
+
if args.add_dir and args.add_specific_archive:
|
|
382
|
+
logger.error("you cannot add both a directory and an archive")
|
|
383
|
+
sys.exit(1)
|
|
384
|
+
|
|
385
|
+
if args.backup_def and not args.backup_def.strip():
|
|
386
|
+
logger.error(f"No backup definition given to --backup-def")
|
|
387
|
+
|
|
199
388
|
if args.backup_def:
|
|
200
389
|
backup_def_path = os.path.join(config_settings.backup_d_dir, args.backup_def)
|
|
201
390
|
if not os.path.exists(backup_def_path):
|
|
@@ -203,6 +392,16 @@ See section 15 and section 16 in the supplied "LICENSE" file.''')
|
|
|
203
392
|
sys.exit(1)
|
|
204
393
|
|
|
205
394
|
|
|
395
|
+
if args.list_catalog_contents and not args.backup_def:
|
|
396
|
+
logger.error(f"--list-catalog-contents requires the --backup-def, exiting")
|
|
397
|
+
sys.exit(1)
|
|
398
|
+
|
|
399
|
+
if args.find_file and not args.backup_def:
|
|
400
|
+
logger.error(f"--find-file requires the --backup-def, exiting")
|
|
401
|
+
sys.exit(1)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
|
|
206
405
|
# Modify config settings based on the arguments
|
|
207
406
|
if args.alternate_archive_dir:
|
|
208
407
|
if not os.path.exists(args.alternate_archive_dir):
|
|
@@ -213,35 +412,49 @@ See section 15 and section 16 in the supplied "LICENSE" file.''')
|
|
|
213
412
|
|
|
214
413
|
if args.create_db:
|
|
215
414
|
if args.backup_def:
|
|
216
|
-
create_db(args.backup_def, config_settings)
|
|
415
|
+
sys.exit(create_db(args.backup_def, config_settings))
|
|
217
416
|
else:
|
|
218
417
|
for root, dirs, files in os.walk(config_settings.backup_d_dir):
|
|
219
418
|
for file in files:
|
|
220
419
|
current_backupdef = os.path.basename(file)
|
|
221
|
-
|
|
222
|
-
|
|
420
|
+
logger.debug(f"Create catalog db for backup definition: '{current_backupdef}'")
|
|
421
|
+
result = create_db(current_backupdef, config_settings)
|
|
422
|
+
if result != 0:
|
|
423
|
+
sys.exit(result)
|
|
223
424
|
|
|
224
425
|
if args.add_specific_archive:
|
|
225
|
-
add_specific_archive(args.add_specific_archive, config_settings)
|
|
426
|
+
sys.exit(add_specific_archive(args.add_specific_archive, config_settings))
|
|
226
427
|
|
|
227
428
|
if args.add_dir:
|
|
228
|
-
|
|
229
|
-
|
|
429
|
+
sys.exit(add_directory(args, config_settings))
|
|
430
|
+
|
|
230
431
|
|
|
231
432
|
if args.remove_specific_archive:
|
|
232
|
-
|
|
233
|
-
|
|
433
|
+
sys.exit(remove_specific_archive(args.remove_specific_archive, config_settings))
|
|
434
|
+
|
|
234
435
|
|
|
235
436
|
|
|
236
|
-
if args.
|
|
437
|
+
if args.list_catalog:
|
|
237
438
|
if args.backup_def:
|
|
238
|
-
|
|
439
|
+
process = list_catalogs(args.backup_def, config_settings)
|
|
440
|
+
result = process.returncode
|
|
239
441
|
else:
|
|
442
|
+
result = 0
|
|
240
443
|
for root, dirs, files in os.walk(config_settings.backup_d_dir):
|
|
241
444
|
for file in files:
|
|
242
445
|
current_backupdef = os.path.basename(file)
|
|
243
|
-
|
|
244
|
-
|
|
446
|
+
if list_catalogs(current_backupdef, config_settings).returncode != 0:
|
|
447
|
+
result = 1
|
|
448
|
+
sys.exit(result)
|
|
449
|
+
|
|
450
|
+
if args.list_catalog_contents:
|
|
451
|
+
result = list_catalog_contents(args.list_catalog_contents, args.backup_def, config_settings)
|
|
452
|
+
sys.exit(result)
|
|
453
|
+
|
|
454
|
+
if args.find_file:
|
|
455
|
+
result = find_file(args.find_file, args.backup_def, config_settings)
|
|
456
|
+
sys.exit(result)
|
|
457
|
+
|
|
245
458
|
|
|
246
459
|
if __name__ == "__main__":
|
|
247
460
|
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dar-backup
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
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: Homepage, https://github.com/per2jensen/dar-backup
|
|
6
6
|
Project-URL: Issues, https://github.com/per2jensen/dar-backup/issues
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
dar_backup/.darrc,sha256=ggex9N6eETOS6u003_QRRJMeWbveQfkT1lDBt0XpU-I,2112
|
|
2
|
-
dar_backup/__about__.py,sha256=
|
|
2
|
+
dar_backup/__about__.py,sha256=_SsQ0ZcyZbUqlFFT370nQxs8UER9D0oW_EmCr4Q-hx4,21
|
|
3
3
|
dar_backup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
dar_backup/cleanup.py,sha256=DgmxSUwKrLLIQuYSIY_yTRhIuOMgI6ivjlQuH4u3wX4,9057
|
|
5
5
|
dar_backup/config_settings.py,sha256=CBMUhLOOZ-x7CRdS3vBDk4TYaGqC4N1Ot8IMH-qPaI0,3617
|
|
6
6
|
dar_backup/dar_backup.py,sha256=YZoVu9NJX3_WIkQIG8EMLSK3-VWdslI0c2XKrM2Un38,32214
|
|
7
|
-
dar_backup/manager.py,sha256=
|
|
7
|
+
dar_backup/manager.py,sha256=Y1dQ7CRGQx5sGoGrjAO62QfJcuW_0Vod-ZGaQmHInFU,19062
|
|
8
8
|
dar_backup/util.py,sha256=6lPCFHr3MDdaLWAW9EDMZ4jdL7pt8rki-5dOXcesmP8,8955
|
|
9
|
-
dar_backup-0.6.
|
|
10
|
-
dar_backup-0.6.
|
|
11
|
-
dar_backup-0.6.
|
|
12
|
-
dar_backup-0.6.
|
|
13
|
-
dar_backup-0.6.
|
|
9
|
+
dar_backup-0.6.3.dist-info/METADATA,sha256=6120hSt2mUxhn3u8PfbJweoPY4ToWFlAPHAgLozaK7Q,22496
|
|
10
|
+
dar_backup-0.6.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
+
dar_backup-0.6.3.dist-info/entry_points.txt,sha256=x9vnW-JEl8mpDJC69f_XBcn0mBSkV1U0cyvFV-NAP1g,126
|
|
12
|
+
dar_backup-0.6.3.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
13
|
+
dar_backup-0.6.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|