1330
1209
@needs_tree_write_lock
1331
1210
def _write_inventory(self, inv):
1332
1211
"""Write inventory as the current inventory."""
1334
raise AssertionError("attempting to write an inventory when the "
1335
"dirstate is dirty will lose pending changes")
1336
had_inventory = self._inventory is not None
1337
# Setting self._inventory = None forces the dirstate to regenerate the
1338
# working inventory. We do this because self.inventory may be inv, or
1339
# may have been modified, and either case would prevent a clean delta
1341
self._inventory = None
1343
delta = inv._make_delta(self.inventory)
1345
self.apply_inventory_delta(delta)
1212
assert not self._dirty, "attempting to write an inventory when the dirstate is dirty will cause data loss"
1213
self.current_dirstate().set_state_from_inventory(inv)
1214
self._make_dirty(reset_inventory=False)
1215
if self._inventory is not None:
1347
1216
self._inventory = inv
1350
@needs_tree_write_lock
1351
def reset_state(self, revision_ids=None):
1352
"""Reset the state of the working tree.
1354
This does a hard-reset to a last-known-good state. This is a way to
1355
fix if something got corrupted (like the .bzr/checkout/dirstate file)
1357
if revision_ids is None:
1358
revision_ids = self.get_parent_ids()
1359
if not revision_ids:
1360
base_tree = self.branch.repository.revision_tree(
1361
_mod_revision.NULL_REVISION)
1364
trees = zip(revision_ids,
1365
self.branch.repository.revision_trees(revision_ids))
1366
base_tree = trees[0][1]
1367
state = self.current_dirstate()
1368
# We don't support ghosts yet
1369
state.set_state_from_scratch(base_tree.inventory, trees, [])
1372
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1374
def __init__(self, tree):
1377
def sha1(self, abspath):
1378
"""See dirstate.SHA1Provider.sha1()."""
1379
filters = self.tree._content_filter_stack(
1380
self.tree.relpath(osutils.safe_unicode(abspath)))
1381
return _mod_filters.internal_size_sha_file_byname(abspath, filters)[1]
1383
def stat_and_sha1(self, abspath):
1384
"""See dirstate.SHA1Provider.stat_and_sha1()."""
1385
filters = self.tree._content_filter_stack(
1386
self.tree.relpath(osutils.safe_unicode(abspath)))
1387
file_obj = file(abspath, 'rb', 65000)
1389
statvalue = os.fstat(file_obj.fileno())
1391
file_obj = _mod_filters.filtered_input_file(file_obj, filters)
1392
sha1 = osutils.size_sha_file(file_obj)[1]
1395
return statvalue, sha1
1398
class ContentFilteringDirStateWorkingTree(DirStateWorkingTree):
1399
"""Dirstate working tree that supports content filtering.
1401
The dirstate holds the hash and size of the canonical form of the file,
1402
and most methods must return that.
1405
def _file_content_summary(self, path, stat_result):
1406
# This is to support the somewhat obsolete path_content_summary method
1407
# with content filtering: see
1408
# <https://bugs.launchpad.net/bzr/+bug/415508>.
1410
# If the dirstate cache is up to date and knows the hash and size,
1412
# Otherwise if there are no content filters, return the on-disk size
1413
# and leave the hash blank.
1414
# Otherwise, read and filter the on-disk file and use its size and
1417
# The dirstate doesn't store the size of the canonical form so we
1418
# can't trust it for content-filtered trees. We just return None.
1419
dirstate_sha1 = self._dirstate.sha1_from_stat(path, stat_result)
1420
executable = self._is_executable_from_path_and_stat(path, stat_result)
1421
return ('file', None, executable, dirstate_sha1)
1424
class WorkingTree4(DirStateWorkingTree):
1425
"""This is the Format 4 working tree.
1427
This differs from WorkingTree by:
1428
- Having a consolidated internal dirstate, stored in a
1429
randomly-accessible sorted file on disk.
1430
- Not having a regular inventory attribute. One can be synthesized
1431
on demand but this is expensive and should be avoided.
1433
This is new in bzr 0.15.
1437
class WorkingTree5(ContentFilteringDirStateWorkingTree):
1438
"""This is the Format 5 working tree.
1440
This differs from WorkingTree4 by:
1441
- Supporting content filtering.
1443
This is new in bzr 1.11.
1447
class WorkingTree6(ContentFilteringDirStateWorkingTree):
1448
"""This is the Format 6 working tree.
1450
This differs from WorkingTree5 by:
1451
- Supporting a current view that may mask the set of files in a tree
1452
impacted by most user operations.
1454
This is new in bzr 1.14.
1457
def _make_views(self):
1458
return views.PathBasedViews(self)
1461
class DirStateWorkingTreeFormat(WorkingTreeFormat):
1463
missing_parent_conflicts = True
1465
supports_versioned_directories = True
1467
_lock_class = LockDir
1468
_lock_file_name = 'lock'
1470
def _open_control_files(self, a_bzrdir):
1471
transport = a_bzrdir.get_workingtree_transport(None)
1472
return LockableFiles(transport, self._lock_file_name,
1475
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1476
accelerator_tree=None, hardlink=False):
1220
class WorkingTreeFormat4(WorkingTreeFormat3):
1221
"""The first consolidated dirstate working tree format.
1224
- exists within a metadir controlling .bzr
1225
- includes an explicit version marker for the workingtree control
1226
files, separate from the BzrDir format
1227
- modifies the hash cache format
1228
- is new in bzr 0.15
1229
- uses a LockDir to guard access to it.
1232
upgrade_recommended = False
1234
def get_format_string(self):
1235
"""See WorkingTreeFormat.get_format_string()."""
1236
return "Bazaar Working Tree Format 4 (bzr 0.15)\n"
1238
def get_format_description(self):
1239
"""See WorkingTreeFormat.get_format_description()."""
1240
return "Working tree format 4"
1242
def initialize(self, a_bzrdir, revision_id=None):
1477
1243
"""See WorkingTreeFormat.initialize().
1479
1245
:param revision_id: allows creating a working tree at a different
1480
revision than the branch is at.
1481
:param accelerator_tree: A tree which can be used for retrieving file
1482
contents more quickly than the revision tree, i.e. a workingtree.
1483
The revision tree will be used for cases where accelerator_tree's
1484
content is different.
1485
:param hardlink: If true, hard-link files from accelerator_tree,
1246
revision than the branch is at.
1488
These trees get an initial random root id, if their repository supports
1489
rich root data, TREE_ROOT otherwise.
1248
These trees get an initial random root id.
1250
revision_id = osutils.safe_revision_id(revision_id)
1491
1251
if not isinstance(a_bzrdir.transport, LocalTransport):
1492
1252
raise errors.NotLocalUrl(a_bzrdir.transport.base)
1493
1253
transport = a_bzrdir.get_workingtree_transport(self)
1494
1254
control_files = self._open_control_files(a_bzrdir)
1495
1255
control_files.create_lock()
1496
1256
control_files.lock_write()
1497
transport.put_bytes('format', self.get_format_string(),
1498
mode=a_bzrdir._get_file_mode())
1499
if from_branch is not None:
1500
branch = from_branch
1502
branch = a_bzrdir.open_branch()
1257
control_files.put_utf8('format', self.get_format_string())
1258
branch = a_bzrdir.open_branch()
1503
1259
if revision_id is None:
1504
1260
revision_id = branch.last_revision()
1505
1261
local_path = transport.local_abspath('dirstate')
2200
1738
if not found_versioned:
2201
1739
# none of the indexes was not 'absent' at all ids for this
2203
not_versioned.append(path)
2204
if len(not_versioned) > 0:
2205
raise errors.PathsNotVersionedError(not_versioned)
1741
all_versioned = False
1743
if not all_versioned:
1744
raise errors.PathsNotVersionedError(specific_files)
2206
1745
# -- remove redundancy in supplied specific_files to prevent over-scanning --
2207
search_specific_files = osutils.minimum_path_selection(specific_files)
1746
search_specific_files = set()
1747
for path in specific_files:
1748
other_specific_files = specific_files.difference(set([path]))
1749
if not osutils.is_inside_any(other_specific_files, path):
1750
# this is a top level path, we must check it.
1751
search_specific_files.add(path)
1753
# compare source_index and target_index at or under each element of search_specific_files.
1754
# follow the following comparison table. Note that we only want to do diff operations when
1755
# the target is fdl because thats when the walkdirs logic will have exposed the pathinfo
1759
# Source | Target | disk | action
1760
# r | fdlt | | add source to search, add id path move and perform
1761
# | | | diff check on source-target
1762
# r | fdlt | a | dangling file that was present in the basis.
1764
# r | a | | add source to search
1766
# r | r | | this path is present in a non-examined tree, skip.
1767
# r | r | a | this path is present in a non-examined tree, skip.
1768
# a | fdlt | | add new id
1769
# a | fdlt | a | dangling locally added file, skip
1770
# a | a | | not present in either tree, skip
1771
# a | a | a | not present in any tree, skip
1772
# a | r | | not present in either tree at this path, skip as it
1773
# | | | may not be selected by the users list of paths.
1774
# a | r | a | not present in either tree at this path, skip as it
1775
# | | | may not be selected by the users list of paths.
1776
# fdlt | fdlt | | content in both: diff them
1777
# fdlt | fdlt | a | deleted locally, but not unversioned - show as deleted ?
1778
# fdlt | a | | unversioned: output deleted id for now
1779
# fdlt | a | a | unversioned and deleted: output deleted id
1780
# fdlt | r | | relocated in this tree, so add target to search.
1781
# | | | Dont diff, we will see an r,fd; pair when we reach
1782
# | | | this id at the other path.
1783
# fdlt | r | a | relocated in this tree, so add target to search.
1784
# | | | Dont diff, we will see an r,fd; pair when we reach
1785
# | | | this id at the other path.
1787
# for all search_indexs in each path at or under each element of
1788
# search_specific_files, if the detail is relocated: add the id, and add the
1789
# relocated path as one to search if its not searched already. If the
1790
# detail is not relocated, add the id.
1791
searched_specific_files = set()
1792
NULL_PARENT_DETAILS = dirstate.DirState.NULL_PARENT_DETAILS
1793
# Using a list so that we can access the values and change them in
1794
# nested scope. Each one is [path, file_id, entry]
1795
last_source_parent = [None, None, None]
1796
last_target_parent = [None, None, None]
2209
1798
use_filesystem_for_exec = (sys.platform != 'win32')
2210
iter_changes = self.target._iter_changes(include_unchanged,
2211
use_filesystem_for_exec, search_specific_files, state,
2212
source_index, target_index, want_unversioned, self.target)
2213
return iter_changes.iter_changes()
1800
def _process_entry(entry, path_info):
1801
"""Compare an entry and real disk to generate delta information.
1803
:param path_info: top_relpath, basename, kind, lstat, abspath for
1804
the path of entry. If None, then the path is considered absent.
1805
(Perhaps we should pass in a concrete entry for this ?)
1806
Basename is returned as a utf8 string because we expect this
1807
tuple will be ignored, and don't want to take the time to
1810
if source_index is None:
1811
source_details = NULL_PARENT_DETAILS
1813
source_details = entry[1][source_index]
1814
target_details = entry[1][target_index]
1815
target_minikind = target_details[0]
1816
if path_info is not None and target_minikind in 'fdlt':
1817
assert target_index == 0
1818
link_or_sha1 = state.update_entry(entry, abspath=path_info[4],
1819
stat_value=path_info[3])
1820
# The entry may have been modified by update_entry
1821
target_details = entry[1][target_index]
1822
target_minikind = target_details[0]
1825
source_minikind = source_details[0]
1826
if source_minikind in 'fdltr' and target_minikind in 'fdlt':
1827
# claimed content in both: diff
1828
# r | fdlt | | add source to search, add id path move and perform
1829
# | | | diff check on source-target
1830
# r | fdlt | a | dangling file that was present in the basis.
1832
if source_minikind in 'r':
1833
# add the source to the search path to find any children it
1834
# has. TODO ? : only add if it is a container ?
1835
if not osutils.is_inside_any(searched_specific_files,
1837
search_specific_files.add(source_details[1])
1838
# generate the old path; this is needed for stating later
1840
old_path = source_details[1]
1841
old_dirname, old_basename = os.path.split(old_path)
1842
path = pathjoin(entry[0][0], entry[0][1])
1843
old_entry = state._get_entry(source_index,
1845
# update the source details variable to be the real
1847
source_details = old_entry[1][source_index]
1848
source_minikind = source_details[0]
1850
old_dirname = entry[0][0]
1851
old_basename = entry[0][1]
1852
old_path = path = pathjoin(old_dirname, old_basename)
1853
if path_info is None:
1854
# the file is missing on disk, show as removed.
1855
content_change = True
1859
# source and target are both versioned and disk file is present.
1860
target_kind = path_info[2]
1861
if target_kind == 'directory':
1862
if source_minikind != 'd':
1863
content_change = True
1865
# directories have no fingerprint
1866
content_change = False
1868
elif target_kind == 'file':
1869
if source_minikind != 'f':
1870
content_change = True
1872
# We could check the size, but we already have the
1874
content_change = (link_or_sha1 != source_details[1])
1875
# Target details is updated at update_entry time
1876
if use_filesystem_for_exec:
1877
# We don't need S_ISREG here, because we are sure
1878
# we are dealing with a file.
1879
target_exec = bool(stat.S_IEXEC & path_info[3].st_mode)
1881
target_exec = target_details[3]
1882
elif target_kind == 'symlink':
1883
if source_minikind != 'l':
1884
content_change = True
1886
content_change = (link_or_sha1 != source_details[1])
1888
elif target_kind == 'tree-reference':
1889
if source_minikind != 't':
1890
content_change = True
1892
content_change = False
1895
raise Exception, "unknown kind %s" % path_info[2]
1896
# parent id is the entry for the path in the target tree
1897
if old_dirname == last_source_parent[0]:
1898
source_parent_id = last_source_parent[1]
1900
source_parent_entry = state._get_entry(source_index,
1901
path_utf8=old_dirname)
1902
source_parent_id = source_parent_entry[0][2]
1903
if source_parent_id == entry[0][2]:
1904
# This is the root, so the parent is None
1905
source_parent_id = None
1907
last_source_parent[0] = old_dirname
1908
last_source_parent[1] = source_parent_id
1909
last_source_parent[2] = source_parent_entry
1910
new_dirname = entry[0][0]
1911
if new_dirname == last_target_parent[0]:
1912
target_parent_id = last_target_parent[1]
1914
# TODO: We don't always need to do the lookup, because the
1915
# parent entry will be the same as the source entry.
1916
target_parent_entry = state._get_entry(target_index,
1917
path_utf8=new_dirname)
1918
target_parent_id = target_parent_entry[0][2]
1919
if target_parent_id == entry[0][2]:
1920
# This is the root, so the parent is None
1921
target_parent_id = None
1923
last_target_parent[0] = new_dirname
1924
last_target_parent[1] = target_parent_id
1925
last_target_parent[2] = target_parent_entry
1927
source_exec = source_details[3]
1928
return ((entry[0][2], (old_path, path), content_change,
1930
(source_parent_id, target_parent_id),
1931
(old_basename, entry[0][1]),
1932
(_minikind_to_kind[source_minikind], target_kind),
1933
(source_exec, target_exec)),)
1934
elif source_minikind in 'a' and target_minikind in 'fdlt':
1935
# looks like a new file
1936
if path_info is not None:
1937
path = pathjoin(entry[0][0], entry[0][1])
1938
# parent id is the entry for the path in the target tree
1939
# TODO: these are the same for an entire directory: cache em.
1940
parent_id = state._get_entry(target_index,
1941
path_utf8=entry[0][0])[0][2]
1942
if parent_id == entry[0][2]:
1944
if use_filesystem_for_exec:
1945
# We need S_ISREG here, because we aren't sure if this
1948
stat.S_ISREG(path_info[3].st_mode)
1949
and stat.S_IEXEC & path_info[3].st_mode)
1951
target_exec = target_details[3]
1952
return ((entry[0][2], (None, path), True,
1955
(None, entry[0][1]),
1956
(None, path_info[2]),
1957
(None, target_exec)),)
1959
# but its not on disk: we deliberately treat this as just
1960
# never-present. (Why ?! - RBC 20070224)
1962
elif source_minikind in 'fdlt' and target_minikind in 'a':
1963
# unversioned, possibly, or possibly not deleted: we dont care.
1964
# if its still on disk, *and* theres no other entry at this
1965
# path [we dont know this in this routine at the moment -
1966
# perhaps we should change this - then it would be an unknown.
1967
old_path = pathjoin(entry[0][0], entry[0][1])
1968
# parent id is the entry for the path in the target tree
1969
parent_id = state._get_entry(source_index, path_utf8=entry[0][0])[0][2]
1970
if parent_id == entry[0][2]:
1972
return ((entry[0][2], (old_path, None), True,
1975
(entry[0][1], None),
1976
(_minikind_to_kind[source_minikind], None),
1977
(source_details[3], None)),)
1978
elif source_minikind in 'fdlt' and target_minikind in 'r':
1979
# a rename; could be a true rename, or a rename inherited from
1980
# a renamed parent. TODO: handle this efficiently. Its not
1981
# common case to rename dirs though, so a correct but slow
1982
# implementation will do.
1983
if not osutils.is_inside_any(searched_specific_files, target_details[1]):
1984
search_specific_files.add(target_details[1])
1985
elif source_minikind in 'ra' and target_minikind in 'ra':
1986
# neither of the selected trees contain this file,
1987
# so skip over it. This is not currently directly tested, but
1988
# is indirectly via test_too_much.TestCommands.test_conflicts.
1991
raise AssertionError("don't know how to compare "
1992
"source_minikind=%r, target_minikind=%r"
1993
% (source_minikind, target_minikind))
1994
## import pdb;pdb.set_trace()
1997
while search_specific_files:
1998
# TODO: the pending list should be lexically sorted? the
1999
# interface doesn't require it.
2000
current_root = search_specific_files.pop()
2001
current_root_unicode = current_root.decode('utf8')
2002
searched_specific_files.add(current_root)
2003
# process the entries for this containing directory: the rest will be
2004
# found by their parents recursively.
2005
root_entries = _entries_for_path(current_root)
2006
root_abspath = self.target.abspath(current_root_unicode)
2008
root_stat = os.lstat(root_abspath)
2010
if e.errno == errno.ENOENT:
2011
# the path does not exist: let _process_entry know that.
2012
root_dir_info = None
2014
# some other random error: hand it up.
2017
root_dir_info = ('', current_root,
2018
osutils.file_kind_from_stat_mode(root_stat.st_mode), root_stat,
2020
if root_dir_info[2] == 'directory':
2021
if self.target._directory_is_tree_reference(
2022
current_root.decode('utf8')):
2023
root_dir_info = root_dir_info[:2] + \
2024
('tree-reference',) + root_dir_info[3:]
2026
if not root_entries and not root_dir_info:
2027
# this specified path is not present at all, skip it.
2029
path_handled = False
2030
for entry in root_entries:
2031
for result in _process_entry(entry, root_dir_info):
2032
# this check should probably be outside the loop: one
2033
# 'iterate two trees' api, and then _iter_changes filters
2034
# unchanged pairs. - RBC 20070226
2036
if (include_unchanged
2037
or result[2] # content change
2038
or result[3][0] != result[3][1] # versioned status
2039
or result[4][0] != result[4][1] # parent id
2040
or result[5][0] != result[5][1] # name
2041
or result[6][0] != result[6][1] # kind
2042
or result[7][0] != result[7][1] # executable
2045
(utf8_decode_or_none(result[1][0]),
2046
utf8_decode_or_none(result[1][1])),
2050
(utf8_decode_or_none(result[5][0]),
2051
utf8_decode_or_none(result[5][1])),
2055
if want_unversioned and not path_handled and root_dir_info:
2056
new_executable = bool(
2057
stat.S_ISREG(root_dir_info[3].st_mode)
2058
and stat.S_IEXEC & root_dir_info[3].st_mode)
2060
(None, current_root_unicode),
2064
(None, splitpath(current_root_unicode)[-1]),
2065
(None, root_dir_info[2]),
2066
(None, new_executable)
2068
initial_key = (current_root, '', '')
2069
block_index, _ = state._find_block_index_from_key(initial_key)
2070
if block_index == 0:
2071
# we have processed the total root already, but because the
2072
# initial key matched it we should skip it here.
2074
if root_dir_info and root_dir_info[2] == 'tree-reference':
2075
current_dir_info = None
2077
dir_iterator = osutils._walkdirs_utf8(root_abspath, prefix=current_root)
2079
current_dir_info = dir_iterator.next()
2081
# on win32, python2.4 has e.errno == ERROR_DIRECTORY, but
2082
# python 2.5 has e.errno == EINVAL,
2083
# and e.winerror == ERROR_DIRECTORY
2084
e_winerror = getattr(e, 'winerror', None)
2085
# there may be directories in the inventory even though
2086
# this path is not a file on disk: so mark it as end of
2088
if e.errno in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
2089
current_dir_info = None
2090
elif (sys.platform == 'win32'
2091
and ERROR_DIRECTORY in (e.errno, e_winerror)):
2092
current_dir_info = None
2096
if current_dir_info[0][0] == '':
2097
# remove .bzr from iteration
2098
bzr_index = bisect_left(current_dir_info[1], ('.bzr',))
2099
assert current_dir_info[1][bzr_index][0] == '.bzr'
2100
del current_dir_info[1][bzr_index]
2101
# walk until both the directory listing and the versioned metadata
2103
if (block_index < len(state._dirblocks) and
2104
osutils.is_inside(current_root, state._dirblocks[block_index][0])):
2105
current_block = state._dirblocks[block_index]
2107
current_block = None
2108
while (current_dir_info is not None or
2109
current_block is not None):
2110
if (current_dir_info and current_block
2111
and current_dir_info[0][0] != current_block[0]):
2112
if current_dir_info[0][0] < current_block[0] :
2113
# filesystem data refers to paths not covered by the dirblock.
2114
# this has two possibilities:
2115
# A) it is versioned but empty, so there is no block for it
2116
# B) it is not versioned.
2117
# in either case it was processed by the containing directories walk:
2118
# if it is root/foo, when we walked root we emitted it,
2119
# or if we ere given root/foo to walk specifically, we
2120
# emitted it when checking the walk-root entries
2121
# advance the iterator and loop - we dont need to emit it.
2123
current_dir_info = dir_iterator.next()
2124
except StopIteration:
2125
current_dir_info = None
2127
# We have a dirblock entry for this location, but there
2128
# is no filesystem path for this. This is most likely
2129
# because a directory was removed from the disk.
2130
# We don't have to report the missing directory,
2131
# because that should have already been handled, but we
2132
# need to handle all of the files that are contained
2134
for current_entry in current_block[1]:
2135
# entry referring to file not present on disk.
2136
# advance the entry only, after processing.
2137
for result in _process_entry(current_entry, None):
2138
# this check should probably be outside the loop: one
2139
# 'iterate two trees' api, and then _iter_changes filters
2140
# unchanged pairs. - RBC 20070226
2141
if (include_unchanged
2142
or result[2] # content change
2143
or result[3][0] != result[3][1] # versioned status
2144
or result[4][0] != result[4][1] # parent id
2145
or result[5][0] != result[5][1] # name
2146
or result[6][0] != result[6][1] # kind
2147
or result[7][0] != result[7][1] # executable
2150
(utf8_decode_or_none(result[1][0]),
2151
utf8_decode_or_none(result[1][1])),
2155
(utf8_decode_or_none(result[5][0]),
2156
utf8_decode_or_none(result[5][1])),
2161
if (block_index < len(state._dirblocks) and
2162
osutils.is_inside(current_root,
2163
state._dirblocks[block_index][0])):
2164
current_block = state._dirblocks[block_index]
2166
current_block = None
2169
if current_block and entry_index < len(current_block[1]):
2170
current_entry = current_block[1][entry_index]
2172
current_entry = None
2173
advance_entry = True
2175
if current_dir_info and path_index < len(current_dir_info[1]):
2176
current_path_info = current_dir_info[1][path_index]
2177
if current_path_info[2] == 'directory':
2178
if self.target._directory_is_tree_reference(
2179
current_path_info[0].decode('utf8')):
2180
current_path_info = current_path_info[:2] + \
2181
('tree-reference',) + current_path_info[3:]
2183
current_path_info = None
2185
path_handled = False
2186
while (current_entry is not None or
2187
current_path_info is not None):
2188
if current_entry is None:
2189
# the check for path_handled when the path is adnvaced
2190
# will yield this path if needed.
2192
elif current_path_info is None:
2193
# no path is fine: the per entry code will handle it.
2194
for result in _process_entry(current_entry, current_path_info):
2195
# this check should probably be outside the loop: one
2196
# 'iterate two trees' api, and then _iter_changes filters
2197
# unchanged pairs. - RBC 20070226
2198
if (include_unchanged
2199
or result[2] # content change
2200
or result[3][0] != result[3][1] # versioned status
2201
or result[4][0] != result[4][1] # parent id
2202
or result[5][0] != result[5][1] # name
2203
or result[6][0] != result[6][1] # kind
2204
or result[7][0] != result[7][1] # executable
2207
(utf8_decode_or_none(result[1][0]),
2208
utf8_decode_or_none(result[1][1])),
2212
(utf8_decode_or_none(result[5][0]),
2213
utf8_decode_or_none(result[5][1])),
2217
elif current_entry[0][1] != current_path_info[1]:
2218
if current_path_info[1] < current_entry[0][1]:
2219
# extra file on disk: pass for now, but only
2220
# increment the path, not the entry
2221
advance_entry = False
2223
# entry referring to file not present on disk.
2224
# advance the entry only, after processing.
2225
for result in _process_entry(current_entry, None):
2226
# this check should probably be outside the loop: one
2227
# 'iterate two trees' api, and then _iter_changes filters
2228
# unchanged pairs. - RBC 20070226
2230
if (include_unchanged
2231
or result[2] # content change
2232
or result[3][0] != result[3][1] # versioned status
2233
or result[4][0] != result[4][1] # parent id
2234
or result[5][0] != result[5][1] # name
2235
or result[6][0] != result[6][1] # kind
2236
or result[7][0] != result[7][1] # executable
2239
(utf8_decode_or_none(result[1][0]),
2240
utf8_decode_or_none(result[1][1])),
2244
(utf8_decode_or_none(result[5][0]),
2245
utf8_decode_or_none(result[5][1])),
2249
advance_path = False
2251
for result in _process_entry(current_entry, current_path_info):
2252
# this check should probably be outside the loop: one
2253
# 'iterate two trees' api, and then _iter_changes filters
2254
# unchanged pairs. - RBC 20070226
2256
if (include_unchanged
2257
or result[2] # content change
2258
or result[3][0] != result[3][1] # versioned status
2259
or result[4][0] != result[4][1] # parent id
2260
or result[5][0] != result[5][1] # name
2261
or result[6][0] != result[6][1] # kind
2262
or result[7][0] != result[7][1] # executable
2265
(utf8_decode_or_none(result[1][0]),
2266
utf8_decode_or_none(result[1][1])),
2270
(utf8_decode_or_none(result[5][0]),
2271
utf8_decode_or_none(result[5][1])),
2275
if advance_entry and current_entry is not None:
2277
if entry_index < len(current_block[1]):
2278
current_entry = current_block[1][entry_index]
2280
current_entry = None
2282
advance_entry = True # reset the advance flaga
2283
if advance_path and current_path_info is not None:
2284
if not path_handled:
2285
# unversioned in all regards
2286
if want_unversioned:
2287
new_executable = bool(
2288
stat.S_ISREG(current_path_info[3].st_mode)
2289
and stat.S_IEXEC & current_path_info[3].st_mode)
2290
if want_unversioned:
2292
(None, utf8_decode_or_none(current_path_info[0])),
2296
(None, utf8_decode_or_none(current_path_info[1])),
2297
(None, current_path_info[2]),
2298
(None, new_executable))
2299
# dont descend into this unversioned path if it is
2301
if current_path_info[2] in ('directory'):
2302
del current_dir_info[1][path_index]
2304
# dont descend the disk iterator into any tree
2306
if current_path_info[2] == 'tree-reference':
2307
del current_dir_info[1][path_index]
2310
if path_index < len(current_dir_info[1]):
2311
current_path_info = current_dir_info[1][path_index]
2312
if current_path_info[2] == 'directory':
2313
if self.target._directory_is_tree_reference(
2314
current_path_info[0].decode('utf8')):
2315
current_path_info = current_path_info[:2] + \
2316
('tree-reference',) + current_path_info[3:]
2318
current_path_info = None
2319
path_handled = False
2321
advance_path = True # reset the advance flagg.
2322
if current_block is not None:
2324
if (block_index < len(state._dirblocks) and
2325
osutils.is_inside(current_root, state._dirblocks[block_index][0])):
2326
current_block = state._dirblocks[block_index]
2328
current_block = None
2329
if current_dir_info is not None:
2331
current_dir_info = dir_iterator.next()
2332
except StopIteration:
2333
current_dir_info = None
2216
2337
def is_compatible(source, target):
2217
2338
# the target must be a dirstate working tree
2218
if not isinstance(target, DirStateWorkingTree):
2339
if not isinstance(target, WorkingTree4):
2220
# the source must be a revtree or dirstate rev tree.
2341
# the source must be a revtreee or dirstate rev tree.
2221
2342
if not isinstance(source,
2222
2343
(revisiontree.RevisionTree, DirStateRevisionTree)):
2224
2345
# the source revid must be in the target dirstate
2225
if not (source._revision_id == _mod_revision.NULL_REVISION or
2346
if not (source._revision_id == NULL_REVISION or
2226
2347
source._revision_id in target.get_parent_ids()):
2227
# TODO: what about ghosts? it may well need to
2348
# TODO: what about ghosts? it may well need to
2228
2349
# check for them explicitly.