~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree_4.py

  • Committer: Marius Kruger
  • Date: 2012-06-10 22:48:08 UTC
  • mto: This revision was merged to the branch mainline in revision 6544.
  • Revision ID: amanic@gmail.com-20120610224808-s7qj3ep4zd21s0u7
use ui.ui_factory.show_user_warning to warn about not checking ssl certs, so that we only do it once

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
WorkingTree.open(dir).
23
23
"""
24
24
 
 
25
from __future__ import absolute_import
 
26
 
25
27
from cStringIO import StringIO
26
28
import os
27
29
import sys
34
36
from bzrlib import (
35
37
    bzrdir,
36
38
    cache_utf8,
 
39
    config,
37
40
    conflicts as _mod_conflicts,
 
41
    controldir,
38
42
    debug,
39
43
    dirstate,
40
44
    errors,
54
58
from bzrlib.lock import LogicalLockResult
55
59
from bzrlib.lockable_files import LockableFiles
56
60
from bzrlib.lockdir import LockDir
57
 
from bzrlib.mutabletree import needs_tree_write_lock
 
61
from bzrlib.mutabletree import (
 
62
    MutableTree,
 
63
    needs_tree_write_lock,
 
64
    )
58
65
from bzrlib.osutils import (
59
66
    file_kind,
60
67
    isdir,
62
69
    realpath,
63
70
    safe_unicode,
64
71
    )
 
72
from bzrlib.symbol_versioning import (
 
73
    deprecated_in,
 
74
    deprecated_method,
 
75
    )
65
76
from bzrlib.transport.local import LocalTransport
66
77
from bzrlib.tree import (
67
78
    InterTree,
70
81
from bzrlib.workingtree import (
71
82
    InventoryWorkingTree,
72
83
    WorkingTree,
73
 
    WorkingTreeFormat,
 
84
    WorkingTreeFormatMetaDir,
74
85
    )
75
86
 
76
87
 
77
88
class DirStateWorkingTree(InventoryWorkingTree):
78
89
 
79
 
    _DEFAULT_WORTH_SAVING_LIMIT = 10
80
 
 
81
90
    def __init__(self, basedir,
82
91
                 branch,
83
92
                 _control_files=None,
251
260
 
252
261
        :return: an integer. -1 means never save.
253
262
        """
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
 
263
        conf = self.get_config_stack()
 
264
        return conf.get('bzr.workingtree.worth_saving_limit')
268
265
 
269
266
    def filter_unversioned_files(self, paths):
270
267
        """Filter out paths that are versioned.
422
419
                return link_or_sha1
423
420
        return None
424
421
 
425
 
    def _get_inventory(self):
 
422
    def _get_root_inventory(self):
426
423
        """Get the inventory for the tree. This is only valid within a lock."""
427
424
        if 'evil' in debug.debug_flags:
428
425
            trace.mutter_callsite(2,
433
430
        self._generate_inventory()
434
431
        return self._inventory
435
432
 
 
433
    @deprecated_method(deprecated_in((2, 5, 0)))
 
434
    def _get_inventory(self):
 
435
        return self.root_inventory
 
436
 
436
437
    inventory = property(_get_inventory,
437
438
                         doc="Inventory of this Tree")
438
439
 
 
440
    root_inventory = property(_get_root_inventory,
 
441
        "Root inventory of this tree")
 
442
 
439
443
    @needs_read_lock
440
444
    def get_parent_ids(self):
441
445
        """See Tree.get_parent_ids.
488
492
            return False # Missing entries are not executable
489
493
        return entry[1][0][3] # Executable?
490
494
 
491
 
    if not osutils.supports_executable():
492
 
        def is_executable(self, file_id, path=None):
493
 
            """Test if a file is executable or not.
 
495
    def is_executable(self, file_id, path=None):
 
496
        """Test if a file is executable or not.
494
497
 
495
 
            Note: The caller is expected to take a read-lock before calling this.
496
 
            """
 
498
        Note: The caller is expected to take a read-lock before calling this.
 
499
        """
 
500
        if not self._supports_executable():
497
501
            entry = self._get_entry(file_id=file_id, path=path)
498
502
            if entry == (None, None):
499
503
                return False
500
504
            return entry[1][0][3]
501
 
 
502
 
        _is_executable_from_path_and_stat = \
503
 
            _is_executable_from_path_and_stat_from_basis
504
 
    else:
505
 
        def is_executable(self, file_id, path=None):
506
 
            """Test if a file is executable or not.
507
 
 
508
 
            Note: The caller is expected to take a read-lock before calling this.
509
 
            """
 
505
        else:
510
506
            self._must_be_locked()
511
507
            if not path:
512
508
                path = self.id2path(file_id)
696
692
 
697
693
        if self._inventory is not None:
698
694
            update_inventory = True
699
 
            inv = self.inventory
 
695
            inv = self.root_inventory
700
696
            to_dir_id = to_entry[0][2]
701
697
            to_dir_ie = inv[to_dir_id]
702
698
        else:
898
894
    @needs_read_lock
899
895
    def path2id(self, path):
900
896
        """Return the id for path in this tree."""
 
897
        if isinstance(path, list):
 
898
            if path == []:
 
899
                path = [""]
 
900
            path = osutils.pathjoin(*path)
901
901
        path = path.strip('/')
902
902
        entry = self._get_entry(path=path)
903
903
        if entry == (None, None):
981
981
                    all_versioned = False
982
982
                    break
983
983
            if not all_versioned:
984
 
                raise errors.PathsNotVersionedError(paths)
 
984
                raise errors.PathsNotVersionedError(
 
985
                    [p.decode('utf-8') for p in paths])
985
986
        # -- remove redundancy in supplied paths to prevent over-scanning --
986
987
        search_paths = osutils.minimum_path_selection(paths)
987
988
        # sketch:
1036
1037
            found_dir_names = set(dir_name_id[:2] for dir_name_id in found)
1037
1038
            for dir_name in split_paths:
1038
1039
                if dir_name not in found_dir_names:
1039
 
                    raise errors.PathsNotVersionedError(paths)
 
1040
                    raise errors.PathsNotVersionedError(
 
1041
                        [p.decode('utf-8') for p in paths])
1040
1042
 
1041
1043
        for dir_name_id, trees_info in found.iteritems():
1042
1044
            for index in search_indexes:
1049
1051
 
1050
1052
        This is a meaningless operation for dirstate, but we obey it anyhow.
1051
1053
        """
1052
 
        return self.inventory
 
1054
        return self.root_inventory
1053
1055
 
1054
1056
    @needs_read_lock
1055
1057
    def revision_tree(self, revision_id):
1163
1165
                # _make_delta if we can't get the RevisionTree
1164
1166
                pass
1165
1167
            else:
1166
 
                delta = rev_tree.inventory._make_delta(basis_tree.inventory)
 
1168
                delta = rev_tree.root_inventory._make_delta(
 
1169
                    basis_tree.root_inventory)
1167
1170
                dirstate.update_basis_by_delta(delta, rev_id)
1168
1171
                updated = True
1169
1172
        if not updated:
1340
1343
        # being created.
1341
1344
        self._inventory = None
1342
1345
        # generate a delta,
1343
 
        delta = inv._make_delta(self.inventory)
 
1346
        delta = inv._make_delta(self.root_inventory)
1344
1347
        # and apply it.
1345
1348
        self.apply_inventory_delta(delta)
1346
1349
        if had_inventory:
1366
1369
            base_tree = trees[0][1]
1367
1370
        state = self.current_dirstate()
1368
1371
        # We don't support ghosts yet
1369
 
        state.set_state_from_scratch(base_tree.inventory, trees, [])
 
1372
        state.set_state_from_scratch(base_tree.root_inventory, trees, [])
1370
1373
 
1371
1374
 
1372
1375
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1458
1461
        return views.PathBasedViews(self)
1459
1462
 
1460
1463
 
1461
 
class DirStateWorkingTreeFormat(WorkingTreeFormat):
 
1464
class DirStateWorkingTreeFormat(WorkingTreeFormatMetaDir):
1462
1465
 
1463
1466
    missing_parent_conflicts = True
1464
1467
 
1494
1497
        control_files = self._open_control_files(a_bzrdir)
1495
1498
        control_files.create_lock()
1496
1499
        control_files.lock_write()
1497
 
        transport.put_bytes('format', self.get_format_string(),
 
1500
        transport.put_bytes('format', self.as_string(),
1498
1501
            mode=a_bzrdir._get_file_mode())
1499
1502
        if from_branch is not None:
1500
1503
            branch = from_branch
1560
1563
                transform.build_tree(basis, wt, accelerator_tree,
1561
1564
                                     hardlink=hardlink,
1562
1565
                                     delta_from_tree=delta_from_tree)
 
1566
                for hook in MutableTree.hooks['post_build_tree']:
 
1567
                    hook(wt)
1563
1568
            finally:
1564
1569
                basis.unlock()
1565
1570
        finally:
1608
1613
    def _get_matchingbzrdir(self):
1609
1614
        """Overrideable method to get a bzrdir for testing."""
1610
1615
        # please test against something that will let us do tree references
1611
 
        return bzrdir.format_registry.make_bzrdir(
1612
 
            'dirstate-with-subtree')
 
1616
        return controldir.format_registry.make_bzrdir(
 
1617
            'development-subtree')
1613
1618
 
1614
1619
    _matchingbzrdir = property(__get_matchingbzrdir)
1615
1620
 
1620
1625
    This format:
1621
1626
        - exists within a metadir controlling .bzr
1622
1627
        - includes an explicit version marker for the workingtree control
1623
 
          files, separate from the BzrDir format
 
1628
          files, separate from the ControlDir format
1624
1629
        - modifies the hash cache format
1625
1630
        - is new in bzr 0.15
1626
1631
        - uses a LockDir to guard access to it.
1630
1635
 
1631
1636
    _tree_class = WorkingTree4
1632
1637
 
1633
 
    def get_format_string(self):
 
1638
    @classmethod
 
1639
    def get_format_string(cls):
1634
1640
        """See WorkingTreeFormat.get_format_string()."""
1635
1641
        return "Bazaar Working Tree Format 4 (bzr 0.15)\n"
1636
1642
 
1647
1653
 
1648
1654
    _tree_class = WorkingTree5
1649
1655
 
1650
 
    def get_format_string(self):
 
1656
    @classmethod
 
1657
    def get_format_string(cls):
1651
1658
        """See WorkingTreeFormat.get_format_string()."""
1652
1659
        return "Bazaar Working Tree Format 5 (bzr 1.11)\n"
1653
1660
 
1667
1674
 
1668
1675
    _tree_class = WorkingTree6
1669
1676
 
1670
 
    def get_format_string(self):
 
1677
    @classmethod
 
1678
    def get_format_string(cls):
1671
1679
        """See WorkingTreeFormat.get_format_string()."""
1672
1680
        return "Bazaar Working Tree Format 6 (bzr 1.14)\n"
1673
1681
 
1773
1781
        if path is not None:
1774
1782
            path = path.encode('utf8')
1775
1783
        parent_index = self._get_parent_index()
1776
 
        return self._dirstate._get_entry(parent_index, fileid_utf8=file_id, path_utf8=path)
 
1784
        return self._dirstate._get_entry(parent_index, fileid_utf8=file_id,
 
1785
            path_utf8=path)
1777
1786
 
1778
1787
    def _generate_inventory(self):
1779
1788
        """Create and set self.inventory from the dirstate object.
1861
1870
        # Make sure the file exists
1862
1871
        entry = self._get_entry(file_id, path=path)
1863
1872
        if entry == (None, None): # do we raise?
1864
 
            return None
 
1873
            raise errors.NoSuchId(self, file_id)
1865
1874
        parent_index = self._get_parent_index()
1866
1875
        last_changed_revision = entry[1][parent_index][4]
1867
1876
        try:
1880
1889
 
1881
1890
    @needs_read_lock
1882
1891
    def get_file_revision(self, file_id):
1883
 
        return self.inventory[file_id].revision
 
1892
        inv, inv_file_id = self._unpack_file_id(file_id)
 
1893
        return inv[inv_file_id].revision
1884
1894
 
1885
1895
    def get_file(self, file_id, path=None):
1886
1896
        return StringIO(self.get_file_text(file_id))
1887
1897
 
1888
1898
    def get_file_size(self, file_id):
1889
1899
        """See Tree.get_file_size"""
1890
 
        return self.inventory[file_id].text_size
 
1900
        inv, inv_file_id = self._unpack_file_id(file_id)
 
1901
        return inv[inv_file_id].text_size
1891
1902
 
1892
1903
    def get_file_text(self, file_id, path=None):
1893
1904
        _, content = list(self.iter_files_bytes([(file_id, None)]))[0]
1894
1905
        return ''.join(content)
1895
1906
 
1896
1907
    def get_reference_revision(self, file_id, path=None):
1897
 
        return self.inventory[file_id].reference_revision
 
1908
        inv, inv_file_id = self._unpack_file_id(file_id)
 
1909
        return inv[inv_file_id].reference_revision
1898
1910
 
1899
1911
    def iter_files_bytes(self, desired_files):
1900
1912
        """See Tree.iter_files_bytes.
1924
1936
        """Return the revision id for this tree."""
1925
1937
        return self._revision_id
1926
1938
 
1927
 
    def _get_inventory(self):
 
1939
    def _get_root_inventory(self):
1928
1940
        if self._inventory is not None:
1929
1941
            return self._inventory
1930
1942
        self._must_be_locked()
1931
1943
        self._generate_inventory()
1932
1944
        return self._inventory
1933
1945
 
 
1946
    root_inventory = property(_get_root_inventory,
 
1947
                         doc="Inventory of this Tree")
 
1948
 
 
1949
    @deprecated_method(deprecated_in((2, 5, 0)))
 
1950
    def _get_inventory(self):
 
1951
        return self.root_inventory
 
1952
 
1934
1953
    inventory = property(_get_inventory,
1935
1954
                         doc="Inventory of this Tree")
1936
1955
 
1954
1973
 
1955
1974
    def path_content_summary(self, path):
1956
1975
        """See Tree.path_content_summary."""
1957
 
        id = self.inventory.path2id(path)
1958
 
        if id is None:
 
1976
        inv, inv_file_id = self._path2inv_file_id(path)
 
1977
        if inv_file_id is None:
1959
1978
            return ('missing', None, None, None)
1960
 
        entry = self._inventory[id]
 
1979
        entry = inv[inv_file_id]
1961
1980
        kind = entry.kind
1962
1981
        if kind == 'file':
1963
1982
            return (kind, entry.text_size, entry.executable, entry.text_sha1)
1967
1986
            return (kind, None, None, None)
1968
1987
 
1969
1988
    def is_executable(self, file_id, path=None):
1970
 
        ie = self.inventory[file_id]
 
1989
        inv, inv_file_id = self._unpack_file_id(file_id)
 
1990
        ie = inv[inv_file_id]
1971
1991
        if ie.kind != "file":
1972
1992
            return False
1973
1993
        return ie.executable
1978
1998
    def list_files(self, include_root=False, from_dir=None, recursive=True):
1979
1999
        # We use a standard implementation, because DirStateRevisionTree is
1980
2000
        # dealing with one of the parents of the current state
1981
 
        inv = self._get_inventory()
1982
2001
        if from_dir is None:
 
2002
            inv = self.root_inventory
1983
2003
            from_dir_id = None
1984
2004
        else:
1985
 
            from_dir_id = inv.path2id(from_dir)
 
2005
            inv, from_dir_id = self._path2inv_file_id(from_dir)
1986
2006
            if from_dir_id is None:
1987
2007
                # Directory not versioned
1988
2008
                return
 
2009
        # FIXME: Support nested trees
1989
2010
        entries = inv.iter_entries(from_dir=from_dir_id, recursive=recursive)
1990
2011
        if inv.root is not None and not include_root and from_dir is None:
1991
2012
            entries.next()
2013
2034
    def path2id(self, path):
2014
2035
        """Return the id for path in this tree."""
2015
2036
        # lookup by path: faster than splitting and walking the ivnentory.
 
2037
        if isinstance(path, list):
 
2038
            if path == []:
 
2039
                path = [""]
 
2040
            path = osutils.pathjoin(*path)
2016
2041
        entry = self._get_entry(path=path)
2017
2042
        if entry == (None, None):
2018
2043
            return None
2041
2066
        # So for now, we just build up the parent inventory, and extract
2042
2067
        # it the same way RevisionTree does.
2043
2068
        _directory = 'directory'
2044
 
        inv = self._get_inventory()
 
2069
        inv = self._get_root_inventory()
2045
2070
        top_id = inv.path2id(prefix)
2046
2071
        if top_id is None:
2047
2072
            pending = []
2186
2211
                path_entries = state._entries_for_path(path)
2187
2212
                if not path_entries:
2188
2213
                    # this specified path is not present at all: error
2189
 
                    not_versioned.append(path)
 
2214
                    not_versioned.append(path.decode('utf-8'))
2190
2215
                    continue
2191
2216
                found_versioned = False
2192
2217
                # for each id at this path
2200
2225
                if not found_versioned:
2201
2226
                    # none of the indexes was not 'absent' at all ids for this
2202
2227
                    # path.
2203
 
                    not_versioned.append(path)
 
2228
                    not_versioned.append(path.decode('utf-8'))
2204
2229
            if len(not_versioned) > 0:
2205
2230
                raise errors.PathsNotVersionedError(not_versioned)
2206
2231
        # -- remove redundancy in supplied specific_files to prevent over-scanning --
2273
2298
    def update_format(self, tree):
2274
2299
        """Change the format marker."""
2275
2300
        tree._transport.put_bytes('format',
2276
 
            self.target_format.get_format_string(),
 
2301
            self.target_format.as_string(),
2277
2302
            mode=tree.bzrdir._get_file_mode())
2278
2303
 
2279
2304
 
2296
2321
    def update_format(self, tree):
2297
2322
        """Change the format marker."""
2298
2323
        tree._transport.put_bytes('format',
2299
 
            self.target_format.get_format_string(),
 
2324
            self.target_format.as_string(),
2300
2325
            mode=tree.bzrdir._get_file_mode())
2301
2326
 
2302
2327
 
2325
2350
    def update_format(self, tree):
2326
2351
        """Change the format marker."""
2327
2352
        tree._transport.put_bytes('format',
2328
 
            self.target_format.get_format_string(),
 
2353
            self.target_format.as_string(),
2329
2354
            mode=tree.bzrdir._get_file_mode())