22
22
from bzrlib import errors
23
23
from bzrlib.bundle.serializer import (BundleSerializer,
28
26
from bzrlib.bundle.serializer import binary_diff
29
27
from bzrlib.bundle.bundle_data import (RevisionInfo, BundleInfo, BundleTree)
31
29
from bzrlib.osutils import pathjoin
32
30
from bzrlib.progress import DummyProgress
33
31
from bzrlib.revision import NULL_REVISION
34
from bzrlib.rio import RioWriter, read_stanzas
36
33
from bzrlib.testament import StrictTestament
34
from bzrlib.timestamp import (
37
38
from bzrlib.textfile import text_file
38
39
from bzrlib.trace import mutter
55
56
self.properties = properties
58
def add_utf8_property(self, name, value):
59
"""Add a property whose value is currently utf8 to the action."""
60
self.properties.append((name, value.decode('utf8')))
57
62
def add_property(self, name, value):
58
63
"""Add a property to the action"""
59
64
self.properties.append((name, value))
131
def write_bundle(self, repository, target, base, fileobj):
132
return self._write_bundle(repository, target, base, fileobj)
126
134
def _write_main_header(self):
127
135
"""Write the header for the changes"""
129
f.write(BUNDLE_HEADER)
137
f.write(_get_bundle_header('0.8'))
133
def _write(self, key, value, indent=1):
134
"""Write out meta information, with proper indenting, etc"""
135
assert indent > 0, 'indentation must be greater than 0'
140
def _write(self, key, value, indent=1, trailing_space_when_empty=False):
141
"""Write out meta information, with proper indenting, etc.
143
:param trailing_space_when_empty: To work around a bug in earlier
144
bundle readers, when writing an empty property, we use "prop: \n"
145
rather than writing "prop:\n".
146
If this parameter is True, and value is the empty string, we will
147
write an extra space.
150
raise ValueError('indentation must be greater than 0')
137
152
f.write('#' + (' ' * indent))
138
153
f.write(key.encode('utf-8'))
141
elif isinstance(value, basestring):
155
if trailing_space_when_empty and value == '':
159
elif isinstance(value, str):
163
elif isinstance(value, unicode):
143
165
f.write(value.encode('utf-8'))
147
169
for entry in value:
148
170
f.write('#' + (' ' * (indent+2)))
149
f.write(entry.encode('utf-8'))
171
if isinstance(entry, str):
174
f.write(entry.encode('utf-8'))
152
177
def _write_revisions(self, pb):
156
181
last_rev_id = None
157
182
last_rev_tree = None
159
i_max = len(self.revision_ids)
184
i_max = len(self.revision_ids)
160
185
for i, rev_id in enumerate(self.revision_ids):
161
186
pb.update("Generating revsion data", i, i_max)
162
187
rev = self.source.get_revision(rev_id)
213
238
w('base id', base_rev)
214
239
if rev.properties:
215
240
self._write('properties', None, indent=1)
216
for name, value in rev.properties.items():
217
self._write(name, value, indent=3)
241
for name, value in sorted(rev.properties.items()):
242
self._write(name, value, indent=3,
243
trailing_space_when_empty=True)
219
245
# Add an extra blank space at the end
220
246
self.to_file.write('\n')
265
291
old_path, new_path):
266
292
entry = new_tree.inventory[file_id]
267
293
if entry.revision != default_revision_id:
268
action.add_property('last-changed', entry.revision)
294
action.add_utf8_property('last-changed', entry.revision)
269
295
if meta_modified:
270
296
action.add_bool_property('executable', entry.executable)
271
297
if text_modified and kind == "symlink":
308
334
if new_rev != old_rev:
309
335
action = Action('modified', [ie.kind,
310
336
new_tree.id2path(ie.file_id)])
311
action.add_property('last-changed', ie.revision)
337
action.add_utf8_property('last-changed', ie.revision)
312
338
action.write(self.to_file)
425
451
revision_info = self.info.revisions[-1]
426
452
if key in revision_info.__dict__:
427
453
if getattr(revision_info, key) is None:
454
if key in ('file_id', 'revision_id', 'base_id'):
455
value = value.encode('utf8')
456
elif key in ('parent_ids'):
457
value = [v.encode('utf8') for v in value]
428
458
setattr(revision_info, key, value)
430
460
raise errors.MalformedHeader('Duplicated Key: %s' % key)
494
524
action, lines, do_continue = self._read_one_patch()
495
525
if action is not None:
496
526
revision_actions.append((action, lines))
497
assert self.info.revisions[-1].tree_actions is None
527
if self.info.revisions[-1].tree_actions is not None:
528
raise AssertionError()
498
529
self.info.revisions[-1].tree_actions = revision_actions
500
531
def _read_footer(self):