/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
0.79.5 by Ian Clatworthy
incorporate git-fast-import tweaks from bzr-fast-export script
20
# There is a bug in git 1.5.4.3 and older by which unquoting a string consumes
21
# one extra character. Set this variable to True to work-around it. It only
22
# happens when renaming a file whose name contains spaces and/or quotes, and
23
# the symptom is:
24
#   % git-fast-import
25
#   fatal: Missing space after source: R "file 1.txt" file 2.txt
26
# http://git.kernel.org/?p=git/git.git;a=commit;h=c8744d6a8b27115503565041566d97c21e722584
27
GIT_FAST_IMPORT_NEEDS_EXTRA_SPACE_AFTER_QUOTE = False
28
29
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
30
# Lists of command names
31
COMMAND_NAMES = ['blob', 'checkpoint', 'commit', 'progress', 'reset', 'tag']
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
32
FILE_COMMAND_NAMES = ['filemodify', 'filedelete', 'filecopy', 'filerename',
33
    'filedeleteall']
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
34
0.64.2 by Ian Clatworthy
use Bazaar file kinds
35
# Bazaar file kinds
36
FILE_KIND = 'file'
37
SYMLINK_KIND = 'symlink'
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
38
39
40
class ImportCommand(object):
41
    """Base class for import commands."""
42
43
    def __init__(self, name):
44
        self.name = name
0.64.9 by Ian Clatworthy
dump parameter for info processor
45
        # List of field names not to display
46
        self._binary = []
47
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
48
    def dump_str(self, names=None, child_lists=None, verbose=False):
49
        """Dump fields as a string.
50
51
        :param names: the list of fields to include or
52
            None for all public fields
53
        :param child_lists: dictionary of child command names to
54
            fields for that child command to include
55
        :param verbose: if True, prefix each line with the command class and
56
            display fields as a dictionary; if False, dump just the field
57
            values with tabs between them
58
        """
0.64.9 by Ian Clatworthy
dump parameter for info processor
59
        interesting = {}
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
60
        if names is None:
61
            fields = [k for k in self.__dict__.keys() if not k.startswith('_')]
62
        else:
63
            fields = names
64
        for field in fields:
65
            value = self.__dict__.get(field)
66
            if field in self._binary and value is not None:
67
                value = '(...)'
0.64.9 by Ian Clatworthy
dump parameter for info processor
68
            interesting[field] = value
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
69
        if verbose:
70
            return "%s: %s" % (self.__class__.__name__, interesting)
71
        else:
0.64.112 by Ian Clatworthy
fix unicode-related exception in fast-import-query
72
            return "\t".join([repr(interesting[k]) for k in fields])
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
73
74
75
class BlobCommand(ImportCommand):
76
0.64.35 by Ian Clatworthy
identify unmarked blobs and commits by line numbers
77
    def __init__(self, mark, data, lineno=0):
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
78
        ImportCommand.__init__(self, 'blob')
79
        self.mark = mark
80
        self.data = data
0.64.35 by Ian Clatworthy
identify unmarked blobs and commits by line numbers
81
        self.lineno = lineno
82
        # Provide a unique id in case the mark is missing
83
        if mark is None:
84
            self.id = '@%d' % lineno
85
        else:
86
            self.id = ':' + mark
0.64.9 by Ian Clatworthy
dump parameter for info processor
87
        self._binary = ['data']
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
88
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
89
    def __repr__(self):
90
        if self.mark is None:
91
            mark_line = ""
92
        else:
93
            mark_line = "\nmark :%s" % self.mark
94
        return "blob%s\ndata %d\n%s" % (mark_line, len(self.data), self.data)
95
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
96
97
class CheckpointCommand(ImportCommand):
98
99
    def __init__(self):
100
        ImportCommand.__init__(self, 'checkpoint')
101
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
102
    def __repr__(self):
103
        return "checkpoint"
104
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
105
106
class CommitCommand(ImportCommand):
107
0.64.60 by Ian Clatworthy
support merges when from clause implicit
108
    def __init__(self, ref, mark, author, committer, message, from_,
109
        merges, file_iter, lineno=0):
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
110
        ImportCommand.__init__(self, 'commit')
111
        self.ref = ref
112
        self.mark = mark
113
        self.author = author
114
        self.committer = committer
115
        self.message = message
0.64.60 by Ian Clatworthy
support merges when from clause implicit
116
        self.from_ = from_
117
        self.merges = merges
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
118
        self.file_iter = file_iter
0.64.35 by Ian Clatworthy
identify unmarked blobs and commits by line numbers
119
        self.lineno = lineno
0.64.9 by Ian Clatworthy
dump parameter for info processor
120
        self._binary = ['file_iter']
0.64.35 by Ian Clatworthy
identify unmarked blobs and commits by line numbers
121
        # Provide a unique id in case the mark is missing
122
        if mark is None:
123
            self.id = '@%d' % lineno
124
        else:
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
125
            self.id = ':%s' % mark
0.64.9 by Ian Clatworthy
dump parameter for info processor
126
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
127
    def __repr__(self):
128
        if self.mark is None:
129
            mark_line = ""
130
        else:
131
            mark_line = "\nmark :%s" % self.mark
132
        if self.author is None:
133
            author_line = ""
134
        else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
135
            author_line = "\nauthor %s" % format_who_when(self.author)
136
        committer = "committer %s" % format_who_when(self.committer)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
137
        if self.message is None:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
138
            msg_section = ""
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
139
        else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
140
            msg = self.message.encode('utf8')
141
            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
142
        if self.from_ is None:
143
            from_line = ""
144
        else:
0.77.4 by Ian Clatworthy
tweak from and merge formatting
145
            from_line = "\nfrom %s" % self.from_
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
146
        if self.merges is None:
147
            merge_lines = ""
148
        else:
0.77.4 by Ian Clatworthy
tweak from and merge formatting
149
            merge_lines = "".join(["\nmerge %s" % (m,)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
150
                for m in self.merges])
151
        if self.file_iter is None:
152
            filecommands = ""
153
        else:
0.77.3 by Ian Clatworthy
get fast-import-filter formatting commands in the output correctly
154
            filecommands = "".join(["\n%r" % (c,)
155
                for c in iter(self.file_iter)])
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
156
        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
157
            committer, msg_section, from_line, merge_lines, filecommands)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
158
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
159
    def dump_str(self, names=None, child_lists=None, verbose=False):
160
        result = [ImportCommand.dump_str(self, names, verbose=verbose)]
0.64.9 by Ian Clatworthy
dump parameter for info processor
161
        for f in self.file_iter():
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
162
            if child_lists is None:
163
                continue
164
            try:
165
                child_names = child_lists[f.name]
166
            except KeyError:
167
                continue
168
            result.append("\t%s" % f.dump_str(child_names, verbose=verbose))
0.64.9 by Ian Clatworthy
dump parameter for info processor
169
        return '\n'.join(result)
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
170
171
172
class ProgressCommand(ImportCommand):
173
174
    def __init__(self, message):
175
        ImportCommand.__init__(self, 'progress')
176
        self.message = message
177
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
178
    def __repr__(self):
179
        return "progress %s" % (self.message,)
180
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
181
182
class ResetCommand(ImportCommand):
183
184
    def __init__(self, ref, from_):
185
        ImportCommand.__init__(self, 'reset')
186
        self.ref = ref
187
        self.from_ = from_
188
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
189
    def __repr__(self):
190
        if self.from_ is None:
191
            from_line = ""
192
        else:
0.79.5 by Ian Clatworthy
incorporate git-fast-import tweaks from bzr-fast-export script
193
            # According to git-fast-import(1), the extra LF is optional here;
194
            # however, versions of git up to 1.5.4.3 had a bug by which the LF
195
            # was needed. Always emit it, since it doesn't hurt and maintains
196
            # compatibility with older versions.
197
            # http://git.kernel.org/?p=git/git.git;a=commit;h=655e8515f279c01f525745d443f509f97cd805ab
198
            from_line = "\nfrom %s\n" % self.from_
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
199
        return "reset %s%s" % (self.ref, from_line)
200
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
201
202
class TagCommand(ImportCommand):
203
204
    def __init__(self, id, from_, tagger, message):
205
        ImportCommand.__init__(self, 'tag')
206
        self.id = id
207
        self.from_ = from_
208
        self.tagger = tagger
209
        self.message = message
210
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
211
    def __repr__(self):
212
        if self.from_ is None:
213
            from_line = ""
214
        else:
0.77.6 by Ian Clatworthy
no filtering tests
215
            from_line = "\nfrom %s" % self.from_
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
216
        if self.tagger is None:
217
            tagger_line = ""
218
        else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
219
            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
220
        if self.message is None:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
221
            msg_section = ""
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
222
        else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
223
            msg = self.message.encode('utf8')
224
            msg_section = "\ndata %d\n%s" % (len(msg), msg)
225
        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
226
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
227
228
class FileCommand(ImportCommand):
229
    """Base class for file commands."""
230
    pass
231
232
233
class FileModifyCommand(FileCommand):
234
235
    def __init__(self, path, kind, is_executable, dataref, data):
236
        # Either dataref or data should be null
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
237
        FileCommand.__init__(self, 'filemodify')
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
238
        self.path = path
239
        self.kind = kind
240
        self.is_executable = is_executable
241
        self.dataref = dataref
242
        self.data = data
0.64.9 by Ian Clatworthy
dump parameter for info processor
243
        self._binary = ['data']
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
244
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
245
    def __repr__(self):
246
        if self.kind == 'symlink':
247
            mode = "120000"
248
        elif self.is_executable:
249
            mode = "755"
250
        else:
251
            mode = "644"
252
        if self.dataref is None:
253
            dataref = "inline"
254
            datastr = "\ndata %d\n%s" % (len(self.data), self.data)
255
        else:
0.77.3 by Ian Clatworthy
get fast-import-filter formatting commands in the output correctly
256
            dataref = "%s" % (self.dataref,)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
257
            datastr = ""
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
258
        path = format_path(self.path)
259
        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
260
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
261
262
class FileDeleteCommand(FileCommand):
263
264
    def __init__(self, path):
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
265
        FileCommand.__init__(self, 'filedelete')
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
266
        self.path = path
267
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
268
    def __repr__(self):
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
269
        return "D %s" % (format_path(self.path),)
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
270
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
271
272
class FileCopyCommand(FileCommand):
273
274
    def __init__(self, src_path, dest_path):
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
275
        FileCommand.__init__(self, 'filecopy')
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
276
        self.src_path = src_path
277
        self.dest_path = dest_path
278
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
279
    def __repr__(self):
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
280
        return "C %s %s" % (
281
            format_path(self.src_path, quote_spaces=True),
282
            format_path(self.dest_path))
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
283
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
284
285
class FileRenameCommand(FileCommand):
286
0.64.2 by Ian Clatworthy
use Bazaar file kinds
287
    def __init__(self, old_path, new_path):
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
288
        FileCommand.__init__(self, 'filerename')
0.64.2 by Ian Clatworthy
use Bazaar file kinds
289
        self.old_path = old_path
290
        self.new_path = new_path
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
291
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
292
    def __repr__(self):
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
293
        return "R %s %s" % (
294
            format_path(self.old_path, quote_spaces=True),
295
            format_path(self.new_path))
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
296
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
297
298
class FileDeleteAllCommand(FileCommand):
299
0.64.2 by Ian Clatworthy
use Bazaar file kinds
300
    def __init__(self):
0.64.19 by Ian Clatworthy
filtering enhancements: selected fields, filecommands, non-verbose format
301
        FileCommand.__init__(self, 'filedeleteall')
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
302
303
    def __repr__(self):
304
        return "deleteall"
305
306
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
307
def format_path(p, quote_spaces=False):
308
    """Format a path in utf8, quoting it if necessary."""
309
    if '\n' in p:
310
        import re
311
        p = re.sub('\n', '\\n', p)
312
        quote = True
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
313
    else:
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
314
        quote = p[0] == '"' or (quote_spaces and ' ' in p)
315
    if quote:
0.79.5 by Ian Clatworthy
incorporate git-fast-import tweaks from bzr-fast-export script
316
        extra = GIT_FAST_IMPORT_NEEDS_EXTRA_SPACE_AFTER_QUOTE and ' ' or ''
317
        p = '"%s"%s' % (p, extra)
0.77.15 by Ian Clatworthy
ensure output is utf8 encoded when required/recommended
318
    return p.encode('utf8')
319
320
321
def format_who_when(fields):
0.77.2 by Ian Clatworthy
code & tests for formatting Commands as file-import stream strings
322
    """Format a tuple of name,email,secs-since-epoch,utc-offset-secs as a string."""
323
    offset = fields[3]
324
    if offset < 0:
325
        offset_sign = '-'
326
        offset = abs(offset)
327
    else:
328
        offset_sign = '+'
329
    offset_hours = offset / 3600
330
    offset_minutes = offset / 60 - offset_hours * 60
331
    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
332
    name = fields[0].encode('utf8')
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
333
    if name == '':
334
        sep = ''
335
    else:
336
        sep = ' '
337
    return "%s%s<%s> %d %s" % (name, sep, fields[1], fields[2], offset_str)