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,
65
49
import bzrlib.branch
66
from bzrlib.transport import get_transport
70
from bzrlib import symbol_versioning
71
53
from bzrlib.decorators import needs_read_lock, needs_write_lock
72
54
from bzrlib.filters import filtered_input_file, internal_size_sha_file_byname
73
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, entry_factory
55
from bzrlib.inventory import Inventory, ROOT_ID, entry_factory
74
56
import bzrlib.mutabletree
75
57
from bzrlib.mutabletree import needs_tree_write_lock
76
58
from bzrlib.osutils import (
86
from bzrlib.trace import mutter, note
65
from bzrlib.trace import mutter
87
66
from bzrlib.transport.local import LocalTransport
88
67
from bzrlib.tree import InterTree
89
from bzrlib.progress import DummyProgress, ProgressPhase
90
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
91
from bzrlib.rio import RioReader, rio_file, Stanza
92
from bzrlib.symbol_versioning import (deprecated_passed,
97
68
from bzrlib.tree import Tree
98
69
from bzrlib.workingtree import WorkingTree, WorkingTree3, WorkingTreeFormat3
464
435
return osutils.lexists(pathjoin(
465
436
self.basedir, row[0].decode('utf8'), row[1].decode('utf8')))
438
def has_or_had_id(self, file_id):
439
state = self.current_dirstate()
440
row, parents = self._get_entry(file_id=file_id)
441
return row is not None
468
444
def id2path(self, file_id):
469
445
"Convert a file-id to a path."
716
692
from_entry = self._get_entry(path=from_rel)
717
693
if from_entry == (None, None):
718
694
raise errors.BzrMoveFailedError(from_rel,to_dir,
719
errors.NotVersionedError(path=str(from_rel)))
695
errors.NotVersionedError(path=from_rel))
721
697
from_id = from_entry[0][2]
722
698
to_rel = pathjoin(to_dir, from_tail)
1051
1027
def set_last_revision(self, new_revision):
1052
1028
"""Change the last revision in the working tree."""
1053
1029
parents = self.get_parent_ids()
1054
if new_revision in (NULL_REVISION, None):
1030
if new_revision in (_mod_revision.NULL_REVISION, None):
1055
1031
if len(parents) >= 2:
1056
1032
raise AssertionError(
1057
1033
"setting the last parent to none with a pending merge is "
1224
1200
# just forget the whole block.
1225
1201
entry_index = 0
1226
1202
while entry_index < len(block[1]):
1227
# Mark this file id as having been removed
1228
1203
entry = block[1][entry_index]
1229
ids_to_unversion.discard(entry[0][2])
1230
if (entry[1][0][0] in 'ar' # don't remove absent or renamed
1232
or not state._make_absent(entry)):
1204
if entry[1][0][0] in 'ar':
1205
# don't remove absent or renamed entries
1233
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.
1234
1213
# go to the next block. (At the moment we dont delete empty
1236
1215
block_index += 1
1321
1300
return statvalue, sha1
1303
class ContentFilteringDirStateWorkingTree(DirStateWorkingTree):
1304
"""Dirstate working tree that supports content filtering.
1306
The dirstate holds the hash and size of the canonical form of the file,
1307
and most methods must return that.
1310
def _file_content_summary(self, path, stat_result):
1311
# This is to support the somewhat obsolete path_content_summary method
1312
# with content filtering: see
1313
# <https://bugs.edge.launchpad.net/bzr/+bug/415508>.
1315
# If the dirstate cache is up to date and knows the hash and size,
1317
# Otherwise if there are no content filters, return the on-disk size
1318
# and leave the hash blank.
1319
# Otherwise, read and filter the on-disk file and use its size and
1322
# The dirstate doesn't store the size of the canonical form so we
1323
# can't trust it for content-filtered trees. We just return None.
1324
dirstate_sha1 = self._dirstate.sha1_from_stat(path, stat_result)
1325
executable = self._is_executable_from_path_and_stat(path, stat_result)
1326
return ('file', None, executable, dirstate_sha1)
1324
1329
class WorkingTree4(DirStateWorkingTree):
1325
1330
"""This is the Format 4 working tree.
1403
1408
wt.lock_tree_write()
1405
1410
self._init_custom_control_files(wt)
1406
if revision_id in (None, NULL_REVISION):
1411
if revision_id in (None, _mod_revision.NULL_REVISION):
1407
1412
if branch.repository.supports_rich_root():
1408
1413
wt._set_root_id(generate_ids.gen_root_id())
1421
1426
if basis is None:
1422
1427
basis = branch.repository.revision_tree(revision_id)
1423
if revision_id == NULL_REVISION:
1428
if revision_id == _mod_revision.NULL_REVISION:
1424
1429
parents_list = []
1426
1431
parents_list = [(revision_id, basis)]
1444
1449
# applied so we can't safely build the inventory delta from
1445
1450
# the source tree.
1446
1451
if wt.supports_content_filtering():
1453
# see https://bugs.edge.launchpad.net/bzr/+bug/408193
1454
trace.warning("hardlinking working copy files is not currently "
1455
"supported in %r" % (wt,))
1447
1456
accelerator_tree = None
1448
1457
delta_from_tree = False
1569
1578
class DirStateRevisionTree(Tree):
1570
"""A revision tree pulling the inventory from a dirstate."""
1579
"""A revision tree pulling the inventory from a dirstate.
1581
Note that this is one of the historical (ie revision) trees cached in the
1582
dirstate for easy access, not the workingtree.
1572
1585
def __init__(self, dirstate, revision_id, repository):
1573
1586
self._dirstate = dirstate
1845
1858
return ie.executable
1847
def list_files(self, include_root=False):
1860
def list_files(self, include_root=False, from_dir=None, recursive=True):
1848
1861
# We use a standard implementation, because DirStateRevisionTree is
1849
1862
# dealing with one of the parents of the current state
1850
1863
inv = self._get_inventory()
1851
entries = inv.iter_entries()
1852
if self.inventory.root is not None and not include_root:
1864
if from_dir is None:
1867
from_dir_id = inv.path2id(from_dir)
1868
if from_dir_id is None:
1869
# Directory not versioned
1871
entries = inv.iter_entries(from_dir=from_dir_id, recursive=recursive)
1872
if inv.root is not None and not include_root and from_dir is None:
1854
1874
for path, entry in entries:
1855
1875
yield path, 'V', entry.kind, entry.file_id, entry
1963
1983
if not CompiledDirstateHelpersFeature.available():
1964
1984
from bzrlib.tests import UnavailableFeature
1965
1985
raise UnavailableFeature(CompiledDirstateHelpersFeature)
1966
from bzrlib._dirstate_helpers_c import ProcessEntryC
1986
from bzrlib._dirstate_helpers_pyx import ProcessEntryC
1967
1987
result = klass.make_source_parent_tree(source, target)
1968
1988
result[1]._iter_changes = ProcessEntryC
2009
2029
require_versioned, want_unversioned=want_unversioned)
2010
2030
parent_ids = self.target.get_parent_ids()
2011
2031
if not (self.source._revision_id in parent_ids
2012
or self.source._revision_id == NULL_REVISION):
2032
or self.source._revision_id == _mod_revision.NULL_REVISION):
2013
2033
raise AssertionError(
2014
2034
"revision {%s} is not stored in {%s}, but %s "
2015
2035
"can only be used for trees stored in the dirstate"
2016
2036
% (self.source._revision_id, self.target, self.iter_changes))
2017
2037
target_index = 0
2018
if self.source._revision_id == NULL_REVISION:
2038
if self.source._revision_id == _mod_revision.NULL_REVISION:
2019
2039
source_index = None
2020
2040
indices = (target_index,)
2042
2062
state._read_dirblocks_if_needed()
2043
2063
if require_versioned:
2044
2064
# -- check all supplied paths are versioned in a search tree. --
2045
all_versioned = True
2046
2066
for path in specific_files:
2047
2067
path_entries = state._entries_for_path(path)
2048
2068
if not path_entries:
2049
2069
# this specified path is not present at all: error
2050
all_versioned = False
2070
not_versioned.append(path)
2052
2072
found_versioned = False
2053
2073
# for each id at this path
2054
2074
for entry in path_entries:
2061
2081
if not found_versioned:
2062
2082
# none of the indexes was not 'absent' at all ids for this
2064
all_versioned = False
2066
if not all_versioned:
2067
raise errors.PathsNotVersionedError(specific_files)
2084
not_versioned.append(path)
2085
if len(not_versioned) > 0:
2086
raise errors.PathsNotVersionedError(not_versioned)
2068
2087
# -- remove redundancy in supplied specific_files to prevent over-scanning --
2069
2088
search_specific_files = osutils.minimum_path_selection(specific_files)
2084
2103
(revisiontree.RevisionTree, DirStateRevisionTree)):
2086
2105
# the source revid must be in the target dirstate
2087
if not (source._revision_id == NULL_REVISION or
2106
if not (source._revision_id == _mod_revision.NULL_REVISION or
2088
2107
source._revision_id in target.get_parent_ids()):
2089
2108
# TODO: what about ghosts? it may well need to
2090
2109
# check for them explicitly.