~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: John Arbash Meinel
  • Date: 2008-07-09 21:42:24 UTC
  • mto: This revision was merged to the branch mainline in revision 3543.
  • Revision ID: john@arbash-meinel.com-20080709214224-r75k87r6a01pfc3h
Restore a real weave merge to 'bzr merge --weave'.

To do so efficiently, we only add the simple LCAs to the final weave
object, unless we run into complexities with the merge graph.
This gives the same effective result as adding all the texts,
with the advantage of not having to extract all of them.

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
24
                                      _get_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
import bzrlib.ui
33
33
from bzrlib.testament import StrictTestament
34
34
from bzrlib.timestamp import (
35
35
    format_highres_date,
36
 
    )
 
36
    unpack_highres_date,
 
37
)
37
38
from bzrlib.textfile import text_file
38
39
from bzrlib.trace import mutter
39
40
 
118
119
        source.lock_read()
119
120
        try:
120
121
            self._write_main_header()
121
 
            pb = ui.ui_factory.nested_progress_bar()
 
122
            pb = DummyProgress()
122
123
            try:
123
124
                self._write_revisions(pb)
124
125
            finally:
125
 
                pb.finished()
 
126
                pass
 
127
                #pb.finished()
126
128
        finally:
127
129
            source.unlock()
128
130
 
181
183
 
182
184
        i_max = len(self.revision_ids)
183
185
        for i, rev_id in enumerate(self.revision_ids):
184
 
            pb.update("Generating revision data", i, i_max)
 
186
            pb.update("Generating revsion data", i, i_max)
185
187
            rev = self.source.get_revision(rev_id)
186
188
            if rev_id == last_rev_id:
187
189
                rev_tree = last_rev_tree
204
206
            else:
205
207
                base_tree = self.source.revision_tree(base_id)
206
208
            force_binary = (i != 0)
207
 
            self._write_revision(rev, rev_tree, base_id, base_tree,
 
209
            self._write_revision(rev, rev_tree, base_id, base_tree, 
208
210
                                 explicit_base, force_binary)
209
211
 
210
212
            last_rev_id = base_id
211
213
            last_rev_tree = base_tree
212
214
 
213
215
    def _testament_sha1(self, revision_id):
214
 
        return StrictTestament.from_revision(self.source,
 
216
        return StrictTestament.from_revision(self.source, 
215
217
                                             revision_id).as_sha1()
216
218
 
217
 
    def _write_revision(self, rev, rev_tree, base_rev, base_tree,
 
219
    def _write_revision(self, rev, rev_tree, base_rev, base_tree, 
218
220
                        explicit_base, force_binary):
219
221
        """Write out the information for a revision."""
220
222
        def w(key, value):
239
241
            for name, value in sorted(rev.properties.items()):
240
242
                self._write(name, value, indent=3,
241
243
                            trailing_space_when_empty=True)
242
 
 
 
244
        
243
245
        # Add an extra blank space at the end
244
246
        self.to_file.write('\n')
245
247
 
252
254
        self.to_file.write(' // '.join(p_texts).encode('utf-8'))
253
255
        self.to_file.write('\n')
254
256
 
255
 
    def _write_delta(self, new_tree, old_tree, default_revision_id,
 
257
    def _write_delta(self, new_tree, old_tree, default_revision_id, 
256
258
                     force_binary):
257
259
        """Write out the changes between the trees."""
258
260
        DEVNULL = '/dev/null'
261
263
 
262
264
        def do_diff(file_id, old_path, new_path, action, force_binary):
263
265
            def tree_lines(tree, require_text=False):
264
 
                if tree.has_id(file_id):
 
266
                if file_id in tree:
265
267
                    tree_file = tree.get_file(file_id)
266
268
                    if require_text is True:
267
269
                        tree_file = text_file(tree_file)
275
277
                old_lines = tree_lines(old_tree, require_text=True)
276
278
                new_lines = tree_lines(new_tree, require_text=True)
277
279
                action.write(self.to_file)
278
 
                internal_diff(old_path, old_lines, new_path, new_lines,
 
280
                internal_diff(old_path, old_lines, new_path, new_lines, 
279
281
                              self.to_file)
280
282
            except errors.BinaryFile:
281
283
                old_lines = tree_lines(old_tree, require_text=False)
282
284
                new_lines = tree_lines(new_tree, require_text=False)
283
285
                action.add_property('encoding', 'base64')
284
286
                action.write(self.to_file)
285
 
                binary_diff(old_path, old_lines, new_path, new_lines,
 
287
                binary_diff(old_path, old_lines, new_path, new_lines, 
286
288
                            self.to_file)
287
289
 
288
290
        def finish_action(action, file_id, kind, meta_modified, text_modified,
289
291
                          old_path, new_path):
290
 
            entry = new_tree.root_inventory[file_id]
 
292
            entry = new_tree.inventory[file_id]
291
293
            if entry.revision != default_revision_id:
292
294
                action.add_utf8_property('last-changed', entry.revision)
293
295
            if meta_modified:
306
308
 
307
309
        for path, file_id, kind in delta.added:
308
310
            action = Action('added', [kind, path], [('file-id', file_id)])
309
 
            meta_modified = (kind=='file' and
 
311
            meta_modified = (kind=='file' and 
310
312
                             new_tree.is_executable(file_id))
311
313
            finish_action(action, file_id, kind, meta_modified, True,
312
314
                          DEVNULL, path)
324
326
                          path, path)
325
327
 
326
328
        for path, file_id, kind in delta.unchanged:
327
 
            new_rev = new_tree.get_file_revision(file_id)
 
329
            ie = new_tree.inventory[file_id]
 
330
            new_rev = getattr(ie, 'revision', None)
328
331
            if new_rev is None:
329
332
                continue
330
 
            old_rev = old_tree.get_file_revision(file_id)
 
333
            old_rev = getattr(old_tree.inventory[ie.file_id], 'revision', None)
331
334
            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)
 
335
                action = Action('modified', [ie.kind, 
 
336
                                             new_tree.id2path(ie.file_id)])
 
337
                action.add_utf8_property('last-changed', ie.revision)
335
338
                action.write(self.to_file)
336
339
 
337
340
 
347
350
        object.__init__(self)
348
351
        self.from_file = iter(from_file)
349
352
        self._next_line = None
350
 
 
 
353
        
351
354
        self.info = self._get_info()
352
355
        # We put the actual inventory ids in the footer, so that the patch
353
356
        # is easier to read for humans.
458
461
        else:
459
462
            # What do we do with a key we don't recognize
460
463
            raise errors.MalformedHeader('Unknown Key: "%s"' % key)
461
 
 
 
464
    
462
465
    def _read_many(self, indent):
463
466
        """If a line ends with no entry, that means that it should be
464
467
        followed with multiple lines of values.
501
504
            elif line.startswith('... '):
502
505
                action += line[len('... '):-1].decode('utf-8')
503
506
 
504
 
            if (self._next_line is not None and
 
507
            if (self._next_line is not None and 
505
508
                self._next_line.startswith('===')):
506
509
                return action, lines, True
507
510
            elif self._next_line is None or self._next_line.startswith('#'):
513
516
                lines.append(line)
514
517
 
515
518
        return action, lines, False
516
 
 
 
519
            
517
520
    def _read_patches(self):
518
521
        do_continue = True
519
522
        revision_actions = []
550
553
        testament = StrictTestament.from_revision(repository, revision_id)
551
554
        return testament.as_sha1()
552
555
 
553
 
    def _testament_sha1(self, revision, tree):
554
 
        return StrictTestament(revision, tree).as_sha1()
 
556
    def _testament_sha1(self, revision, inventory):
 
557
        return StrictTestament(revision, inventory).as_sha1()