~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

(jelmer) Support upgrading between the 2a and development-colo formats.
 (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2009 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Serializer factory for reading and writing bundles.
18
18
"""
19
19
 
20
20
import os
21
21
 
22
 
from bzrlib import errors
 
22
from bzrlib import (
 
23
    errors,
 
24
    ui,
 
25
    )
23
26
from bzrlib.bundle.serializer import (BundleSerializer,
24
27
                                      _get_bundle_header,
25
28
                                     )
27
30
from bzrlib.bundle.bundle_data import (RevisionInfo, BundleInfo, BundleTree)
28
31
from bzrlib.diff import internal_diff
29
32
from bzrlib.osutils import pathjoin
30
 
from bzrlib.progress import DummyProgress
31
33
from bzrlib.revision import NULL_REVISION
32
 
import bzrlib.ui
33
34
from bzrlib.testament import StrictTestament
34
35
from bzrlib.timestamp import (
35
36
    format_highres_date,
119
120
        source.lock_read()
120
121
        try:
121
122
            self._write_main_header()
122
 
            pb = DummyProgress()
 
123
            pb = ui.ui_factory.nested_progress_bar()
123
124
            try:
124
125
                self._write_revisions(pb)
125
126
            finally:
126
 
                pass
127
 
                #pb.finished()
 
127
                pb.finished()
128
128
        finally:
129
129
            source.unlock()
130
130
 
146
146
            If this parameter is True, and value is the empty string, we will
147
147
            write an extra space.
148
148
        """
149
 
        assert indent > 0, 'indentation must be greater than 0'
 
149
        if indent < 1:
 
150
            raise ValueError('indentation must be greater than 0')
150
151
        f = self.to_file
151
152
        f.write('#' + (' ' * indent))
152
153
        f.write(key.encode('utf-8'))
182
183
 
183
184
        i_max = len(self.revision_ids)
184
185
        for i, rev_id in enumerate(self.revision_ids):
185
 
            pb.update("Generating revsion data", i, i_max)
 
186
            pb.update("Generating revision data", i, i_max)
186
187
            rev = self.source.get_revision(rev_id)
187
188
            if rev_id == last_rev_id:
188
189
                rev_tree = last_rev_tree
205
206
            else:
206
207
                base_tree = self.source.revision_tree(base_id)
207
208
            force_binary = (i != 0)
208
 
            self._write_revision(rev, rev_tree, base_id, base_tree, 
 
209
            self._write_revision(rev, rev_tree, base_id, base_tree,
209
210
                                 explicit_base, force_binary)
210
211
 
211
212
            last_rev_id = base_id
212
213
            last_rev_tree = base_tree
213
214
 
214
215
    def _testament_sha1(self, revision_id):
215
 
        return StrictTestament.from_revision(self.source, 
 
216
        return StrictTestament.from_revision(self.source,
216
217
                                             revision_id).as_sha1()
217
218
 
218
 
    def _write_revision(self, rev, rev_tree, base_rev, base_tree, 
 
219
    def _write_revision(self, rev, rev_tree, base_rev, base_tree,
219
220
                        explicit_base, force_binary):
220
221
        """Write out the information for a revision."""
221
222
        def w(key, value):
240
241
            for name, value in sorted(rev.properties.items()):
241
242
                self._write(name, value, indent=3,
242
243
                            trailing_space_when_empty=True)
243
 
        
 
244
 
244
245
        # Add an extra blank space at the end
245
246
        self.to_file.write('\n')
246
247
 
253
254
        self.to_file.write(' // '.join(p_texts).encode('utf-8'))
254
255
        self.to_file.write('\n')
255
256
 
256
 
    def _write_delta(self, new_tree, old_tree, default_revision_id, 
 
257
    def _write_delta(self, new_tree, old_tree, default_revision_id,
257
258
                     force_binary):
258
259
        """Write out the changes between the trees."""
259
260
        DEVNULL = '/dev/null'
262
263
 
263
264
        def do_diff(file_id, old_path, new_path, action, force_binary):
264
265
            def tree_lines(tree, require_text=False):
265
 
                if file_id in tree:
 
266
                if tree.has_id(file_id):
266
267
                    tree_file = tree.get_file(file_id)
267
268
                    if require_text is True:
268
269
                        tree_file = text_file(tree_file)
276
277
                old_lines = tree_lines(old_tree, require_text=True)
277
278
                new_lines = tree_lines(new_tree, require_text=True)
278
279
                action.write(self.to_file)
279
 
                internal_diff(old_path, old_lines, new_path, new_lines, 
 
280
                internal_diff(old_path, old_lines, new_path, new_lines,
280
281
                              self.to_file)
281
282
            except errors.BinaryFile:
282
283
                old_lines = tree_lines(old_tree, require_text=False)
283
284
                new_lines = tree_lines(new_tree, require_text=False)
284
285
                action.add_property('encoding', 'base64')
285
286
                action.write(self.to_file)
286
 
                binary_diff(old_path, old_lines, new_path, new_lines, 
 
287
                binary_diff(old_path, old_lines, new_path, new_lines,
287
288
                            self.to_file)
288
289
 
289
290
        def finish_action(action, file_id, kind, meta_modified, text_modified,
307
308
 
308
309
        for path, file_id, kind in delta.added:
309
310
            action = Action('added', [kind, path], [('file-id', file_id)])
310
 
            meta_modified = (kind=='file' and 
 
311
            meta_modified = (kind=='file' and
311
312
                             new_tree.is_executable(file_id))
312
313
            finish_action(action, file_id, kind, meta_modified, True,
313
314
                          DEVNULL, path)
331
332
                continue
332
333
            old_rev = getattr(old_tree.inventory[ie.file_id], 'revision', None)
333
334
            if new_rev != old_rev:
334
 
                action = Action('modified', [ie.kind, 
 
335
                action = Action('modified', [ie.kind,
335
336
                                             new_tree.id2path(ie.file_id)])
336
337
                action.add_utf8_property('last-changed', ie.revision)
337
338
                action.write(self.to_file)
349
350
        object.__init__(self)
350
351
        self.from_file = iter(from_file)
351
352
        self._next_line = None
352
 
        
 
353
 
353
354
        self.info = self._get_info()
354
355
        # We put the actual inventory ids in the footer, so that the patch
355
356
        # is easier to read for humans.
460
461
        else:
461
462
            # What do we do with a key we don't recognize
462
463
            raise errors.MalformedHeader('Unknown Key: "%s"' % key)
463
 
    
 
464
 
464
465
    def _read_many(self, indent):
465
466
        """If a line ends with no entry, that means that it should be
466
467
        followed with multiple lines of values.
503
504
            elif line.startswith('... '):
504
505
                action += line[len('... '):-1].decode('utf-8')
505
506
 
506
 
            if (self._next_line is not None and 
 
507
            if (self._next_line is not None and
507
508
                self._next_line.startswith('===')):
508
509
                return action, lines, True
509
510
            elif self._next_line is None or self._next_line.startswith('#'):
515
516
                lines.append(line)
516
517
 
517
518
        return action, lines, False
518
 
            
 
519
 
519
520
    def _read_patches(self):
520
521
        do_continue = True
521
522
        revision_actions = []
523
524
            action, lines, do_continue = self._read_one_patch()
524
525
            if action is not None:
525
526
                revision_actions.append((action, lines))
526
 
        assert self.info.revisions[-1].tree_actions is None
 
527
        if self.info.revisions[-1].tree_actions is not None:
 
528
            raise AssertionError()
527
529
        self.info.revisions[-1].tree_actions = revision_actions
528
530
 
529
531
    def _read_footer(self):
551
553
        testament = StrictTestament.from_revision(repository, revision_id)
552
554
        return testament.as_sha1()
553
555
 
554
 
    def _testament_sha1(self, revision, inventory):
555
 
        return StrictTestament(revision, inventory).as_sha1()
 
556
    def _testament_sha1(self, revision, tree):
 
557
        return StrictTestament(revision, tree).as_sha1()