29
29
from bzrlib.lazy_import import lazy_import
30
30
lazy_import(globals(), """
31
from bisect import bisect_left
33
from copy import deepcopy
42
35
from bzrlib import (
45
conflicts as _mod_conflicts,
55
43
revision as _mod_revision,
64
49
import bzrlib.branch
65
from bzrlib.transport import get_transport
69
from bzrlib import symbol_versioning
70
53
from bzrlib.decorators import needs_read_lock, needs_write_lock
71
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, entry_factory
72
import bzrlib.mutabletree
54
from bzrlib.filters import filtered_input_file, internal_size_sha_file_byname
55
from bzrlib.inventory import Inventory, ROOT_ID, entry_factory
56
from bzrlib.lock import LogicalLockResult
73
57
from bzrlib.mutabletree import needs_tree_write_lock
74
58
from bzrlib.osutils import (
84
from bzrlib.trace import mutter, note
65
from bzrlib.trace import mutter
85
66
from bzrlib.transport.local import LocalTransport
86
67
from bzrlib.tree import InterTree
87
from bzrlib.progress import DummyProgress, ProgressPhase
88
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
89
from bzrlib.rio import RioReader, rio_file, Stanza
90
from bzrlib.symbol_versioning import (deprecated_passed,
95
68
from bzrlib.tree import Tree
96
69
from bzrlib.workingtree import WorkingTree, WorkingTree3, WorkingTreeFormat3
245
218
return self._dirstate
246
219
local_path = self.bzrdir.get_workingtree_transport(None
247
220
).local_abspath('dirstate')
248
self._dirstate = dirstate.DirState.on_file(local_path)
221
self._dirstate = dirstate.DirState.on_file(local_path,
222
self._sha1_provider())
249
223
return self._dirstate
225
def _sha1_provider(self):
226
"""A function that returns a SHA1Provider suitable for this tree.
228
:return: None if content filtering is not supported by this tree.
229
Otherwise, a SHA1Provider is returned that sha's the canonical
230
form of files, i.e. after read filters are applied.
232
if self.supports_content_filtering():
233
return ContentFilterAwareSHA1Provider(self)
251
237
def filter_unversioned_files(self, paths):
252
238
"""Filter out paths that are versioned.
618
612
self.branch.unlock()
614
return LogicalLockResult(self.unlock)
621
616
def lock_tree_write(self):
622
"""See MutableTree.lock_tree_write, and WorkingTree.unlock."""
617
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
619
:return: A bzrlib.lock.LogicalLockResult.
623
621
self.branch.lock_read()
624
self._lock_self_write()
622
return self._lock_self_write()
626
624
def lock_write(self):
627
"""See MutableTree.lock_write, and WorkingTree.unlock."""
625
"""See MutableTree.lock_write, and WorkingTree.unlock.
627
:return: A bzrlib.lock.LogicalLockResult.
628
629
self.branch.lock_write()
629
self._lock_self_write()
630
return self._lock_self_write()
631
632
@needs_tree_write_lock
632
633
def move(self, from_paths, to_dir, after=False):
1210
1211
# just forget the whole block.
1211
1212
entry_index = 0
1212
1213
while entry_index < len(block[1]):
1213
# Mark this file id as having been removed
1214
1214
entry = block[1][entry_index]
1215
ids_to_unversion.discard(entry[0][2])
1216
if (entry[1][0][0] in 'ar' # don't remove absent or renamed
1218
or not state._make_absent(entry)):
1215
if entry[1][0][0] in 'ar':
1216
# don't remove absent or renamed entries
1219
1217
entry_index += 1
1219
# Mark this file id as having been removed
1220
ids_to_unversion.discard(entry[0][2])
1221
if not state._make_absent(entry):
1222
# The block has not shrunk.
1220
1224
# go to the next block. (At the moment we dont delete empty
1222
1226
block_index += 1
1274
1278
if self._dirty:
1275
1279
raise AssertionError("attempting to write an inventory when the "
1276
1280
"dirstate is dirty will lose pending changes")
1277
self.current_dirstate().set_state_from_inventory(inv)
1278
self._make_dirty(reset_inventory=False)
1279
if self._inventory is not None:
1281
had_inventory = self._inventory is not None
1282
# Setting self._inventory = None forces the dirstate to regenerate the
1283
# working inventory. We do this because self.inventory may be inv, or
1284
# may have been modified, and either case would prevent a clean delta
1286
self._inventory = None
1288
delta = inv._make_delta(self.inventory)
1290
self.apply_inventory_delta(delta)
1280
1292
self._inventory = inv
1296
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1298
def __init__(self, tree):
1301
def sha1(self, abspath):
1302
"""See dirstate.SHA1Provider.sha1()."""
1303
filters = self.tree._content_filter_stack(
1304
self.tree.relpath(osutils.safe_unicode(abspath)))
1305
return internal_size_sha_file_byname(abspath, filters)[1]
1307
def stat_and_sha1(self, abspath):
1308
"""See dirstate.SHA1Provider.stat_and_sha1()."""
1309
filters = self.tree._content_filter_stack(
1310
self.tree.relpath(osutils.safe_unicode(abspath)))
1311
file_obj = file(abspath, 'rb', 65000)
1313
statvalue = os.fstat(file_obj.fileno())
1315
file_obj = filtered_input_file(file_obj, filters)
1316
sha1 = osutils.size_sha_file(file_obj)[1]
1319
return statvalue, sha1
1322
class ContentFilteringDirStateWorkingTree(DirStateWorkingTree):
1323
"""Dirstate working tree that supports content filtering.
1325
The dirstate holds the hash and size of the canonical form of the file,
1326
and most methods must return that.
1329
def _file_content_summary(self, path, stat_result):
1330
# This is to support the somewhat obsolete path_content_summary method
1331
# with content filtering: see
1332
# <https://bugs.launchpad.net/bzr/+bug/415508>.
1334
# If the dirstate cache is up to date and knows the hash and size,
1336
# Otherwise if there are no content filters, return the on-disk size
1337
# and leave the hash blank.
1338
# Otherwise, read and filter the on-disk file and use its size and
1341
# The dirstate doesn't store the size of the canonical form so we
1342
# can't trust it for content-filtered trees. We just return None.
1343
dirstate_sha1 = self._dirstate.sha1_from_stat(path, stat_result)
1344
executable = self._is_executable_from_path_and_stat(path, stat_result)
1345
return ('file', None, executable, dirstate_sha1)
1284
1348
class WorkingTree4(DirStateWorkingTree):
1285
1349
"""This is the Format 4 working tree.
1287
1351
This differs from WorkingTree3 by:
1288
1352
- Having a consolidated internal dirstate, stored in a
1289
1353
randomly-accessible sorted file on disk.
1290
- Not having a regular inventory attribute. One can be synthesized
1354
- Not having a regular inventory attribute. One can be synthesized
1291
1355
on demand but this is expensive and should be avoided.
1293
1357
This is new in bzr 0.15.
1297
class WorkingTree5(DirStateWorkingTree):
1361
class WorkingTree5(ContentFilteringDirStateWorkingTree):
1298
1362
"""This is the Format 5 working tree.
1300
1364
This differs from WorkingTree4 by:
1301
1365
- Supporting content filtering.
1367
This is new in bzr 1.11.
1371
class WorkingTree6(ContentFilteringDirStateWorkingTree):
1372
"""This is the Format 6 working tree.
1374
This differs from WorkingTree5 by:
1302
1375
- Supporting a current view that may mask the set of files in a tree
1303
1376
impacted by most user operations.
1305
This is new in bzr 1.11.
1378
This is new in bzr 1.14.
1381
def _make_views(self):
1382
return views.PathBasedViews(self)
1309
1385
class DirStateWorkingTreeFormat(WorkingTreeFormat3):
1310
1387
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1311
1388
accelerator_tree=None, hardlink=False):
1312
1389
"""See WorkingTreeFormat.initialize().
1382
1459
if basis_root_id is not None:
1383
1460
wt._set_root_id(basis_root_id)
1462
if wt.supports_content_filtering():
1463
# The original tree may not have the same content filters
1464
# applied so we can't safely build the inventory delta from
1466
delta_from_tree = False
1468
delta_from_tree = True
1385
1469
# delta_from_tree is safe even for DirStateRevisionTrees,
1386
1470
# because wt4.apply_inventory_delta does not mutate the input
1387
1471
# inventory entries.
1388
1472
transform.build_tree(basis, wt, accelerator_tree,
1389
hardlink=hardlink, delta_from_tree=True)
1474
delta_from_tree=delta_from_tree)
1464
1553
"""See WorkingTreeFormat.get_format_description()."""
1465
1554
return "Working tree format 5"
1556
def supports_content_filtering(self):
1560
class WorkingTreeFormat6(DirStateWorkingTreeFormat):
1561
"""WorkingTree format supporting views.
1564
upgrade_recommended = False
1566
_tree_class = WorkingTree6
1568
def get_format_string(self):
1569
"""See WorkingTreeFormat.get_format_string()."""
1570
return "Bazaar Working Tree Format 6 (bzr 1.14)\n"
1572
def get_format_description(self):
1573
"""See WorkingTreeFormat.get_format_description()."""
1574
return "Working tree format 6"
1467
1576
def _init_custom_control_files(self, wt):
1468
1577
"""Subclasses with custom control files should override this method."""
1469
1578
wt._transport.put_bytes('views', '', mode=wt.bzrdir._get_file_mode())
1754
1872
return ie.executable
1756
def list_files(self, include_root=False):
1874
def is_locked(self):
1877
def list_files(self, include_root=False, from_dir=None, recursive=True):
1757
1878
# We use a standard implementation, because DirStateRevisionTree is
1758
1879
# dealing with one of the parents of the current state
1759
1880
inv = self._get_inventory()
1760
entries = inv.iter_entries()
1761
if self.inventory.root is not None and not include_root:
1881
if from_dir is None:
1884
from_dir_id = inv.path2id(from_dir)
1885
if from_dir_id is None:
1886
# Directory not versioned
1888
entries = inv.iter_entries(from_dir=from_dir_id, recursive=recursive)
1889
if inv.root is not None and not include_root and from_dir is None:
1763
1891
for path, entry in entries:
1764
1892
yield path, 'V', entry.kind, entry.file_id, entry
1766
1894
def lock_read(self):
1767
"""Lock the tree for a set of operations."""
1895
"""Lock the tree for a set of operations.
1897
:return: A bzrlib.lock.LogicalLockResult.
1768
1899
if not self._locked:
1769
1900
self._repository.lock_read()
1770
1901
if self._dirstate._lock_token is None:
1771
1902
self._dirstate.lock_read()
1772
1903
self._dirstate_locked = True
1773
1904
self._locked += 1
1905
return LogicalLockResult(self.unlock)
1775
1907
def _must_be_locked(self):
1776
1908
if not self._locked:
1869
def make_source_parent_tree_compiled_dirstate(klass, test_case, source, target):
2001
def make_source_parent_tree_compiled_dirstate(klass, test_case, source,
1870
2003
from bzrlib.tests.test__dirstate_helpers import \
1871
CompiledDirstateHelpersFeature
1872
if not CompiledDirstateHelpersFeature.available():
1873
from bzrlib.tests import UnavailableFeature
1874
raise UnavailableFeature(CompiledDirstateHelpersFeature)
1875
from bzrlib._dirstate_helpers_c import ProcessEntryC
2004
compiled_dirstate_helpers_feature
2005
test_case.requireFeature(compiled_dirstate_helpers_feature)
2006
from bzrlib._dirstate_helpers_pyx import ProcessEntryC
1876
2007
result = klass.make_source_parent_tree(source, target)
1877
2008
result[1]._iter_changes = ProcessEntryC
1918
2047
require_versioned, want_unversioned=want_unversioned)
1919
2048
parent_ids = self.target.get_parent_ids()
1920
2049
if not (self.source._revision_id in parent_ids
1921
or self.source._revision_id == NULL_REVISION):
2050
or self.source._revision_id == _mod_revision.NULL_REVISION):
1922
2051
raise AssertionError(
1923
2052
"revision {%s} is not stored in {%s}, but %s "
1924
2053
"can only be used for trees stored in the dirstate"
1925
2054
% (self.source._revision_id, self.target, self.iter_changes))
1926
2055
target_index = 0
1927
if self.source._revision_id == NULL_REVISION:
2056
if self.source._revision_id == _mod_revision.NULL_REVISION:
1928
2057
source_index = None
1929
2058
indices = (target_index,)
1946
2075
specific_files = set([''])
1947
2076
# -- specific_files is now a utf8 path set --
1948
search_specific_files = set()
1949
2078
# -- get the state object and prepare it.
1950
2079
state = self.target.current_dirstate()
1951
2080
state._read_dirblocks_if_needed()
1952
2081
if require_versioned:
1953
2082
# -- check all supplied paths are versioned in a search tree. --
1954
all_versioned = True
1955
2084
for path in specific_files:
1956
2085
path_entries = state._entries_for_path(path)
1957
2086
if not path_entries:
1958
2087
# this specified path is not present at all: error
1959
all_versioned = False
2088
not_versioned.append(path)
1961
2090
found_versioned = False
1962
2091
# for each id at this path
1963
2092
for entry in path_entries:
1970
2099
if not found_versioned:
1971
2100
# none of the indexes was not 'absent' at all ids for this
1973
all_versioned = False
1975
if not all_versioned:
1976
raise errors.PathsNotVersionedError(specific_files)
2102
not_versioned.append(path)
2103
if len(not_versioned) > 0:
2104
raise errors.PathsNotVersionedError(not_versioned)
1977
2105
# -- remove redundancy in supplied specific_files to prevent over-scanning --
1978
for path in specific_files:
1979
other_specific_files = specific_files.difference(set([path]))
1980
if not osutils.is_inside_any(other_specific_files, path):
1981
# this is a top level path, we must check it.
1982
search_specific_files.add(path)
2106
search_specific_files = osutils.minimum_path_selection(specific_files)
1984
2108
use_filesystem_for_exec = (sys.platform != 'win32')
1985
2109
iter_changes = self.target._iter_changes(include_unchanged,
2061
2185
def convert(self, tree):
2062
2186
# lock the control files not the tree, so that we don't get tree
2063
# on-unlock behaviours, and so that no-one else diddles with the
2187
# on-unlock behaviours, and so that no-one else diddles with the
2188
# tree during upgrade.
2189
tree._control_files.lock_write()
2191
self.update_format(tree)
2193
tree._control_files.unlock()
2195
def update_format(self, tree):
2196
"""Change the format marker."""
2197
tree._transport.put_bytes('format',
2198
self.target_format.get_format_string(),
2199
mode=tree.bzrdir._get_file_mode())
2202
class Converter4or5to6(object):
2203
"""Perform an in-place upgrade of format 4 or 5 to format 6 trees."""
2206
self.target_format = WorkingTreeFormat6()
2208
def convert(self, tree):
2209
# lock the control files not the tree, so that we don't get tree
2210
# on-unlock behaviours, and so that no-one else diddles with the
2064
2211
# tree during upgrade.
2065
2212
tree._control_files.lock_write()