/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/testament.py

  • Committer: Jelmer Vernooij
  • Date: 2018-11-21 03:39:28 UTC
  • mto: This revision was merged to the branch mainline in revision 7206.
  • Revision ID: jelmer@jelmer.uk-20181121033928-ck4sb5zfdwosw35b
Fix test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
59
59
* the testament uses unix line-endings (\n)
60
60
"""
61
61
 
 
62
from __future__ import absolute_import
 
63
 
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
71
73
 
72
74
from copy import copy
73
75
 
74
 
from bzrlib.osutils import (
 
76
from .osutils import (
75
77
    contains_whitespace,
76
78
    contains_linebreaks,
77
 
    sha,
 
79
    sha_strings,
78
80
    )
 
81
from .sixish import text_type
 
82
from .tree import Tree
79
83
 
80
84
 
81
85
class Testament(object):
91
95
 
92
96
    long_header = 'bazaar-ng testament version 1\n'
93
97
    short_header = 'bazaar-ng testament short form 1\n'
 
98
    include_root = False
94
99
 
95
100
    @classmethod
96
101
    def from_revision(cls, repository, revision_id):
97
 
        """Produce a new testament from a historical revision"""
 
102
        """Produce a new testament from a historical revision."""
98
103
        rev = repository.get_revision(revision_id)
99
 
        inventory = repository.get_inventory(revision_id)
100
 
        return cls(rev, inventory)
101
 
 
102
 
    def __init__(self, rev, inventory):
103
 
        """Create a new testament for rev using inventory."""
 
104
        tree = repository.revision_tree(revision_id)
 
105
        return cls(rev, tree)
 
106
 
 
107
    @classmethod
 
108
    def from_revision_tree(cls, tree):
 
109
        """Produce a new testament from a revision tree."""
 
110
        rev = tree._repository.get_revision(tree.get_revision_id())
 
111
        return cls(rev, tree)
 
112
 
 
113
    def __init__(self, rev, tree):
 
114
        """Create a new testament for rev using tree."""
104
115
        self.revision_id = rev.revision_id
105
116
        self.committer = rev.committer
106
117
        self.timezone = rev.timezone or 0
107
118
        self.timestamp = rev.timestamp
108
119
        self.message = rev.message
109
120
        self.parent_ids = rev.parent_ids[:]
110
 
        self.inventory = inventory
 
121
        if not isinstance(tree, Tree):
 
122
            raise TypeError("As of bzr 2.4 Testament.__init__() takes a "
 
123
                            "Revision and a Tree.")
 
124
        self.tree = tree
111
125
        self.revprops = copy(rev.properties)
112
126
        if contains_whitespace(self.revision_id):
113
127
            raise ValueError(self.revision_id)
123
137
        r = []
124
138
        a = r.append
125
139
        a(self.long_header)
126
 
        a('revision-id: %s\n' % self.revision_id)
 
140
        a('revision-id: %s\n' % self.revision_id.decode('utf-8'))
127
141
        a('committer: %s\n' % self.committer)
128
142
        a('timestamp: %d\n' % self.timestamp)
129
143
        a('timezone: %d\n' % self.timezone)
132
146
        for parent_id in sorted(self.parent_ids):
133
147
            if contains_whitespace(parent_id):
134
148
                raise ValueError(parent_id)
135
 
            a('  %s\n' % parent_id)
 
149
            a('  %s\n' % parent_id.decode('utf-8'))
136
150
        a('message:\n')
137
151
        for l in self.message.splitlines():
138
152
            a('  %s\n' % l)
143
157
        return [line.encode('utf-8') for line in r]
144
158
 
145
159
    def _get_entries(self):
146
 
        entries = self.inventory.iter_entries()
147
 
        entries.next()
148
 
        return entries
 
160
        return ((path, ie) for (path, versioned, kind, file_id, ie) in
 
161
                self.tree.list_files(include_root=self.include_root))
149
162
 
150
163
    def _escape_path(self, path):
151
164
        if contains_linebreaks(path):
152
165
            raise ValueError(path)
153
 
        return unicode(path.replace('\\', '/').replace(' ', '\ '))
 
166
        if not isinstance(path, text_type):
 
167
            # TODO(jelmer): Clean this up for pad.lv/1696545
 
168
            path = path.decode('ascii')
 
169
        return path.replace(u'\\', u'/').replace(u' ', u'\\ ')
154
170
 
155
171
    def _entry_to_line(self, path, ie):
156
172
        """Turn an inventory entry into a testament line"""
157
173
        if contains_whitespace(ie.file_id):
158
174
            raise ValueError(ie.file_id)
159
175
        content = ''
160
 
        content_spacer=''
 
176
        content_spacer = ''
161
177
        if ie.kind == 'file':
162
178
            # TODO: avoid switching on kind
163
179
            if not ie.text_sha1:
164
180
                raise AssertionError()
165
 
            content = ie.text_sha1
 
181
            content = ie.text_sha1.decode('ascii')
166
182
            content_spacer = ' '
167
183
        elif ie.kind == 'symlink':
168
184
            if not ie.symlink_target:
176
192
        return l
177
193
 
178
194
    def as_text(self):
179
 
        return ''.join(self.as_text_lines())
 
195
        return b''.join(self.as_text_lines())
180
196
 
181
197
    def as_short_text(self):
182
198
        """Return short digest-based testament."""
183
 
        return (self.short_header +
184
 
                'revision-id: %s\n'
185
 
                'sha1: %s\n'
 
199
        return (self.short_header.encode('ascii') +
 
200
                b'revision-id: %s\n'
 
201
                b'sha1: %s\n'
186
202
                % (self.revision_id, self.as_sha1()))
187
203
 
188
204
    def _revprops_to_lines(self):
199
215
        return r
200
216
 
201
217
    def as_sha1(self):
202
 
        s = sha()
203
 
        map(s.update, self.as_text_lines())
204
 
        return s.hexdigest()
 
218
        return sha_strings(self.as_text_lines())
205
219
 
206
220
 
207
221
class StrictTestament(Testament):
209
223
 
210
224
    long_header = 'bazaar-ng testament version 2.1\n'
211
225
    short_header = 'bazaar-ng testament short form 2.1\n'
 
226
    include_root = False
 
227
 
212
228
    def _entry_to_line(self, path, ie):
213
229
        l = Testament._entry_to_line(self, path, ie)[:-1]
214
 
        l += ' ' + ie.revision
 
230
        l += ' ' + ie.revision.decode('utf-8')
215
231
        l += {True: ' yes\n', False: ' no\n'}[ie.executable]
216
232
        return l
217
233
 
224
240
 
225
241
    long_header = 'bazaar testament version 3 strict\n'
226
242
    short_header = 'bazaar testament short form 3 strict\n'
227
 
    def _get_entries(self):
228
 
        return self.inventory.iter_entries()
 
243
    include_root = True
229
244
 
230
245
    def _escape_path(self, path):
231
246
        if contains_linebreaks(path):
232
247
            raise ValueError(path)
233
 
        if path == '':
234
 
            path = '.'
235
 
        return unicode(path.replace('\\', '/').replace(' ', '\ '))
 
248
        if not isinstance(path, text_type):
 
249
            # TODO(jelmer): Clean this up for pad.lv/1696545
 
250
            path = path.decode('ascii')
 
251
        if path == u'':
 
252
            path = u'.'
 
253
        return path.replace(u'\\', u'/').replace(u' ', u'\\ ')