~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

(gz) Never raise KnownFailure in tests,
 use knownFailure method instead (Martin [gz])

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
    generate_ids,
55
55
    globbing,
56
56
    graph as _mod_graph,
 
57
    hashcache,
57
58
    ignores,
58
59
    inventory,
59
60
    merge,
71
72
 
72
73
from bzrlib import symbol_versioning
73
74
from bzrlib.decorators import needs_read_lock, needs_write_lock
74
 
from bzrlib.i18n import gettext
75
75
from bzrlib.lock import LogicalLockResult
76
76
import bzrlib.mutabletree
77
77
from bzrlib.mutabletree import needs_tree_write_lock
172
172
 
173
173
    def __init__(self, basedir='.',
174
174
                 branch=DEPRECATED_PARAMETER,
 
175
                 _control_files=None,
175
176
                 _internal=False,
176
 
                 _transport=None,
177
177
                 _format=None,
178
178
                 _bzrdir=None):
179
179
        """Construct a WorkingTree instance. This is not a public API.
192
192
        else:
193
193
            self._branch = self.bzrdir.open_branch()
194
194
        self.basedir = realpath(basedir)
195
 
        self._transport = _transport
 
195
        self._control_files = _control_files
 
196
        self._transport = self._control_files._transport
 
197
        # update the whole cache up front and write to disk if anything changed;
 
198
        # in the future we might want to do this more selectively
 
199
        # two possible ways offer themselves : in self._unlock, write the cache
 
200
        # if needed, or, when the cache sees a change, append it to the hash
 
201
        # cache file, and have the parser take the most recent entry for a
 
202
        # given path only.
 
203
        wt_trans = self.bzrdir.get_workingtree_transport(None)
 
204
        cache_filename = wt_trans.local_abspath('stat-cache')
 
205
        self._hashcache = hashcache.HashCache(basedir, cache_filename,
 
206
            self.bzrdir._get_file_mode(),
 
207
            self._content_filter_stack_provider())
 
208
        hc = self._hashcache
 
209
        hc.read()
 
210
        # is this scan needed ? it makes things kinda slow.
 
211
        #hc.scan()
 
212
 
 
213
        if hc.needs_write:
 
214
            mutter("write hc")
 
215
            hc.write()
 
216
 
 
217
        self._detect_case_handling()
196
218
        self._rules_searcher = None
197
219
        self.views = self._make_views()
198
220
 
216
238
        """
217
239
        return self.bzrdir.is_control_filename(filename)
218
240
 
 
241
    def _detect_case_handling(self):
 
242
        wt_trans = self.bzrdir.get_workingtree_transport(None)
 
243
        try:
 
244
            wt_trans.stat(self._format.case_sensitive_filename)
 
245
        except errors.NoSuchFile:
 
246
            self.case_sensitive = True
 
247
        else:
 
248
            self.case_sensitive = False
 
249
 
 
250
        self._setup_directory_is_tree_reference()
 
251
 
219
252
    branch = property(
220
253
        fget=lambda self: self._branch,
221
254
        doc="""The branch this WorkingTree is connected to.
224
257
            the working tree has been constructed from.
225
258
            """)
226
259
 
227
 
    def has_versioned_directories(self):
228
 
        """See `Tree.has_versioned_directories`."""
229
 
        return self._format.supports_versioned_directories
230
 
 
231
260
    def break_lock(self):
232
261
        """Break a lock if one is present from another instance.
233
262
 
236
265
 
237
266
        This will probe the repository for its lock as well.
238
267
        """
239
 
        raise NotImplementedError(self.break_lock)
 
268
        self._control_files.break_lock()
 
269
        self.branch.break_lock()
240
270
 
241
271
    def requires_rich_root(self):
242
272
        return self._format.requires_rich_root
257
287
        """
258
288
        if path is None:
259
289
            path = osutils.getcwd()
260
 
        control = controldir.ControlDir.open(path, _unsupported)
 
290
        control = bzrdir.BzrDir.open(path, _unsupported)
261
291
        return control.open_workingtree(_unsupported)
262
292
 
263
293
    @staticmethod
275
305
        """
276
306
        if path is None:
277
307
            path = osutils.getcwd()
278
 
        control, relpath = controldir.ControlDir.open_containing(path)
 
308
        control, relpath = bzrdir.BzrDir.open_containing(path)
279
309
        return control.open_workingtree(), relpath
280
310
 
281
311
    @staticmethod
301
331
                if view_files:
302
332
                    file_list = view_files
303
333
                    view_str = views.view_display_str(view_files)
304
 
                    note(gettext("Ignoring files outside view. View is %s") % view_str)
 
334
                    note("Ignoring files outside view. View is %s" % view_str)
305
335
            return tree, file_list
306
336
        if default_directory == u'.':
307
337
            seed = file_list[0]
364
394
            else:
365
395
                return True, tree
366
396
        t = transport.get_transport(location)
367
 
        iterator = controldir.ControlDir.find_bzrdirs(t, evaluate=evaluate,
 
397
        iterator = bzrdir.BzrDir.find_bzrdirs(t, evaluate=evaluate,
368
398
                                              list_current=list_current)
369
399
        return [tr for tr in iterator if tr is not None]
370
400
 
492
522
        raise NotImplementedError(self.get_root_id)
493
523
 
494
524
    @needs_read_lock
495
 
    def clone(self, to_controldir, revision_id=None):
 
525
    def clone(self, to_bzrdir, revision_id=None):
496
526
        """Duplicate this working tree into to_bzr, including all state.
497
527
 
498
528
        Specifically modified files are kept as modified, but
499
529
        ignored and unknown files are discarded.
500
530
 
501
 
        If you want to make a new line of development, see ControlDir.sprout()
 
531
        If you want to make a new line of development, see bzrdir.sprout()
502
532
 
503
533
        revision
504
534
            If not None, the cloned tree will have its last revision set to
506
536
            and this one merged in.
507
537
        """
508
538
        # assumes the target bzr dir format is compatible.
509
 
        result = to_controldir.create_workingtree()
 
539
        result = to_bzrdir.create_workingtree()
510
540
        self.copy_content_into(result, revision_id)
511
541
        return result
512
542
 
520
550
            # TODO now merge from tree.last_revision to revision (to preserve
521
551
            # user local changes)
522
552
            merge.transform_tree(tree, self)
523
 
            if revision_id == _mod_revision.NULL_REVISION:
524
 
                new_parents = []
525
 
            else:
526
 
                new_parents = [revision_id]
527
 
            tree.set_parent_ids(new_parents)
 
553
            tree.set_parent_ids([revision_id])
528
554
 
529
555
    def id2abspath(self, file_id):
530
556
        return self.abspath(self.id2path(file_id))
739
765
 
740
766
    @needs_tree_write_lock
741
767
    def set_merge_modified(self, modified_hashes):
742
 
        """Set the merge modified hashes."""
743
 
        raise NotImplementedError(self.set_merge_modified)
 
768
        def iter_stanzas():
 
769
            for file_id, hash in modified_hashes.iteritems():
 
770
                yield _mod_rio.Stanza(file_id=file_id.decode('utf8'),
 
771
                    hash=hash)
 
772
        self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
744
773
 
745
774
    def _sha_from_stat(self, path, stat_result):
746
775
        """Get a sha digest from the tree's stat cache.
752
781
        """
753
782
        return None
754
783
 
 
784
    def _put_rio(self, filename, stanzas, header):
 
785
        self._must_be_locked()
 
786
        my_file = _mod_rio.rio_file(stanzas, header)
 
787
        self._transport.put_file(filename, my_file,
 
788
            mode=self.bzrdir._get_file_mode())
 
789
 
755
790
    @needs_write_lock # because merge pulls data into the branch.
756
791
    def merge_from_branch(self, branch, to_revision=None, from_revision=None,
757
792
                          merge_type=None, force=False):
997
1032
                                show_base=show_base)
998
1033
                    basis_root_id = basis_tree.get_root_id()
999
1034
                    new_root_id = new_basis_tree.get_root_id()
1000
 
                    if new_root_id is not None and basis_root_id != new_root_id:
 
1035
                    if basis_root_id != new_root_id:
1001
1036
                        self.set_root_id(new_root_id)
1002
1037
                finally:
1003
1038
                    basis_tree.unlock()
1004
1039
                # TODO - dedup parents list with things merged by pull ?
1005
1040
                # reuse the revisiontree we merged against to set the new
1006
1041
                # tree data.
1007
 
                parent_trees = []
1008
 
                if self.branch.last_revision() != _mod_revision.NULL_REVISION:
1009
 
                    parent_trees.append(
1010
 
                        (self.branch.last_revision(), new_basis_tree))
 
1042
                parent_trees = [(self.branch.last_revision(), new_basis_tree)]
1011
1043
                # we have to pull the merge trees out again, because
1012
1044
                # merge_inner has set the ids. - this corner is not yet
1013
1045
                # layered well enough to prevent double handling.
1030
1062
            stream.write(bytes)
1031
1063
        finally:
1032
1064
            stream.close()
 
1065
        # TODO: update the hashcache here ?
1033
1066
 
1034
1067
    def extras(self):
1035
1068
        """Yield all unversioned files in this WorkingTree.
1137
1170
        return _mod_revision.ensure_null(self.branch.last_revision())
1138
1171
 
1139
1172
    def is_locked(self):
1140
 
        """Check if this tree is locked."""
1141
 
        raise NotImplementedError(self.is_locked)
 
1173
        return self._control_files.is_locked()
 
1174
 
 
1175
    def _must_be_locked(self):
 
1176
        if not self.is_locked():
 
1177
            raise errors.ObjectNotLocked(self)
1142
1178
 
1143
1179
    def lock_read(self):
1144
1180
        """Lock the tree for reading.
1147
1183
 
1148
1184
        :return: A bzrlib.lock.LogicalLockResult.
1149
1185
        """
1150
 
        raise NotImplementedError(self.lock_read)
 
1186
        if not self.is_locked():
 
1187
            self._reset_data()
 
1188
        self.branch.lock_read()
 
1189
        try:
 
1190
            self._control_files.lock_read()
 
1191
            return LogicalLockResult(self.unlock)
 
1192
        except:
 
1193
            self.branch.unlock()
 
1194
            raise
1151
1195
 
1152
1196
    def lock_tree_write(self):
1153
1197
        """See MutableTree.lock_tree_write, and WorkingTree.unlock.
1154
1198
 
1155
1199
        :return: A bzrlib.lock.LogicalLockResult.
1156
1200
        """
1157
 
        raise NotImplementedError(self.lock_tree_write)
 
1201
        if not self.is_locked():
 
1202
            self._reset_data()
 
1203
        self.branch.lock_read()
 
1204
        try:
 
1205
            self._control_files.lock_write()
 
1206
            return LogicalLockResult(self.unlock)
 
1207
        except:
 
1208
            self.branch.unlock()
 
1209
            raise
1158
1210
 
1159
1211
    def lock_write(self):
1160
1212
        """See MutableTree.lock_write, and WorkingTree.unlock.
1161
1213
 
1162
1214
        :return: A bzrlib.lock.LogicalLockResult.
1163
1215
        """
1164
 
        raise NotImplementedError(self.lock_write)
 
1216
        if not self.is_locked():
 
1217
            self._reset_data()
 
1218
        self.branch.lock_write()
 
1219
        try:
 
1220
            self._control_files.lock_write()
 
1221
            return LogicalLockResult(self.unlock)
 
1222
        except:
 
1223
            self.branch.unlock()
 
1224
            raise
1165
1225
 
1166
1226
    def get_physical_lock_status(self):
1167
 
        raise NotImplementedError(self.get_physical_lock_status)
 
1227
        return self._control_files.get_physical_lock_status()
 
1228
 
 
1229
    def _reset_data(self):
 
1230
        """Reset transient data that cannot be revalidated."""
 
1231
        raise NotImplementedError(self._reset_data)
1168
1232
 
1169
1233
    def set_last_revision(self, new_revision):
1170
1234
        """Change the last revision in the working tree."""
1464
1528
                                             show_base=show_base)
1465
1529
            if nb_conflicts:
1466
1530
                self.add_parent_tree((old_tip, other_tree))
1467
 
                note(gettext('Rerun update after fixing the conflicts.'))
 
1531
                note('Rerun update after fixing the conflicts.')
1468
1532
                return nb_conflicts
1469
1533
 
1470
1534
        if last_rev != _mod_revision.ensure_null(revision):
1512
1576
            last_rev = parent_trees[0][0]
1513
1577
        return nb_conflicts
1514
1578
 
 
1579
    def _write_hashcache_if_dirty(self):
 
1580
        """Write out the hashcache if it is dirty."""
 
1581
        if self._hashcache.needs_write:
 
1582
            try:
 
1583
                self._hashcache.write()
 
1584
            except OSError, e:
 
1585
                if e.errno not in (errno.EPERM, errno.EACCES):
 
1586
                    raise
 
1587
                # TODO: jam 20061219 Should this be a warning? A single line
 
1588
                #       warning might be sufficient to let the user know what
 
1589
                #       is going on.
 
1590
                mutter('Could not write hashcache for %s\nError: %s',
 
1591
                              self._hashcache.cache_file_name(), e)
 
1592
 
1515
1593
    def set_conflicts(self, arg):
1516
1594
        raise errors.UnsupportedOperation(self.set_conflicts, self)
1517
1595
 
1746
1824
        :param branch: A branch to override probing for the branch.
1747
1825
        """
1748
1826
        super(InventoryWorkingTree, self).__init__(basedir=basedir,
1749
 
            branch=branch, _transport=_control_files._transport,
1750
 
            _internal=_internal, _format=_format, _bzrdir=_bzrdir)
1751
 
 
1752
 
        self._control_files = _control_files
1753
 
        self._detect_case_handling()
 
1827
            branch=branch, _control_files=_control_files, _internal=_internal,
 
1828
            _format=_format, _bzrdir=_bzrdir)
1754
1829
 
1755
1830
        if _inventory is None:
1756
1831
            # This will be acquired on lock_read() or lock_write()
1776
1851
        self._inventory = inv
1777
1852
        self._inventory_is_modified = dirty
1778
1853
 
1779
 
    def _detect_case_handling(self):
1780
 
        wt_trans = self.bzrdir.get_workingtree_transport(None)
1781
 
        try:
1782
 
            wt_trans.stat(self._format.case_sensitive_filename)
1783
 
        except errors.NoSuchFile:
1784
 
            self.case_sensitive = True
1785
 
        else:
1786
 
            self.case_sensitive = False
1787
 
 
1788
 
        self._setup_directory_is_tree_reference()
1789
 
 
1790
1854
    def _serialize(self, inventory, out_file):
1791
1855
        xml5.serializer_v5.write_inventory(self._inventory, out_file,
1792
1856
            working=True)
1794
1858
    def _deserialize(selt, in_file):
1795
1859
        return xml5.serializer_v5.read_inventory(in_file)
1796
1860
 
1797
 
    def break_lock(self):
1798
 
        """Break a lock if one is present from another instance.
1799
 
 
1800
 
        Uses the ui factory to ask for confirmation if the lock may be from
1801
 
        an active process.
1802
 
 
1803
 
        This will probe the repository for its lock as well.
1804
 
        """
1805
 
        self._control_files.break_lock()
1806
 
        self.branch.break_lock()
1807
 
 
1808
 
    def is_locked(self):
1809
 
        return self._control_files.is_locked()
1810
 
 
1811
 
    def _must_be_locked(self):
1812
 
        if not self.is_locked():
1813
 
            raise errors.ObjectNotLocked(self)
1814
 
 
1815
 
    def lock_read(self):
1816
 
        """Lock the tree for reading.
1817
 
 
1818
 
        This also locks the branch, and can be unlocked via self.unlock().
1819
 
 
1820
 
        :return: A bzrlib.lock.LogicalLockResult.
1821
 
        """
1822
 
        if not self.is_locked():
1823
 
            self._reset_data()
1824
 
        self.branch.lock_read()
1825
 
        try:
1826
 
            self._control_files.lock_read()
1827
 
            return LogicalLockResult(self.unlock)
1828
 
        except:
1829
 
            self.branch.unlock()
1830
 
            raise
1831
 
 
1832
 
    def lock_tree_write(self):
1833
 
        """See MutableTree.lock_tree_write, and WorkingTree.unlock.
1834
 
 
1835
 
        :return: A bzrlib.lock.LogicalLockResult.
1836
 
        """
1837
 
        if not self.is_locked():
1838
 
            self._reset_data()
1839
 
        self.branch.lock_read()
1840
 
        try:
1841
 
            self._control_files.lock_write()
1842
 
            return LogicalLockResult(self.unlock)
1843
 
        except:
1844
 
            self.branch.unlock()
1845
 
            raise
1846
 
 
1847
 
    def lock_write(self):
1848
 
        """See MutableTree.lock_write, and WorkingTree.unlock.
1849
 
 
1850
 
        :return: A bzrlib.lock.LogicalLockResult.
1851
 
        """
1852
 
        if not self.is_locked():
1853
 
            self._reset_data()
1854
 
        self.branch.lock_write()
1855
 
        try:
1856
 
            self._control_files.lock_write()
1857
 
            return LogicalLockResult(self.unlock)
1858
 
        except:
1859
 
            self.branch.unlock()
1860
 
            raise
1861
 
 
1862
 
    def get_physical_lock_status(self):
1863
 
        return self._control_files.get_physical_lock_status()
1864
 
 
1865
1861
    @needs_tree_write_lock
1866
1862
    def _write_inventory(self, inv):
1867
1863
        """Write inventory as the current inventory."""
2164
2160
            mode=self.bzrdir._get_file_mode())
2165
2161
        self._inventory_is_modified = False
2166
2162
 
 
2163
    @needs_read_lock
 
2164
    def get_file_sha1(self, file_id, path=None, stat_value=None):
 
2165
        if not path:
 
2166
            path = self._inventory.id2path(file_id)
 
2167
        return self._hashcache.get_sha1(path, stat_value)
 
2168
 
2167
2169
    def get_file_mtime(self, file_id, path=None):
2168
2170
        """See Tree.get_file_mtime."""
2169
2171
        if not path:
2170
2172
            path = self.inventory.id2path(file_id)
2171
 
        try:
2172
 
            return os.lstat(self.abspath(path)).st_mtime
2173
 
        except OSError, e:
2174
 
            if e.errno == errno.ENOENT:
2175
 
                raise errors.FileTimestampUnavailable(path)
2176
 
            raise
 
2173
        return os.lstat(self.abspath(path)).st_mtime
2177
2174
 
2178
2175
    def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
2179
2176
        file_id = self.path2id(path)
2286
2283
                       for key, line in annotator.annotate_flat(this_key)]
2287
2284
        return annotations
2288
2285
 
2289
 
    def _put_rio(self, filename, stanzas, header):
2290
 
        self._must_be_locked()
2291
 
        my_file = _mod_rio.rio_file(stanzas, header)
2292
 
        self._transport.put_file(filename, my_file,
2293
 
            mode=self.bzrdir._get_file_mode())
2294
 
 
2295
 
    @needs_tree_write_lock
2296
 
    def set_merge_modified(self, modified_hashes):
2297
 
        def iter_stanzas():
2298
 
            for file_id, hash in modified_hashes.iteritems():
2299
 
                yield _mod_rio.Stanza(file_id=file_id.decode('utf8'),
2300
 
                    hash=hash)
2301
 
        self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
2302
 
 
2303
2286
    @needs_read_lock
2304
2287
    def merge_modified(self):
2305
2288
        """Return a dictionary of files modified by a merge.
3030
3013
    supports_versioned_directories = None
3031
3014
 
3032
3015
    @classmethod
3033
 
    def find_format_string(klass, controldir):
3034
 
        """Return format name for the working tree object in controldir."""
 
3016
    def find_format_string(klass, a_bzrdir):
 
3017
        """Return format name for the working tree object in a_bzrdir."""
3035
3018
        try:
3036
 
            transport = controldir.get_workingtree_transport(None)
 
3019
            transport = a_bzrdir.get_workingtree_transport(None)
3037
3020
            return transport.get_bytes("format")
3038
3021
        except errors.NoSuchFile:
3039
3022
            raise errors.NoWorkingTree(base=transport.base)
3040
3023
 
3041
3024
    @classmethod
3042
 
    def find_format(klass, controldir):
3043
 
        """Return the format for the working tree object in controldir."""
 
3025
    def find_format(klass, a_bzrdir):
 
3026
        """Return the format for the working tree object in a_bzrdir."""
3044
3027
        try:
3045
 
            format_string = klass.find_format_string(controldir)
 
3028
            format_string = klass.find_format_string(a_bzrdir)
3046
3029
            return format_registry.get(format_string)
3047
3030
        except KeyError:
3048
3031
            raise errors.UnknownFormatError(format=format_string,
3049
3032
                                            kind="working tree")
3050
3033
 
3051
 
    def initialize(self, controldir, revision_id=None, from_branch=None,
 
3034
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
3052
3035
                   accelerator_tree=None, hardlink=False):
3053
 
        """Initialize a new working tree in controldir.
 
3036
        """Initialize a new working tree in a_bzrdir.
3054
3037
 
3055
 
        :param controldir: ControlDir to initialize the working tree in.
 
3038
        :param a_bzrdir: BzrDir to initialize the working tree in.
3056
3039
        :param revision_id: allows creating a working tree at a different
3057
3040
            revision than the branch is at.
3058
3041
        :param from_branch: Branch to checkout
3139
3122
    def unregister_format(klass, format):
3140
3123
        format_registry.remove(format)
3141
3124
 
3142
 
    def get_controldir_for_branch(self):
3143
 
        """Get the control directory format for creating branches.
3144
 
 
3145
 
        This is to support testing of working tree formats that can not exist
3146
 
        in the same control directory as a branch.
3147
 
        """
3148
 
        return self._matchingbzrdir
3149
 
 
3150
3125
 
3151
3126
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3152
3127
    "bzrlib.workingtree_4", "WorkingTreeFormat4")