~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-02-01 23:48:08 UTC
  • mfrom: (2225.1.6 revert)
  • Revision ID: pqm@pqm.ubuntu.com-20070201234808-3b1302d73474bd8c
Display changes made by revert

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
import os
19
19
import errno
20
 
from tempfile import mkdtemp
21
20
import warnings
22
21
 
 
22
from bzrlib import (
 
23
    osutils,
 
24
    )
23
25
from bzrlib.branch import Branch
24
26
from bzrlib.conflicts import ConflictList, Conflict
25
27
from bzrlib.errors import (BzrCommandError,
36
38
                           BinaryFile,
37
39
                           )
38
40
from bzrlib.merge3 import Merge3
39
 
import bzrlib.osutils
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,
 
48
                              ROOT_PARENT)
47
49
from bzrlib.versionedfile import WeaveMerge
48
50
from bzrlib import ui
49
51
 
50
52
# TODO: Report back as changes are merged in
51
53
 
52
54
def _get_tree(treespec, local_branch=None):
 
55
    from bzrlib import workingtree
53
56
    location, revno = treespec
 
57
    if revno is None:
 
58
        tree = workingtree.WorkingTree.open_containing(location)[0]
 
59
        return tree.branch, tree
54
60
    branch = Branch.open_containing(location)[0]
55
 
    if revno is None:
56
 
        revision = None
57
 
    elif revno == -1:
 
61
    if revno == -1:
58
62
        revision = branch.last_revision()
59
63
    else:
60
64
        revision = branch.get_rev_id(revno)
137
141
 
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')")
141
146
        if check_clean:
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:
183
188
            return
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))
185
190
 
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.
 
193
 
 
194
        This sets the other_tree, other_rev_id, other_basis attributes.
 
195
 
 
196
        :param other_revision: The [path, revision] list to merge from.
 
197
        """
 
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])
207
218
 
208
219
    def set_base(self, base_revision):
 
220
        """Set the base revision to use for the merge.
 
221
 
 
222
        :param base_revision: A 2-list containing a path and revision number.
 
223
        """
209
224
        mutter("doing merge() with no base_revision specified")
210
225
        if base_revision == [None, None]:
211
226
            try:
212
 
                pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
227
                pb = ui.ui_factory.nested_progress_bar()
213
228
                try:
214
229
                    this_repo = self.this_branch.repository
215
230
                    self.base_rev_id = common_ancestor(self.this_basis, 
312
327
            else:
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)
318
333
            else:
361
376
        else:
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)
366
381
        try:
367
382
            self.pp.next_phase()
374
389
                    self.merge_executable(file_id, file_status)
375
390
            finally:
376
391
                child_pb.finished()
377
 
                
 
392
            self.fix_root()
378
393
            self.pp.next_phase()
379
394
            child_pb = ui.ui_factory.nested_progress_bar()
380
395
            try:
396
411
            working_tree.unlock()
397
412
            self.pb.clear()
398
413
 
 
414
    def fix_root(self):
 
415
        try:
 
416
            self.tt.final_kind(self.tt.root)
 
417
        except NoSuchFile:
 
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), 
 
421
                                 self.tt.root)
 
422
        if self.other_tree.inventory.root is None:
 
423
            return
 
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:
 
427
            return
 
428
        try:
 
429
            self.tt.final_kind(other_root)
 
430
        except NoSuchFile:
 
431
            return
 
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)
 
435
 
 
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)
 
440
 
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,
511
 
                            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)
512
555
 
513
556
    def merge_contents(self, file_id):
514
557
        """Performa a merge on file_id contents."""
516
559
            if file_id not in tree:
517
560
                return (None, None)
518
561
            kind = tree.kind(file_id)
519
 
            if kind == "root_directory":
520
 
                kind = "directory"
521
562
            if kind == "file":
522
563
                contents = tree.get_file_sha1(file_id)
523
564
            elif kind == "symlink":
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.
859
901
        """
860
902
        import bzrlib.patch
861
 
        temp_dir = mkdtemp(prefix="bzr-")
 
903
        temp_dir = osutils.mkdtemp(prefix="bzr-")
862
904
        try:
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))
880
922
        finally:
881
 
            rmtree(temp_dir)
 
923
            osutils.rmtree(temp_dir)
882
924
 
883
925
 
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