~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge.py

  • Committer: Martin Pool
  • Date: 2008-01-16 00:26:25 UTC
  • mto: This revision was merged to the branch mainline in revision 3190.
  • Revision ID: mbp@sourcefrog.net-20080116002625-c1hbpaxotm5be1rj
Improved and reformatted developer documentation on the Bazaar release process.

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
from bzrlib.revision import (NULL_REVISION, ensure_null)
49
49
from bzrlib.textfile import check_text_lines
50
50
from bzrlib.trace import mutter, warning, note
51
 
from bzrlib.transform import (TransformPreview, TreeTransform,
52
 
                              resolve_conflicts, cook_conflicts,
 
51
from bzrlib.transform import (TreeTransform, resolve_conflicts, cook_conflicts,
53
52
                              conflict_pass, FinalPaths, create_by_entry,
54
53
                              unique_add, ROOT_PARENT)
55
54
from bzrlib.versionedfile import PlanWeaveMerge
377
376
                    base_branch.get_rev_id(base_revision[1]))
378
377
            self._maybe_fetch(base_branch, self.this_branch, self.base_rev_id)
379
378
 
380
 
    def make_merger(self):
 
379
    def do_merge(self):
381
380
        kwargs = {'working_tree':self.this_tree, 'this_tree': self.this_tree,
382
381
                  'other_tree': self.other_tree,
383
382
                  'interesting_ids': self.interesting_ids,
384
383
                  'interesting_files': self.interesting_files,
385
 
                  'pp': self.pp,
386
 
                  'do_merge': False}
 
384
                  'pp': self.pp}
387
385
        if self.merge_type.requires_base:
388
386
            kwargs['base_tree'] = self.base_tree
389
387
        if self.merge_type.supports_reprocess:
395
393
            kwargs['show_base'] = self.show_base
396
394
        elif self.show_base:
397
395
            raise BzrError("Showing base is not supported for this"
398
 
                           " merge type. %s" % self.merge_type)
 
396
                                  " merge type. %s" % self.merge_type)
399
397
        if (not getattr(self.merge_type, 'supports_reverse_cherrypick', True)
400
398
            and not self.base_is_other_ancestor):
401
399
            raise errors.CannotReverseCherrypick()
402
400
        if self.merge_type.history_based:
403
401
            kwargs['cherrypick'] = (not self.base_is_ancestor or
404
402
                                    not self.base_is_other_ancestor)
405
 
        return self.merge_type(pb=self._pb,
406
 
                               change_reporter=self.change_reporter,
407
 
                               **kwargs)
408
 
 
409
 
    def do_merge(self):
410
 
        merge = self.make_merger()
411
403
        self.this_tree.lock_tree_write()
412
404
        if self.base_tree is not None:
413
405
            self.base_tree.lock_read()
414
406
        if self.other_tree is not None:
415
407
            self.other_tree.lock_read()
416
408
        try:
417
 
            merge.do_merge()
 
409
            merge = self.merge_type(pb=self._pb,
 
410
                                    change_reporter=self.change_reporter,
 
411
                                    **kwargs)
418
412
            if self.recurse == 'down':
419
413
                for path, file_id in self.this_tree.iter_references():
420
414
                    sub_tree = self.this_tree.get_nested_tree(file_id, path)
459
453
    def __init__(self, working_tree, this_tree, base_tree, other_tree, 
460
454
                 interesting_ids=None, reprocess=False, show_base=False,
461
455
                 pb=DummyProgress(), pp=None, change_reporter=None,
462
 
                 interesting_files=None, do_merge=True):
 
456
                 interesting_files=None):
463
457
        """Initialize the merger object and perform the merge.
464
458
 
465
459
        :param working_tree: The working tree to apply the merge to
488
482
        self.interesting_ids = interesting_ids
489
483
        self.interesting_files = interesting_files
490
484
        self.this_tree = working_tree
 
485
        self.this_tree.lock_tree_write()
491
486
        self.base_tree = base_tree
 
487
        self.base_tree.lock_read()
492
488
        self.other_tree = other_tree
 
489
        self.other_tree.lock_read()
493
490
        self._raw_conflicts = []
494
491
        self.cooked_conflicts = []
495
492
        self.reprocess = reprocess
499
496
        self.change_reporter = change_reporter
500
497
        if self.pp is None:
501
498
            self.pp = ProgressPhase("Merge phase", 3, self.pb)
502
 
        if do_merge:
503
 
            self.do_merge()
504
499
 
505
 
    def do_merge(self):
506
 
        self.this_tree.lock_tree_write()
507
 
        self.base_tree.lock_read()
508
 
        self.other_tree.lock_read()
509
 
        self.tt = TreeTransform(self.this_tree, self.pb)
 
500
        self.tt = TreeTransform(working_tree, self.pb)
510
501
        try:
511
502
            self.pp.next_phase()
512
 
            self._compute_transform()
 
503
            entries = self._entries3()
 
504
            child_pb = ui.ui_factory.nested_progress_bar()
 
505
            try:
 
506
                for num, (file_id, changed, parents3, names3,
 
507
                          executable3) in enumerate(entries):
 
508
                    child_pb.update('Preparing file merge', num, len(entries))
 
509
                    self._merge_names(file_id, parents3, names3)
 
510
                    if changed:
 
511
                        file_status = self.merge_contents(file_id)
 
512
                    else:
 
513
                        file_status = 'unmodified'
 
514
                    self._merge_executable(file_id,
 
515
                        executable3, file_status)
 
516
            finally:
 
517
                child_pb.finished()
 
518
            self.fix_root()
 
519
            self.pp.next_phase()
 
520
            child_pb = ui.ui_factory.nested_progress_bar()
 
521
            try:
 
522
                fs_conflicts = resolve_conflicts(self.tt, child_pb,
 
523
                    lambda t, c: conflict_pass(t, c, self.other_tree))
 
524
            finally:
 
525
                child_pb.finished()
 
526
            if change_reporter is not None:
 
527
                from bzrlib import delta
 
528
                delta.report_changes(self.tt._iter_changes(), change_reporter)
 
529
            self.cook_conflicts(fs_conflicts)
 
530
            for conflict in self.cooked_conflicts:
 
531
                warning(conflict)
513
532
            self.pp.next_phase()
514
533
            results = self.tt.apply(no_conflicts=True)
515
534
            self.write_modified(results)
516
535
            try:
517
 
                self.this_tree.add_conflicts(self.cooked_conflicts)
 
536
                working_tree.add_conflicts(self.cooked_conflicts)
518
537
            except UnsupportedOperation:
519
538
                pass
520
539
        finally:
524
543
            self.this_tree.unlock()
525
544
            self.pb.clear()
526
545
 
527
 
    def make_preview_transform(self):
528
 
        self.base_tree.lock_read()
529
 
        self.other_tree.lock_read()
530
 
        self.tt = TransformPreview(self.this_tree)
531
 
        try:
532
 
            self.pp.next_phase()
533
 
            self._compute_transform()
534
 
            self.pp.next_phase()
535
 
        finally:
536
 
            self.other_tree.unlock()
537
 
            self.base_tree.unlock()
538
 
            self.pb.clear()
539
 
        return self.tt
540
 
 
541
 
    def _compute_transform(self):
542
 
        entries = self._entries3()
543
 
        child_pb = ui.ui_factory.nested_progress_bar()
544
 
        try:
545
 
            for num, (file_id, changed, parents3, names3,
546
 
                      executable3) in enumerate(entries):
547
 
                child_pb.update('Preparing file merge', num, len(entries))
548
 
                self._merge_names(file_id, parents3, names3)
549
 
                if changed:
550
 
                    file_status = self.merge_contents(file_id)
551
 
                else:
552
 
                    file_status = 'unmodified'
553
 
                self._merge_executable(file_id,
554
 
                    executable3, file_status)
555
 
        finally:
556
 
            child_pb.finished()
557
 
        self.fix_root()
558
 
        self.pp.next_phase()
559
 
        child_pb = ui.ui_factory.nested_progress_bar()
560
 
        try:
561
 
            fs_conflicts = resolve_conflicts(self.tt, child_pb,
562
 
                lambda t, c: conflict_pass(t, c, self.other_tree))
563
 
        finally:
564
 
            child_pb.finished()
565
 
        if self.change_reporter is not None:
566
 
            from bzrlib import delta
567
 
            delta.report_changes(
568
 
                self.tt._iter_changes(), self.change_reporter)
569
 
        self.cook_conflicts(fs_conflicts)
570
 
        for conflict in self.cooked_conflicts:
571
 
            warning(conflict)
572
 
 
573
546
    def _entries3(self):
574
547
        """Gather data about files modified between three trees.
575
548
 
1043
1016
    def __init__(self, working_tree, this_tree, base_tree, other_tree, 
1044
1017
                 interesting_ids=None, pb=DummyProgress(), pp=None,
1045
1018
                 reprocess=False, change_reporter=None,
1046
 
                 interesting_files=None, cherrypick=False, do_merge=True):
 
1019
                 interesting_files=None, cherrypick=False):
1047
1020
        self.cherrypick = cherrypick
1048
1021
        super(WeaveMerger, self).__init__(working_tree, this_tree, 
1049
1022
                                          base_tree, other_tree, 
1050
1023
                                          interesting_ids=interesting_ids, 
1051
1024
                                          pb=pb, pp=pp, reprocess=reprocess,
1052
 
                                          change_reporter=change_reporter,
1053
 
                                          do_merge=do_merge)
 
1025
                                          change_reporter=change_reporter)
1054
1026
 
1055
1027
    def _merged_lines(self, file_id):
1056
1028
        """Generate the merged lines.