~bzr-fastimport/+junk/fast-import-append

« back to all changes in this revision

Viewing changes to commands.py

  • Committer: Matt McClure
  • Date: 2009-09-08 03:35:11 UTC
  • mfrom: (205.1.36 trunk)
  • Revision ID: mlm@aya.yale.edu-20090908033511-py9mtd09os4am626
MergesĀ upstreamĀ changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
 
30
30
# Lists of command names
31
 
COMMAND_NAMES = ['blob', 'checkpoint', 'commit', 'progress', 'reset', 'tag']
 
31
COMMAND_NAMES = ['blob', 'checkpoint', 'commit', 'feature', 'progress',
 
32
    'reset', 'tag']
32
33
FILE_COMMAND_NAMES = ['filemodify', 'filedelete', 'filecopy', 'filerename',
33
34
    'filedeleteall']
34
35
 
35
36
# Bazaar file kinds
36
37
FILE_KIND = 'file'
 
38
DIRECTORY_KIND = 'directory'
37
39
SYMLINK_KIND = 'symlink'
 
40
TREE_REFERENCE_KIND = 'tree-reference'
 
41
 
 
42
# Feature names
 
43
MULTIPLE_AUTHORS_FEATURE = "multiple-authors"
 
44
COMMIT_PROPERTIES_FEATURE = "commit-properties"
 
45
EMPTY_DIRS_FEATURE = "empty-directories"
 
46
FEATURE_NAMES = [
 
47
    MULTIPLE_AUTHORS_FEATURE,
 
48
    COMMIT_PROPERTIES_FEATURE,
 
49
    EMPTY_DIRS_FEATURE,
 
50
    ]
38
51
 
39
52
 
40
53
class ImportCommand(object):
45
58
        # List of field names not to display
46
59
        self._binary = []
47
60
 
 
61
    def __str__(self):
 
62
        return repr(self)
 
63
 
48
64
    def dump_str(self, names=None, child_lists=None, verbose=False):
49
65
        """Dump fields as a string.
50
66
 
106
122
class CommitCommand(ImportCommand):
107
123
 
108
124
    def __init__(self, ref, mark, author, committer, message, from_,
109
 
        merges, file_iter, lineno=0):
 
125
        merges, file_iter, lineno=0, more_authors=None, properties=None):
110
126
        ImportCommand.__init__(self, 'commit')
111
127
        self.ref = ref
112
128
        self.mark = mark
116
132
        self.from_ = from_
117
133
        self.merges = merges
118
134
        self.file_iter = file_iter
 
135
        self.more_authors = more_authors
 
136
        self.properties = properties
119
137
        self.lineno = lineno
120
138
        self._binary = ['file_iter']
121
139
        # Provide a unique id in case the mark is missing
125
143
            self.id = ':%s' % mark
126
144
 
127
145
    def __repr__(self):
 
146
        return self.to_string(include_file_contents=True)
 
147
 
 
148
    def __str__(self):
 
149
        return self.to_string(include_file_contents=False)
 
150
 
 
151
    def to_string(self, use_features=True, include_file_contents=False):
128
152
        if self.mark is None:
129
153
            mark_line = ""
130
154
        else:
131
155
            mark_line = "\nmark :%s" % self.mark
132
156
        if self.author is None:
133
 
            author_line = ""
 
157
            author_section = ""
134
158
        else:
135
 
            author_line = "\nauthor %s" % format_who_when(self.author)
 
159
            author_section = "\nauthor %s" % format_who_when(self.author)
 
160
            if use_features and self.more_authors:
 
161
                for author in self.more_authors:
 
162
                    author_section += "\nauthor %s" % format_who_when(author)
136
163
        committer = "committer %s" % format_who_when(self.committer)
137
164
        if self.message is None:
138
165
            msg_section = ""
148
175
        else:
149
176
            merge_lines = "".join(["\nmerge %s" % (m,)
150
177
                for m in self.merges])
 
178
        if use_features and self.properties:
 
179
            property_lines = []
 
180
            for name in sorted(self.properties):
 
181
                value = self.properties[name]
 
182
                property_lines.append("\n" + format_property(name, value))
 
183
            properties_section = "".join(property_lines)
 
184
        else:
 
185
            properties_section = ""
151
186
        if self.file_iter is None:
152
187
            filecommands = ""
153
188
        else:
154
 
            filecommands = "".join(["\n%r" % (c,)
155
 
                for c in iter(self.file_iter)])
156
 
        return "commit %s%s%s\n%s%s%s%s%s" % (self.ref, mark_line, author_line,
157
 
            committer, msg_section, from_line, merge_lines, filecommands)
 
189
            if include_file_contents:
 
190
                format_str = "\n%r"
 
191
            else:
 
192
                format_str = "\n%s"
 
193
            filecommands = "".join([format_str % (c,)
 
194
                for c in self.iter_files()])
 
195
        return "commit %s%s%s\n%s%s%s%s%s%s" % (self.ref, mark_line,
 
196
            author_section, committer, msg_section, from_line, merge_lines,
 
197
            properties_section, filecommands)
158
198
 
159
199
    def dump_str(self, names=None, child_lists=None, verbose=False):
160
200
        result = [ImportCommand.dump_str(self, names, verbose=verbose)]
161
 
        for f in iter(self.file_iter):
 
201
        for f in self.iter_files():
162
202
            if child_lists is None:
163
203
                continue
164
204
            try:
168
208
            result.append("\t%s" % f.dump_str(child_names, verbose=verbose))
169
209
        return '\n'.join(result)
170
210
 
 
211
    def iter_files(self):
 
212
        """Iterate over files."""
 
213
        # file_iter may be a callable or an iterator
 
214
        if callable(self.file_iter):
 
215
            return self.file_iter()
 
216
        elif self.file_iter:
 
217
            return iter(self.file_iter)
 
218
 
 
219
 
 
220
class FeatureCommand(ImportCommand):
 
221
 
 
222
    def __init__(self, feature_name, value=None, lineno=0):
 
223
        ImportCommand.__init__(self, 'feature')
 
224
        self.feature_name = feature_name
 
225
        self.value = value
 
226
        self.lineno = lineno
 
227
 
 
228
    def __repr__(self):
 
229
        if self.value is None:
 
230
            value_text = ""
 
231
        else:
 
232
            value_text = "=%s" % self.value
 
233
        return "feature %s%s" % (self.feature_name, value_text)
 
234
 
171
235
 
172
236
class ProgressCommand(ImportCommand):
173
237
 
243
307
        self._binary = ['data']
244
308
 
245
309
    def __repr__(self):
246
 
        if self.kind == 'symlink':
247
 
            mode = "120000"
248
 
        elif self.is_executable:
 
310
        return self.to_string(include_file_contents=True)
 
311
 
 
312
    def __str__(self):
 
313
        return self.to_string(include_file_contents=False)
 
314
 
 
315
    def to_string(self, include_file_contents=False):
 
316
        if self.is_executable:
249
317
            mode = "755"
250
 
        else:
 
318
        elif self.kind == 'file':
251
319
            mode = "644"
252
 
        if self.dataref is None:
 
320
        elif self.kind == 'directory':
 
321
            mode = "040000"
 
322
        elif self.kind == 'symlink':
 
323
            mode = "120000"
 
324
        elif self.kind == 'tree-reference':
 
325
            mode = "160000"
 
326
        else:
 
327
            raise AssertionError("unknown kind %s" % (self.kind,))
 
328
        datastr = ""
 
329
        if self.kind == 'directory':
 
330
            dataref = '-'
 
331
        elif self.dataref is None:
253
332
            dataref = "inline"
254
 
            datastr = "\ndata %d\n%s" % (len(self.data), self.data)
 
333
            if include_file_contents:
 
334
                datastr = "\ndata %d\n%s" % (len(self.data), self.data)
255
335
        else:
256
336
            dataref = "%s" % (self.dataref,)
257
 
            datastr = ""
258
337
        path = format_path(self.path)
259
338
        return "M %s %s %s%s" % (mode, dataref, path, datastr)
260
339
 
345
424
        sep = ''
346
425
    else:
347
426
        sep = ' '
348
 
    result = "%s%s<%s> %d %s" % (name, sep, fields[1], fields[2], offset_str)
349
 
    return result.encode('utf8')
 
427
    if isinstance(name, unicode):
 
428
        name = name.encode('utf8')
 
429
    email = fields[1]
 
430
    if isinstance(email, unicode):
 
431
        email = email.encode('utf8')
 
432
    result = "%s%s<%s> %d %s" % (name, sep, email, fields[2], offset_str)
 
433
    return result
 
434
 
 
435
 
 
436
def format_property(name, value):
 
437
    """Format the name and value (both unicode) of a property as a string."""
 
438
    utf8_name = name.encode('utf8')
 
439
    if value is not None:
 
440
        utf8_value = value.encode('utf8')
 
441
        result = "property %s %d %s" % (utf8_name, len(utf8_value), utf8_value)
 
442
    else:
 
443
        result = "property %s" % (utf8_name,)
 
444
    return result