/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/conflicts.py

  • Committer: Martin Pool
  • Date: 2011-05-20 14:46:02 UTC
  • mto: This revision was merged to the branch mainline in revision 5923.
  • Revision ID: mbp@canonical.com-20110520144602-bqli0t6dj01gl0pv
Various pyflakes import fixes.

Some modules were used for subclassing or at module load time, so there is no
point loading them lazily.

Some were not imported when they should be.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2009, 2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011 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
24
24
import errno
25
25
 
26
26
from bzrlib import (
27
 
    builtins,
28
27
    cleanup,
29
 
    commands,
30
28
    errors,
31
29
    osutils,
32
30
    rio,
36
34
    )
37
35
""")
38
36
from bzrlib import (
 
37
    commands,
39
38
    option,
40
39
    registry,
41
40
    )
59
58
    Use bzr resolve when you have fixed a problem.
60
59
    """
61
60
    takes_options = [
 
61
            'directory',
62
62
            option.Option('text',
63
63
                          help='List paths of files with text conflicts.'),
64
64
        ]
65
65
    _see_also = ['resolve', 'conflict-types']
66
66
 
67
 
    def run(self, text=False):
68
 
        wt = workingtree.WorkingTree.open_containing(u'.')[0]
 
67
    def run(self, text=False, directory=u'.'):
 
68
        wt = workingtree.WorkingTree.open_containing(directory)[0]
69
69
        for conflict in wt.conflicts():
70
70
            if text:
71
71
                if conflict.typestring != 'text conflict':
112
112
    aliases = ['resolved']
113
113
    takes_args = ['file*']
114
114
    takes_options = [
 
115
            'directory',
115
116
            option.Option('all', help='Resolve all conflicts in this tree.'),
116
117
            ResolveActionOption(),
117
118
            ]
118
119
    _see_also = ['conflicts']
119
 
    def run(self, file_list=None, all=False, action=None):
 
120
    def run(self, file_list=None, all=False, action=None, directory=None):
120
121
        if all:
121
122
            if file_list:
122
123
                raise errors.BzrCommandError("If --all is specified,"
123
124
                                             " no FILE may be provided")
124
 
            tree = workingtree.WorkingTree.open_containing('.')[0]
 
125
            if directory is None:
 
126
                directory = u'.'
 
127
            tree = workingtree.WorkingTree.open_containing(directory)[0]
125
128
            if action is None:
126
129
                action = 'done'
127
130
        else:
128
 
            tree, file_list = builtins.tree_files(file_list)
 
131
            tree, file_list = workingtree.WorkingTree.open_containing_paths(
 
132
                file_list, directory)
129
133
            if file_list is None:
130
134
                if action is None:
131
135
                    # FIXME: There is a special case here related to the option
155
159
                # conflict.auto(tree) --vila 091242
156
160
                pass
157
161
        else:
158
 
            resolve(tree, file_list, action=action)
 
162
            before, after = resolve(tree, file_list, action=action)
 
163
            trace.note('%d conflict(s) resolved, %d remaining'
 
164
                       % (before - after, after))
159
165
 
160
166
 
161
167
def resolve(tree, paths=None, ignore_misses=False, recursive=False,
174
180
    :param action: How the conflict should be resolved,
175
181
    """
176
182
    tree.lock_tree_write()
 
183
    nb_conflicts_after = None
177
184
    try:
178
185
        tree_conflicts = tree.conflicts()
 
186
        nb_conflicts_before = len(tree_conflicts)
179
187
        if paths is None:
180
188
            new_conflicts = ConflictList()
181
189
            to_process = tree_conflicts
189
197
            except NotImplementedError:
190
198
                new_conflicts.append(conflict)
191
199
        try:
 
200
            nb_conflicts_after = len(new_conflicts)
192
201
            tree.set_conflicts(new_conflicts)
193
202
        except errors.UnsupportedOperation:
194
203
            pass
195
204
    finally:
196
205
        tree.unlock()
 
206
    if nb_conflicts_after is None:
 
207
        nb_conflicts_after = nb_conflicts_before
 
208
    return nb_conflicts_before, nb_conflicts_after
197
209
 
198
210
 
199
211
def restore(filename):
502
514
        # Adjust the path for the retained file id
503
515
        tid = tt.trans_id_file_id(file_id)
504
516
        parent_tid = tt.get_tree_parent(tid)
505
 
        tt.adjust_path(path, parent_tid, tid)
 
517
        tt.adjust_path(osutils.basename(path), parent_tid, tid)
506
518
        tt.apply()
507
519
 
508
520
    def _revision_tree(self, tree, revid):
588
600
        # 'item.suffix_to_remove' has been deleted, this is a no-op)
589
601
        this_tid = tt.trans_id_file_id(self.file_id)
590
602
        parent_tid = tt.get_tree_parent(this_tid)
591
 
        tt.adjust_path(self.path, parent_tid, this_tid)
 
603
        tt.adjust_path(osutils.basename(self.path), parent_tid, this_tid)
592
604
        tt.apply()
593
605
 
594
606
    def action_take_this(self, tree):
598
610
        self._resolve_with_cleanups(tree, 'THIS')
599
611
 
600
612
 
601
 
# FIXME: TextConflict is about a single file-id, there never is a conflict_path
602
 
# attribute so we shouldn't inherit from PathConflict but simply from Conflict
603
 
 
604
613
# TODO: There should be a base revid attribute to better inform the user about
605
614
# how the conflicts were generated.
606
 
class TextConflict(PathConflict):
 
615
class TextConflict(Conflict):
607
616
    """The merge algorithm could not resolve all differences encountered."""
608
617
 
609
618
    has_files = True
612
621
 
613
622
    format = 'Text conflict in %(path)s'
614
623
 
 
624
    rformat = '%(class)s(%(path)r, %(file_id)r)'
 
625
 
615
626
    def associated_filenames(self):
616
627
        return [self.path + suffix for suffix in CONFLICT_SUFFIXES]
617
628
 
 
629
    def _resolve(self, tt, winner_suffix):
 
630
        """Resolve the conflict by copying one of .THIS or .OTHER into file.
 
631
 
 
632
        :param tt: The TreeTransform where the conflict is resolved.
 
633
        :param winner_suffix: Either 'THIS' or 'OTHER'
 
634
 
 
635
        The resolution is symmetric, when taking THIS, item.THIS is renamed
 
636
        into item and vice-versa. This takes one of the files as a whole
 
637
        ignoring every difference that could have been merged cleanly.
 
638
        """
 
639
        # To avoid useless copies, we switch item and item.winner_suffix, only
 
640
        # item will exist after the conflict has been resolved anyway.
 
641
        item_tid = tt.trans_id_file_id(self.file_id)
 
642
        item_parent_tid = tt.get_tree_parent(item_tid)
 
643
        winner_path = self.path + '.' + winner_suffix
 
644
        winner_tid = tt.trans_id_tree_path(winner_path)
 
645
        winner_parent_tid = tt.get_tree_parent(winner_tid)
 
646
        # Switch the paths to preserve the content
 
647
        tt.adjust_path(osutils.basename(self.path),
 
648
                       winner_parent_tid, winner_tid)
 
649
        tt.adjust_path(osutils.basename(winner_path), item_parent_tid, item_tid)
 
650
        # Associate the file_id to the right content
 
651
        tt.unversion_file(item_tid)
 
652
        tt.version_file(self.file_id, winner_tid)
 
653
        tt.apply()
 
654
 
 
655
    def action_take_this(self, tree):
 
656
        self._resolve_with_cleanups(tree, 'THIS')
 
657
 
 
658
    def action_take_other(self, tree):
 
659
        self._resolve_with_cleanups(tree, 'OTHER')
 
660
 
618
661
 
619
662
class HandledConflict(Conflict):
620
663
    """A path problem that has been provisionally resolved.
713
756
        pass
714
757
 
715
758
    def action_take_other(self, tree):
716
 
        # FIXME: We shouldn't have to manipulate so many paths here (and there
717
 
        # is probably a bug or two...)
718
 
        base_path = osutils.basename(self.path)
719
 
        conflict_base_path = osutils.basename(self.conflict_path)
720
759
        tt = transform.TreeTransform(tree)
721
760
        try:
722
761
            p_tid = tt.trans_id_file_id(self.file_id)
723
762
            parent_tid = tt.get_tree_parent(p_tid)
724
763
            cp_tid = tt.trans_id_file_id(self.conflict_file_id)
725
764
            cparent_tid = tt.get_tree_parent(cp_tid)
726
 
            tt.adjust_path(base_path, cparent_tid, cp_tid)
727
 
            tt.adjust_path(conflict_base_path, parent_tid, p_tid)
 
765
            tt.adjust_path(osutils.basename(self.path), cparent_tid, cp_tid)
 
766
            tt.adjust_path(osutils.basename(self.conflict_path),
 
767
                           parent_tid, p_tid)
728
768
            tt.apply()
729
769
        finally:
730
770
            tt.finalize()