/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
1
# Copyright (C) 2008 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Import command classes."""
18
19
20
# Lists of command names
21
COMMAND_NAMES = ['blob', 'checkpoint', 'commit', 'progress', 'reset', 'tag']
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
22
FILE_COMMAND_NAMES = ['filemodify', 'filedelete', 'filecopy', 'filerename',
23
    'filedeleteall']
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
24
0.64.2 by Ian Clatworthy
use Bazaar file kinds
25
# Bazaar file kinds
26
FILE_KIND = 'file'
27
SYMLINK_KIND = 'symlink'
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
28
29
30
class ImportCommand(object):
31
    """Base class for import commands."""
32
33
    def __init__(self, name):
34
        self.name = name
0.64.9 by Ian Clatworthy
dump parameter for info processor
35
        # List of field names not to display
36
        self._binary = []
37
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
38
    def dump_str(self, names=None, child_lists=None, verbose=False):
39
        """Dump fields as a string.
40
41
        :param names: the list of fields to include or
42
            None for all public fields
43
        :param child_lists: dictionary of child command names to
44
            fields for that child command to include
45
        :param verbose: if True, prefix each line with the command class and
46
            display fields as a dictionary; if False, dump just the field
47
            values with tabs between them
48
        """
0.64.9 by Ian Clatworthy
dump parameter for info processor
49
        interesting = {}
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
50
        if names is None:
51
            fields = [k for k in self.__dict__.keys() if not k.startswith('_')]
52
        else:
53
            fields = names
54
        for field in fields:
55
            value = self.__dict__.get(field)
56
            if field in self._binary and value is not None:
57
                value = '(...)'
0.64.9 by Ian Clatworthy
dump parameter for info processor
58
            interesting[field] = value
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
59
        if verbose:
60
            return "%s: %s" % (self.__class__.__name__, interesting)
61
        else:
0.64.112 by Ian Clatworthy
fix unicode-related exception in fast-import-query
62
            return "\t".join([repr(interesting[k]) for k in fields])
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
63
64
65
class BlobCommand(ImportCommand):
66
0.64.35 by Ian Clatworthy
identify unmarked blobs and commits by line numbers
67
    def __init__(self, mark, data, lineno=0):
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
68
        ImportCommand.__init__(self, 'blob')
69
        self.mark = mark
70
        self.data = data
0.64.35 by Ian Clatworthy
identify unmarked blobs and commits by line numbers
71
        self.lineno = lineno
72
        # Provide a unique id in case the mark is missing
73
        if mark is None:
74
            self.id = '@%d' % lineno
75
        else:
76
            self.id = ':' + mark
0.64.9 by Ian Clatworthy
dump parameter for info processor
77
        self._binary = ['data']
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
78
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
79
    def __repr__(self):
80
        if self.mark is None:
81
            mark_line = ""
82
        else:
83
            mark_line = "\nmark :%s" % self.mark
84
        return "blob%s\ndata %d\n%s" % (mark_line, len(self.data), self.data)
85
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
86
87
class CheckpointCommand(ImportCommand):
88
89
    def __init__(self):
90
        ImportCommand.__init__(self, 'checkpoint')
91
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
92
    def __repr__(self):
93
        return "checkpoint"
94
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
95
96
class CommitCommand(ImportCommand):
97
0.64.60 by Ian Clatworthy
support merges when from clause implicit
98
    def __init__(self, ref, mark, author, committer, message, from_,
99
        merges, file_iter, lineno=0):
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
100
        ImportCommand.__init__(self, 'commit')
101
        self.ref = ref
102
        self.mark = mark
103
        self.author = author
104
        self.committer = committer
105
        self.message = message
0.64.60 by Ian Clatworthy
support merges when from clause implicit
106
        self.from_ = from_
107
        self.merges = merges
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
108
        self.file_iter = file_iter
0.64.35 by Ian Clatworthy
identify unmarked blobs and commits by line numbers
109
        self.lineno = lineno
0.64.9 by Ian Clatworthy
dump parameter for info processor
110
        self._binary = ['file_iter']
0.64.35 by Ian Clatworthy
identify unmarked blobs and commits by line numbers
111
        # Provide a unique id in case the mark is missing
112
        if mark is None:
113
            self.id = '@%d' % lineno
114
        else:
115
            self.id = ':' + mark
0.64.9 by Ian Clatworthy
dump parameter for info processor
116
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
117
    def __repr__(self):
118
        if self.mark is None:
119
            mark_line = ""
120
        else:
121
            mark_line = "\nmark :%s" % self.mark
122
        if self.author is None:
123
            author_line = ""
124
        else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
125
            author_line = "\nauthor %s" % format_who_when(self.author)
126
        committer = "committer %s" % format_who_when(self.committer)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
127
        if self.message is None:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
128
            msg_section = ""
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
129
        else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
130
            msg = self.message.encode('utf8')
131
            msg_section = "\ndata %d\n%s" % (len(msg), msg)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
132
        if self.from_ is None:
133
            from_line = ""
134
        else:
0.77.4 by Ian Clatworthy
tweak from and merge formatting
135
            from_line = "\nfrom %s" % self.from_
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
136
        if self.merges is None:
137
            merge_lines = ""
138
        else:
0.77.4 by Ian Clatworthy
tweak from and merge formatting
139
            merge_lines = "".join(["\nmerge %s" % (m,)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
140
                for m in self.merges])
141
        if self.file_iter is None:
142
            filecommands = ""
143
        else:
0.77.3 by Ian Clatworthy
get fast-import-filter formatting commands in the output correctly
144
            filecommands = "".join(["\n%r" % (c,)
145
                for c in iter(self.file_iter)])
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
146
        return "commit %s%s%s\n%s%s%s%s%s" % (self.ref, mark_line, author_line,
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
147
            committer, msg_section, from_line, merge_lines, filecommands)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
148
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
149
    def dump_str(self, names=None, child_lists=None, verbose=False):
150
        result = [ImportCommand.dump_str(self, names, verbose=verbose)]
0.64.9 by Ian Clatworthy
dump parameter for info processor
151
        for f in self.file_iter():
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
152
            if child_lists is None:
153
                continue
154
            try:
155
                child_names = child_lists[f.name]
156
            except KeyError:
157
                continue
158
            result.append("\t%s" % f.dump_str(child_names, verbose=verbose))
0.64.9 by Ian Clatworthy
dump parameter for info processor
159
        return '\n'.join(result)
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
160
161
162
class ProgressCommand(ImportCommand):
163
164
    def __init__(self, message):
165
        ImportCommand.__init__(self, 'progress')
166
        self.message = message
167
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
168
    def __repr__(self):
169
        return "progress %s" % (self.message,)
170
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
171
172
class ResetCommand(ImportCommand):
173
174
    def __init__(self, ref, from_):
175
        ImportCommand.__init__(self, 'reset')
176
        self.ref = ref
177
        self.from_ = from_
178
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
179
    def __repr__(self):
180
        if self.from_ is None:
181
            from_line = ""
182
        else:
0.77.6 by Ian Clatworthy
no filtering tests
183
            from_line = "\nfrom %s" % self.from_
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
184
        return "reset %s%s" % (self.ref, from_line)
185
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
186
187
class TagCommand(ImportCommand):
188
189
    def __init__(self, id, from_, tagger, message):
190
        ImportCommand.__init__(self, 'tag')
191
        self.id = id
192
        self.from_ = from_
193
        self.tagger = tagger
194
        self.message = message
195
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
196
    def __repr__(self):
197
        if self.from_ is None:
198
            from_line = ""
199
        else:
0.77.6 by Ian Clatworthy
no filtering tests
200
            from_line = "\nfrom %s" % self.from_
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
201
        if self.tagger is None:
202
            tagger_line = ""
203
        else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
204
            tagger_line = "\ntagger %s" % format_who_when(self.tagger)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
205
        if self.message is None:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
206
            msg_section = ""
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
207
        else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
208
            msg = self.message.encode('utf8')
209
            msg_section = "\ndata %d\n%s" % (len(msg), msg)
210
        return "tag %s%s%s%s" % (self.id, from_line, tagger_line, msg_section)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
211
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
212
213
class FileCommand(ImportCommand):
214
    """Base class for file commands."""
215
    pass
216
217
218
class FileModifyCommand(FileCommand):
219
220
    def __init__(self, path, kind, is_executable, dataref, data):
221
        # Either dataref or data should be null
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
222
        FileCommand.__init__(self, 'filemodify')
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
223
        self.path = path
224
        self.kind = kind
225
        self.is_executable = is_executable
226
        self.dataref = dataref
227
        self.data = data
0.64.9 by Ian Clatworthy
dump parameter for info processor
228
        self._binary = ['data']
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
229
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
230
    def __repr__(self):
231
        if self.kind == 'symlink':
232
            mode = "120000"
233
        elif self.is_executable:
234
            mode = "755"
235
        else:
236
            mode = "644"
237
        if self.dataref is None:
238
            dataref = "inline"
239
            datastr = "\ndata %d\n%s" % (len(self.data), self.data)
240
        else:
0.77.3 by Ian Clatworthy
get fast-import-filter formatting commands in the output correctly
241
            dataref = "%s" % (self.dataref,)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
242
            datastr = ""
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
243
        path = format_path(self.path)
244
        return "M %s %s %s%s" % (mode, dataref, path, datastr)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
245
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
246
247
class FileDeleteCommand(FileCommand):
248
249
    def __init__(self, path):
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
250
        FileCommand.__init__(self, 'filedelete')
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
251
        self.path = path
252
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
253
    def __repr__(self):
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
254
        return "D %s" % (format_path(self.path),)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
255
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
256
257
class FileCopyCommand(FileCommand):
258
259
    def __init__(self, src_path, dest_path):
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
260
        FileCommand.__init__(self, 'filecopy')
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
261
        self.src_path = src_path
262
        self.dest_path = dest_path
263
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
264
    def __repr__(self):
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
265
        return "C %s %s" % (
266
            format_path(self.src_path, quote_spaces=True),
267
            format_path(self.dest_path))
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
268
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
269
270
class FileRenameCommand(FileCommand):
271
0.64.2 by Ian Clatworthy
use Bazaar file kinds
272
    def __init__(self, old_path, new_path):
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
273
        FileCommand.__init__(self, 'filerename')
0.64.2 by Ian Clatworthy
use Bazaar file kinds
274
        self.old_path = old_path
275
        self.new_path = new_path
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
276
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
277
    def __repr__(self):
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
278
        return "R %s %s" % (
279
            format_path(self.old_path, quote_spaces=True),
280
            format_path(self.new_path))
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
281
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
282
283
class FileDeleteAllCommand(FileCommand):
284
0.64.2 by Ian Clatworthy
use Bazaar file kinds
285
    def __init__(self):
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
286
        FileCommand.__init__(self, 'filedeleteall')
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
287
288
    def __repr__(self):
289
        return "deleteall"
290
291
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
292
def format_path(p, quote_spaces=False):
293
    """Format a path in utf8, quoting it if necessary."""
294
    if '\n' in p:
295
        import re
296
        p = re.sub('\n', '\\n', p)
297
        quote = True
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
298
    else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
299
        quote = p[0] == '"' or (quote_spaces and ' ' in p)
300
    if quote:
301
        p = '"%s"' % p
302
    return p.encode('utf8')
303
304
305
def format_who_when(fields):
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
306
    """Format a tuple of name,email,secs-since-epoch,utc-offset-secs as a string."""
307
    offset = fields[3]
308
    if offset < 0:
309
        offset_sign = '-'
310
        offset = abs(offset)
311
    else:
312
        offset_sign = '+'
313
    offset_hours = offset / 3600
314
    offset_minutes = offset / 60 - offset_hours * 60
315
    offset_str = "%s%02d%02d" % (offset_sign, offset_hours, offset_minutes)
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
316
    name = fields[0].encode('utf8')
317
    return "%s <%s> %d %s" % (name, fields[1], fields[2], offset_str)