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
54
from bzrlib.filters import filtered_input_file, internal_size_sha_file_byname
55
from bzrlib.inventory import Inventory, ROOT_ID, entry_factory
72
56
import bzrlib.mutabletree
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.
1210
1200
# just forget the whole block.
1211
1201
entry_index = 0
1212
1202
while entry_index < len(block[1]):
1213
# Mark this file id as having been removed
1214
1203
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)):
1204
if entry[1][0][0] in 'ar':
1205
# don't remove absent or renamed entries
1219
1206
entry_index += 1
1208
# Mark this file id as having been removed
1209
ids_to_unversion.discard(entry[0][2])
1210
if not state._make_absent(entry):
1211
# The block has not shrunk.
1220
1213
# go to the next block. (At the moment we dont delete empty
1222
1215
block_index += 1
1274
1267
if self._dirty:
1275
1268
raise AssertionError("attempting to write an inventory when the "
1276
1269
"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:
1270
had_inventory = self._inventory is not None
1271
# Setting self._inventory = None forces the dirstate to regenerate the
1272
# working inventory. We do this because self.inventory may be inv, or
1273
# may have been modified, and either case would prevent a clean delta
1275
self._inventory = None
1277
delta = inv._make_delta(self.inventory)
1279
self.apply_inventory_delta(delta)
1280
1281
self._inventory = inv
1285
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1287
def __init__(self, tree):
1290
def sha1(self, abspath):
1291
"""See dirstate.SHA1Provider.sha1()."""
1292
filters = self.tree._content_filter_stack(
1293
self.tree.relpath(osutils.safe_unicode(abspath)))
1294
return internal_size_sha_file_byname(abspath, filters)[1]
1296
def stat_and_sha1(self, abspath):
1297
"""See dirstate.SHA1Provider.stat_and_sha1()."""
1298
filters = self.tree._content_filter_stack(
1299
self.tree.relpath(osutils.safe_unicode(abspath)))
1300
file_obj = file(abspath, 'rb', 65000)
1302
statvalue = os.fstat(file_obj.fileno())
1304
file_obj = filtered_input_file(file_obj, filters)
1305
sha1 = osutils.size_sha_file(file_obj)[1]
1308
return statvalue, sha1
1311
class ContentFilteringDirStateWorkingTree(DirStateWorkingTree):
1312
"""Dirstate working tree that supports content filtering.
1314
The dirstate holds the hash and size of the canonical form of the file,
1315
and most methods must return that.
1318
def _file_content_summary(self, path, stat_result):
1319
# This is to support the somewhat obsolete path_content_summary method
1320
# with content filtering: see
1321
# <https://bugs.edge.launchpad.net/bzr/+bug/415508>.
1323
# If the dirstate cache is up to date and knows the hash and size,
1325
# Otherwise if there are no content filters, return the on-disk size
1326
# and leave the hash blank.
1327
# Otherwise, read and filter the on-disk file and use its size and
1330
# The dirstate doesn't store the size of the canonical form so we
1331
# can't trust it for content-filtered trees. We just return None.
1332
dirstate_sha1 = self._dirstate.sha1_from_stat(path, stat_result)
1333
executable = self._is_executable_from_path_and_stat(path, stat_result)
1334
return ('file', None, executable, dirstate_sha1)
1284
1337
class WorkingTree4(DirStateWorkingTree):
1285
1338
"""This is the Format 4 working tree.
1287
1340
This differs from WorkingTree3 by:
1288
1341
- Having a consolidated internal dirstate, stored in a
1289
1342
randomly-accessible sorted file on disk.
1290
- Not having a regular inventory attribute. One can be synthesized
1343
- Not having a regular inventory attribute. One can be synthesized
1291
1344
on demand but this is expensive and should be avoided.
1293
1346
This is new in bzr 0.15.
1297
class WorkingTree5(DirStateWorkingTree):
1350
class WorkingTree5(ContentFilteringDirStateWorkingTree):
1298
1351
"""This is the Format 5 working tree.
1300
1353
This differs from WorkingTree4 by:
1301
1354
- Supporting content filtering.
1356
This is new in bzr 1.11.
1360
class WorkingTree6(ContentFilteringDirStateWorkingTree):
1361
"""This is the Format 6 working tree.
1363
This differs from WorkingTree5 by:
1302
1364
- Supporting a current view that may mask the set of files in a tree
1303
1365
impacted by most user operations.
1305
This is new in bzr 1.11.
1367
This is new in bzr 1.14.
1370
def _make_views(self):
1371
return views.PathBasedViews(self)
1309
1374
class DirStateWorkingTreeFormat(WorkingTreeFormat3):
1310
1375
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1382
1447
if basis_root_id is not None:
1383
1448
wt._set_root_id(basis_root_id)
1450
if wt.supports_content_filtering():
1451
# The original tree may not have the same content filters
1452
# applied so we can't safely build the inventory delta from
1454
delta_from_tree = False
1456
delta_from_tree = True
1385
1457
# delta_from_tree is safe even for DirStateRevisionTrees,
1386
1458
# because wt4.apply_inventory_delta does not mutate the input
1387
1459
# inventory entries.
1388
1460
transform.build_tree(basis, wt, accelerator_tree,
1389
hardlink=hardlink, delta_from_tree=True)
1462
delta_from_tree=delta_from_tree)
1464
1541
"""See WorkingTreeFormat.get_format_description()."""
1465
1542
return "Working tree format 5"
1544
def supports_content_filtering(self):
1548
class WorkingTreeFormat6(DirStateWorkingTreeFormat):
1549
"""WorkingTree format supporting views.
1552
upgrade_recommended = False
1554
_tree_class = WorkingTree6
1556
def get_format_string(self):
1557
"""See WorkingTreeFormat.get_format_string()."""
1558
return "Bazaar Working Tree Format 6 (bzr 1.14)\n"
1560
def get_format_description(self):
1561
"""See WorkingTreeFormat.get_format_description()."""
1562
return "Working tree format 6"
1467
1564
def _init_custom_control_files(self, wt):
1468
1565
"""Subclasses with custom control files should override this method."""
1469
1566
wt._transport.put_bytes('views', '', mode=wt.bzrdir._get_file_mode())
1754
1859
return ie.executable
1756
def list_files(self, include_root=False):
1861
def list_files(self, include_root=False, from_dir=None, recursive=True):
1757
1862
# We use a standard implementation, because DirStateRevisionTree is
1758
1863
# dealing with one of the parents of the current state
1759
1864
inv = self._get_inventory()
1760
entries = inv.iter_entries()
1761
if self.inventory.root is not None and not include_root:
1865
if from_dir is None:
1868
from_dir_id = inv.path2id(from_dir)
1869
if from_dir_id is None:
1870
# Directory not versioned
1872
entries = inv.iter_entries(from_dir=from_dir_id, recursive=recursive)
1873
if inv.root is not None and not include_root and from_dir is None:
1763
1875
for path, entry in entries:
1764
1876
yield path, 'V', entry.kind, entry.file_id, entry
1869
def make_source_parent_tree_compiled_dirstate(klass, test_case, source, target):
1981
def make_source_parent_tree_compiled_dirstate(klass, test_case, source,
1870
1983
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
1984
compiled_dirstate_helpers_feature
1985
test_case.requireFeature(compiled_dirstate_helpers_feature)
1986
from bzrlib._dirstate_helpers_pyx import ProcessEntryC
1876
1987
result = klass.make_source_parent_tree(source, target)
1877
1988
result[1]._iter_changes = ProcessEntryC
1918
2027
require_versioned, want_unversioned=want_unversioned)
1919
2028
parent_ids = self.target.get_parent_ids()
1920
2029
if not (self.source._revision_id in parent_ids
1921
or self.source._revision_id == NULL_REVISION):
2030
or self.source._revision_id == _mod_revision.NULL_REVISION):
1922
2031
raise AssertionError(
1923
2032
"revision {%s} is not stored in {%s}, but %s "
1924
2033
"can only be used for trees stored in the dirstate"
1925
2034
% (self.source._revision_id, self.target, self.iter_changes))
1926
2035
target_index = 0
1927
if self.source._revision_id == NULL_REVISION:
2036
if self.source._revision_id == _mod_revision.NULL_REVISION:
1928
2037
source_index = None
1929
2038
indices = (target_index,)
1946
2055
specific_files = set([''])
1947
2056
# -- specific_files is now a utf8 path set --
1948
search_specific_files = set()
1949
2058
# -- get the state object and prepare it.
1950
2059
state = self.target.current_dirstate()
1951
2060
state._read_dirblocks_if_needed()
1952
2061
if require_versioned:
1953
2062
# -- check all supplied paths are versioned in a search tree. --
1954
all_versioned = True
1955
2064
for path in specific_files:
1956
2065
path_entries = state._entries_for_path(path)
1957
2066
if not path_entries:
1958
2067
# this specified path is not present at all: error
1959
all_versioned = False
2068
not_versioned.append(path)
1961
2070
found_versioned = False
1962
2071
# for each id at this path
1963
2072
for entry in path_entries:
1970
2079
if not found_versioned:
1971
2080
# 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)
2082
not_versioned.append(path)
2083
if len(not_versioned) > 0:
2084
raise errors.PathsNotVersionedError(not_versioned)
1977
2085
# -- 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)
2086
search_specific_files = osutils.minimum_path_selection(specific_files)
1984
2088
use_filesystem_for_exec = (sys.platform != 'win32')
1985
2089
iter_changes = self.target._iter_changes(include_unchanged,
2061
2165
def convert(self, tree):
2062
2166
# 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
2167
# on-unlock behaviours, and so that no-one else diddles with the
2168
# tree during upgrade.
2169
tree._control_files.lock_write()
2171
self.update_format(tree)
2173
tree._control_files.unlock()
2175
def update_format(self, tree):
2176
"""Change the format marker."""
2177
tree._transport.put_bytes('format',
2178
self.target_format.get_format_string(),
2179
mode=tree.bzrdir._get_file_mode())
2182
class Converter4or5to6(object):
2183
"""Perform an in-place upgrade of format 4 or 5 to format 6 trees."""
2186
self.target_format = WorkingTreeFormat6()
2188
def convert(self, tree):
2189
# lock the control files not the tree, so that we don't get tree
2190
# on-unlock behaviours, and so that no-one else diddles with the
2064
2191
# tree during upgrade.
2065
2192
tree._control_files.lock_write()