20
from tempfile import mkdtemp
23
25
from bzrlib.branch import Branch
24
26
from bzrlib.conflicts import ConflictList, Conflict
25
27
from bzrlib.errors import (BzrCommandError,
38
40
from bzrlib.merge3 import Merge3
40
from bzrlib.osutils import rename, pathjoin, rmtree
41
from bzrlib.osutils import rename, pathjoin
41
42
from progress import DummyProgress, ProgressPhase
42
43
from bzrlib.revision import common_ancestor, is_ancestor, NULL_REVISION
43
44
from bzrlib.textfile import check_text_lines
44
45
from bzrlib.trace import mutter, warning, note
45
46
from bzrlib.transform import (TreeTransform, resolve_conflicts, cook_conflicts,
46
FinalPaths, create_by_entry, unique_add)
47
FinalPaths, create_by_entry, unique_add,
47
49
from bzrlib.versionedfile import WeaveMerge
48
50
from bzrlib import ui
50
52
# TODO: Report back as changes are merged in
52
54
def _get_tree(treespec, local_branch=None):
55
from bzrlib import workingtree
53
56
location, revno = treespec
58
tree = workingtree.WorkingTree.open_containing(location)[0]
59
return tree.branch, tree
54
60
branch = Branch.open_containing(location)[0]
58
62
revision = branch.last_revision()
60
64
revision = branch.get_rev_id(revno)
138
142
def check_basis(self, check_clean, require_commits=True):
139
143
if self.this_basis is None and require_commits is True:
140
raise BzrCommandError("This branch has no commits")
144
raise BzrCommandError("This branch has no commits."
145
" (perhaps you would prefer 'bzr pull')")
142
147
self.compare_basis()
143
148
if self.this_basis != self.this_rev_id:
181
186
ancestry = self.this_branch.repository.get_ancestry(self.this_basis)
182
187
if self.other_rev_id in ancestry:
184
self.this_tree.add_pending_merge(self.other_rev_id)
189
self.this_tree.add_parent_tree((self.other_rev_id, self.other_tree))
186
191
def set_other(self, other_revision):
187
other_branch, self.other_tree = _get_tree(other_revision,
192
"""Set the revision and tree to merge from.
194
This sets the other_tree, other_rev_id, other_basis attributes.
196
:param other_revision: The [path, revision] list to merge from.
198
other_branch, self.other_tree = _get_tree(other_revision,
188
199
self.this_branch)
189
200
if other_revision[1] == -1:
190
201
self.other_rev_id = other_branch.last_revision()
206
217
self.set_base([None, None])
208
219
def set_base(self, base_revision):
220
"""Set the base revision to use for the merge.
222
:param base_revision: A 2-list containing a path and revision number.
209
224
mutter("doing merge() with no base_revision specified")
210
225
if base_revision == [None, None]:
212
pb = bzrlib.ui.ui_factory.nested_progress_bar()
227
pb = ui.ui_factory.nested_progress_bar()
214
229
this_repo = self.this_branch.repository
215
230
self.base_rev_id = common_ancestor(self.this_basis,
313
328
parent = by_path[os.path.dirname(path)]
314
329
abspath = pathjoin(self.this_tree.basedir, path)
315
kind = bzrlib.osutils.file_kind(abspath)
330
kind = osutils.file_kind(abspath)
316
331
if file_id in self.base_tree.inventory:
317
332
executable = getattr(self.base_tree.inventory[file_id], 'executable', False)
362
377
all_ids = set(base_tree)
363
378
all_ids.update(other_tree)
364
working_tree.lock_write()
379
working_tree.lock_tree_write()
365
380
self.tt = TreeTransform(working_tree, self.pb)
367
382
self.pp.next_phase()
396
411
working_tree.unlock()
416
self.tt.final_kind(self.tt.root)
418
self.tt.cancel_deletion(self.tt.root)
419
if self.tt.final_file_id(self.tt.root) is None:
420
self.tt.version_file(self.tt.tree_file_id(self.tt.root),
422
if self.other_tree.inventory.root is None:
424
other_root_file_id = self.other_tree.inventory.root.file_id
425
other_root = self.tt.trans_id_file_id(other_root_file_id)
426
if other_root == self.tt.root:
429
self.tt.final_kind(other_root)
432
self.reparent_children(self.other_tree.inventory.root, self.tt.root)
433
self.tt.cancel_creation(other_root)
434
self.tt.cancel_versioning(other_root)
436
def reparent_children(self, ie, target):
437
for thing, child in ie.children.iteritems():
438
trans_id = self.tt.trans_id_file_id(child.file_id)
439
self.tt.adjust_path(self.tt.final_name(trans_id), target, trans_id)
399
441
def write_modified(self, results):
400
442
modified_hashes = {}
401
443
for path in results.modified_paths:
506
548
"conflict": other_entry}
507
549
trans_id = self.tt.trans_id_file_id(file_id)
508
550
parent_id = winner_entry[parent_id_winner].parent_id
509
parent_trans_id = self.tt.trans_id_file_id(parent_id)
510
self.tt.adjust_path(winner_entry[name_winner].name, parent_trans_id,
551
if parent_id is not None:
552
parent_trans_id = self.tt.trans_id_file_id(parent_id)
553
self.tt.adjust_path(winner_entry[name_winner].name,
554
parent_trans_id, trans_id)
513
556
def merge_contents(self, file_id):
514
557
"""Performa a merge on file_id contents."""
532
573
parent_id = self.tt.final_parent(trans_id)
533
574
if file_id in self.this_tree.inventory:
534
575
self.tt.unversion_file(trans_id)
535
self.tt.delete_contents(trans_id)
576
if file_id in self.this_tree:
577
self.tt.delete_contents(trans_id)
536
578
file_group = self._dump_conflicts(name, parent_id, file_id,
537
579
set_version=True)
538
580
self._raw_conflicts.append(('contents conflict', file_group))
858
900
will be dumped, and a will be conflict noted.
860
902
import bzrlib.patch
861
temp_dir = mkdtemp(prefix="bzr-")
903
temp_dir = osutils.mkdtemp(prefix="bzr-")
863
905
new_file = pathjoin(temp_dir, "new")
864
906
this = self.dump_file(temp_dir, "this", self.this_tree, file_id)
876
918
name = self.tt.final_name(trans_id)
877
919
parent_id = self.tt.final_parent(trans_id)
878
920
self._dump_conflicts(name, parent_id, file_id)
879
self._raw_conflicts.append(('text conflict', trans_id))
921
self._raw_conflicts.append(('text conflict', trans_id))
923
osutils.rmtree(temp_dir)
884
926
def merge_inner(this_branch, other_tree, base_tree, ignore_zero=False,
913
955
assert not interesting_ids, ('Only supply interesting_ids'
914
956
' or interesting_files')
915
957
merger._set_interesting_files(interesting_files)
916
merger.show_base = show_base
958
merger.show_base = show_base
917
959
merger.reprocess = reprocess
918
960
merger.other_rev_id = other_rev_id
919
961
merger.other_basis = other_rev_id