~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree_4.py

  • Committer: Jelmer Vernooij
  • Date: 2011-04-09 19:25:42 UTC
  • mto: (5777.5.1 inventoryworkingtree)
  • mto: This revision was merged to the branch mainline in revision 5781.
  • Revision ID: jelmer@samba.org-20110409192542-8bbedp36s7nj928e
Split InventoryTree out of Tree.

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
from bzrlib import (
35
35
    bzrdir,
36
36
    cache_utf8,
37
 
    config,
38
 
    conflicts as _mod_conflicts,
39
37
    debug,
40
38
    dirstate,
41
39
    errors,
53
51
from bzrlib.decorators import needs_read_lock, needs_write_lock
54
52
from bzrlib.inventory import Inventory, ROOT_ID, entry_factory
55
53
from bzrlib.lock import LogicalLockResult
56
 
from bzrlib.lockable_files import LockableFiles
57
 
from bzrlib.lockdir import LockDir
58
54
from bzrlib.mutabletree import needs_tree_write_lock
59
55
from bzrlib.osutils import (
60
56
    file_kind,
69
65
    InventoryTree,
70
66
    )
71
67
from bzrlib.workingtree import (
72
 
    InventoryWorkingTree,
73
68
    WorkingTree,
74
 
    WorkingTreeFormat,
 
69
    WorkingTree3,
 
70
    WorkingTreeFormat3,
75
71
    )
76
72
 
77
73
 
78
 
class DirStateWorkingTree(InventoryWorkingTree):
 
74
class DirStateWorkingTree(WorkingTree3):
79
75
 
80
76
    def __init__(self, basedir,
81
77
                 branch,
132
128
            state.add(f, file_id, kind, None, '')
133
129
        self._make_dirty(reset_inventory=True)
134
130
 
135
 
    def _get_check_refs(self):
136
 
        """Return the references needed to perform a check of this tree."""
137
 
        return [('trees', self.last_revision())]
138
 
 
139
131
    def _make_dirty(self, reset_inventory):
140
132
        """Make the tree state dirty.
141
133
 
193
185
 
194
186
    def _comparison_data(self, entry, path):
195
187
        kind, executable, stat_value = \
196
 
            WorkingTree._comparison_data(self, entry, path)
 
188
            WorkingTree3._comparison_data(self, entry, path)
197
189
        # it looks like a plain directory, but it's really a reference -- see
198
190
        # also kind()
199
191
        if (self._repo_supports_tree_reference and kind == 'directory'
205
197
    def commit(self, message=None, revprops=None, *args, **kwargs):
206
198
        # mark the tree as dirty post commit - commit
207
199
        # can change the current versioned list by doing deletes.
208
 
        result = WorkingTree.commit(self, message, revprops, *args, **kwargs)
 
200
        result = WorkingTree3.commit(self, message, revprops, *args, **kwargs)
209
201
        self._make_dirty(reset_inventory=True)
210
202
        return result
211
203
 
230
222
        local_path = self.bzrdir.get_workingtree_transport(None
231
223
            ).local_abspath('dirstate')
232
224
        self._dirstate = dirstate.DirState.on_file(local_path,
233
 
            self._sha1_provider(), self._worth_saving_limit())
 
225
            self._sha1_provider())
234
226
        return self._dirstate
235
227
 
236
228
    def _sha1_provider(self):
245
237
        else:
246
238
            return None
247
239
 
248
 
    def _worth_saving_limit(self):
249
 
        """How many hash changes are ok before we must save the dirstate.
250
 
 
251
 
        :return: an integer. -1 means never save.
252
 
        """
253
 
        # FIXME: We want a WorkingTreeStack here -- vila 20110812
254
 
        conf = config.BranchStack(self.branch)
255
 
        return conf.get('bzr.workingtree.worth_saving_limit')
256
 
 
257
240
    def filter_unversioned_files(self, paths):
258
241
        """Filter out paths that are versioned.
259
242
 
870
853
                rollback_rename()
871
854
                raise
872
855
            result.append((from_rel, to_rel))
873
 
            state._mark_modified()
 
856
            state._dirblock_state = dirstate.DirState.IN_MEMORY_MODIFIED
874
857
            self._make_dirty(reset_inventory=False)
875
858
 
876
859
        return result
1133
1116
                        _mod_revision.NULL_REVISION)))
1134
1117
                ghosts.append(rev_id)
1135
1118
            accepted_revisions.add(rev_id)
1136
 
        updated = False
1137
 
        if (len(real_trees) == 1
1138
 
            and not ghosts
1139
 
            and self.branch.repository._format.fast_deltas
1140
 
            and isinstance(real_trees[0][1],
1141
 
                revisiontree.InventoryRevisionTree)
1142
 
            and self.get_parent_ids()):
1143
 
            rev_id, rev_tree = real_trees[0]
1144
 
            basis_id = self.get_parent_ids()[0]
1145
 
            # There are times when basis_tree won't be in
1146
 
            # self.branch.repository, (switch, for example)
1147
 
            try:
1148
 
                basis_tree = self.branch.repository.revision_tree(basis_id)
1149
 
            except errors.NoSuchRevision:
1150
 
                # Fall back to the set_parent_trees(), since we can't use
1151
 
                # _make_delta if we can't get the RevisionTree
1152
 
                pass
1153
 
            else:
1154
 
                delta = rev_tree.inventory._make_delta(basis_tree.inventory)
1155
 
                dirstate.update_basis_by_delta(delta, rev_id)
1156
 
                updated = True
1157
 
        if not updated:
1158
 
            dirstate.set_parent_trees(real_trees, ghosts=ghosts)
 
1119
        dirstate.set_parent_trees(real_trees, ghosts=ghosts)
1159
1120
        self._make_dirty(reset_inventory=False)
1160
1121
 
1161
1122
    def _set_root_id(self, file_id):
1181
1142
 
1182
1143
    def unlock(self):
1183
1144
        """Unlock in format 4 trees needs to write the entire dirstate."""
 
1145
        # do non-implementation specific cleanup
 
1146
        self._cleanup()
 
1147
 
1184
1148
        if self._control_files._lock_count == 1:
1185
 
            # do non-implementation specific cleanup
1186
 
            self._cleanup()
1187
 
 
1188
1149
            # eventually we should do signature checking during read locks for
1189
1150
            # dirstate updates.
1190
1151
            if self._control_files._lock_mode == 'w':
1412
1373
class WorkingTree4(DirStateWorkingTree):
1413
1374
    """This is the Format 4 working tree.
1414
1375
 
1415
 
    This differs from WorkingTree by:
 
1376
    This differs from WorkingTree3 by:
1416
1377
     - Having a consolidated internal dirstate, stored in a
1417
1378
       randomly-accessible sorted file on disk.
1418
1379
     - Not having a regular inventory attribute.  One can be synthesized
1446
1407
        return views.PathBasedViews(self)
1447
1408
 
1448
1409
 
1449
 
class DirStateWorkingTreeFormat(WorkingTreeFormat):
 
1410
class DirStateWorkingTreeFormat(WorkingTreeFormat3):
1450
1411
 
1451
1412
    missing_parent_conflicts = True
1452
1413
 
1453
 
    supports_versioned_directories = True
1454
 
 
1455
 
    _lock_class = LockDir
1456
 
    _lock_file_name = 'lock'
1457
 
 
1458
 
    def _open_control_files(self, a_bzrdir):
1459
 
        transport = a_bzrdir.get_workingtree_transport(None)
1460
 
        return LockableFiles(transport, self._lock_file_name,
1461
 
                             self._lock_class)
1462
 
 
1463
1414
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1464
1415
                   accelerator_tree=None, hardlink=False):
1465
1416
        """See WorkingTreeFormat.initialize().
1466
1417
 
1467
1418
        :param revision_id: allows creating a working tree at a different
1468
 
            revision than the branch is at.
 
1419
        revision than the branch is at.
1469
1420
        :param accelerator_tree: A tree which can be used for retrieving file
1470
1421
            contents more quickly than the revision tree, i.e. a workingtree.
1471
1422
            The revision tree will be used for cases where accelerator_tree's
1564
1515
        :param wt: the WorkingTree object
1565
1516
        """
1566
1517
 
1567
 
    def open(self, a_bzrdir, _found=False):
1568
 
        """Return the WorkingTree object for a_bzrdir
1569
 
 
1570
 
        _found is a private parameter, do not use it. It is used to indicate
1571
 
               if format probing has already been done.
1572
 
        """
1573
 
        if not _found:
1574
 
            # we are being called directly and must probe.
1575
 
            raise NotImplementedError
1576
 
        if not isinstance(a_bzrdir.transport, LocalTransport):
1577
 
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
1578
 
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
1579
 
        return wt
1580
 
 
1581
1518
    def _open(self, a_bzrdir, control_files):
1582
1519
        """Open the tree itself.
1583
1520
 
1608
1545
    This format:
1609
1546
        - exists within a metadir controlling .bzr
1610
1547
        - includes an explicit version marker for the workingtree control
1611
 
          files, separate from the ControlDir format
 
1548
          files, separate from the BzrDir format
1612
1549
        - modifies the hash cache format
1613
1550
        - is new in bzr 0.15
1614
1551
        - uses a LockDir to guard access to it.
1699
1636
    def annotate_iter(self, file_id,
1700
1637
                      default_revision=_mod_revision.CURRENT_REVISION):
1701
1638
        """See Tree.annotate_iter"""
1702
 
        text_key = (file_id, self.get_file_revision(file_id))
 
1639
        text_key = (file_id, self.inventory[file_id].revision)
1703
1640
        annotations = self._repository.texts.annotate(text_key)
1704
1641
        return [(key[-1], line) for (key, line) in annotations]
1705
1642
 
 
1643
    def _get_ancestors(self, default_revision):
 
1644
        return set(self._repository.get_ancestry(self._revision_id,
 
1645
                                                 topo_sorted=False))
1706
1646
    def _comparison_data(self, entry, path):
1707
1647
        """See Tree._comparison_data."""
1708
1648
        if entry is None:
1849
1789
        # Make sure the file exists
1850
1790
        entry = self._get_entry(file_id, path=path)
1851
1791
        if entry == (None, None): # do we raise?
1852
 
            raise errors.NoSuchId(self, file_id)
 
1792
            return None
1853
1793
        parent_index = self._get_parent_index()
1854
1794
        last_changed_revision = entry[1][parent_index][4]
1855
1795
        try:
1866
1806
            return parent_details[1]
1867
1807
        return None
1868
1808
 
1869
 
    @needs_read_lock
1870
 
    def get_file_revision(self, file_id):
1871
 
        return self.inventory[file_id].revision
1872
 
 
1873
1809
    def get_file(self, file_id, path=None):
1874
1810
        return StringIO(self.get_file_text(file_id))
1875
1811
 
1898
1834
                                       identifier))
1899
1835
        return self._repository.iter_files_bytes(repo_desired_files)
1900
1836
 
1901
 
    def get_symlink_target(self, file_id, path=None):
 
1837
    def get_symlink_target(self, file_id):
1902
1838
        entry = self._get_entry(file_id=file_id)
1903
1839
        parent_index = self._get_parent_index()
1904
1840
        if entry[1][parent_index][0] != 'l':
2076
2012
    def make_source_parent_tree(source, target):
2077
2013
        """Change the source tree into a parent of the target."""
2078
2014
        revid = source.commit('record tree')
2079
 
        target.branch.fetch(source.branch, revid)
 
2015
        target.branch.repository.fetch(source.branch.repository, revid)
2080
2016
        target.set_parent_ids([revid])
2081
2017
        return target.basis_tree(), target
2082
2018