/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: Vincent Ladeuil
  • Date: 2012-01-18 14:09:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120118140919-rlvdrhpc0nq1lbwi
Change set/remove to require a lock for the branch config files.

This means that tests (or any plugin for that matter) do not requires an
explicit lock on the branch anymore to change a single option. This also
means the optimisation becomes "opt-in" and as such won't be as
spectacular as it may be and/or harder to get right (nothing fails
anymore).

This reduces the diff by ~300 lines.

Code/tests that were updating more than one config option is still taking
a lock to at least avoid some IOs and demonstrate the benefits through
the decreased number of hpss calls.

The duplication between BranchStack and BranchOnlyStack will be removed
once the same sharing is in place for local config files, at which point
the Stack class itself may be able to host the changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2012 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
38
38
    cache_utf8,
39
39
    config,
40
40
    conflicts as _mod_conflicts,
41
 
    controldir,
42
41
    debug,
43
42
    dirstate,
44
43
    errors,
58
57
from bzrlib.lock import LogicalLockResult
59
58
from bzrlib.lockable_files import LockableFiles
60
59
from bzrlib.lockdir import LockDir
61
 
from bzrlib.mutabletree import (
62
 
    MutableTree,
63
 
    needs_tree_write_lock,
64
 
    )
 
60
from bzrlib.mutabletree import needs_tree_write_lock
65
61
from bzrlib.osutils import (
66
62
    file_kind,
67
63
    isdir,
69
65
    realpath,
70
66
    safe_unicode,
71
67
    )
72
 
from bzrlib.symbol_versioning import (
73
 
    deprecated_in,
74
 
    deprecated_method,
75
 
    )
76
68
from bzrlib.transport.local import LocalTransport
77
69
from bzrlib.tree import (
78
70
    InterTree,
260
252
 
261
253
        :return: an integer. -1 means never save.
262
254
        """
263
 
        conf = self.get_config_stack()
 
255
        # FIXME: We want a WorkingTreeStack here -- vila 20110812
 
256
        conf = config.BranchStack(self.branch)
264
257
        return conf.get('bzr.workingtree.worth_saving_limit')
265
258
 
266
259
    def filter_unversioned_files(self, paths):
419
412
                return link_or_sha1
420
413
        return None
421
414
 
422
 
    def _get_root_inventory(self):
 
415
    def _get_inventory(self):
423
416
        """Get the inventory for the tree. This is only valid within a lock."""
424
417
        if 'evil' in debug.debug_flags:
425
418
            trace.mutter_callsite(2,
430
423
        self._generate_inventory()
431
424
        return self._inventory
432
425
 
433
 
    @deprecated_method(deprecated_in((2, 5, 0)))
434
 
    def _get_inventory(self):
435
 
        return self.root_inventory
436
 
 
437
426
    inventory = property(_get_inventory,
438
427
                         doc="Inventory of this Tree")
439
428
 
440
 
    root_inventory = property(_get_root_inventory,
441
 
        "Root inventory of this tree")
442
 
 
443
429
    @needs_read_lock
444
430
    def get_parent_ids(self):
445
431
        """See Tree.get_parent_ids.
692
678
 
693
679
        if self._inventory is not None:
694
680
            update_inventory = True
695
 
            inv = self.root_inventory
 
681
            inv = self.inventory
696
682
            to_dir_id = to_entry[0][2]
697
683
            to_dir_ie = inv[to_dir_id]
698
684
        else:
894
880
    @needs_read_lock
895
881
    def path2id(self, path):
896
882
        """Return the id for path in this tree."""
897
 
        if isinstance(path, list):
898
 
            if path == []:
899
 
                path = [""]
900
 
            path = osutils.pathjoin(*path)
901
883
        path = path.strip('/')
902
884
        entry = self._get_entry(path=path)
903
885
        if entry == (None, None):
1051
1033
 
1052
1034
        This is a meaningless operation for dirstate, but we obey it anyhow.
1053
1035
        """
1054
 
        return self.root_inventory
 
1036
        return self.inventory
1055
1037
 
1056
1038
    @needs_read_lock
1057
1039
    def revision_tree(self, revision_id):
1165
1147
                # _make_delta if we can't get the RevisionTree
1166
1148
                pass
1167
1149
            else:
1168
 
                delta = rev_tree.root_inventory._make_delta(
1169
 
                    basis_tree.root_inventory)
 
1150
                delta = rev_tree.inventory._make_delta(basis_tree.inventory)
1170
1151
                dirstate.update_basis_by_delta(delta, rev_id)
1171
1152
                updated = True
1172
1153
        if not updated:
1343
1324
        # being created.
1344
1325
        self._inventory = None
1345
1326
        # generate a delta,
1346
 
        delta = inv._make_delta(self.root_inventory)
 
1327
        delta = inv._make_delta(self.inventory)
1347
1328
        # and apply it.
1348
1329
        self.apply_inventory_delta(delta)
1349
1330
        if had_inventory:
1369
1350
            base_tree = trees[0][1]
1370
1351
        state = self.current_dirstate()
1371
1352
        # We don't support ghosts yet
1372
 
        state.set_state_from_scratch(base_tree.root_inventory, trees, [])
 
1353
        state.set_state_from_scratch(base_tree.inventory, trees, [])
1373
1354
 
1374
1355
 
1375
1356
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1563
1544
                transform.build_tree(basis, wt, accelerator_tree,
1564
1545
                                     hardlink=hardlink,
1565
1546
                                     delta_from_tree=delta_from_tree)
1566
 
                for hook in MutableTree.hooks['post_build_tree']:
1567
 
                    hook(wt)
1568
1547
            finally:
1569
1548
                basis.unlock()
1570
1549
        finally:
1613
1592
    def _get_matchingbzrdir(self):
1614
1593
        """Overrideable method to get a bzrdir for testing."""
1615
1594
        # please test against something that will let us do tree references
1616
 
        return controldir.format_registry.make_bzrdir(
1617
 
            'development-subtree')
 
1595
        return bzrdir.format_registry.make_bzrdir(
 
1596
            'dirstate-with-subtree')
1618
1597
 
1619
1598
    _matchingbzrdir = property(__get_matchingbzrdir)
1620
1599
 
1693
1672
    def supports_views(self):
1694
1673
        return True
1695
1674
 
1696
 
    def _get_matchingbzrdir(self):
1697
 
        """Overrideable method to get a bzrdir for testing."""
1698
 
        # We use 'development-subtree' instead of '2a', because we have a
1699
 
        # few tests that want to test tree references
1700
 
        return bzrdir.format_registry.make_bzrdir('development-subtree')
1701
 
 
1702
1675
 
1703
1676
class DirStateRevisionTree(InventoryTree):
1704
1677
    """A revision tree pulling the inventory from a dirstate.
1787
1760
        if path is not None:
1788
1761
            path = path.encode('utf8')
1789
1762
        parent_index = self._get_parent_index()
1790
 
        return self._dirstate._get_entry(parent_index, fileid_utf8=file_id,
1791
 
            path_utf8=path)
 
1763
        return self._dirstate._get_entry(parent_index, fileid_utf8=file_id, path_utf8=path)
1792
1764
 
1793
1765
    def _generate_inventory(self):
1794
1766
        """Create and set self.inventory from the dirstate object.
1895
1867
 
1896
1868
    @needs_read_lock
1897
1869
    def get_file_revision(self, file_id):
1898
 
        inv, inv_file_id = self._unpack_file_id(file_id)
1899
 
        return inv[inv_file_id].revision
 
1870
        return self.inventory[file_id].revision
1900
1871
 
1901
1872
    def get_file(self, file_id, path=None):
1902
1873
        return StringIO(self.get_file_text(file_id))
1903
1874
 
1904
1875
    def get_file_size(self, file_id):
1905
1876
        """See Tree.get_file_size"""
1906
 
        inv, inv_file_id = self._unpack_file_id(file_id)
1907
 
        return inv[inv_file_id].text_size
 
1877
        return self.inventory[file_id].text_size
1908
1878
 
1909
1879
    def get_file_text(self, file_id, path=None):
1910
 
        content = None
1911
 
        for _, content_iter in self.iter_files_bytes([(file_id, None)]):
1912
 
            if content is not None:
1913
 
                raise AssertionError('iter_files_bytes returned'
1914
 
                    ' too many entries')
1915
 
            # For each entry returned by iter_files_bytes, we must consume the
1916
 
            # content_iter before we step the files iterator.
1917
 
            content = ''.join(content_iter)
1918
 
        if content is None:
1919
 
            raise AssertionError('iter_files_bytes did not return'
1920
 
                ' the requested data')
1921
 
        return content
 
1880
        _, content = list(self.iter_files_bytes([(file_id, None)]))[0]
 
1881
        return ''.join(content)
1922
1882
 
1923
1883
    def get_reference_revision(self, file_id, path=None):
1924
 
        inv, inv_file_id = self._unpack_file_id(file_id)
1925
 
        return inv[inv_file_id].reference_revision
 
1884
        return self.inventory[file_id].reference_revision
1926
1885
 
1927
1886
    def iter_files_bytes(self, desired_files):
1928
1887
        """See Tree.iter_files_bytes.
1952
1911
        """Return the revision id for this tree."""
1953
1912
        return self._revision_id
1954
1913
 
1955
 
    def _get_root_inventory(self):
 
1914
    def _get_inventory(self):
1956
1915
        if self._inventory is not None:
1957
1916
            return self._inventory
1958
1917
        self._must_be_locked()
1959
1918
        self._generate_inventory()
1960
1919
        return self._inventory
1961
1920
 
1962
 
    root_inventory = property(_get_root_inventory,
1963
 
                         doc="Inventory of this Tree")
1964
 
 
1965
 
    @deprecated_method(deprecated_in((2, 5, 0)))
1966
 
    def _get_inventory(self):
1967
 
        return self.root_inventory
1968
 
 
1969
1921
    inventory = property(_get_inventory,
1970
1922
                         doc="Inventory of this Tree")
1971
1923
 
1989
1941
 
1990
1942
    def path_content_summary(self, path):
1991
1943
        """See Tree.path_content_summary."""
1992
 
        inv, inv_file_id = self._path2inv_file_id(path)
1993
 
        if inv_file_id is None:
 
1944
        id = self.inventory.path2id(path)
 
1945
        if id is None:
1994
1946
            return ('missing', None, None, None)
1995
 
        entry = inv[inv_file_id]
 
1947
        entry = self._inventory[id]
1996
1948
        kind = entry.kind
1997
1949
        if kind == 'file':
1998
1950
            return (kind, entry.text_size, entry.executable, entry.text_sha1)
2002
1954
            return (kind, None, None, None)
2003
1955
 
2004
1956
    def is_executable(self, file_id, path=None):
2005
 
        inv, inv_file_id = self._unpack_file_id(file_id)
2006
 
        ie = inv[inv_file_id]
 
1957
        ie = self.inventory[file_id]
2007
1958
        if ie.kind != "file":
2008
1959
            return False
2009
1960
        return ie.executable
2014
1965
    def list_files(self, include_root=False, from_dir=None, recursive=True):
2015
1966
        # We use a standard implementation, because DirStateRevisionTree is
2016
1967
        # dealing with one of the parents of the current state
 
1968
        inv = self._get_inventory()
2017
1969
        if from_dir is None:
2018
 
            inv = self.root_inventory
2019
1970
            from_dir_id = None
2020
1971
        else:
2021
 
            inv, from_dir_id = self._path2inv_file_id(from_dir)
 
1972
            from_dir_id = inv.path2id(from_dir)
2022
1973
            if from_dir_id is None:
2023
1974
                # Directory not versioned
2024
1975
                return
2025
 
        # FIXME: Support nested trees
2026
1976
        entries = inv.iter_entries(from_dir=from_dir_id, recursive=recursive)
2027
1977
        if inv.root is not None and not include_root and from_dir is None:
2028
1978
            entries.next()
2050
2000
    def path2id(self, path):
2051
2001
        """Return the id for path in this tree."""
2052
2002
        # lookup by path: faster than splitting and walking the ivnentory.
2053
 
        if isinstance(path, list):
2054
 
            if path == []:
2055
 
                path = [""]
2056
 
            path = osutils.pathjoin(*path)
2057
2003
        entry = self._get_entry(path=path)
2058
2004
        if entry == (None, None):
2059
2005
            return None
2082
2028
        # So for now, we just build up the parent inventory, and extract
2083
2029
        # it the same way RevisionTree does.
2084
2030
        _directory = 'directory'
2085
 
        inv = self._get_root_inventory()
 
2031
        inv = self._get_inventory()
2086
2032
        top_id = inv.path2id(prefix)
2087
2033
        if top_id is None:
2088
2034
            pending = []