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
35
42
from bzrlib import (
45
conflicts as _mod_conflicts,
43
55
revision as _mod_revision,
49
64
import bzrlib.branch
65
from bzrlib.transport import get_transport
69
from bzrlib import symbol_versioning
53
70
from bzrlib.decorators import needs_read_lock, needs_write_lock
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
71
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, entry_factory
72
import bzrlib.mutabletree
57
73
from bzrlib.mutabletree import needs_tree_write_lock
58
74
from bzrlib.osutils import (
65
from bzrlib.trace import mutter
84
from bzrlib.trace import mutter, note
66
85
from bzrlib.transport.local import LocalTransport
67
86
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,
68
95
from bzrlib.tree import Tree
69
96
from bzrlib.workingtree import WorkingTree, WorkingTree3, WorkingTreeFormat3
218
245
return self._dirstate
219
246
local_path = self.bzrdir.get_workingtree_transport(None
220
247
).local_abspath('dirstate')
221
self._dirstate = dirstate.DirState.on_file(local_path,
222
self._sha1_provider())
248
self._dirstate = dirstate.DirState.on_file(local_path)
223
249
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)
237
251
def filter_unversioned_files(self, paths):
238
252
"""Filter out paths that are versioned.
612
618
self.branch.unlock()
614
return LogicalLockResult(self.unlock)
616
621
def lock_tree_write(self):
617
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
619
:return: A bzrlib.lock.LogicalLockResult.
622
"""See MutableTree.lock_tree_write, and WorkingTree.unlock."""
621
623
self.branch.lock_read()
622
return self._lock_self_write()
624
self._lock_self_write()
624
626
def lock_write(self):
625
"""See MutableTree.lock_write, and WorkingTree.unlock.
627
:return: A bzrlib.lock.LogicalLockResult.
627
"""See MutableTree.lock_write, and WorkingTree.unlock."""
629
628
self.branch.lock_write()
630
return self._lock_self_write()
629
self._lock_self_write()
632
631
@needs_tree_write_lock
633
632
def move(self, from_paths, to_dir, after=False):
1211
1210
# just forget the whole block.
1212
1211
entry_index = 0
1213
1212
while entry_index < len(block[1]):
1213
# Mark this file id as having been removed
1214
1214
entry = block[1][entry_index]
1215
if entry[1][0][0] in 'ar':
1216
# don't remove absent or renamed entries
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)):
1217
1219
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.
1224
1220
# go to the next block. (At the moment we dont delete empty
1226
1222
block_index += 1
1278
1274
if self._dirty:
1279
1275
raise AssertionError("attempting to write an inventory when the "
1280
1276
"dirstate is dirty will lose pending changes")
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)
1277
self.current_dirstate().set_state_from_inventory(inv)
1278
self._make_dirty(reset_inventory=False)
1279
if self._inventory is not None:
1292
1280
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.edge.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)
1348
1284
class WorkingTree4(DirStateWorkingTree):
1349
1285
"""This is the Format 4 working tree.
1351
1287
This differs from WorkingTree3 by:
1352
1288
- Having a consolidated internal dirstate, stored in a
1353
1289
randomly-accessible sorted file on disk.
1354
- Not having a regular inventory attribute. One can be synthesized
1290
- Not having a regular inventory attribute. One can be synthesized
1355
1291
on demand but this is expensive and should be avoided.
1357
1293
This is new in bzr 0.15.
1361
class WorkingTree5(ContentFilteringDirStateWorkingTree):
1297
class WorkingTree5(DirStateWorkingTree):
1362
1298
"""This is the Format 5 working tree.
1364
1300
This differs from WorkingTree4 by:
1365
1301
- 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:
1375
1302
- Supporting a current view that may mask the set of files in a tree
1376
1303
impacted by most user operations.
1378
This is new in bzr 1.14.
1305
This is new in bzr 1.11.
1381
def _make_views(self):
1382
return views.PathBasedViews(self)
1385
1309
class DirStateWorkingTreeFormat(WorkingTreeFormat3):
1387
1310
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1388
1311
accelerator_tree=None, hardlink=False):
1389
1312
"""See WorkingTreeFormat.initialize().
1459
1382
if basis_root_id is not None:
1460
1383
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
1469
1385
# delta_from_tree is safe even for DirStateRevisionTrees,
1470
1386
# because wt4.apply_inventory_delta does not mutate the input
1471
1387
# inventory entries.
1472
1388
transform.build_tree(basis, wt, accelerator_tree,
1474
delta_from_tree=delta_from_tree)
1389
hardlink=hardlink, delta_from_tree=True)
1553
1464
"""See WorkingTreeFormat.get_format_description()."""
1554
1465
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"
1576
1467
def _init_custom_control_files(self, wt):
1577
1468
"""Subclasses with custom control files should override this method."""
1578
1469
wt._transport.put_bytes('views', '', mode=wt.bzrdir._get_file_mode())
1872
1754
return ie.executable
1874
def is_locked(self):
1877
def list_files(self, include_root=False, from_dir=None, recursive=True):
1756
def list_files(self, include_root=False):
1878
1757
# We use a standard implementation, because DirStateRevisionTree is
1879
1758
# dealing with one of the parents of the current state
1880
1759
inv = self._get_inventory()
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:
1760
entries = inv.iter_entries()
1761
if self.inventory.root is not None and not include_root:
1891
1763
for path, entry in entries:
1892
1764
yield path, 'V', entry.kind, entry.file_id, entry
1894
1766
def lock_read(self):
1895
"""Lock the tree for a set of operations.
1897
:return: A bzrlib.lock.LogicalLockResult.
1767
"""Lock the tree for a set of operations."""
1899
1768
if not self._locked:
1900
1769
self._repository.lock_read()
1901
1770
if self._dirstate._lock_token is None:
1902
1771
self._dirstate.lock_read()
1903
1772
self._dirstate_locked = True
1904
1773
self._locked += 1
1905
return LogicalLockResult(self.unlock)
1907
1775
def _must_be_locked(self):
1908
1776
if not self._locked:
2001
def make_source_parent_tree_compiled_dirstate(klass, test_case, source,
1869
def make_source_parent_tree_compiled_dirstate(klass, test_case, source, target):
2003
1870
from bzrlib.tests.test__dirstate_helpers import \
2004
compiled_dirstate_helpers_feature
2005
test_case.requireFeature(compiled_dirstate_helpers_feature)
2006
from bzrlib._dirstate_helpers_pyx import ProcessEntryC
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
2007
1876
result = klass.make_source_parent_tree(source, target)
2008
1877
result[1]._iter_changes = ProcessEntryC
2047
1918
require_versioned, want_unversioned=want_unversioned)
2048
1919
parent_ids = self.target.get_parent_ids()
2049
1920
if not (self.source._revision_id in parent_ids
2050
or self.source._revision_id == _mod_revision.NULL_REVISION):
1921
or self.source._revision_id == NULL_REVISION):
2051
1922
raise AssertionError(
2052
1923
"revision {%s} is not stored in {%s}, but %s "
2053
1924
"can only be used for trees stored in the dirstate"
2054
1925
% (self.source._revision_id, self.target, self.iter_changes))
2055
1926
target_index = 0
2056
if self.source._revision_id == _mod_revision.NULL_REVISION:
1927
if self.source._revision_id == NULL_REVISION:
2057
1928
source_index = None
2058
1929
indices = (target_index,)
2075
1946
specific_files = set([''])
2076
1947
# -- specific_files is now a utf8 path set --
1948
search_specific_files = set()
2078
1949
# -- get the state object and prepare it.
2079
1950
state = self.target.current_dirstate()
2080
1951
state._read_dirblocks_if_needed()
2081
1952
if require_versioned:
2082
1953
# -- check all supplied paths are versioned in a search tree. --
1954
all_versioned = True
2084
1955
for path in specific_files:
2085
1956
path_entries = state._entries_for_path(path)
2086
1957
if not path_entries:
2087
1958
# this specified path is not present at all: error
2088
not_versioned.append(path)
1959
all_versioned = False
2090
1961
found_versioned = False
2091
1962
# for each id at this path
2092
1963
for entry in path_entries:
2099
1970
if not found_versioned:
2100
1971
# none of the indexes was not 'absent' at all ids for this
2102
not_versioned.append(path)
2103
if len(not_versioned) > 0:
2104
raise errors.PathsNotVersionedError(not_versioned)
1973
all_versioned = False
1975
if not all_versioned:
1976
raise errors.PathsNotVersionedError(specific_files)
2105
1977
# -- remove redundancy in supplied specific_files to prevent over-scanning --
2106
search_specific_files = osutils.minimum_path_selection(specific_files)
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)
2108
1984
use_filesystem_for_exec = (sys.platform != 'win32')
2109
1985
iter_changes = self.target._iter_changes(include_unchanged,
2185
2061
def convert(self, tree):
2186
2062
# lock the control files not the tree, so that we don't get tree
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
2063
# on-unlock behaviours, and so that no-one else diddles with the
2211
2064
# tree during upgrade.
2212
2065
tree._control_files.lock_write()