~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bundle/serializer/v08.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-03-28 06:58:22 UTC
  • mfrom: (2379.2.3 hpss-chroot)
  • Revision ID: pqm@pqm.ubuntu.com-20070328065822-999550a858a3ced3
(robertc) Fix chroot urls to not expose the url of the transport they are protecting, allowing regular url operations to work on them. (Robert Collins, Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2009 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Serializer factory for reading and writing bundles.
18
18
"""
19
19
 
20
 
from __future__ import absolute_import
 
20
import os
21
21
 
22
 
from bzrlib import (
23
 
    errors,
24
 
    ui,
25
 
    )
 
22
from bzrlib import errors
26
23
from bzrlib.bundle.serializer import (BundleSerializer,
27
 
                                      _get_bundle_header,
 
24
                                      BUNDLE_HEADER,
28
25
                                     )
29
26
from bzrlib.bundle.serializer import binary_diff
30
 
from bzrlib.bundle.bundle_data import (RevisionInfo, BundleInfo)
 
27
from bzrlib.bundle.bundle_data import (RevisionInfo, BundleInfo, BundleTree)
31
28
from bzrlib.diff import internal_diff
 
29
from bzrlib.osutils import pathjoin
 
30
from bzrlib.progress import DummyProgress
32
31
from bzrlib.revision import NULL_REVISION
 
32
from bzrlib.rio import RioWriter, read_stanzas
 
33
import bzrlib.ui
33
34
from bzrlib.testament import StrictTestament
34
35
from bzrlib.timestamp import (
35
36
    format_highres_date,
36
 
    )
 
37
    unpack_highres_date,
 
38
)
37
39
from bzrlib.textfile import text_file
38
40
from bzrlib.trace import mutter
39
41
 
118
120
        source.lock_read()
119
121
        try:
120
122
            self._write_main_header()
121
 
            pb = ui.ui_factory.nested_progress_bar()
 
123
            pb = DummyProgress()
122
124
            try:
123
125
                self._write_revisions(pb)
124
126
            finally:
125
 
                pb.finished()
 
127
                pass
 
128
                #pb.finished()
126
129
        finally:
127
130
            source.unlock()
128
131
 
129
 
    def write_bundle(self, repository, target, base, fileobj):
130
 
        return self._write_bundle(repository, target, base, fileobj)
131
 
 
132
132
    def _write_main_header(self):
133
133
        """Write the header for the changes"""
134
134
        f = self.to_file
135
 
        f.write(_get_bundle_header('0.8'))
 
135
        f.write(BUNDLE_HEADER)
 
136
        f.write('0.8\n')
136
137
        f.write('#\n')
137
138
 
138
 
    def _write(self, key, value, indent=1, trailing_space_when_empty=False):
139
 
        """Write out meta information, with proper indenting, etc.
140
 
 
141
 
        :param trailing_space_when_empty: To work around a bug in earlier
142
 
            bundle readers, when writing an empty property, we use "prop: \n"
143
 
            rather than writing "prop:\n".
144
 
            If this parameter is True, and value is the empty string, we will
145
 
            write an extra space.
146
 
        """
147
 
        if indent < 1:
148
 
            raise ValueError('indentation must be greater than 0')
 
139
    def _write(self, key, value, indent=1):
 
140
        """Write out meta information, with proper indenting, etc"""
 
141
        assert indent > 0, 'indentation must be greater than 0'
149
142
        f = self.to_file
150
143
        f.write('#' + (' ' * indent))
151
144
        f.write(key.encode('utf-8'))
152
145
        if not value:
153
 
            if trailing_space_when_empty and value == '':
154
 
                f.write(': \n')
155
 
            else:
156
 
                f.write(':\n')
 
146
            f.write(':\n')
157
147
        elif isinstance(value, str):
158
148
            f.write(': ')
159
149
            f.write(value)
181
171
 
182
172
        i_max = len(self.revision_ids)
183
173
        for i, rev_id in enumerate(self.revision_ids):
184
 
            pb.update("Generating revision data", i, i_max)
 
174
            pb.update("Generating revsion data", i, i_max)
185
175
            rev = self.source.get_revision(rev_id)
186
176
            if rev_id == last_rev_id:
187
177
                rev_tree = last_rev_tree
204
194
            else:
205
195
                base_tree = self.source.revision_tree(base_id)
206
196
            force_binary = (i != 0)
207
 
            self._write_revision(rev, rev_tree, base_id, base_tree,
 
197
            self._write_revision(rev, rev_tree, base_id, base_tree, 
208
198
                                 explicit_base, force_binary)
209
199
 
210
200
            last_rev_id = base_id
211
201
            last_rev_tree = base_tree
212
202
 
213
203
    def _testament_sha1(self, revision_id):
214
 
        return StrictTestament.from_revision(self.source,
 
204
        return StrictTestament.from_revision(self.source, 
215
205
                                             revision_id).as_sha1()
216
206
 
217
 
    def _write_revision(self, rev, rev_tree, base_rev, base_tree,
 
207
    def _write_revision(self, rev, rev_tree, base_rev, base_tree, 
218
208
                        explicit_base, force_binary):
219
209
        """Write out the information for a revision."""
220
210
        def w(key, value):
236
226
            w('base id', base_rev)
237
227
        if rev.properties:
238
228
            self._write('properties', None, indent=1)
239
 
            for name, value in sorted(rev.properties.items()):
240
 
                self._write(name, value, indent=3,
241
 
                            trailing_space_when_empty=True)
242
 
 
 
229
            for name, value in rev.properties.items():
 
230
                self._write(name, value, indent=3)
 
231
        
243
232
        # Add an extra blank space at the end
244
233
        self.to_file.write('\n')
245
234
 
252
241
        self.to_file.write(' // '.join(p_texts).encode('utf-8'))
253
242
        self.to_file.write('\n')
254
243
 
255
 
    def _write_delta(self, new_tree, old_tree, default_revision_id,
 
244
    def _write_delta(self, new_tree, old_tree, default_revision_id, 
256
245
                     force_binary):
257
246
        """Write out the changes between the trees."""
258
247
        DEVNULL = '/dev/null'
261
250
 
262
251
        def do_diff(file_id, old_path, new_path, action, force_binary):
263
252
            def tree_lines(tree, require_text=False):
264
 
                if tree.has_id(file_id):
 
253
                if file_id in tree:
265
254
                    tree_file = tree.get_file(file_id)
266
255
                    if require_text is True:
267
256
                        tree_file = text_file(tree_file)
275
264
                old_lines = tree_lines(old_tree, require_text=True)
276
265
                new_lines = tree_lines(new_tree, require_text=True)
277
266
                action.write(self.to_file)
278
 
                internal_diff(old_path, old_lines, new_path, new_lines,
 
267
                internal_diff(old_path, old_lines, new_path, new_lines, 
279
268
                              self.to_file)
280
269
            except errors.BinaryFile:
281
270
                old_lines = tree_lines(old_tree, require_text=False)
282
271
                new_lines = tree_lines(new_tree, require_text=False)
283
272
                action.add_property('encoding', 'base64')
284
273
                action.write(self.to_file)
285
 
                binary_diff(old_path, old_lines, new_path, new_lines,
 
274
                binary_diff(old_path, old_lines, new_path, new_lines, 
286
275
                            self.to_file)
287
276
 
288
277
        def finish_action(action, file_id, kind, meta_modified, text_modified,
289
278
                          old_path, new_path):
290
 
            entry = new_tree.root_inventory[file_id]
 
279
            entry = new_tree.inventory[file_id]
291
280
            if entry.revision != default_revision_id:
292
281
                action.add_utf8_property('last-changed', entry.revision)
293
282
            if meta_modified:
306
295
 
307
296
        for path, file_id, kind in delta.added:
308
297
            action = Action('added', [kind, path], [('file-id', file_id)])
309
 
            meta_modified = (kind=='file' and
 
298
            meta_modified = (kind=='file' and 
310
299
                             new_tree.is_executable(file_id))
311
300
            finish_action(action, file_id, kind, meta_modified, True,
312
301
                          DEVNULL, path)
324
313
                          path, path)
325
314
 
326
315
        for path, file_id, kind in delta.unchanged:
327
 
            new_rev = new_tree.get_file_revision(file_id)
 
316
            ie = new_tree.inventory[file_id]
 
317
            new_rev = getattr(ie, 'revision', None)
328
318
            if new_rev is None:
329
319
                continue
330
 
            old_rev = old_tree.get_file_revision(file_id)
 
320
            old_rev = getattr(old_tree.inventory[ie.file_id], 'revision', None)
331
321
            if new_rev != old_rev:
332
 
                action = Action('modified', [new_tree.kind(file_id),
333
 
                                             new_tree.id2path(file_id)])
334
 
                action.add_utf8_property('last-changed', new_rev)
 
322
                action = Action('modified', [ie.kind, 
 
323
                                             new_tree.id2path(ie.file_id)])
 
324
                action.add_utf8_property('last-changed', ie.revision)
335
325
                action.write(self.to_file)
336
326
 
337
327
 
347
337
        object.__init__(self)
348
338
        self.from_file = iter(from_file)
349
339
        self._next_line = None
350
 
 
 
340
        
351
341
        self.info = self._get_info()
352
342
        # We put the actual inventory ids in the footer, so that the patch
353
343
        # is easier to read for humans.
458
448
        else:
459
449
            # What do we do with a key we don't recognize
460
450
            raise errors.MalformedHeader('Unknown Key: "%s"' % key)
461
 
 
 
451
    
462
452
    def _read_many(self, indent):
463
453
        """If a line ends with no entry, that means that it should be
464
454
        followed with multiple lines of values.
501
491
            elif line.startswith('... '):
502
492
                action += line[len('... '):-1].decode('utf-8')
503
493
 
504
 
            if (self._next_line is not None and
 
494
            if (self._next_line is not None and 
505
495
                self._next_line.startswith('===')):
506
496
                return action, lines, True
507
497
            elif self._next_line is None or self._next_line.startswith('#'):
513
503
                lines.append(line)
514
504
 
515
505
        return action, lines, False
516
 
 
 
506
            
517
507
    def _read_patches(self):
518
508
        do_continue = True
519
509
        revision_actions = []
521
511
            action, lines, do_continue = self._read_one_patch()
522
512
            if action is not None:
523
513
                revision_actions.append((action, lines))
524
 
        if self.info.revisions[-1].tree_actions is not None:
525
 
            raise AssertionError()
 
514
        assert self.info.revisions[-1].tree_actions is None
526
515
        self.info.revisions[-1].tree_actions = revision_actions
527
516
 
528
517
    def _read_footer(self):
540
529
                self._next().next()
541
530
                break
542
531
 
 
532
 
543
533
class BundleInfo08(BundleInfo):
544
534
 
545
535
    def _update_tree(self, bundle_tree, revision_id):
550
540
        testament = StrictTestament.from_revision(repository, revision_id)
551
541
        return testament.as_sha1()
552
542
 
553
 
    def _testament_sha1(self, revision, tree):
554
 
        return StrictTestament(revision, tree).as_sha1()
 
543
    def _testament_sha1(self, revision, inventory):
 
544
        return StrictTestament(revision, inventory).as_sha1()