1
# Copyright (C) 2007-2011 Canonical Ltd
1
# Copyright (C) 2007-2012 Canonical Ltd
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
55
58
from bzrlib.lock import LogicalLockResult
56
59
from bzrlib.lockable_files import LockableFiles
57
60
from bzrlib.lockdir import LockDir
58
from bzrlib.mutabletree import needs_tree_write_lock
61
from bzrlib.mutabletree import (
63
needs_tree_write_lock,
59
65
from bzrlib.osutils import (
251
261
:return: an integer. -1 means never save.
253
# FIXME: We want a WorkingTreeStack here -- vila 20110812
254
conf = config.BranchStack(self.branch)
263
conf = self.get_config_stack()
255
264
return conf.get('bzr.workingtree.worth_saving_limit')
257
266
def filter_unversioned_files(self, paths):
421
430
self._generate_inventory()
422
431
return self._inventory
433
@deprecated_method(deprecated_in((2, 5, 0)))
434
def _get_inventory(self):
435
return self.root_inventory
424
437
inventory = property(_get_inventory,
425
438
doc="Inventory of this Tree")
440
root_inventory = property(_get_root_inventory,
441
"Root inventory of this tree")
428
444
def get_parent_ids(self):
429
445
"""See Tree.get_parent_ids.
476
492
return False # Missing entries are not executable
477
493
return entry[1][0][3] # Executable?
479
if not osutils.supports_executable():
480
def is_executable(self, file_id, path=None):
481
"""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.
483
Note: The caller is expected to take a read-lock before calling this.
498
Note: The caller is expected to take a read-lock before calling this.
500
if not self._supports_executable():
485
501
entry = self._get_entry(file_id=file_id, path=path)
486
502
if entry == (None, None):
488
504
return entry[1][0][3]
490
_is_executable_from_path_and_stat = \
491
_is_executable_from_path_and_stat_from_basis
493
def is_executable(self, file_id, path=None):
494
"""Test if a file is executable or not.
496
Note: The caller is expected to take a read-lock before calling this.
498
506
self._must_be_locked()
500
508
path = self.id2path(file_id)
887
895
def path2id(self, path):
888
896
"""Return the id for path in this tree."""
897
if isinstance(path, list):
900
path = osutils.pathjoin(*path)
889
901
path = path.strip('/')
890
902
entry = self._get_entry(path=path)
891
903
if entry == (None, None):
969
981
all_versioned = False
971
983
if not all_versioned:
972
raise errors.PathsNotVersionedError(paths)
984
raise errors.PathsNotVersionedError(
985
[p.decode('utf-8') for p in paths])
973
986
# -- remove redundancy in supplied paths to prevent over-scanning --
974
987
search_paths = osutils.minimum_path_selection(paths)
1024
1037
found_dir_names = set(dir_name_id[:2] for dir_name_id in found)
1025
1038
for dir_name in split_paths:
1026
1039
if dir_name not in found_dir_names:
1027
raise errors.PathsNotVersionedError(paths)
1040
raise errors.PathsNotVersionedError(
1041
[p.decode('utf-8') for p in paths])
1029
1043
for dir_name_id, trees_info in found.iteritems():
1030
1044
for index in search_indexes:
1151
1165
# _make_delta if we can't get the RevisionTree
1154
delta = rev_tree.inventory._make_delta(basis_tree.inventory)
1168
delta = rev_tree.root_inventory._make_delta(
1169
basis_tree.root_inventory)
1155
1170
dirstate.update_basis_by_delta(delta, rev_id)
1157
1172
if not updated:
1354
1369
base_tree = trees[0][1]
1355
1370
state = self.current_dirstate()
1356
1371
# We don't support ghosts yet
1357
state.set_state_from_scratch(base_tree.inventory, trees, [])
1372
state.set_state_from_scratch(base_tree.root_inventory, trees, [])
1360
1375
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1482
1497
control_files = self._open_control_files(a_bzrdir)
1483
1498
control_files.create_lock()
1484
1499
control_files.lock_write()
1485
transport.put_bytes('format', self.get_format_string(),
1500
transport.put_bytes('format', self.as_string(),
1486
1501
mode=a_bzrdir._get_file_mode())
1487
1502
if from_branch is not None:
1488
1503
branch = from_branch
1548
1563
transform.build_tree(basis, wt, accelerator_tree,
1549
1564
hardlink=hardlink,
1550
1565
delta_from_tree=delta_from_tree)
1566
for hook in MutableTree.hooks['post_build_tree']:
1596
1613
def _get_matchingbzrdir(self):
1597
1614
"""Overrideable method to get a bzrdir for testing."""
1598
1615
# please test against something that will let us do tree references
1599
return bzrdir.format_registry.make_bzrdir(
1600
'dirstate-with-subtree')
1616
return controldir.format_registry.make_bzrdir(
1617
'development-subtree')
1602
1619
_matchingbzrdir = property(__get_matchingbzrdir)
1609
1626
- exists within a metadir controlling .bzr
1610
1627
- includes an explicit version marker for the workingtree control
1611
files, separate from the BzrDir format
1628
files, separate from the ControlDir format
1612
1629
- modifies the hash cache format
1613
1630
- is new in bzr 0.15
1614
1631
- uses a LockDir to guard access to it.
1619
1636
_tree_class = WorkingTree4
1621
def get_format_string(self):
1639
def get_format_string(cls):
1622
1640
"""See WorkingTreeFormat.get_format_string()."""
1623
1641
return "Bazaar Working Tree Format 4 (bzr 0.15)\n"
1636
1654
_tree_class = WorkingTree5
1638
def get_format_string(self):
1657
def get_format_string(cls):
1639
1658
"""See WorkingTreeFormat.get_format_string()."""
1640
1659
return "Bazaar Working Tree Format 5 (bzr 1.11)\n"
1656
1675
_tree_class = WorkingTree6
1658
def get_format_string(self):
1678
def get_format_string(cls):
1659
1679
"""See WorkingTreeFormat.get_format_string()."""
1660
1680
return "Bazaar Working Tree Format 6 (bzr 1.14)\n"
1673
1693
def supports_views(self):
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')
1677
1703
class DirStateRevisionTree(InventoryTree):
1678
1704
"""A revision tree pulling the inventory from a dirstate.
1761
1787
if path is not None:
1762
1788
path = path.encode('utf8')
1763
1789
parent_index = self._get_parent_index()
1764
return self._dirstate._get_entry(parent_index, fileid_utf8=file_id, path_utf8=path)
1790
return self._dirstate._get_entry(parent_index, fileid_utf8=file_id,
1766
1793
def _generate_inventory(self):
1767
1794
"""Create and set self.inventory from the dirstate object.
1849
1876
# Make sure the file exists
1850
1877
entry = self._get_entry(file_id, path=path)
1851
1878
if entry == (None, None): # do we raise?
1879
raise errors.NoSuchId(self, file_id)
1853
1880
parent_index = self._get_parent_index()
1854
1881
last_changed_revision = entry[1][parent_index][4]
1869
1896
@needs_read_lock
1870
1897
def get_file_revision(self, file_id):
1871
return self.inventory[file_id].revision
1898
inv, inv_file_id = self._unpack_file_id(file_id)
1899
return inv[inv_file_id].revision
1873
1901
def get_file(self, file_id, path=None):
1874
1902
return StringIO(self.get_file_text(file_id))
1876
1904
def get_file_size(self, file_id):
1877
1905
"""See Tree.get_file_size"""
1878
return self.inventory[file_id].text_size
1906
inv, inv_file_id = self._unpack_file_id(file_id)
1907
return inv[inv_file_id].text_size
1880
1909
def get_file_text(self, file_id, path=None):
1881
_, content = list(self.iter_files_bytes([(file_id, None)]))[0]
1882
return ''.join(content)
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)
1919
raise AssertionError('iter_files_bytes did not return'
1920
' the requested data')
1884
1923
def get_reference_revision(self, file_id, path=None):
1885
return self.inventory[file_id].reference_revision
1924
inv, inv_file_id = self._unpack_file_id(file_id)
1925
return inv[inv_file_id].reference_revision
1887
1927
def iter_files_bytes(self, desired_files):
1888
1928
"""See Tree.iter_files_bytes.
1912
1952
"""Return the revision id for this tree."""
1913
1953
return self._revision_id
1915
def _get_inventory(self):
1955
def _get_root_inventory(self):
1916
1956
if self._inventory is not None:
1917
1957
return self._inventory
1918
1958
self._must_be_locked()
1919
1959
self._generate_inventory()
1920
1960
return self._inventory
1962
root_inventory = property(_get_root_inventory,
1963
doc="Inventory of this Tree")
1965
@deprecated_method(deprecated_in((2, 5, 0)))
1966
def _get_inventory(self):
1967
return self.root_inventory
1922
1969
inventory = property(_get_inventory,
1923
1970
doc="Inventory of this Tree")
1943
1990
def path_content_summary(self, path):
1944
1991
"""See Tree.path_content_summary."""
1945
id = self.inventory.path2id(path)
1992
inv, inv_file_id = self._path2inv_file_id(path)
1993
if inv_file_id is None:
1947
1994
return ('missing', None, None, None)
1948
entry = self._inventory[id]
1995
entry = inv[inv_file_id]
1949
1996
kind = entry.kind
1950
1997
if kind == 'file':
1951
1998
return (kind, entry.text_size, entry.executable, entry.text_sha1)
1955
2002
return (kind, None, None, None)
1957
2004
def is_executable(self, file_id, path=None):
1958
ie = self.inventory[file_id]
2005
inv, inv_file_id = self._unpack_file_id(file_id)
2006
ie = inv[inv_file_id]
1959
2007
if ie.kind != "file":
1961
2009
return ie.executable
1966
2014
def list_files(self, include_root=False, from_dir=None, recursive=True):
1967
2015
# We use a standard implementation, because DirStateRevisionTree is
1968
2016
# dealing with one of the parents of the current state
1969
inv = self._get_inventory()
1970
2017
if from_dir is None:
2018
inv = self.root_inventory
1971
2019
from_dir_id = None
1973
from_dir_id = inv.path2id(from_dir)
2021
inv, from_dir_id = self._path2inv_file_id(from_dir)
1974
2022
if from_dir_id is None:
1975
2023
# Directory not versioned
2025
# FIXME: Support nested trees
1977
2026
entries = inv.iter_entries(from_dir=from_dir_id, recursive=recursive)
1978
2027
if inv.root is not None and not include_root and from_dir is None:
2001
2050
def path2id(self, path):
2002
2051
"""Return the id for path in this tree."""
2003
2052
# lookup by path: faster than splitting and walking the ivnentory.
2053
if isinstance(path, list):
2056
path = osutils.pathjoin(*path)
2004
2057
entry = self._get_entry(path=path)
2005
2058
if entry == (None, None):
2029
2082
# So for now, we just build up the parent inventory, and extract
2030
2083
# it the same way RevisionTree does.
2031
2084
_directory = 'directory'
2032
inv = self._get_inventory()
2085
inv = self._get_root_inventory()
2033
2086
top_id = inv.path2id(prefix)
2034
2087
if top_id is None:
2174
2227
path_entries = state._entries_for_path(path)
2175
2228
if not path_entries:
2176
2229
# this specified path is not present at all: error
2177
not_versioned.append(path)
2230
not_versioned.append(path.decode('utf-8'))
2179
2232
found_versioned = False
2180
2233
# for each id at this path
2188
2241
if not found_versioned:
2189
2242
# none of the indexes was not 'absent' at all ids for this
2191
not_versioned.append(path)
2244
not_versioned.append(path.decode('utf-8'))
2192
2245
if len(not_versioned) > 0:
2193
2246
raise errors.PathsNotVersionedError(not_versioned)
2194
2247
# -- remove redundancy in supplied specific_files to prevent over-scanning --
2261
2314
def update_format(self, tree):
2262
2315
"""Change the format marker."""
2263
2316
tree._transport.put_bytes('format',
2264
self.target_format.get_format_string(),
2317
self.target_format.as_string(),
2265
2318
mode=tree.bzrdir._get_file_mode())
2284
2337
def update_format(self, tree):
2285
2338
"""Change the format marker."""
2286
2339
tree._transport.put_bytes('format',
2287
self.target_format.get_format_string(),
2340
self.target_format.as_string(),
2288
2341
mode=tree.bzrdir._get_file_mode())
2313
2366
def update_format(self, tree):
2314
2367
"""Change the format marker."""
2315
2368
tree._transport.put_bytes('format',
2316
self.target_format.get_format_string(),
2369
self.target_format.as_string(),
2317
2370
mode=tree.bzrdir._get_file_mode())