63
63
Use brz resolve when you have fixed a problem.
68
help='List paths of files with text conflicts.'),
68
help='List paths of files with text conflicts.'),
70
70
_see_also = ['resolve', 'conflict-types']
86
86
resolve_action_registry.register(
87
'auto', 'auto', 'Detect whether conflict has been resolved by user.')
88
resolve_action_registry.register(
89
87
'done', 'done', 'Marks the conflict as resolved.')
90
88
resolve_action_registry.register(
91
89
'take-this', 'take_this',
120
117
aliases = ['resolved']
121
118
takes_args = ['file*']
122
119
takes_options = [
124
option.Option('all', help='Resolve all conflicts in this tree.'),
125
ResolveActionOption(),
121
option.Option('all', help='Resolve all conflicts in this tree.'),
122
ResolveActionOption(),
127
124
_see_also = ['conflicts']
129
125
def run(self, file_list=None, all=False, action=None, directory=None):
132
128
raise errors.BzrCommandError(gettext("If --all is specified,"
133
" no FILE may be provided"))
129
" no FILE may be provided"))
134
130
if directory is None:
136
132
tree = workingtree.WorkingTree.open_containing(directory)[0]
140
136
tree, file_list = workingtree.WorkingTree.open_containing_paths(
141
137
file_list, directory)
143
if file_list is None:
138
if file_list is None:
140
# FIXME: There is a special case here related to the option
141
# handling that could be clearer and easier to discover by
142
# providing an --auto action (bug #344013 and #383396) and
143
# make it mandatory instead of implicit and active only
144
# when no file_list is provided -- vila 091229
147
before, after = resolve(tree, file_list, action=action)
148
# GZ 2012-07-27: Should unify UI below now that auto is less magical.
149
if action == 'auto' and file_list is None:
152
ngettext('%d conflict auto-resolved.',
153
'%d conflicts auto-resolved.', before - after),
155
trace.note(gettext('Remaining conflicts:'))
156
for conflict in tree.conflicts():
157
trace.note(text_type(conflict))
150
if file_list is None:
151
un_resolved, resolved = tree.auto_resolve()
152
if len(un_resolved) > 0:
153
trace.note(ngettext('%d conflict auto-resolved.',
154
'%d conflicts auto-resolved.', len(resolved)),
156
trace.note(gettext('Remaining conflicts:'))
157
for conflict in un_resolved:
158
trace.note(text_type(conflict))
161
trace.note(gettext('All conflicts resolved.'))
160
trace.note(gettext('All conflicts resolved.'))
164
# FIXME: This can never occur but the block above needs some
165
# refactoring to transfer tree.auto_resolve() to
166
# conflict.auto(tree) --vila 091242
169
before, after = resolve(tree, file_list, action=action)
163
170
trace.note(ngettext('{0} conflict resolved, {1} remaining',
164
171
'{0} conflicts resolved, {1} remaining',
165
before - after).format(before - after, after))
172
before-after).format(before - after, after))
168
175
def resolve(tree, paths=None, ignore_misses=False, recursive=False,
379
386
def __cmp__(self, other):
380
387
if getattr(other, "_cmp_list", None) is None:
383
y = other._cmp_list()
384
return (x > y) - (x < y)
389
return cmp(self._cmp_list(), other._cmp_list())
386
391
def __hash__(self):
387
392
return hash((type(self), self.path, self.file_id))
444
443
if e.errno != errno.ENOENT:
447
def action_auto(self, tree):
448
raise NotImplementedError(self.action_auto)
450
446
def action_done(self, tree):
451
447
"""Mark the conflict as solved once it has been handled."""
452
448
# This method does nothing but simplifies the design of upper levels.
459
455
raise NotImplementedError(self.action_take_other)
461
457
def _resolve_with_cleanups(self, tree, *args, **kwargs):
462
with tree.get_transform() as tt:
463
self._resolve(tt, *args, **kwargs)
458
tt = transform.TreeTransform(tree)
459
op = cleanup.OperationWithCleanups(self._resolve)
460
op.add_cleanup(tt.finalize)
461
op.run_simple(tt, *args, **kwargs)
466
464
class PathConflict(Conflict):
517
515
tid = tt.trans_id_tree_path(path_to_create)
518
516
tree = self._revision_tree(tt._tree, revid)
519
517
transform.create_from_tree(
520
tt, tid, tree, tree.id2path(file_id))
518
tt, tid, tree, tree.id2path(file_id), file_id=file_id)
521
519
tt.version_file(file_id, tid)
523
521
tid = tt.trans_id_file_id(file_id)
612
610
# deleted the file either manually or when resolving a conflict on
613
611
# the parent. We may raise some exception to indicate that the
614
612
# conflict doesn't exist anymore and as such doesn't need to be
615
# resolved ? -- vila 20110615
613
# resolved ? -- vila 20110615
618
616
this_tid = tt.trans_id_tree_path(this_path)
668
664
# Switch the paths to preserve the content
669
665
tt.adjust_path(osutils.basename(self.path),
670
666
winner_parent_tid, winner_tid)
671
tt.adjust_path(osutils.basename(winner_path),
672
item_parent_tid, item_tid)
667
tt.adjust_path(osutils.basename(winner_path), item_parent_tid, item_tid)
673
668
# Associate the file_id to the right content
674
669
tt.unversion_file(item_tid)
675
670
tt.version_file(self.file_id, winner_tid)
678
def action_auto(self, tree):
679
# GZ 2012-07-27: Using NotImplementedError to signal that a conflict
680
# can't be auto resolved does not seem ideal.
682
kind = tree.kind(self.path)
683
except errors.NoSuchFile:
686
raise NotImplementedError("Conflict is not a file")
687
conflict_markers_in_line = self._conflict_re.search
688
# GZ 2012-07-27: What if not tree.has_id(self.file_id) due to removal?
689
with tree.get_file(self.path) as f:
691
if conflict_markers_in_line(line):
692
raise NotImplementedError("Conflict markers present")
694
673
def action_take_this(self, tree):
695
674
self._resolve_with_cleanups(tree, 'THIS')
798
777
def action_take_other(self, tree):
799
with tree.get_transform() as tt:
778
tt = transform.TreeTransform(tree)
800
780
p_tid = tt.trans_id_file_id(self.file_id)
801
781
parent_tid = tt.get_tree_parent(p_tid)
802
782
cp_tid = tt.trans_id_file_id(self.conflict_file_id)
909
891
for conflict_type in conflict_types:
910
892
ctype[conflict_type.typestring] = conflict_type
913
894
register_types(ContentsConflict, TextConflict, PathConflict, DuplicateID,
914
895
DuplicateEntry, ParentLoop, UnversionedParent, MissingParent,
915
896
DeletingParent, NonDirectoryParent)