/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 bzrlib/workingtree_4.py

  • Committer: Jonathan Riddell
  • Date: 2011-05-25 13:07:26 UTC
  • mto: This revision was merged to the branch mainline in revision 5914.
  • Revision ID: jriddell@canonical.com-20110525130726-rgvup0ktqxn4ct9r
fix unescapted \n needed by sphinx

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 Canonical Ltd
 
1
# Copyright (C) 2007-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
31
31
import errno
32
32
import stat
33
33
 
34
 
import bzrlib
35
34
from bzrlib import (
36
35
    bzrdir,
37
36
    cache_utf8,
 
37
    conflicts as _mod_conflicts,
38
38
    debug,
39
39
    dirstate,
40
40
    errors,
 
41
    filters as _mod_filters,
41
42
    generate_ids,
42
43
    osutils,
43
44
    revision as _mod_revision,
46
47
    transform,
47
48
    views,
48
49
    )
49
 
import bzrlib.branch
50
 
import bzrlib.ui
51
50
""")
52
51
 
53
52
from bzrlib.decorators import needs_read_lock, needs_write_lock
54
 
from bzrlib.filters import filtered_input_file, internal_size_sha_file_byname
55
53
from bzrlib.inventory import Inventory, ROOT_ID, entry_factory
 
54
from bzrlib.lock import LogicalLockResult
 
55
from bzrlib.lockable_files import LockableFiles
 
56
from bzrlib.lockdir import LockDir
56
57
from bzrlib.mutabletree import needs_tree_write_lock
57
58
from bzrlib.osutils import (
58
59
    file_kind,
61
62
    realpath,
62
63
    safe_unicode,
63
64
    )
64
 
from bzrlib.trace import mutter
65
65
from bzrlib.transport.local import LocalTransport
66
 
from bzrlib.tree import InterTree
67
 
from bzrlib.tree import Tree
68
 
from bzrlib.workingtree import WorkingTree, WorkingTree3, WorkingTreeFormat3
69
 
 
70
 
 
71
 
class DirStateWorkingTree(WorkingTree3):
 
66
from bzrlib.tree import (
 
67
    InterTree,
 
68
    InventoryTree,
 
69
    )
 
70
from bzrlib.workingtree import (
 
71
    InventoryWorkingTree,
 
72
    WorkingTree,
 
73
    WorkingTreeFormat,
 
74
    )
 
75
 
 
76
 
 
77
class DirStateWorkingTree(InventoryWorkingTree):
 
78
 
 
79
    _DEFAULT_WORTH_SAVING_LIMIT = 10
 
80
 
72
81
    def __init__(self, basedir,
73
82
                 branch,
74
83
                 _control_files=None,
84
93
        self._format = _format
85
94
        self.bzrdir = _bzrdir
86
95
        basedir = safe_unicode(basedir)
87
 
        mutter("opening working tree %r", basedir)
 
96
        trace.mutter("opening working tree %r", basedir)
88
97
        self._branch = branch
89
98
        self.basedir = realpath(basedir)
90
99
        # if branch is at our basedir and is a format 6 or less
124
133
            state.add(f, file_id, kind, None, '')
125
134
        self._make_dirty(reset_inventory=True)
126
135
 
 
136
    def _get_check_refs(self):
 
137
        """Return the references needed to perform a check of this tree."""
 
138
        return [('trees', self.last_revision())]
 
139
 
127
140
    def _make_dirty(self, reset_inventory):
128
141
        """Make the tree state dirty.
129
142
 
181
194
 
182
195
    def _comparison_data(self, entry, path):
183
196
        kind, executable, stat_value = \
184
 
            WorkingTree3._comparison_data(self, entry, path)
 
197
            WorkingTree._comparison_data(self, entry, path)
185
198
        # it looks like a plain directory, but it's really a reference -- see
186
199
        # also kind()
187
200
        if (self._repo_supports_tree_reference and kind == 'directory'
193
206
    def commit(self, message=None, revprops=None, *args, **kwargs):
194
207
        # mark the tree as dirty post commit - commit
195
208
        # can change the current versioned list by doing deletes.
196
 
        result = WorkingTree3.commit(self, message, revprops, *args, **kwargs)
 
209
        result = WorkingTree.commit(self, message, revprops, *args, **kwargs)
197
210
        self._make_dirty(reset_inventory=True)
198
211
        return result
199
212
 
218
231
        local_path = self.bzrdir.get_workingtree_transport(None
219
232
            ).local_abspath('dirstate')
220
233
        self._dirstate = dirstate.DirState.on_file(local_path,
221
 
            self._sha1_provider())
 
234
            self._sha1_provider(), self._worth_saving_limit())
222
235
        return self._dirstate
223
236
 
224
237
    def _sha1_provider(self):
233
246
        else:
234
247
            return None
235
248
 
 
249
    def _worth_saving_limit(self):
 
250
        """How many hash changes are ok before we must save the dirstate.
 
251
 
 
252
        :return: an integer. -1 means never save.
 
253
        """
 
254
        config = self.branch.get_config()
 
255
        val = config.get_user_option('bzr.workingtree.worth_saving_limit')
 
256
        if val is None:
 
257
            val = self._DEFAULT_WORTH_SAVING_LIMIT
 
258
        else:
 
259
            try:
 
260
                val = int(val)
 
261
            except ValueError, e:
 
262
                trace.warning('Invalid config value for'
 
263
                              ' "bzr.workingtree.worth_saving_limit"'
 
264
                              ' value %r is not an integer.'
 
265
                              % (val,))
 
266
                val = self._DEFAULT_WORTH_SAVING_LIMIT
 
267
        return val
 
268
 
236
269
    def filter_unversioned_files(self, paths):
237
270
        """Filter out paths that are versioned.
238
271
 
368
401
        state = self.current_dirstate()
369
402
        if stat_value is None:
370
403
            try:
371
 
                stat_value = os.lstat(file_abspath)
 
404
                stat_value = osutils.lstat(file_abspath)
372
405
            except OSError, e:
373
406
                if e.errno == errno.ENOENT:
374
407
                    return None
477
510
            self._must_be_locked()
478
511
            if not path:
479
512
                path = self.id2path(file_id)
480
 
            mode = os.lstat(self.abspath(path)).st_mode
 
513
            mode = osutils.lstat(self.abspath(path)).st_mode
481
514
            return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
482
515
 
483
516
    def all_file_ids(self):
567
600
            return _mod_revision.NULL_REVISION
568
601
 
569
602
    def lock_read(self):
570
 
        """See Branch.lock_read, and WorkingTree.unlock."""
 
603
        """See Branch.lock_read, and WorkingTree.unlock.
 
604
 
 
605
        :return: A bzrlib.lock.LogicalLockResult.
 
606
        """
571
607
        self.branch.lock_read()
572
608
        try:
573
609
            self._control_files.lock_read()
586
622
        except:
587
623
            self.branch.unlock()
588
624
            raise
 
625
        return LogicalLockResult(self.unlock)
589
626
 
590
627
    def _lock_self_write(self):
591
628
        """This should be called after the branch is locked."""
606
643
        except:
607
644
            self.branch.unlock()
608
645
            raise
 
646
        return LogicalLockResult(self.unlock)
609
647
 
610
648
    def lock_tree_write(self):
611
 
        """See MutableTree.lock_tree_write, and WorkingTree.unlock."""
 
649
        """See MutableTree.lock_tree_write, and WorkingTree.unlock.
 
650
 
 
651
        :return: A bzrlib.lock.LogicalLockResult.
 
652
        """
612
653
        self.branch.lock_read()
613
 
        self._lock_self_write()
 
654
        return self._lock_self_write()
614
655
 
615
656
    def lock_write(self):
616
 
        """See MutableTree.lock_write, and WorkingTree.unlock."""
 
657
        """See MutableTree.lock_write, and WorkingTree.unlock.
 
658
 
 
659
        :return: A bzrlib.lock.LogicalLockResult.
 
660
        """
617
661
        self.branch.lock_write()
618
 
        self._lock_self_write()
 
662
        return self._lock_self_write()
619
663
 
620
664
    @needs_tree_write_lock
621
665
    def move(self, from_paths, to_dir, after=False):
838
882
                rollback_rename()
839
883
                raise
840
884
            result.append((from_rel, to_rel))
841
 
            state._dirblock_state = dirstate.DirState.IN_MEMORY_MODIFIED
 
885
            state._mark_modified()
842
886
            self._make_dirty(reset_inventory=False)
843
887
 
844
888
        return result
1101
1145
                        _mod_revision.NULL_REVISION)))
1102
1146
                ghosts.append(rev_id)
1103
1147
            accepted_revisions.add(rev_id)
1104
 
        dirstate.set_parent_trees(real_trees, ghosts=ghosts)
 
1148
        updated = False
 
1149
        if (len(real_trees) == 1
 
1150
            and not ghosts
 
1151
            and self.branch.repository._format.fast_deltas
 
1152
            and isinstance(real_trees[0][1],
 
1153
                revisiontree.InventoryRevisionTree)
 
1154
            and self.get_parent_ids()):
 
1155
            rev_id, rev_tree = real_trees[0]
 
1156
            basis_id = self.get_parent_ids()[0]
 
1157
            # There are times when basis_tree won't be in
 
1158
            # self.branch.repository, (switch, for example)
 
1159
            try:
 
1160
                basis_tree = self.branch.repository.revision_tree(basis_id)
 
1161
            except errors.NoSuchRevision:
 
1162
                # Fall back to the set_parent_trees(), since we can't use
 
1163
                # _make_delta if we can't get the RevisionTree
 
1164
                pass
 
1165
            else:
 
1166
                delta = rev_tree.inventory._make_delta(basis_tree.inventory)
 
1167
                dirstate.update_basis_by_delta(delta, rev_id)
 
1168
                updated = True
 
1169
        if not updated:
 
1170
            dirstate.set_parent_trees(real_trees, ghosts=ghosts)
1105
1171
        self._make_dirty(reset_inventory=False)
1106
1172
 
1107
1173
    def _set_root_id(self, file_id):
1127
1193
 
1128
1194
    def unlock(self):
1129
1195
        """Unlock in format 4 trees needs to write the entire dirstate."""
1130
 
        # do non-implementation specific cleanup
1131
 
        self._cleanup()
1132
 
 
1133
1196
        if self._control_files._lock_count == 1:
 
1197
            # do non-implementation specific cleanup
 
1198
            self._cleanup()
 
1199
 
1134
1200
            # eventually we should do signature checking during read locks for
1135
1201
            # dirstate updates.
1136
1202
            if self._control_files._lock_mode == 'w':
1235
1301
        # have to change the legacy inventory too.
1236
1302
        if self._inventory is not None:
1237
1303
            for file_id in file_ids:
1238
 
                self._inventory.remove_recursive_id(file_id)
 
1304
                if self._inventory.has_id(file_id):
 
1305
                    self._inventory.remove_recursive_id(file_id)
1239
1306
 
1240
1307
    @needs_tree_write_lock
1241
1308
    def rename_one(self, from_rel, to_rel, after=False):
1242
1309
        """See WorkingTree.rename_one"""
1243
1310
        self.flush()
1244
 
        WorkingTree.rename_one(self, from_rel, to_rel, after)
 
1311
        super(DirStateWorkingTree, self).rename_one(from_rel, to_rel, after)
1245
1312
 
1246
1313
    @needs_tree_write_lock
1247
1314
    def apply_inventory_delta(self, changes):
1280
1347
            self._inventory = inv
1281
1348
        self.flush()
1282
1349
 
 
1350
    @needs_tree_write_lock
 
1351
    def reset_state(self, revision_ids=None):
 
1352
        """Reset the state of the working tree.
 
1353
 
 
1354
        This does a hard-reset to a last-known-good state. This is a way to
 
1355
        fix if something got corrupted (like the .bzr/checkout/dirstate file)
 
1356
        """
 
1357
        if revision_ids is None:
 
1358
            revision_ids = self.get_parent_ids()
 
1359
        if not revision_ids:
 
1360
            base_tree = self.branch.repository.revision_tree(
 
1361
                _mod_revision.NULL_REVISION)
 
1362
            trees = []
 
1363
        else:
 
1364
            trees = zip(revision_ids,
 
1365
                        self.branch.repository.revision_trees(revision_ids))
 
1366
            base_tree = trees[0][1]
 
1367
        state = self.current_dirstate()
 
1368
        # We don't support ghosts yet
 
1369
        state.set_state_from_scratch(base_tree.inventory, trees, [])
 
1370
 
1283
1371
 
1284
1372
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1285
1373
 
1290
1378
        """See dirstate.SHA1Provider.sha1()."""
1291
1379
        filters = self.tree._content_filter_stack(
1292
1380
            self.tree.relpath(osutils.safe_unicode(abspath)))
1293
 
        return internal_size_sha_file_byname(abspath, filters)[1]
 
1381
        return _mod_filters.internal_size_sha_file_byname(abspath, filters)[1]
1294
1382
 
1295
1383
    def stat_and_sha1(self, abspath):
1296
1384
        """See dirstate.SHA1Provider.stat_and_sha1()."""
1300
1388
        try:
1301
1389
            statvalue = os.fstat(file_obj.fileno())
1302
1390
            if filters:
1303
 
                file_obj = filtered_input_file(file_obj, filters)
 
1391
                file_obj = _mod_filters.filtered_input_file(file_obj, filters)
1304
1392
            sha1 = osutils.size_sha_file(file_obj)[1]
1305
1393
        finally:
1306
1394
            file_obj.close()
1317
1405
    def _file_content_summary(self, path, stat_result):
1318
1406
        # This is to support the somewhat obsolete path_content_summary method
1319
1407
        # with content filtering: see
1320
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/415508>.
 
1408
        # <https://bugs.launchpad.net/bzr/+bug/415508>.
1321
1409
        #
1322
1410
        # If the dirstate cache is up to date and knows the hash and size,
1323
1411
        # return that.
1336
1424
class WorkingTree4(DirStateWorkingTree):
1337
1425
    """This is the Format 4 working tree.
1338
1426
 
1339
 
    This differs from WorkingTree3 by:
 
1427
    This differs from WorkingTree by:
1340
1428
     - Having a consolidated internal dirstate, stored in a
1341
1429
       randomly-accessible sorted file on disk.
1342
1430
     - Not having a regular inventory attribute.  One can be synthesized
1370
1458
        return views.PathBasedViews(self)
1371
1459
 
1372
1460
 
1373
 
class DirStateWorkingTreeFormat(WorkingTreeFormat3):
 
1461
class DirStateWorkingTreeFormat(WorkingTreeFormat):
 
1462
 
 
1463
    missing_parent_conflicts = True
 
1464
 
 
1465
    _lock_class = LockDir
 
1466
    _lock_file_name = 'lock'
 
1467
 
 
1468
    def _open_control_files(self, a_bzrdir):
 
1469
        transport = a_bzrdir.get_workingtree_transport(None)
 
1470
        return LockableFiles(transport, self._lock_file_name,
 
1471
                             self._lock_class)
1374
1472
 
1375
1473
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1376
1474
                   accelerator_tree=None, hardlink=False):
1377
1475
        """See WorkingTreeFormat.initialize().
1378
1476
 
1379
1477
        :param revision_id: allows creating a working tree at a different
1380
 
        revision than the branch is at.
 
1478
            revision than the branch is at.
1381
1479
        :param accelerator_tree: A tree which can be used for retrieving file
1382
1480
            contents more quickly than the revision tree, i.e. a workingtree.
1383
1481
            The revision tree will be used for cases where accelerator_tree's
1476
1574
        :param wt: the WorkingTree object
1477
1575
        """
1478
1576
 
 
1577
    def open(self, a_bzrdir, _found=False):
 
1578
        """Return the WorkingTree object for a_bzrdir
 
1579
 
 
1580
        _found is a private parameter, do not use it. It is used to indicate
 
1581
               if format probing has already been done.
 
1582
        """
 
1583
        if not _found:
 
1584
            # we are being called directly and must probe.
 
1585
            raise NotImplementedError
 
1586
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
1587
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
1588
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
 
1589
        return wt
 
1590
 
1479
1591
    def _open(self, a_bzrdir, control_files):
1480
1592
        """Open the tree itself.
1481
1593
 
1572
1684
        return True
1573
1685
 
1574
1686
 
1575
 
class DirStateRevisionTree(Tree):
 
1687
class DirStateRevisionTree(InventoryTree):
1576
1688
    """A revision tree pulling the inventory from a dirstate.
1577
1689
    
1578
1690
    Note that this is one of the historical (ie revision) trees cached in the
1597
1709
    def annotate_iter(self, file_id,
1598
1710
                      default_revision=_mod_revision.CURRENT_REVISION):
1599
1711
        """See Tree.annotate_iter"""
1600
 
        text_key = (file_id, self.inventory[file_id].revision)
 
1712
        text_key = (file_id, self.get_file_revision(file_id))
1601
1713
        annotations = self._repository.texts.annotate(text_key)
1602
1714
        return [(key[-1], line) for (key, line) in annotations]
1603
1715
 
1725
1837
                elif kind == 'directory':
1726
1838
                    parent_ies[(dirname + '/' + name).strip('/')] = inv_entry
1727
1839
                elif kind == 'symlink':
1728
 
                    inv_entry.executable = False
1729
 
                    inv_entry.text_size = None
1730
1840
                    inv_entry.symlink_target = utf8_decode(fingerprint)[0]
1731
1841
                elif kind == 'tree-reference':
1732
1842
                    inv_entry.reference_revision = fingerprint or None
1769
1879
            return parent_details[1]
1770
1880
        return None
1771
1881
 
 
1882
    @needs_read_lock
 
1883
    def get_file_revision(self, file_id):
 
1884
        return self.inventory[file_id].revision
 
1885
 
1772
1886
    def get_file(self, file_id, path=None):
1773
1887
        return StringIO(self.get_file_text(file_id))
1774
1888
 
1797
1911
                                       identifier))
1798
1912
        return self._repository.iter_files_bytes(repo_desired_files)
1799
1913
 
1800
 
    def get_symlink_target(self, file_id):
 
1914
    def get_symlink_target(self, file_id, path=None):
1801
1915
        entry = self._get_entry(file_id=file_id)
1802
1916
        parent_index = self._get_parent_index()
1803
1917
        if entry[1][parent_index][0] != 'l':
1856
1970
    def is_executable(self, file_id, path=None):
1857
1971
        ie = self.inventory[file_id]
1858
1972
        if ie.kind != "file":
1859
 
            return None
 
1973
            return False
1860
1974
        return ie.executable
1861
1975
 
 
1976
    def is_locked(self):
 
1977
        return self._locked
 
1978
 
1862
1979
    def list_files(self, include_root=False, from_dir=None, recursive=True):
1863
1980
        # We use a standard implementation, because DirStateRevisionTree is
1864
1981
        # dealing with one of the parents of the current state
1877
1994
            yield path, 'V', entry.kind, entry.file_id, entry
1878
1995
 
1879
1996
    def lock_read(self):
1880
 
        """Lock the tree for a set of operations."""
 
1997
        """Lock the tree for a set of operations.
 
1998
 
 
1999
        :return: A bzrlib.lock.LogicalLockResult.
 
2000
        """
1881
2001
        if not self._locked:
1882
2002
            self._repository.lock_read()
1883
2003
            if self._dirstate._lock_token is None:
1884
2004
                self._dirstate.lock_read()
1885
2005
                self._dirstate_locked = True
1886
2006
        self._locked += 1
 
2007
        return LogicalLockResult(self.unlock)
1887
2008
 
1888
2009
    def _must_be_locked(self):
1889
2010
        if not self._locked:
1968
2089
    def make_source_parent_tree(source, target):
1969
2090
        """Change the source tree into a parent of the target."""
1970
2091
        revid = source.commit('record tree')
1971
 
        target.branch.repository.fetch(source.branch.repository, revid)
 
2092
        target.branch.fetch(source.branch, revid)
1972
2093
        target.set_parent_ids([revid])
1973
2094
        return target.basis_tree(), target
1974
2095