~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/conflicts.py

  • Committer: Aaron Bentley
  • Date: 2007-03-07 23:15:10 UTC
  • mto: (1551.19.24 Aaron's mergeable stuff)
  • mto: This revision was merged to the branch mainline in revision 2325.
  • Revision ID: abentley@panoramicfeedback.com-20070307231510-jae63zsli83db3eb
Make ChangeReporter private

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2007 Canonical Ltd
 
1
# Copyright (C) 2005 Aaron Bentley, 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
# TODO: Move this into builtins
18
18
 
19
 
# TODO: 'bzr resolve' should accept a directory name and work from that
 
19
# TODO: 'bzr resolve' should accept a directory name and work from that 
20
20
# point down
21
21
 
22
22
import os
56
56
 
57
57
    See also bzr resolve.
58
58
    """
59
 
    takes_options = [
60
 
            Option('text',
61
 
                   help='List paths of files with text conflicts.'),
62
 
        ]
 
59
    takes_options = [Option('text', help='list text conflicts by pathname')]
63
60
 
64
61
    def run(self, text=False):
65
62
        from bzrlib.workingtree import WorkingTree
89
86
    """
90
87
    aliases = ['resolved']
91
88
    takes_args = ['file*']
92
 
    takes_options = [
93
 
            Option('all', help='Resolve all conflicts in this tree.'),
94
 
            ]
 
89
    takes_options = [Option('all', help='Resolve all conflicts in this tree')]
95
90
    def run(self, file_list=None, all=False):
96
91
        from bzrlib.workingtree import WorkingTree
97
92
        if all:
117
112
                resolve(tree, file_list)
118
113
 
119
114
 
120
 
def resolve(tree, paths=None, ignore_misses=False, recursive=False):
121
 
    """Resolve some or all of the conflicts in a working tree.
122
 
 
123
 
    :param paths: If None, resolve all conflicts.  Otherwise, select only
124
 
        specified conflicts.
125
 
    :param recursive: If True, then elements of paths which are directories
126
 
        have all their children resolved, etc.  When invoked as part of
127
 
        recursive commands like revert, this should be True.  For commands
128
 
        or applications wishing finer-grained control, like the resolve
129
 
        command, this should be False.
130
 
    :ignore_misses: If False, warnings will be printed if the supplied paths
131
 
        do not have conflicts.
132
 
    """
 
115
def resolve(tree, paths=None, ignore_misses=False):
133
116
    tree.lock_tree_write()
134
117
    try:
135
118
        tree_conflicts = tree.conflicts()
138
121
            selected_conflicts = tree_conflicts
139
122
        else:
140
123
            new_conflicts, selected_conflicts = \
141
 
                tree_conflicts.select_conflicts(tree, paths, ignore_misses,
142
 
                    recursive)
 
124
                tree_conflicts.select_conflicts(tree, paths, ignore_misses)
143
125
        try:
144
126
            tree.set_conflicts(new_conflicts)
145
127
        except errors.UnsupportedOperation:
228
210
        """Generator of stanzas"""
229
211
        for conflict in self:
230
212
            yield conflict.as_stanza()
231
 
 
 
213
            
232
214
    def to_strings(self):
233
215
        """Generate strings for the provided conflicts"""
234
216
        for conflict in self:
246
228
                    if e.errno != errno.ENOENT:
247
229
                        raise
248
230
 
249
 
    def select_conflicts(self, tree, paths, ignore_misses=False,
250
 
                         recurse=False):
 
231
    def select_conflicts(self, tree, paths, ignore_misses=False):
251
232
        """Select the conflicts associated with paths in a tree.
252
 
 
 
233
        
253
234
        File-ids are also used for this.
254
235
        :return: a pair of ConflictLists: (not_selected, selected)
255
236
        """
272
253
                if cpath in path_set:
273
254
                    selected = True
274
255
                    selected_paths.add(cpath)
275
 
                if recurse:
276
 
                    if osutils.is_inside_any(path_set, cpath):
277
 
                        selected = True
278
 
                        selected_paths.add(cpath)
279
 
 
280
256
            for key in ('file_id', 'conflict_file_id'):
281
257
                cfile_id = getattr(conflict, key, None)
282
258
                if cfile_id is None:
299
275
                    print "%s is not conflicted" % path
300
276
        return new_conflicts, selected_conflicts
301
277
 
302
 
 
 
278
 
303
279
class Conflict(object):
304
280
    """Base class for all types of conflict"""
305
281
 
403
379
    """
404
380
 
405
381
    rformat = "%(class)s(%(action)r, %(path)r, %(file_id)r)"
406
 
 
 
382
    
407
383
    def __init__(self, action, path, file_id=None):
408
384
        Conflict.__init__(self, path, file_id)
409
385
        self.action = action
428
404
    def __init__(self, action, path, conflict_path, file_id=None,
429
405
                 conflict_file_id=None):
430
406
        HandledConflict.__init__(self, action, path, file_id)
431
 
        self.conflict_path = conflict_path
 
407
        self.conflict_path = conflict_path 
432
408
        # warn turned off, because the factory blindly transfers the Stanza
433
409
        # values to __init__.
434
410
        self.conflict_file_id = osutils.safe_file_id(conflict_file_id,
435
411
                                                     warn=False)
436
 
 
 
412
        
437
413
    def _cmp_list(self):
438
 
        return HandledConflict._cmp_list(self) + [self.conflict_path,
 
414
        return HandledConflict._cmp_list(self) + [self.conflict_path, 
439
415
                                                  self.conflict_file_id]
440
416
 
441
417
    def as_stanza(self):
443
419
        s.add('conflict_path', self.conflict_path)
444
420
        if self.conflict_file_id is not None:
445
421
            s.add('conflict_file_id', self.conflict_file_id.decode('utf8'))
446
 
 
 
422
            
447
423
        return s
448
424
 
449
425
 
515
491
             "%(action)s."
516
492
 
517
493
 
518
 
class NonDirectoryParent(HandledConflict):
519
 
    """An attempt to add files to a directory that is not a director or
520
 
    an attempt to change the kind of a directory with files.
521
 
    """
522
 
 
523
 
    typestring = 'non-directory parent'
524
 
 
525
 
    format = "Conflict: %(path)s is not a directory, but has files in it."\
526
 
             "  %(action)s."
527
 
 
528
494
ctype = {}
529
495
 
530
496
 
537
503
 
538
504
register_types(ContentsConflict, TextConflict, PathConflict, DuplicateID,
539
505
               DuplicateEntry, ParentLoop, UnversionedParent, MissingParent,
540
 
               DeletingParent, NonDirectoryParent)
 
506
               DeletingParent,)