1
# Copyright (C) 2005 Aaron Bentley, Canonical Ltd
1
# Copyright (C) 2005, 2007 Canonical Ltd
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
55
57
See also bzr resolve.
57
takes_options = [Option('text', help='list text conflicts by pathname')]
61
help='List paths of files with text conflicts.'),
59
64
def run(self, text=False):
60
65
from bzrlib.workingtree import WorkingTree
76
81
it will mark a conflict. A conflict means that you need to fix something,
77
82
before you should commit.
79
Once you have fixed a problem, use "bzr resolve FILE.." to mark
80
individual files as fixed, or "bzr resolve --all" to mark all conflicts as
84
Once you have fixed a problem, use "bzr resolve" to automatically mark
85
text conflicts as fixed, resolve FILE to mark a specific conflict as
86
resolved, or "bzr resolve --all" to mark all conflicts as resolved.
83
88
See also bzr conflicts.
85
90
aliases = ['resolved']
86
91
takes_args = ['file*']
87
takes_options = [Option('all', help='Resolve all conflicts in this tree')]
93
Option('all', help='Resolve all conflicts in this tree.'),
88
95
def run(self, file_list=None, all=False):
89
96
from bzrlib.workingtree import WorkingTree
94
101
tree = WorkingTree.open_containing('.')[0]
104
tree, file_list = builtins.tree_files(file_list)
97
105
if file_list is None:
98
raise errors.BzrCommandError("command 'resolve' needs one or"
99
" more FILE, or --all")
100
tree = WorkingTree.open_containing(file_list[0])[0]
101
to_resolve = [tree.relpath(p) for p in file_list]
102
resolve(tree, to_resolve)
105
def resolve(tree, paths=None, ignore_misses=False):
106
un_resolved, resolved = tree.auto_resolve()
107
if len(un_resolved) > 0:
108
trace.note('%d conflict(s) auto-resolved.', len(resolved))
109
trace.note('Remaining conflicts:')
110
for conflict in un_resolved:
114
trace.note('All conflicts resolved.')
117
resolve(tree, file_list)
120
def resolve(tree, paths=None, ignore_misses=False, recursive=False):
121
"""Resolve some or all of the conflicts in a working tree.
123
:param paths: If None, resolve all conflicts. Otherwise, select only
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.
106
133
tree.lock_tree_write()
108
135
tree_conflicts = tree.conflicts()
111
138
selected_conflicts = tree_conflicts
113
140
new_conflicts, selected_conflicts = \
114
tree_conflicts.select_conflicts(tree, paths, ignore_misses)
141
tree_conflicts.select_conflicts(tree, paths, ignore_misses,
116
144
tree.set_conflicts(new_conflicts)
117
145
except errors.UnsupportedOperation:
218
246
if e.errno != errno.ENOENT:
221
def select_conflicts(self, tree, paths, ignore_misses=False):
249
def select_conflicts(self, tree, paths, ignore_misses=False,
222
251
"""Select the conflicts associated with paths in a tree.
224
253
File-ids are also used for this.
243
272
if cpath in path_set:
245
274
selected_paths.add(cpath)
276
if osutils.is_inside_any(path_set, cpath):
278
selected_paths.add(cpath)
246
280
for key in ('file_id', 'conflict_file_id'):
247
281
cfile_id = getattr(conflict, key, None)
248
282
if cfile_id is None:
274
308
def __init__(self, path, file_id=None):
276
self.file_id = file_id
310
# warn turned off, because the factory blindly transfers the Stanza
311
# values to __init__ and Stanza is purely a Unicode api.
312
self.file_id = osutils.safe_file_id(file_id, warn=False)
278
314
def as_stanza(self):
279
315
s = rio.Stanza(type=self.typestring, path=self.path)
280
316
if self.file_id is not None:
281
s.add('file_id', self.file_id)
317
# Stanza requires Unicode apis
318
s.add('file_id', self.file_id.decode('utf8'))
284
321
def _cmp_list(self):
392
429
conflict_file_id=None):
393
430
HandledConflict.__init__(self, action, path, file_id)
394
431
self.conflict_path = conflict_path
395
self.conflict_file_id = conflict_file_id
432
# warn turned off, because the factory blindly transfers the Stanza
433
# values to __init__.
434
self.conflict_file_id = osutils.safe_file_id(conflict_file_id,
397
437
def _cmp_list(self):
398
438
return HandledConflict._cmp_list(self) + [self.conflict_path,
402
442
s = HandledConflict.as_stanza(self)
403
443
s.add('conflict_path', self.conflict_path)
404
444
if self.conflict_file_id is not None:
405
s.add('conflict_file_id', self.conflict_file_id)
445
s.add('conflict_file_id', self.conflict_file_id.decode('utf8'))
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.
523
typestring = 'non-directory parent'
525
format = "Conflict: %(path)s is not a directory, but has files in it."\
488
538
register_types(ContentsConflict, TextConflict, PathConflict, DuplicateID,
489
539
DuplicateEntry, ParentLoop, UnversionedParent, MissingParent,
540
DeletingParent, NonDirectoryParent)