/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/workingtree.py

  • Committer: Jelmer Vernooij
  • Date: 2018-06-14 17:59:16 UTC
  • mto: This revision was merged to the branch mainline in revision 7065.
  • Revision ID: jelmer@jelmer.uk-20180614175916-a2e2xh5k533guq1x
Move breezy.plugins.git to breezy.git.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
WorkingTree.open(dir).
28
28
"""
29
29
 
30
 
import contextlib
 
30
from __future__ import absolute_import
 
31
 
31
32
import errno
32
33
import os
 
34
import re
 
35
import shutil
33
36
import sys
34
37
 
35
38
import breezy
36
39
 
37
40
from .lazy_import import lazy_import
38
41
lazy_import(globals(), """
39
 
import shutil
40
42
import stat
41
43
 
42
44
from breezy import (
 
45
    branch,
43
46
    conflicts as _mod_conflicts,
 
47
    controldir,
 
48
    errors,
44
49
    filters as _mod_filters,
 
50
    generate_ids,
45
51
    merge,
46
52
    revision as _mod_revision,
47
53
    transform,
48
54
    transport,
 
55
    ui,
49
56
    views,
50
57
    )
51
 
from breezy.bzr import (
52
 
    generate_ids,
53
 
    )
54
58
""")
55
59
 
56
60
from . import (
57
 
    errors,
58
 
    )
59
 
from .controldir import (
60
 
    ControlComponent,
61
 
    ControlComponentFormatRegistry,
62
 
    ControlComponentFormat,
63
 
    ControlDir,
64
 
    ControlDirFormat,
65
 
    )
66
 
from . import (
67
61
    osutils,
68
62
    )
69
63
from .i18n import gettext
70
64
from . import mutabletree
71
 
from .symbol_versioning import deprecated_method, deprecated_in
 
65
from .sixish import (
 
66
    text_type,
 
67
    )
72
68
from .trace import mutter, note
73
69
 
74
70
 
 
71
ERROR_PATH_NOT_FOUND = 3    # WindowsError errno code, equivalent to ENOENT
 
72
 
 
73
 
75
74
class SettingFileIdUnsupported(errors.BzrError):
76
75
 
77
76
    _fmt = "This format does not support setting file ids."
82
81
    _fmt = "This format does not support shelving changes."
83
82
 
84
83
 
85
 
class WorkingTree(mutabletree.MutableTree, ControlComponent):
 
84
class WorkingTree(mutabletree.MutableTree,
 
85
    controldir.ControlComponent):
86
86
    """Working copy tree.
87
87
 
88
88
    :ivar basedir: The root of the tree on disk. This is a unicode path object
107
107
        self.controldir = _controldir
108
108
        if not _internal:
109
109
            raise errors.BzrError("Please use controldir.open_workingtree or "
110
 
                                  "WorkingTree.open() to obtain a WorkingTree.")
 
110
                "WorkingTree.open() to obtain a WorkingTree.")
111
111
        basedir = osutils.safe_unicode(basedir)
112
112
        mutter("opening working tree %r", basedir)
113
113
        if branch is not None:
127
127
    def control_transport(self):
128
128
        return self._transport
129
129
 
130
 
    def supports_symlinks(self):
131
 
        return osutils.supports_symlinks(self.basedir)
132
 
 
133
130
    def is_control_filename(self, filename):
134
131
        """True if filename is the name of a control file in this tree.
135
132
 
160
157
        return self._format.supports_merge_modified
161
158
 
162
159
    def _supports_executable(self):
163
 
        return osutils.supports_executable(self.basedir)
 
160
        if sys.platform == 'win32':
 
161
            return False
 
162
        # FIXME: Ideally this should check the file system
 
163
        return True
164
164
 
165
165
    def break_lock(self):
166
166
        """Break a lock if one is present from another instance.
202
202
        """
203
203
        if path is None:
204
204
            path = osutils.getcwd()
205
 
        control = ControlDir.open(path, _unsupported=_unsupported)
 
205
        control = controldir.ControlDir.open(path, _unsupported=_unsupported)
206
206
        return control.open_workingtree(unsupported=_unsupported)
207
207
 
208
208
    @staticmethod
220
220
        """
221
221
        if path is None:
222
222
            path = osutils.getcwd()
223
 
        control, relpath = ControlDir.open_containing(path)
 
223
        control, relpath = controldir.ControlDir.open_containing(path)
224
224
        return control.open_workingtree(), relpath
225
225
 
226
226
    @staticmethod
279
279
        # self.relpath exists as a "thunk" to osutils, but canonical_relpath
280
280
        # doesn't - fix that up here before we enter the loop.
281
281
        if canonicalize:
282
 
            def fixer(p):
283
 
                return osutils.canonical_relpath(self.basedir, p)
 
282
            fixer = lambda p: osutils.canonical_relpath(self.basedir, p)
284
283
        else:
285
284
            fixer = self.relpath
286
285
        for filename in file_list:
298
297
        """
299
298
        return WorkingTree.open(path, _unsupported=True)
300
299
 
 
300
    @staticmethod
 
301
    def find_trees(location):
 
302
        def list_current(transport):
 
303
            return [d for d in transport.list_dir('')
 
304
                    if not controldir.is_control_filename(d)]
 
305
        def evaluate(controldir):
 
306
            try:
 
307
                tree = controldir.open_workingtree()
 
308
            except errors.NoWorkingTree:
 
309
                return True, None
 
310
            else:
 
311
                return True, tree
 
312
        t = transport.get_transport(location)
 
313
        iterator = controldir.ControlDir.find_controldirs(t, evaluate=evaluate,
 
314
                                              list_current=list_current)
 
315
        return [tr for tr in iterator if tr is not None]
 
316
 
301
317
    def __repr__(self):
302
318
        return "<%s of %s>" % (self.__class__.__name__,
303
319
                               getattr(self, 'basedir', None))
319
335
            # in the future this should return the tree for
320
336
            # 'empty:' - the implicit root empty tree.
321
337
            return self.branch.repository.revision_tree(
322
 
                _mod_revision.NULL_REVISION)
 
338
                       _mod_revision.NULL_REVISION)
323
339
        try:
324
340
            return self.revision_tree(revision_id)
325
341
        except errors.NoSuchRevision:
337
353
                raise
338
354
            # the basis tree is a ghost so return an empty tree.
339
355
            return self.branch.repository.revision_tree(
340
 
                _mod_revision.NULL_REVISION)
 
356
                       _mod_revision.NULL_REVISION)
341
357
 
342
358
    def relpath(self, path):
343
359
        """Return the local path portion from a given path.
350
366
    def has_filename(self, filename):
351
367
        return osutils.lexists(self.abspath(filename))
352
368
 
353
 
    def get_file(self, path, filtered=True):
354
 
        return self.get_file_with_stat(path, filtered=filtered)[0]
 
369
    def get_file(self, path, file_id=None, filtered=True):
 
370
        return self.get_file_with_stat(path, file_id, filtered=filtered)[0]
355
371
 
356
 
    def get_file_with_stat(self, path, filtered=True,
 
372
    def get_file_with_stat(self, path, file_id=None, filtered=True,
357
373
                           _fstat=osutils.fstat):
358
374
        """See Tree.get_file_with_stat."""
359
375
        abspath = self.abspath(path)
366
382
        stat_value = _fstat(file_obj.fileno())
367
383
        if filtered and self.supports_content_filtering():
368
384
            filters = self._content_filter_stack(path)
369
 
            if filters:
370
 
                file_obj, size = _mod_filters.filtered_input_file(
371
 
                    file_obj, filters)
372
 
                stat_value = _mod_filters.FilteredStat(
373
 
                    stat_value, st_size=size)
 
385
            file_obj = _mod_filters.filtered_input_file(file_obj, filters)
374
386
        return (file_obj, stat_value)
375
387
 
376
 
    def get_file_text(self, path, filtered=True):
377
 
        with self.get_file(path, filtered=filtered) as my_file:
 
388
    def get_file_text(self, path, file_id=None, filtered=True):
 
389
        with self.get_file(path, file_id, filtered=filtered) as my_file:
378
390
            return my_file.read()
379
391
 
380
 
    def get_file_lines(self, path, filtered=True):
 
392
    def get_file_lines(self, path, file_id=None, filtered=True):
381
393
        """See Tree.get_file_lines()"""
382
 
        with self.get_file(path, filtered=filtered) as file:
 
394
        with self.get_file(path, file_id, filtered=filtered) as file:
383
395
            return file.readlines()
384
396
 
385
397
    def get_parent_ids(self):
399
411
            pass
400
412
        else:
401
413
            for l in osutils.split_lines(merges_bytes):
402
 
                revision_id = l.rstrip(b'\n')
 
414
                revision_id = l.rstrip('\n')
403
415
                parents.append(revision_id)
404
416
        return parents
405
417
 
 
418
    def get_root_id(self):
 
419
        """Return the id of this trees root"""
 
420
        raise NotImplementedError(self.get_root_id)
 
421
 
406
422
    def clone(self, to_controldir, revision_id=None):
407
423
        """Duplicate this working tree into to_bzr, including all state.
408
424
 
425
441
    def copy_content_into(self, tree, revision_id=None):
426
442
        """Copy the current content and user files of this tree into tree."""
427
443
        with self.lock_read():
428
 
            tree.set_root_id(self.path2id(''))
 
444
            tree.set_root_id(self.get_root_id())
429
445
            if revision_id is None:
430
446
                merge.transform_tree(tree, self)
431
447
            else:
435
451
                    other_tree = self.revision_tree(revision_id)
436
452
                except errors.NoSuchRevision:
437
453
                    other_tree = self.branch.repository.revision_tree(
438
 
                        revision_id)
 
454
                            revision_id)
439
455
 
440
456
                merge.transform_tree(tree, other_tree)
441
457
                if revision_id == _mod_revision.NULL_REVISION:
444
460
                    new_parents = [revision_id]
445
461
                tree.set_parent_ids(new_parents)
446
462
 
447
 
    def get_file_size(self, path):
 
463
    def get_file_size(self, path, file_id=None):
448
464
        """See Tree.get_file_size"""
449
465
        # XXX: this returns the on-disk size; it should probably return the
450
466
        # canonical size
482
498
        with self.lock_write():
483
499
            parents = self.get_parent_ids() + [revision_id]
484
500
            self.set_parent_ids(parents, allow_leftmost_as_ghost=len(parents) > 1
485
 
                                or allow_leftmost_as_ghost)
 
501
                or allow_leftmost_as_ghost)
486
502
 
487
503
    def add_parent_tree(self, parent_tuple, allow_leftmost_as_ghost=False):
488
504
        """Add revision_id, tree tuple as a parent.
504
520
                # was.
505
521
                allow_leftmost_as_ghost = True
506
522
            self.set_parent_ids(parent_ids,
507
 
                                allow_leftmost_as_ghost=allow_leftmost_as_ghost)
 
523
                allow_leftmost_as_ghost=allow_leftmost_as_ghost)
508
524
 
509
525
    def add_pending_merge(self, *revision_ids):
510
526
        with self.lock_tree_write():
521
537
                self.set_parent_ids(parents, allow_leftmost_as_ghost=True)
522
538
 
523
539
    def path_content_summary(self, path, _lstat=os.lstat,
524
 
                             _mapper=osutils.file_kind_from_stat_mode):
 
540
        _mapper=osutils.file_kind_from_stat_mode):
525
541
        """See Tree.path_content_summary."""
526
542
        abspath = self.abspath(path)
527
543
        try:
563
579
        if len(revision_ids) > 0:
564
580
            leftmost_id = revision_ids[0]
565
581
            if (not allow_leftmost_as_ghost and not
566
 
                    self.branch.repository.has_revision(leftmost_id)):
 
582
                self.branch.repository.has_revision(leftmost_id)):
567
583
                raise errors.GhostRevisionUnusableHere(leftmost_id)
568
584
 
569
585
    def _set_merges_from_parent_ids(self, parent_ids):
570
586
        merges = parent_ids[1:]
571
587
        self._transport.put_bytes('pending-merges', b'\n'.join(merges),
572
 
                                  mode=self.controldir._get_file_mode())
 
588
            mode=self.controldir._get_file_mode())
573
589
 
574
590
    def _filter_parent_ids_by_ancestry(self, revision_ids):
575
591
        """Check that all merged revisions are proper 'heads'.
587
603
                new_revision_ids.append(revision_id)
588
604
        if new_revision_ids != revision_ids:
589
605
            mutter('requested to set revision_ids = %s,'
590
 
                   ' but filtered to %s', revision_ids, new_revision_ids)
 
606
                         ' but filtered to %s', revision_ids, new_revision_ids)
591
607
        return new_revision_ids
592
608
 
593
609
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
604
620
        """
605
621
        with self.lock_tree_write():
606
622
            self._check_parents_for_ghosts(revision_ids,
607
 
                                           allow_leftmost_as_ghost=allow_leftmost_as_ghost)
 
623
                allow_leftmost_as_ghost=allow_leftmost_as_ghost)
608
624
            for revision_id in revision_ids:
609
625
                _mod_revision.check_not_reserved_id(revision_id)
610
626
 
659
675
            merger.other_rev_id = to_revision
660
676
            if _mod_revision.is_null(merger.other_rev_id):
661
677
                raise errors.NoCommits(branch)
662
 
            self.branch.fetch(branch, stop_revision=merger.other_rev_id)
 
678
            self.branch.fetch(branch, last_revision=merger.other_rev_id)
663
679
            merger.other_basis = merger.other_rev_id
664
680
            merger.other_tree = self.branch.repository.revision_tree(
665
681
                merger.other_rev_id)
707
723
            self.add(path, file_id, 'directory')
708
724
            return file_id
709
725
 
710
 
    def get_symlink_target(self, path):
 
726
    def get_symlink_target(self, path, file_id=None):
711
727
        abspath = self.abspath(path)
712
728
        target = osutils.readlink(abspath)
713
729
        return target
715
731
    def subsume(self, other_tree):
716
732
        raise NotImplementedError(self.subsume)
717
733
 
718
 
    def _directory_is_tree_reference(self, relpath):
719
 
        raise NotImplementedError(self._directory_is_tree_reference)
720
 
 
721
 
    def extract(self, path, format=None):
 
734
    def _setup_directory_is_tree_reference(self):
 
735
        if self._branch.repository._format.supports_tree_reference:
 
736
            self._directory_is_tree_reference = \
 
737
                self._directory_may_be_tree_reference
 
738
        else:
 
739
            self._directory_is_tree_reference = \
 
740
                self._directory_is_never_tree_reference
 
741
 
 
742
    def _directory_is_never_tree_reference(self, relpath):
 
743
        return False
 
744
 
 
745
    def _directory_may_be_tree_reference(self, relpath):
 
746
        # as a special case, if a directory contains control files then
 
747
        # it's a tree reference, except that the root of the tree is not
 
748
        return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
 
749
        # TODO: We could ask all the control formats whether they
 
750
        # recognize this directory, but at the moment there's no cheap api
 
751
        # to do that.  Since we probably can only nest bzr checkouts and
 
752
        # they always use this name it's ok for now.  -- mbp 20060306
 
753
        #
 
754
        # FIXME: There is an unhandled case here of a subdirectory
 
755
        # containing .bzr but not a branch; that will probably blow up
 
756
        # when you try to commit it.  It might happen if there is a
 
757
        # checkout in a subdirectory.  This can be avoided by not adding
 
758
        # it.  mbp 20070306
 
759
 
 
760
    def extract(self, path, file_id=None, format=None):
722
761
        """Extract a subtree from this tree.
723
762
 
724
763
        A new branch will be created, relative to the path for this tree.
729
768
        """Write the in memory meta data to disk."""
730
769
        raise NotImplementedError(self.flush)
731
770
 
732
 
    def kind(self, relpath):
 
771
    def kind(self, relpath, file_id=None):
733
772
        return osutils.file_kind(self.abspath(relpath))
734
773
 
735
 
    def list_files(self, include_root=False, from_dir=None, recursive=True,
736
 
                   recurse_nested=False):
 
774
    def list_files(self, include_root=False, from_dir=None, recursive=True):
737
775
        """List all files as (path, class, kind, id, entry).
738
776
 
739
777
        Lists, but does not descend into unversioned directories.
819
857
 
820
858
    def pull(self, source, overwrite=False, stop_revision=None,
821
859
             change_reporter=None, possible_transports=None, local=False,
822
 
             show_base=False, tag_selector=None):
 
860
             show_base=False):
823
861
        with self.lock_write(), source.lock_read():
824
862
            old_revision_info = self.branch.last_revision_info()
825
863
            basis_tree = self.basis_tree()
826
864
            count = self.branch.pull(source, overwrite, stop_revision,
827
865
                                     possible_transports=possible_transports,
828
 
                                     local=local, tag_selector=tag_selector)
 
866
                                     local=local)
829
867
            new_revision_info = self.branch.last_revision_info()
830
868
            if new_revision_info != old_revision_info:
831
869
                repository = self.branch.repository
837
875
                with basis_tree.lock_read():
838
876
                    new_basis_tree = self.branch.basis_tree()
839
877
                    merge.merge_inner(
840
 
                        self.branch,
841
 
                        new_basis_tree,
842
 
                        basis_tree,
843
 
                        this_tree=self,
844
 
                        change_reporter=change_reporter,
845
 
                        show_base=show_base)
846
 
                    basis_root_id = basis_tree.path2id('')
847
 
                    new_root_id = new_basis_tree.path2id('')
 
878
                                self.branch,
 
879
                                new_basis_tree,
 
880
                                basis_tree,
 
881
                                this_tree=self,
 
882
                                change_reporter=change_reporter,
 
883
                                show_base=show_base)
 
884
                    basis_root_id = basis_tree.get_root_id()
 
885
                    new_root_id = new_basis_tree.get_root_id()
848
886
                    if new_root_id is not None and basis_root_id != new_root_id:
849
887
                        self.set_root_id(new_root_id)
850
888
                # TODO - dedup parents list with things merged by pull ?
862
900
                merges = self.get_parent_ids()[1:]
863
901
                parent_trees.extend([
864
902
                    (parent, repository.revision_tree(parent)) for
865
 
                    parent in merges])
 
903
                     parent in merges])
866
904
                self.set_parent_trees(parent_trees)
867
905
            return count
868
906
 
869
 
    def put_file_bytes_non_atomic(self, path, bytes):
 
907
    def put_file_bytes_non_atomic(self, path, bytes, file_id=None):
870
908
        """See MutableTree.put_file_bytes_non_atomic."""
871
909
        with self.lock_write(), open(self.abspath(path), 'wb') as stream:
872
 
            stream.write(bytes)
 
910
                stream.write(bytes)
873
911
 
874
912
    def extras(self):
875
913
        """Yield all unversioned files in this WorkingTree.
876
914
 
877
 
        If there are any unversioned directories and the file format
878
 
        supports versioning directories, then only the directory is returned,
879
 
        not all its children. But if there are unversioned files under a
880
 
        versioned subdirectory, they are returned.
 
915
        If there are any unversioned directories then only the directory is
 
916
        returned, not all its children.  But if there are unversioned files
 
917
        under a versioned subdirectory, they are returned.
881
918
 
882
919
        Currently returned depth-first, sorted by name within directories.
883
920
        This is the same order used by 'osutils.walkdirs'.
896
933
        """
897
934
        raise NotImplementedError(self.is_ignored)
898
935
 
899
 
    def stored_kind(self, path):
 
936
    def stored_kind(self, path, file_id=None):
900
937
        """See Tree.stored_kind"""
901
938
        raise NotImplementedError(self.stored_kind)
902
939
 
1000
1037
    def revert(self, filenames=None, old_tree=None, backups=True,
1001
1038
               pb=None, report_changes=False):
1002
1039
        from .conflicts import resolve
1003
 
        with contextlib.ExitStack() as exit_stack:
1004
 
            exit_stack.enter_context(self.lock_tree_write())
 
1040
        with self.lock_tree_write():
1005
1041
            if old_tree is None:
1006
1042
                basis_tree = self.basis_tree()
1007
 
                exit_stack.enter_context(basis_tree.lock_read())
 
1043
                basis_tree.lock_read()
1008
1044
                old_tree = basis_tree
1009
1045
            else:
1010
1046
                basis_tree = None
1011
 
            conflicts = transform.revert(self, old_tree, filenames, backups, pb,
1012
 
                                         report_changes)
1013
 
            if filenames is None and len(self.get_parent_ids()) > 1:
1014
 
                parent_trees = []
1015
 
                last_revision = self.last_revision()
1016
 
                if last_revision != _mod_revision.NULL_REVISION:
1017
 
                    if basis_tree is None:
1018
 
                        basis_tree = self.basis_tree()
1019
 
                        exit_stack.enter_context(basis_tree.lock_read())
1020
 
                    parent_trees.append((last_revision, basis_tree))
1021
 
                self.set_parent_trees(parent_trees)
1022
 
                resolve(self)
1023
 
            else:
1024
 
                resolve(self, filenames, ignore_misses=True, recursive=True)
 
1047
            try:
 
1048
                conflicts = transform.revert(self, old_tree, filenames, backups, pb,
 
1049
                                             report_changes)
 
1050
                if filenames is None and len(self.get_parent_ids()) > 1:
 
1051
                    parent_trees = []
 
1052
                    last_revision = self.last_revision()
 
1053
                    if last_revision != _mod_revision.NULL_REVISION:
 
1054
                        if basis_tree is None:
 
1055
                            basis_tree = self.basis_tree()
 
1056
                            basis_tree.lock_read()
 
1057
                        parent_trees.append((last_revision, basis_tree))
 
1058
                    self.set_parent_trees(parent_trees)
 
1059
                    resolve(self)
 
1060
                else:
 
1061
                    resolve(self, filenames, ignore_misses=True, recursive=True)
 
1062
            finally:
 
1063
                if basis_tree is not None:
 
1064
                    basis_tree.unlock()
1025
1065
            return conflicts
1026
1066
 
1027
1067
    def store_uncommitted(self):
1045
1085
        if not self.supports_setting_file_ids():
1046
1086
            raise SettingFileIdUnsupported()
1047
1087
        with self.lock_tree_write():
1048
 
            # for compatibility
 
1088
            # for compatability
1049
1089
            if file_id is None:
1050
1090
                raise ValueError(
1051
1091
                    'WorkingTree.set_root_id with fileid=None')
 
1092
            file_id = osutils.safe_file_id(file_id)
1052
1093
            self._set_root_id(file_id)
1053
1094
 
1054
1095
    def _set_root_id(self, file_id):
1153
1194
            if not _mod_revision.is_null(old_tip) and old_tip != last_rev:
1154
1195
                # the branch we are bound to was updated
1155
1196
                # merge those changes in first
1156
 
                base_tree = self.basis_tree()
 
1197
                base_tree  = self.basis_tree()
1157
1198
                other_tree = self.branch.repository.revision_tree(old_tip)
1158
1199
                nb_conflicts = merge.merge_inner(self.branch, other_tree,
1159
1200
                                                 base_tree, this_tree=self,
1168
1209
                # the working tree is up to date with the branch
1169
1210
                # we can merge the specified revision from master
1170
1211
                to_tree = self.branch.repository.revision_tree(revision)
1171
 
                to_root_id = to_tree.path2id('')
 
1212
                to_root_id = to_tree.get_root_id()
1172
1213
 
1173
1214
                basis = self.basis_tree()
1174
1215
                with basis.lock_read():
1175
 
                    if (basis.path2id('') is None or basis.path2id('') != to_root_id):
 
1216
                    if (basis.get_root_id() is None or basis.get_root_id() != to_root_id):
1176
1217
                        self.set_root_id(to_root_id)
1177
1218
                        self.flush()
1178
1219
 
1231
1272
        """
1232
1273
        raise NotImplementedError(self.walkdirs)
1233
1274
 
1234
 
    @deprecated_method(deprecated_in((3, 0, 1)))
1235
1275
    def auto_resolve(self):
1236
1276
        """Automatically resolve text conflicts according to contents.
1237
1277
 
1245
1285
        with self.lock_tree_write():
1246
1286
            un_resolved = _mod_conflicts.ConflictList()
1247
1287
            resolved = _mod_conflicts.ConflictList()
 
1288
            conflict_re = re.compile('^(<{7}|={7}|>{7})')
1248
1289
            for conflict in self.conflicts():
1249
 
                try:
1250
 
                    conflict.action_auto(self)
1251
 
                except NotImplementedError:
 
1290
                path = self.id2path(conflict.file_id)
 
1291
                if (conflict.typestring != 'text conflict' or
 
1292
                    self.kind(path, conflict.file_id) != 'file'):
1252
1293
                    un_resolved.append(conflict)
1253
 
                else:
1254
 
                    conflict.cleanup(self)
1255
 
                    resolved.append(conflict)
 
1294
                    continue
 
1295
                with open(self.abspath(path), 'rb') as my_file:
 
1296
                    for line in my_file:
 
1297
                        if conflict_re.search(line):
 
1298
                            un_resolved.append(conflict)
 
1299
                            break
 
1300
                    else:
 
1301
                        resolved.append(conflict)
 
1302
            resolved.remove_files(self)
1256
1303
            self.set_conflicts(un_resolved)
1257
1304
            return un_resolved, resolved
1258
1305
 
1283
1330
        """See Tree._get_rules_searcher."""
1284
1331
        if self._rules_searcher is None:
1285
1332
            self._rules_searcher = super(WorkingTree,
1286
 
                                         self)._get_rules_searcher(default_searcher)
 
1333
                self)._get_rules_searcher(default_searcher)
1287
1334
        return self._rules_searcher
1288
1335
 
1289
1336
    def get_shelf_manager(self):
1290
1337
        """Return the ShelfManager for this WorkingTree."""
1291
1338
        raise NotImplementedError(self.get_shelf_manager)
1292
1339
 
1293
 
    def get_canonical_paths(self, paths):
1294
 
        """Like get_canonical_path() but works on multiple items.
1295
 
 
1296
 
        :param paths: A sequence of paths relative to the root of the tree.
1297
 
        :return: A list of paths, with each item the corresponding input path
1298
 
            adjusted to account for existing elements that match case
1299
 
            insensitively.
1300
 
        """
1301
 
        with self.lock_read():
1302
 
            for path in paths:
1303
 
                yield path
1304
 
 
1305
 
    def get_canonical_path(self, path):
1306
 
        """Returns the first item in the tree that matches a path.
1307
 
 
1308
 
        This is meant to allow case-insensitive path lookups on e.g.
1309
 
        FAT filesystems.
1310
 
 
1311
 
        If a path matches exactly, it is returned. If no path matches exactly
1312
 
        but more than one path matches according to the underlying file system,
1313
 
        it is implementation defined which is returned.
1314
 
 
1315
 
        If no path matches according to the file system, the input path is
1316
 
        returned, but with as many path entries that do exist changed to their
1317
 
        canonical form.
1318
 
 
1319
 
        If you need to resolve many names from the same tree, you should
1320
 
        use get_canonical_paths() to avoid O(N) behaviour.
1321
 
 
1322
 
        :param path: A paths relative to the root of the tree.
1323
 
        :return: The input path adjusted to account for existing elements
1324
 
        that match case insensitively.
1325
 
        """
1326
 
        with self.lock_read():
1327
 
            return next(self.get_canonical_paths([path]))
1328
 
 
1329
 
    def reference_parent(self, path, branch=None, possible_transports=None):
1330
 
        raise errors.UnsupportedOperation(self.reference_parent, self)
1331
 
 
1332
 
    def get_reference_info(self, path, branch=None):
1333
 
        raise errors.UnsupportedOperation(self.get_reference_info, self)
1334
 
 
1335
 
    def set_reference_info(self, tree_path, branch_location):
1336
 
        raise errors.UnsupportedOperation(self.set_reference_info, self)
1337
 
 
1338
 
 
1339
 
class WorkingTreeFormatRegistry(ControlComponentFormatRegistry):
 
1340
 
 
1341
class WorkingTreeFormatRegistry(controldir.ControlComponentFormatRegistry):
1340
1342
    """Registry for working tree formats."""
1341
1343
 
1342
1344
    def __init__(self, other_registry=None):
1347
1349
    def get_default(self):
1348
1350
        """Return the current default format."""
1349
1351
        if (self._default_format_key is not None and
1350
 
                self._default_format is None):
 
1352
            self._default_format is None):
1351
1353
            self._default_format = self.get(self._default_format_key)
1352
1354
        return self._default_format
1353
1355
 
1365
1367
format_registry = WorkingTreeFormatRegistry()
1366
1368
 
1367
1369
 
1368
 
class WorkingTreeFormat(ControlComponentFormat):
 
1370
class WorkingTreeFormat(controldir.ControlComponentFormat):
1369
1371
    """An encapsulation of the initialization and open routines for a format.
1370
1372
 
1371
1373
    Formats provide three things:
1466
1468
 
1467
1469
 
1468
1470
format_registry.register_lazy(b"Bazaar Working Tree Format 4 (bzr 0.15)\n",
1469
 
                              "breezy.bzr.workingtree_4", "WorkingTreeFormat4")
 
1471
    "breezy.bzr.workingtree_4", "WorkingTreeFormat4")
1470
1472
format_registry.register_lazy(b"Bazaar Working Tree Format 5 (bzr 1.11)\n",
1471
 
                              "breezy.bzr.workingtree_4", "WorkingTreeFormat5")
 
1473
    "breezy.bzr.workingtree_4", "WorkingTreeFormat5")
1472
1474
format_registry.register_lazy(b"Bazaar Working Tree Format 6 (bzr 1.14)\n",
1473
 
                              "breezy.bzr.workingtree_4", "WorkingTreeFormat6")
 
1475
    "breezy.bzr.workingtree_4", "WorkingTreeFormat6")
1474
1476
format_registry.register_lazy(b"Bazaar-NG Working Tree format 3",
1475
 
                              "breezy.bzr.workingtree_3", "WorkingTreeFormat3")
 
1477
    "breezy.bzr.workingtree_3", "WorkingTreeFormat3")
1476
1478
format_registry.set_default_key(b"Bazaar Working Tree Format 6 (bzr 1.14)\n")