~mterry/duplicity/gdrive

« back to all changes in this revision

Viewing changes to rdiffdir

  • Committer: bescoto
  • Date: 2002-10-29 01:49:46 UTC
  • Revision ID: vcs-imports@canonical.com-20021029014946-3m4rmm5plom7pl6q
Initial checkin

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# rdiffdir -- Extend rdiff functionality to directories
 
3
# Version $version released June 30, 2002
 
4
#
 
5
# Copyright (C) 2002 Ben Escoto <bescoto@stanford.edu>
 
6
#
 
7
# This program is licensed under the GNU General Public License (GPL).
 
8
# you can redistribute it and/or modify it under the terms of the GNU
 
9
# General Public License as published by the Free Software Foundation,
 
10
# Inc., 675 Mass Ave, Cambridge MA 02139, USA; either version 2 of the
 
11
# License, or (at your option) any later version.  Distributions of
 
12
# rdiff-backup should include a copy of the GPL in a file called
 
13
# COPYING.  The GPL is also available online at
 
14
# http://www.gnu.org/copyleft/gpl.html.
 
15
#
 
16
# See http://rdiff-backup.stanford.edu/duplicity for more information.
 
17
# Please send mail to me or the mailing list if you find bugs or have
 
18
# any suggestions.
 
19
 
 
20
import sys, getopt, gzip, os
 
21
from duplicity import diffdir, patchdir, log, tarfile, globals, selection, path
 
22
 
 
23
# If set, compress diff and delta files using gzip
 
24
gzip_compress = None
 
25
 
 
26
# If set, when computing delta, also compute signature and write to
 
27
# specified file.
 
28
sig_fileobj = None
 
29
 
 
30
# Add selection argument tuples to this
 
31
select_opts = []
 
32
 
 
33
def parse_cmdline_options(arglist):
 
34
        """Parse argument list"""
 
35
        global gzip_compress, select_opts, sig_fileobj
 
36
        try: optlist, args = getopt.getopt(arglist, "v:Vz",
 
37
                 ["gzip-compress", "exclude=", "exclude-device-files",
 
38
                  "exclude-filelist=", "exclude-filelist-stdin",
 
39
                  "exclude-other-filesystems", "exclude-regexp=", "include=",
 
40
                  "include-filelist=", "include-filelist-stdin",
 
41
                  "include-regexp=", "null-separator", "verbosity=",
 
42
                  "write-sig-to="])
 
43
        except getopt.error, e:
 
44
                command_line_error("Bad command line option: %s" % (str(e),))
 
45
 
 
46
        for opt, arg in optlist:
 
47
                if opt == "--gzip_compress" or opt == "-z": gzip_compress = 1
 
48
                elif (opt == "--exclude" or opt == "--exclude-regexp" or
 
49
                          opt == "--include" or opt == "--include-regexp"):
 
50
                        select_opts.append((opt, arg))
 
51
                elif (opt == "--exclude-device-files" or
 
52
                          opt == "--exclude-other-filesystems"):
 
53
                        select_opts.append((opt, None))
 
54
                elif opt == "--exclude-filelist" or opt == "--include-filelist":
 
55
                        select_opts.append((opt, (arg, open(arg, "rb"))))
 
56
                elif (opt == "--exclude-filelist-stdin" or
 
57
                          opt == "--include-filelist-stdin"):
 
58
                        select_opts.append((opt, ("stdin", sys.stdin)))
 
59
                elif opt == "--null-separator": globals.null_separator = 1
 
60
                elif opt == "-V":
 
61
                        print "rdiffdir", str(globals.version)
 
62
                        sys.exit(0)
 
63
                elif opt == "-v" or opt == "--verbosity": log.setverbosity(int(arg))
 
64
                elif opt == "--write-sig-to" or opt == "--write-signature-to":
 
65
                        sig_fileobj = get_fileobj(arg, "wb")
 
66
                else: command_line_error("Unknown option %s" % opt)
 
67
 
 
68
        return args
 
69
 
 
70
def command_line_error(message):
 
71
        """Indicate a command line error and exit"""
 
72
        sys.stderr.write("Error: %s\n" % (message,))
 
73
        sys.stderr.write("See the rdiffdir manual page for instructions\n")
 
74
        sys.exit(1)
 
75
 
 
76
def check_does_not_exist(filename):
 
77
        """Exit with error message if filename already exists"""
 
78
        try: os.lstat(filename)
 
79
        except OSError: pass
 
80
        else: log.FatalError("File %s already exists, will not "
 
81
                                                 "overwrite." % filename)
 
82
 
 
83
def get_action(args):
 
84
        """Figure out the main action from the arguments"""
 
85
        def require_args(num):
 
86
                if len(args)-1 < num: command_line_error("Too few arguments")
 
87
                elif len(args)-1 > num: command_line_error("Too many arguments")
 
88
 
 
89
        if not args: command_line_error("No arguments found")
 
90
        command = args[0]
 
91
        if command == "sig" or command == "signature":
 
92
                require_args(2)
 
93
                command = "sig"
 
94
        elif command == "tar": require_args(2)
 
95
        elif command == "delta": require_args(3)
 
96
        elif command == "patch": require_args(2)
 
97
        return command, args[1:]
 
98
 
 
99
def get_selection(filename):
 
100
        """Return selection iter starting at path with arguments applied"""
 
101
        sel = selection.Select(path.Path(filename))
 
102
        sel.ParseArgs(select_opts)
 
103
        return sel.set_iter()
 
104
 
 
105
def get_fileobj(filename, mode):
 
106
        """Get file object or stdin/stdout from filename"""
 
107
        if mode == "r" or mode == "rb":
 
108
                if filename == "-": fp = sys.stdin
 
109
                else: fp = open(filename, mode)
 
110
        elif mode == "w" or mode == "wb":
 
111
                if filename == "-": fp = sys.stdout
 
112
                else:
 
113
                        check_does_not_exist(filename)
 
114
                        fp = open(filename, mode)
 
115
        else: assert 0, "Unknown mode " + str(mode)
 
116
 
 
117
        if gzip_compress: return gzip.GzipFile(None, fp.mode, 9, fp)
 
118
        else: return fp
 
119
 
 
120
def write_sig(dirname, outfp):
 
121
        """Write signature of dirname into file object outfp"""
 
122
        diffdir.write_block_iter(diffdir.DirSig(get_selection(dirname)), outfp)
 
123
 
 
124
def write_delta(dirname, sig_infp, outfp):
 
125
        """Write delta to fileobj outfp, reading from dirname and sig_infp"""
 
126
        delta_iter = diffdir.DirDelta(get_selection(dirname), sig_infp)
 
127
        diffdir.write_block_iter(delta_iter, outfp)
 
128
        assert not outfp.close()
 
129
 
 
130
def write_delta_and_sig(filename, sig_infp, delta_outfp, sig_outfp):
 
131
        """Write delta and also signature of filename"""
 
132
        sel = get_selection(filename)
 
133
        delta_iter = diffdir.DirDelta_WriteSig(sel, sig_infp, sig_outfp)
 
134
        diffdir.write_block_iter(delta_iter, outfp)
 
135
        assert not sig_outfp.close()
 
136
 
 
137
def patch(dirname, deltafp):
 
138
        """Patch dirname, reading delta tar from deltafp"""
 
139
        patchdir.Patch(path.Path(dirname), deltafp)
 
140
 
 
141
def write_tar(dirname, outfp):
 
142
        """Store dirname into a tarfile, write to outfp"""
 
143
        diffdir.write_block_iter(diffdir.DirFull(get_selection(filename)), outfp)
 
144
 
 
145
def write_tar_and_sig(dirname, outfp, sig_outfp):
 
146
        """Write tar of dirname to outfp, signature of same to sig_outfp"""
 
147
        full_iter = diffdir.DirFull_WriteSig(get_selection(filename), sig_outfp)
 
148
        diffdir.write_block_iter(full_iter, outfp)
 
149
 
 
150
 
 
151
def main():
 
152
        """Start here"""
 
153
        args = parse_cmdline_options(sys.argv[1:])
 
154
        action, file_args = get_action(args)
 
155
        if action == "sig":
 
156
                write_sig(file_args[0], get_fileobj(file_args[1], "wb"))
 
157
        elif action == "delta":
 
158
                sig_infp = get_fileobj(file_args[0], "rb")
 
159
                delta_outfp = get_fileobj(file_args[2], "wb")
 
160
                if sig_fileobj: write_delta_and_sig(file_args[1], sig_infp,
 
161
                                                                                        delta_outfp, sig_fileobj)
 
162
                else: write_delta(file_args[1], sig_infp, delta_outfp)
 
163
        elif action == "patch":
 
164
                patch(file_args[0], get_fileobj(file_args[1], "rb"))
 
165
        elif action == "tar":
 
166
                if sig_fileobj: write_tar_and_sig(file_args[0],
 
167
                                                                                  get_fileobj(file_args[1], "wb"),
 
168
                                                                                  sig_fileobj)
 
169
                else: write_tar(file_args[0], get_fileobj(file_args[1], "wb"))
 
170
        else: command_line_error("Bad command " + action)
 
171
 
 
172
 
 
173
if __name__ == "__main__": main()