59
59
* the testament uses unix line-endings (\n)
62
from __future__ import absolute_import
62
64
# XXX: At the moment, clients trust that the graph described in a weave
63
65
# is accurate, but that's not covered by the testament. Perhaps the best
64
66
# fix is when verifying a revision to make sure that every file mentioned
117
119
self.parent_ids = rev.parent_ids[:]
118
120
if not isinstance(tree, Tree):
119
121
raise TypeError("As of bzr 2.4 Testament.__init__() takes a "
120
"Revision and a Tree.")
122
"Revision and a Tree.")
122
124
self.revprops = copy(rev.properties)
123
125
if contains_whitespace(self.revision_id):
136
138
a(self.long_header)
137
a('revision-id: %s\n' % self.revision_id.decode('utf-8'))
139
a('revision-id: %s\n' % self.revision_id)
138
140
a('committer: %s\n' % self.committer)
139
141
a('timestamp: %d\n' % self.timestamp)
140
142
a('timezone: %d\n' % self.timezone)
143
145
for parent_id in sorted(self.parent_ids):
144
146
if contains_whitespace(parent_id):
145
147
raise ValueError(parent_id)
146
a(' %s\n' % parent_id.decode('utf-8'))
148
a(' %s\n' % parent_id)
148
150
for l in self.message.splitlines():
154
156
return [line.encode('utf-8') for line in r]
156
158
def _get_entries(self):
157
return ((path, ie) for (path, file_class, kind, ie) in
159
return ((path, ie) for (path, versioned, kind, file_id, ie) in
158
160
self.tree.list_files(include_root=self.include_root))
160
162
def _escape_path(self, path):
161
163
if contains_linebreaks(path):
162
164
raise ValueError(path)
163
if not isinstance(path, str):
164
# TODO(jelmer): Clean this up for pad.lv/1696545
165
path = path.decode('ascii')
166
return path.replace(u'\\', u'/').replace(u' ', u'\\ ')
165
return unicode(path.replace('\\', '/').replace(' ', '\\ '))
168
167
def _entry_to_line(self, path, ie):
169
168
"""Turn an inventory entry into a testament line"""
170
169
if contains_whitespace(ie.file_id):
171
170
raise ValueError(ie.file_id)
174
173
if ie.kind == 'file':
175
174
# TODO: avoid switching on kind
176
175
if not ie.text_sha1:
177
176
raise AssertionError()
178
content = ie.text_sha1.decode('ascii')
177
content = ie.text_sha1
179
178
content_spacer = ' '
180
179
elif ie.kind == 'symlink':
181
180
if not ie.symlink_target:
191
190
def as_text(self):
192
return b''.join(self.as_text_lines())
191
return ''.join(self.as_text_lines())
194
193
def as_short_text(self):
195
194
"""Return short digest-based testament."""
196
return (self.short_header.encode('ascii') +
195
return (self.short_header +
199
198
% (self.revision_id, self.as_sha1()))
201
200
def _revprops_to_lines(self):
221
220
long_header = 'bazaar-ng testament version 2.1\n'
222
221
short_header = 'bazaar-ng testament short form 2.1\n'
223
222
include_root = False
225
223
def _entry_to_line(self, path, ie):
226
224
l = Testament._entry_to_line(self, path, ie)[:-1]
227
l += ' ' + ie.revision.decode('utf-8')
225
l += ' ' + ie.revision
228
226
l += {True: ' yes\n', False: ' no\n'}[ie.executable]
242
240
def _escape_path(self, path):
243
241
if contains_linebreaks(path):
244
242
raise ValueError(path)
245
if not isinstance(path, str):
246
# TODO(jelmer): Clean this up for pad.lv/1696545
247
path = path.decode('ascii')
250
return path.replace(u'\\', u'/').replace(u' ', u'\\ ')
245
return unicode(path.replace('\\', '/').replace(' ', '\\ '))