~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/testament.py

- more testament development

Show diffs side-by-side

added added

removed removed

Lines of Context:
64
64
# fix is when verifying a revision to make sure that every file mentioned 
65
65
# in the revision has compatible ancestry links.
66
66
 
 
67
# TODO: perhaps write timestamp in a more readable form
 
68
 
67
69
from cStringIO import StringIO
68
70
import string
69
71
import sha
110
112
        t.message = rev.message
111
113
        t.parent_ids = rev.parent_ids[:]
112
114
        t.inventory = branch.get_inventory(revision_id)
 
115
        assert not contains_whitespace(t.revision_id)
 
116
        assert not contains_linebreaks(t.committer)
113
117
        return t
114
118
 
115
 
    def text_form_1_to_file(self, f):
116
 
        """Convert to externalizable text form.
 
119
    def as_text_lines(self):
 
120
        """Yield text form as a sequence of lines.
117
121
 
118
122
        The result is returned in utf-8, because it should be signed or
119
123
        hashed in that encoding.
120
124
        """
121
 
        # TODO: Set right encoding
122
 
        print >>f, 'bazaar-ng testament version 1'
123
 
        assert not contains_whitespace(self.revision_id)
124
 
        print >>f, 'revision-id:', self.revision_id
125
 
        assert not contains_linebreaks(self.committer)
126
 
        print >>f, 'committer:', self.committer
127
 
        # TODO: perhaps write timestamp in a more readable form
128
 
        print >>f, 'timestamp:', self.timestamp
129
 
        print >>f, 'timezone:', self.timezone
 
125
        r = []
 
126
        def a(s):
 
127
            r.append(s)
 
128
        a('bazaar-ng testament version 1\n')
 
129
        a('revision-id: %s\n' % self.revision_id)
 
130
        a('committer: %s\n' % self.committer)
 
131
        a('timestamp: %d\n' % self.timestamp)
 
132
        a('timezone: %d\n' % self.timezone)
130
133
        # inventory length contains the root, which is not shown here
131
 
        print >>f, 'entries:', len(self.inventory) - 1
132
 
        print >>f, 'parents:'
 
134
        a('parents:\n')
133
135
        for parent_id in sorted(self.parent_ids):
134
136
            assert not contains_whitespace(parent_id)
135
 
            print >>f, '  ' + parent_id
136
 
        print >>f, 'message:'
 
137
            a('  %s\n' % parent_id)
 
138
        a('message:\n')
137
139
        for l in self.message.splitlines():
138
 
            print >>f, '  ' + l
139
 
        print >>f, 'inventory:'
 
140
            a('  %s\n' % l)
 
141
        a('inventory:\n')
140
142
        for path, ie in self.inventory.iter_entries():
141
 
            print >>f, ' ', ie.kind, path
142
 
 
143
 
    def to_text_form_1(self):
144
 
        s = StringIO()
145
 
        self.text_form_1_to_file(s)
146
 
        return s.getvalue()
 
143
            a(self._entry_to_line(path, ie))
 
144
        if __debug__:
 
145
            for l in r:
 
146
                assert isinstance(l, str), \
 
147
                    '%r of type %s is not a plain string' % (l, type(l))
 
148
        return r
 
149
 
 
150
    def _escape_path(self, path):
 
151
        assert not contains_linebreaks(path)
 
152
        return unicode(path.replace('\\', '\\\\').replace(' ', '\ ')).encode('utf-8')
 
153
 
 
154
    def _entry_to_line(self, path, ie):
 
155
        """Turn an inventory entry into a testament line"""
 
156
        l = '  ' + str(ie.kind)
 
157
        l += ' ' + self._escape_path(path)
 
158
        assert not contains_whitespace(ie.file_id)
 
159
        l += ' ' + unicode(ie.file_id).encode('utf-8')
 
160
        if ie.kind == 'file':
 
161
            # TODO: avoid switching on kind
 
162
            assert ie.text_sha1
 
163
            l += ' ' + ie.text_sha1
 
164
        l += '\n'
 
165
        return l
 
166
 
 
167
    def as_text(self):
 
168
        return ''.join(self.as_text_lines())
147
169
 
148
170
    def as_short_text(self):
149
171
        """Return short digest-based testament."""
150
 
        s = sha.sha(self.to_text_form_1())
 
172
        s = sha.sha()
 
173
        map(s.update, self.as_text_lines())
151
174
        return ('bazaar-ng testament short form 1\n'
152
175
                'revision %s\n'
153
176
                'sha1 %s\n'