3 # Copyright (C) 2013 Intra2net AG
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.
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.
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>
28 from datetime import datetime
29 from functools import partial
31 from deltatar.deltatar import DeltaTar, NO_MATCH, MATCH, PARENT_MATCH
32 from deltatar.tarfile import TarFile, GNU_FORMAT
34 consoleLogger = logging.StreamHandler()
35 consoleLogger.setLevel(logging.DEBUG)
37 def check_equal_dirs(path1, path2, deltatar):
39 compare the two directories source_dir and target_dir and check
42 nbars1 = len(path1.split('/'))
43 nbars2 = len(path2.split('/'))
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)
51 sitem = next(source_it)
52 titem = next(target_it)
55 titem = next(target_it)
56 raise Exception("iterators do not stop at the same time")
60 assert deltatar._equal_stat_dicts(sitem, titem)
61 except Exception as e:
67 if __name__ == "__main__":
70 #top = tracemalloc.DisplayTop(25)
71 #top.show_lineno = True
73 parser = argparse.ArgumentParser()
75 parser.add_argument("-m", "--mode", default='',
77 """Mode in which to read/write the backup.
80 'gz' open with gzip compression;
81 'bz2' open with bzip2 compression;
82 '#gz' encrypted stream of individually
83 compressed tar blocks.
84 To enable encryption, supply a password.
86 parser.add_argument("-t", "--targetpath", help="Target path directory.")
87 parser.add_argument("-s", "--sourcepath", help="Source path directory.")
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 "
93 "be preferred to this. Enables encryption.")
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.")
98 parser.add_argument("-R", "--recover", action='store_true',
99 help="Recover a potentially damaged backup with an index file.")
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.")
107 parser.add_argument("-x", "--excluded", nargs='+', default=[],
108 help="Files to exclude from backup.")
109 parser.add_argument("-inc", "--included", nargs='+', default=[],
110 help="Files to include in the backup.")
111 parser.add_argument("-ip", "--included-path", default=None,
112 help="Path to a file containing a list of included paths.")
113 parser.add_argument("-xp", "--excluded-path", default=None,
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.")
118 args = parser.parse_args()
120 if args.excluded_path:
121 f = open(args.excluded_path, 'r')
122 excluded_files = f.readlines()
125 excluded_files = args.excluded
127 if args.included_path:
128 f = open(args.included_path, 'r')
129 included_files = f.readlines()
132 included_files = args.included
134 deltatar = DeltaTar(mode=args.mode, password=args.password,
135 logger=consoleLogger, excluded_files=excluded_files,
136 included_files=included_files)
139 deltatar.create_full_backup(args.sourcepath, args.targetpath, args.volsize)
141 deltatar.create_diff_backup(args.sourcepath, args.targetpath, args.indexes[0], args.volsize)
142 elif args.list_files:
143 deltatar.list_backup(args.sourcepath, lambda e: print (e.name))
145 if args.indexes is not None:
146 deltatar.restore_backup(args.targetpath, backup_indexes_paths=args.indexes)
148 deltatar.restore_backup(args.targetpath, backup_tar_path=args.sourcepath)
150 if args.sourcepath is not None:
151 print("Disaster recovery conflicts with --sourcepath; please supply"
152 " an\nindex file (--indexes).", file=sys.stderr)
153 failed = deltatar.recover_backup(args.targetpath,
154 backup_indexes_paths=args.indexes)
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]))
162 check_equal_dirs(os.path.abspath(args.sourcepath), os.path.abspath(args.targetpath), deltatar)
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)