Commit | Line | Data |
---|---|---|
e4a93a2f ERE |
1 | #!/usr/bin/env python3 |
2 | ||
3 | # Copyright (C) 2013 Intra2net AG | |
4 | # | |
5 | # This program is free software; you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Lesser General Public License as published | |
7 | # by the Free Software Foundation; either version 3 of the License, or | |
8 | # (at your option) any later version. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU Lesser General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the GNU General Public License | |
16 | # along with this program. If not, see | |
17 | # <http://www.gnu.org/licenses/lgpl-3.0.html> | |
18 | ||
10c70dc6 ERE |
19 | import argparse |
20 | import binascii | |
21 | import json | |
22 | import logging | |
23 | import os | |
24 | import re | |
25 | import random | |
26 | import shutil | |
174794cc | 27 | import sys |
10c70dc6 ERE |
28 | from datetime import datetime |
29 | from functools import partial | |
30 | ||
31 | from deltatar.deltatar import DeltaTar, NO_MATCH, MATCH, PARENT_MATCH | |
32 | from deltatar.tarfile import TarFile, GNU_FORMAT | |
33 | ||
10c70dc6 ERE |
34 | consoleLogger = logging.StreamHandler() |
35 | consoleLogger.setLevel(logging.DEBUG) | |
36 | ||
37 | def check_equal_dirs(path1, path2, deltatar): | |
38 | ''' | |
39 | compare the two directories source_dir and target_dir and check | |
40 | # they are the same | |
41 | ''' | |
42 | nbars1 = len(path1.split('/')) | |
43 | nbars2 = len(path2.split('/')) | |
44 | ||
45 | source_it = deltatar._recursive_walk_dir(path1) | |
46 | source_it = deltatar.jsonize_path_iterator(source_it, strip=nbars1) | |
47 | target_it = deltatar._recursive_walk_dir(path2) | |
48 | target_it = deltatar.jsonize_path_iterator(target_it, strip=nbars2) | |
49 | while True: | |
50 | try: | |
e4a93a2f ERE |
51 | sitem = next(source_it) |
52 | titem = next(target_it) | |
10c70dc6 ERE |
53 | except StopIteration: |
54 | try: | |
e4a93a2f | 55 | titem = next(target_it) |
10c70dc6 ERE |
56 | raise Exception("iterators do not stop at the same time") |
57 | except StopIteration: | |
58 | break | |
59 | try: | |
60 | assert deltatar._equal_stat_dicts(sitem, titem) | |
e4a93a2f ERE |
61 | except Exception as e: |
62 | print(sitem) | |
63 | print(titem) | |
64 | print("FAIL") | |
10c70dc6 ERE |
65 | raise |
66 | ||
67 | if __name__ == "__main__": | |
1046c582 ERE |
68 | #import tracemalloc |
69 | #tracemalloc.enable() | |
70 | #top = tracemalloc.DisplayTop(25) | |
71 | #top.show_lineno = True | |
253d4cdd | 72 | #top.start(20) |
10c70dc6 ERE |
73 | parser = argparse.ArgumentParser() |
74 | ||
75 | parser.add_argument("-m", "--mode", default='', | |
47fb2d67 PG |
76 | help= |
77 | """Mode in which to read/write the backup. | |
78 | Valid modes are: | |
79 | '' open uncompressed; | |
80 | 'gz' open with gzip compression; | |
81 | 'bz2' open with bzip2 compression; | |
e0631598 PG |
82 | '#gz' encrypted stream of individually |
83 | compressed tar blocks. | |
84 | To enable encryption, supply a password. | |
47fb2d67 PG |
85 | """) |
86 | parser.add_argument("-t", "--targetpath", help="Target path directory.") | |
87 | parser.add_argument("-s", "--sourcepath", help="Source path directory.") | |
ecb9676d PG |
88 | epw = os.getenv ("PDTCRYPT_PASSWORD") |
89 | parser.add_argument("-p", "--password", | |
90 | default=epw.strip () if epw is not None else None, | |
91 | help="Password for symmetric encryption. " | |
92 | "The environment variable PDTCRYPT_PASSWORD should " | |
e0631598 | 93 | "be preferred to this. Enables encryption.") |
47fb2d67 PG |
94 | parser.add_argument("-v", "--volsize", default=None, |
95 | help="Maximum volume size, in megabytes.") | |
96 | parser.add_argument("-r", "--restore", action='store_true', | |
97 | help="Restore a backup.") | |
e93f83f1 PG |
98 | parser.add_argument("-R", "--recover", action='store_true', |
99 | help="Restore a backup with an index file.") | |
47fb2d67 PG |
100 | parser.add_argument("-f", "--full", action='store_true', |
101 | help="Create a full backup.") | |
102 | parser.add_argument("-d", "--diff", action='store_true', | |
103 | help="Create a diff backup.") | |
104 | parser.add_argument("-i", "--indexes", nargs='+', help="Indexes paths.") | |
105 | parser.add_argument("-l", "--list-files", action='store_true', | |
106 | help="List files in a tarball.") | |
8c65a2b1 | 107 | parser.add_argument("-x", "--excluded", nargs='+', default=[], |
47fb2d67 | 108 | help="Files to exclude from backup.") |
4cbed687 | 109 | parser.add_argument("-inc", "--included", nargs='+', default=[], |
47fb2d67 | 110 | help="Files to include in the backup.") |
4cbed687 | 111 | parser.add_argument("-ip", "--included-path", default=None, |
47fb2d67 | 112 | help="Path to a file containing a list of included paths.") |
8c65a2b1 | 113 | parser.add_argument("-xp", "--excluded-path", default=None, |
47fb2d67 PG |
114 | help="Path to a file containing a list of excluded paths.") |
115 | parser.add_argument("-e", "--equals", action='store_true', | |
116 | help="Check if two dirs are equal.") | |
10c70dc6 ERE |
117 | |
118 | args = parser.parse_args() | |
8c65a2b1 ERE |
119 | |
120 | if args.excluded_path: | |
121 | f = open(args.excluded_path, 'r') | |
122 | excluded_files = f.readlines() | |
123 | f.close() | |
124 | else: | |
125 | excluded_files = args.excluded | |
126 | ||
4cbed687 ERE |
127 | if args.included_path: |
128 | f = open(args.included_path, 'r') | |
129 | included_files = f.readlines() | |
130 | f.close() | |
131 | else: | |
132 | included_files = args.included | |
133 | ||
8c65a2b1 | 134 | deltatar = DeltaTar(mode=args.mode, password=args.password, |
4cbed687 ERE |
135 | logger=consoleLogger, excluded_files=excluded_files, |
136 | included_files=included_files) | |
10c70dc6 ERE |
137 | |
138 | if args.full: | |
139 | deltatar.create_full_backup(args.sourcepath, args.targetpath, args.volsize) | |
140 | elif args.diff: | |
141 | deltatar.create_diff_backup(args.sourcepath, args.targetpath, args.indexes[0], args.volsize) | |
8c65a2b1 | 142 | elif args.list_files: |
ec96293d | 143 | deltatar.list_backup(args.sourcepath, lambda e: print (e.name)) |
10c70dc6 ERE |
144 | elif args.restore: |
145 | if args.indexes is not None: | |
146 | deltatar.restore_backup(args.targetpath, backup_indexes_paths=args.indexes) | |
147 | else: | |
148 | deltatar.restore_backup(args.targetpath, backup_tar_path=args.sourcepath) | |
e93f83f1 | 149 | elif args.recover: |
174794cc PG |
150 | if args.sourcepath is not None: |
151 | print("Disaster recovery conflicts with --sourcepath; please supply" | |
152 | " an\nindex file (--indexes).", file=sys.stderr) | |
e93f83f1 | 153 | failed = deltatar.recover_backup(args.targetpath, |
174794cc | 154 | backup_indexes_paths=args.indexes) |
e93f83f1 PG |
155 | if len (failed) > 0: |
156 | logger = logging.getLogger('deltatar.DeltaTar') | |
157 | print ("%d files could not be restored:" % len (failed)) | |
158 | for i, f in enumerate (failed): | |
159 | print (" [%d] %s (%s)" % (i, f [0], f [1])) | |
160 | ||
10c70dc6 | 161 | elif args.equals: |
1817bfb4 PG |
162 | check_equal_dirs(os.path.abspath(args.sourcepath), os.path.abspath(args.targetpath), deltatar) |
163 | else: | |
1817bfb4 PG |
164 | print("Nothing to do.\nPlease specify one of --full, --diff, --list-files, " |
165 | "--restore, --equals.\n", file=sys.stderr) | |
166 | parser.print_help(file=sys.stderr) | |
167 | ||
e93f83f1 | 168 |