270
269
self._dirstate = dirstate.DirState.on_file(local_path)
271
270
return self._dirstate
272
def _directory_is_tree_reference(self, relpath):
273
# as a special case, if a directory contains control files then
274
# it's a tree reference, except that the root of the tree is not
275
return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
276
# TODO: We could ask all the control formats whether they
277
# recognize this directory, but at the moment there's no cheap api
278
# to do that. Since we probably can only nest bzr checkouts and
279
# they always use this name it's ok for now. -- mbp 20060306
281
# FIXME: There is an unhandled case here of a subdirectory
282
# containing .bzr but not a branch; that will probably blow up
283
# when you try to commit it. It might happen if there is a
284
# checkout in a subdirectory. This can be avoided by not adding
273
287
def filter_unversioned_files(self, paths):
274
288
"""Filter out paths that are versioned.
393
407
def get_file_sha1(self, file_id, path=None, stat_value=None):
394
408
# check file id is valid unconditionally.
395
409
entry = self._get_entry(file_id=file_id, path=path)
397
raise errors.NoSuchId(self, file_id)
410
assert entry[0] is not None, 'what error should this raise'
399
412
path = pathjoin(entry[0][0], entry[0][1]).decode('utf8')
401
414
file_abspath = self.abspath(path)
402
415
state = self.current_dirstate()
403
if stat_value is None:
405
stat_value = os.lstat(file_abspath)
407
if e.errno == errno.ENOENT:
411
416
link_or_sha1 = state.update_entry(entry, file_abspath,
412
417
stat_value=stat_value)
413
418
if entry[1][0][0] == 'f':
469
472
path_utf8 = osutils.pathjoin(entry[0][0], entry[0][1])
470
473
return path_utf8.decode('utf8')
472
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
473
entry = self._get_entry(path=path)
474
if entry == (None, None):
475
return False # Missing entries are not executable
476
return entry[1][0][3] # Executable?
478
475
if not osutils.supports_executable():
479
477
def is_executable(self, file_id, path=None):
480
"""Test if a file is executable or not.
482
Note: The caller is expected to take a read-lock before calling this.
478
file_id = osutils.safe_file_id(file_id)
484
479
entry = self._get_entry(file_id=file_id, path=path)
485
480
if entry == (None, None):
487
482
return entry[1][0][3]
489
_is_executable_from_path_and_stat = \
490
_is_executable_from_path_and_stat_from_basis
492
485
def is_executable(self, file_id, path=None):
493
"""Test if a file is executable or not.
495
Note: The caller is expected to take a read-lock before calling this.
497
self._must_be_locked()
487
file_id = osutils.safe_file_id(file_id)
499
488
path = self.id2path(file_id)
500
489
mode = os.lstat(self.abspath(path)).st_mode
501
490
return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
503
def all_file_ids(self):
504
"""See Tree.iter_all_file_ids"""
505
self._must_be_locked()
507
for key, tree_details in self.current_dirstate()._iter_entries():
508
if tree_details[0][0] in ('a', 'r'): # relocated
514
493
def __iter__(self):
515
494
"""Iterate through file_ids for this tree.
1085
1075
# convert absent trees to the null tree, which we convert back to
1086
1076
# missing on access.
1087
1077
for rev_id, tree in parents_list:
1088
_mod_revision.check_not_reserved_id(rev_id)
1078
rev_id = osutils.safe_revision_id(rev_id)
1089
1079
if tree is not None:
1090
1080
real_trees.append((rev_id, tree))
1092
1082
real_trees.append((rev_id,
1093
1083
self.branch.repository.revision_tree(None)))
1094
1084
ghosts.append(rev_id)
1085
dirstate._validate()
1095
1086
dirstate.set_parent_trees(real_trees, ghosts=ghosts)
1087
dirstate._validate()
1096
1088
self._make_dirty(reset_inventory=False)
1089
dirstate._validate()
1098
1091
def _set_root_id(self, file_id):
1099
1092
"""See WorkingTree.set_root_id."""
1102
1095
if state._dirblock_state == dirstate.DirState.IN_MEMORY_MODIFIED:
1103
1096
self._make_dirty(reset_inventory=True)
1105
def _sha_from_stat(self, path, stat_result):
1106
"""Get a sha digest from the tree's stat cache.
1108
The default implementation assumes no stat cache is present.
1110
:param path: The path.
1111
:param stat_result: The stat result being looked up.
1113
return self.current_dirstate().sha1_from_stat(path, stat_result)
1115
1098
@needs_read_lock
1116
1099
def supports_tree_reference(self):
1117
1100
return self._repo_supports_tree_reference
1119
1102
def unlock(self):
1120
1103
"""Unlock in format 4 trees needs to write the entire dirstate."""
1121
# do non-implementation specific cleanup
1124
1104
if self._control_files._lock_count == 1:
1125
1105
# eventually we should do signature checking during read locks for
1126
1106
# dirstate updates.
1225
1206
for file_id in file_ids:
1226
1207
self._inventory.remove_recursive_id(file_id)
1228
@needs_tree_write_lock
1229
def rename_one(self, from_rel, to_rel, after=False):
1230
"""See WorkingTree.rename_one"""
1232
WorkingTree.rename_one(self, from_rel, to_rel, after)
1234
@needs_tree_write_lock
1235
def apply_inventory_delta(self, changes):
1236
"""See MutableTree.apply_inventory_delta"""
1237
state = self.current_dirstate()
1238
state.update_by_delta(changes)
1239
self._make_dirty(reset_inventory=True)
1241
def update_basis_by_delta(self, new_revid, delta):
1242
"""See MutableTree.update_basis_by_delta."""
1243
assert self.last_revision() != new_revid
1244
self.current_dirstate().update_basis_by_delta(delta, new_revid)
1246
1209
@needs_read_lock
1247
1210
def _validate(self):
1248
1211
self._dirstate._validate()
1281
1243
"""See WorkingTreeFormat.get_format_description()."""
1282
1244
return "Working tree format 4"
1284
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1285
accelerator_tree=None, hardlink=False):
1246
def initialize(self, a_bzrdir, revision_id=None):
1286
1247
"""See WorkingTreeFormat.initialize().
1288
1249
:param revision_id: allows creating a working tree at a different
1289
1250
revision than the branch is at.
1290
:param accelerator_tree: A tree which can be used for retrieving file
1291
contents more quickly than the revision tree, i.e. a workingtree.
1292
The revision tree will be used for cases where accelerator_tree's
1293
content is different.
1294
:param hardlink: If true, hard-link files from accelerator_tree,
1297
1252
These trees get an initial random root id, if their repository supports
1298
1253
rich root data, TREE_ROOT otherwise.
1255
revision_id = osutils.safe_revision_id(revision_id)
1300
1256
if not isinstance(a_bzrdir.transport, LocalTransport):
1301
1257
raise errors.NotLocalUrl(a_bzrdir.transport.base)
1302
1258
transport = a_bzrdir.get_workingtree_transport(self)
1330
1284
wt._set_root_id(ROOT_ID)
1333
# frequently, we will get here due to branching. The accelerator
1334
# tree will be the tree from the branch, so the desired basis
1335
# tree will often be a parent of the accelerator tree.
1336
if accelerator_tree is not None:
1338
basis = accelerator_tree.revision_tree(revision_id)
1339
except errors.NoSuchRevision:
1342
basis = branch.repository.revision_tree(revision_id)
1343
if revision_id == NULL_REVISION:
1346
parents_list = [(revision_id, basis)]
1286
wt.current_dirstate()._validate()
1287
wt.set_last_revision(revision_id)
1289
basis = wt.basis_tree()
1347
1290
basis.lock_read()
1349
wt.set_parent_trees(parents_list, allow_leftmost_as_ghost=True)
1291
# if the basis has a root id we have to use that; otherwise we use
1293
basis_root_id = basis.get_root_id()
1294
if basis_root_id is not None:
1295
wt._set_root_id(basis_root_id)
1351
# if the basis has a root id we have to use that; otherwise we
1352
# use a new random one
1353
basis_root_id = basis.get_root_id()
1354
if basis_root_id is not None:
1355
wt._set_root_id(basis_root_id)
1357
transform.build_tree(basis, wt, accelerator_tree,
1297
transform.build_tree(basis, wt)
1362
1300
control_files.unlock()
1398
1336
return "<%s of %s in %s>" % \
1399
1337
(self.__class__.__name__, self._revision_id, self._dirstate)
1401
def annotate_iter(self, file_id,
1402
default_revision=_mod_revision.CURRENT_REVISION):
1339
def annotate_iter(self, file_id):
1403
1340
"""See Tree.annotate_iter"""
1404
w = self._get_weave(file_id)
1341
w = self._repository.weave_store.get_weave(file_id,
1342
self._repository.get_transaction())
1405
1343
return w.annotate_iter(self.inventory[file_id].revision)
1407
def _get_ancestors(self, default_revision):
1408
return set(self._repository.get_ancestry(self._revision_id,
1410
1345
def _comparison_data(self, entry, path):
1411
1346
"""See Tree._comparison_data."""
1412
1347
if entry is None:
1429
1364
def get_root_id(self):
1430
1365
return self.path2id('')
1432
def id2path(self, file_id):
1433
"Convert a file-id to a path."
1434
entry = self._get_entry(file_id=file_id)
1435
if entry == (None, None):
1436
raise errors.NoSuchId(tree=self, file_id=file_id)
1437
path_utf8 = osutils.pathjoin(entry[0][0], entry[0][1])
1438
return path_utf8.decode('utf8')
1440
1367
def _get_parent_index(self):
1441
1368
"""Return the index in the dirstate referenced by this tree."""
1442
1369
return self._dirstate.get_parent_ids().index(self._revision_id) + 1
1552
1480
return parent_details[1]
1555
@symbol_versioning.deprecated_method(symbol_versioning.zero_ninety)
1556
def get_weave(self, file_id):
1557
return self._get_weave(file_id)
1559
def _get_weave(self, file_id):
1560
return self._repository.weave_store.get_weave(file_id,
1561
self._repository.get_transaction())
1563
def get_file(self, file_id, path=None):
1483
def get_file(self, file_id):
1564
1484
return StringIO(self.get_file_text(file_id))
1566
1486
def get_file_lines(self, file_id):
1567
entry = self._get_entry(file_id=file_id)[1]
1569
raise errors.NoSuchId(tree=self, file_id=file_id)
1570
return self._get_weave(file_id).get_lines(entry[1][4])
1487
ie = self.inventory[file_id]
1488
return self._repository.weave_store.get_weave(file_id,
1489
self._repository.get_transaction()).get_lines(ie.revision)
1572
1491
def get_file_size(self, file_id):
1573
1492
return self.inventory[file_id].text_size
1578
1497
def get_reference_revision(self, file_id, path=None):
1579
1498
return self.inventory[file_id].reference_revision
1581
def iter_files_bytes(self, desired_files):
1582
"""See Tree.iter_files_bytes.
1584
This version is implemented on top of Repository.iter_files_bytes"""
1585
parent_index = self._get_parent_index()
1586
repo_desired_files = []
1587
for file_id, identifier in desired_files:
1588
entry = self._get_entry(file_id)
1589
if entry == (None, None):
1590
raise errors.NoSuchId(self, file_id)
1591
repo_desired_files.append((file_id, entry[1][parent_index][4],
1593
return self._repository.iter_files_bytes(repo_desired_files)
1595
1500
def get_symlink_target(self, file_id):
1596
1501
entry = self._get_entry(file_id=file_id)
1597
1502
parent_index = self._get_parent_index()
1625
1530
return bool(self.path2id(filename))
1627
1532
def kind(self, file_id):
1628
entry = self._get_entry(file_id=file_id)[1]
1630
raise errors.NoSuchId(tree=self, file_id=file_id)
1631
return dirstate.DirState._minikind_to_kind[entry[1][0]]
1633
def stored_kind(self, file_id):
1634
"""See Tree.stored_kind"""
1635
return self.kind(file_id)
1637
def path_content_summary(self, path):
1638
"""See Tree.path_content_summary."""
1639
id = self.inventory.path2id(path)
1641
return ('missing', None, None, None)
1642
entry = self._inventory[id]
1645
return (kind, entry.text_size, entry.executable, entry.text_sha1)
1646
elif kind == 'symlink':
1647
return (kind, None, None, entry.symlink_target)
1649
return (kind, None, None, None)
1533
return self.inventory[file_id].kind
1651
1535
def is_executable(self, file_id, path=None):
1652
1536
ie = self.inventory[file_id]
1760
1644
_matching_to_tree_format = WorkingTreeFormat4()
1761
1645
_test_mutable_trees_to_test_trees = make_source_parent_tree
1763
def iter_changes(self, include_unchanged=False,
1647
def _iter_changes(self, include_unchanged=False,
1764
1648
specific_files=None, pb=None, extra_trees=[],
1765
1649
require_versioned=True, want_unversioned=False):
1766
1650
"""Return the changes from source to target.
1768
:return: An iterator that yields tuples. See InterTree.iter_changes
1652
:return: An iterator that yields tuples. See InterTree._iter_changes
1770
1654
:param specific_files: An optional list of file paths to restrict the
1771
1655
comparison to. When mapping filenames to ids, all matches in all
1782
1666
output. An unversioned file is defined as one with (False, False)
1783
1667
for the versioned pair.
1785
utf8_decode = cache_utf8._utf8_decode
1669
utf8_decode_or_none = cache_utf8._utf8_decode_with_None
1786
1670
_minikind_to_kind = dirstate.DirState._minikind_to_kind
1787
cmp_by_dirs = dirstate.cmp_by_dirs
1788
1671
# NB: show_status depends on being able to pass in non-versioned files
1789
1672
# and report them as unknown
1790
1673
# TODO: handle extra trees in the dirstate.
1791
if (extra_trees or specific_files == []):
1674
# TODO: handle comparisons as an empty tree as a different special
1675
# case? mbp 20070226
1676
if extra_trees or (self.source._revision_id == NULL_REVISION):
1792
1677
# we can't fast-path these cases (yet)
1793
for f in super(InterDirStateTree, self).iter_changes(
1678
for f in super(InterDirStateTree, self)._iter_changes(
1794
1679
include_unchanged, specific_files, pb, extra_trees,
1795
1680
require_versioned, want_unversioned=want_unversioned):
1798
1683
parent_ids = self.target.get_parent_ids()
1799
assert (self.source._revision_id in parent_ids
1800
or self.source._revision_id == NULL_REVISION), \
1684
assert (self.source._revision_id in parent_ids), \
1801
1685
"revision {%s} is not stored in {%s}, but %s " \
1802
1686
"can only be used for trees stored in the dirstate" \
1803
% (self.source._revision_id, self.target, self.iter_changes)
1687
% (self.source._revision_id, self.target, self._iter_changes)
1804
1688
target_index = 0
1805
1689
if self.source._revision_id == NULL_REVISION:
1806
1690
source_index = None
1916
1800
NULL_PARENT_DETAILS = dirstate.DirState.NULL_PARENT_DETAILS
1917
1801
# Using a list so that we can access the values and change them in
1918
1802
# nested scope. Each one is [path, file_id, entry]
1919
last_source_parent = [None, None]
1920
last_target_parent = [None, None]
1803
last_source_parent = [None, None, None]
1804
last_target_parent = [None, None, None]
1922
1806
use_filesystem_for_exec = (sys.platform != 'win32')
1924
# Just a sentry, so that _process_entry can say that this
1925
# record is handled, but isn't interesting to process (unchanged)
1926
uninteresting = object()
1929
old_dirname_to_file_id = {}
1930
new_dirname_to_file_id = {}
1931
# TODO: jam 20070516 - Avoid the _get_entry lookup overhead by
1932
# keeping a cache of directories that we have seen.
1934
1808
def _process_entry(entry, path_info):
1935
1809
"""Compare an entry and real disk to generate delta information.
1983
1852
path_utf8=old_path)
1984
1853
# update the source details variable to be the real
1986
if old_entry == (None, None):
1987
raise errors.CorruptDirstate(state._filename,
1988
"entry '%s/%s' is considered renamed from %r"
1989
" but source does not exist\n"
1990
"entry: %s" % (entry[0][0], entry[0][1], old_path, entry))
1991
1855
source_details = old_entry[1][source_index]
1992
1856
source_minikind = source_details[0]
1994
1858
old_dirname = entry[0][0]
1995
1859
old_basename = entry[0][1]
1996
old_path = path = None
1860
old_path = path = pathjoin(old_dirname, old_basename)
1997
1861
if path_info is None:
1998
1862
# the file is missing on disk, show as removed.
1999
1863
content_change = True
2040
1901
target_exec = False
2042
1903
raise Exception, "unknown kind %s" % path_info[2]
2043
if source_minikind == 'd':
2045
old_path = path = pathjoin(old_dirname, old_basename)
2046
old_dirname_to_file_id[old_path] = file_id
2047
1904
# parent id is the entry for the path in the target tree
2048
1905
if old_dirname == last_source_parent[0]:
2049
1906
source_parent_id = last_source_parent[1]
2052
source_parent_id = old_dirname_to_file_id[old_dirname]
2054
source_parent_entry = state._get_entry(source_index,
2055
path_utf8=old_dirname)
2056
source_parent_id = source_parent_entry[0][2]
1908
source_parent_entry = state._get_entry(source_index,
1909
path_utf8=old_dirname)
1910
source_parent_id = source_parent_entry[0][2]
2057
1911
if source_parent_id == entry[0][2]:
2058
1912
# This is the root, so the parent is None
2059
1913
source_parent_id = None
2061
1915
last_source_parent[0] = old_dirname
2062
1916
last_source_parent[1] = source_parent_id
1917
last_source_parent[2] = source_parent_entry
2063
1918
new_dirname = entry[0][0]
2064
1919
if new_dirname == last_target_parent[0]:
2065
1920
target_parent_id = last_target_parent[1]
2068
target_parent_id = new_dirname_to_file_id[new_dirname]
2070
# TODO: We don't always need to do the lookup, because the
2071
# parent entry will be the same as the source entry.
2072
target_parent_entry = state._get_entry(target_index,
2073
path_utf8=new_dirname)
2074
assert target_parent_entry != (None, None), (
2075
"Could not find target parent in wt: %s\nparent of: %s"
2076
% (new_dirname, entry))
2077
target_parent_id = target_parent_entry[0][2]
1922
# TODO: We don't always need to do the lookup, because the
1923
# parent entry will be the same as the source entry.
1924
target_parent_entry = state._get_entry(target_index,
1925
path_utf8=new_dirname)
1926
assert target_parent_entry != (None, None), (
1927
"Could not find target parent in wt: %s\nparent of: %s"
1928
% (new_dirname, entry))
1929
target_parent_id = target_parent_entry[0][2]
2078
1930
if target_parent_id == entry[0][2]:
2079
1931
# This is the root, so the parent is None
2080
1932
target_parent_id = None
2082
1934
last_target_parent[0] = new_dirname
2083
1935
last_target_parent[1] = target_parent_id
1936
last_target_parent[2] = target_parent_entry
2085
1938
source_exec = source_details[3]
2086
if (include_unchanged
2088
or source_parent_id != target_parent_id
2089
or old_basename != entry[0][1]
2090
or source_exec != target_exec
2092
if old_path is None:
2093
old_path = path = pathjoin(old_dirname, old_basename)
2094
old_path_u = utf8_decode(old_path)[0]
2097
old_path_u = utf8_decode(old_path)[0]
2098
if old_path == path:
2101
path_u = utf8_decode(path)[0]
2102
source_kind = _minikind_to_kind[source_minikind]
2103
return (entry[0][2],
2104
(old_path_u, path_u),
2107
(source_parent_id, target_parent_id),
2108
(utf8_decode(old_basename)[0], utf8_decode(entry[0][1])[0]),
2109
(source_kind, target_kind),
2110
(source_exec, target_exec))
2112
return uninteresting
1939
return ((entry[0][2], (old_path, path), content_change,
1941
(source_parent_id, target_parent_id),
1942
(old_basename, entry[0][1]),
1943
(_minikind_to_kind[source_minikind], target_kind),
1944
(source_exec, target_exec)),)
2113
1945
elif source_minikind in 'a' and target_minikind in 'fdlt':
2114
1946
# looks like a new file
2115
1947
if path_info is not None:
2150
1980
parent_id = state._get_entry(source_index, path_utf8=entry[0][0])[0][2]
2151
1981
if parent_id == entry[0][2]:
2152
1982
parent_id = None
2153
return (entry[0][2],
2154
(utf8_decode(old_path)[0], None),
2158
(utf8_decode(entry[0][1])[0], None),
2159
(_minikind_to_kind[source_minikind], None),
2160
(source_details[3], None))
1983
return ((entry[0][2], (old_path, None), True,
1986
(entry[0][1], None),
1987
(_minikind_to_kind[source_minikind], None),
1988
(source_details[3], None)),)
2161
1989
elif source_minikind in 'fdlt' and target_minikind in 'r':
2162
1990
# a rename; could be a true rename, or a rename inherited from
2163
1991
# a renamed parent. TODO: handle this efficiently. Its not
2212
2040
path_handled = False
2213
2041
for entry in root_entries:
2214
result = _process_entry(entry, root_dir_info)
2215
if result is not None:
2042
for result in _process_entry(entry, root_dir_info):
2043
# this check should probably be outside the loop: one
2044
# 'iterate two trees' api, and then _iter_changes filters
2045
# unchanged pairs. - RBC 20070226
2216
2046
path_handled = True
2217
if result is not uninteresting:
2047
if (include_unchanged
2048
or result[2] # content change
2049
or result[3][0] != result[3][1] # versioned status
2050
or result[4][0] != result[4][1] # parent id
2051
or result[5][0] != result[5][1] # name
2052
or result[6][0] != result[6][1] # kind
2053
or result[7][0] != result[7][1] # executable
2056
(utf8_decode_or_none(result[1][0]),
2057
utf8_decode_or_none(result[1][1])),
2061
(utf8_decode_or_none(result[5][0]),
2062
utf8_decode_or_none(result[5][1])),
2219
2066
if want_unversioned and not path_handled and root_dir_info:
2220
2067
new_executable = bool(
2221
2068
stat.S_ISREG(root_dir_info[3].st_mode)
2298
2145
stat.S_ISREG(current_path_info[3].st_mode)
2299
2146
and stat.S_IEXEC & current_path_info[3].st_mode)
2301
(None, utf8_decode(current_path_info[0])[0]),
2148
(None, utf8_decode_or_none(current_path_info[0])),
2303
2150
(False, False),
2305
(None, utf8_decode(current_path_info[1])[0]),
2152
(None, utf8_decode_or_none(current_path_info[1])),
2306
2153
(None, current_path_info[2]),
2307
2154
(None, new_executable))
2308
2155
# dont descend into this unversioned path if it is
2329
2176
for current_entry in current_block[1]:
2330
2177
# entry referring to file not present on disk.
2331
2178
# advance the entry only, after processing.
2332
result = _process_entry(current_entry, None)
2333
if result is not None:
2334
if result is not uninteresting:
2179
for result in _process_entry(current_entry, None):
2180
# this check should probably be outside the loop: one
2181
# 'iterate two trees' api, and then _iter_changes filters
2182
# unchanged pairs. - RBC 20070226
2183
if (include_unchanged
2184
or result[2] # content change
2185
or result[3][0] != result[3][1] # versioned status
2186
or result[4][0] != result[4][1] # parent id
2187
or result[5][0] != result[5][1] # name
2188
or result[6][0] != result[6][1] # kind
2189
or result[7][0] != result[7][1] # executable
2192
(utf8_decode_or_none(result[1][0]),
2193
utf8_decode_or_none(result[1][1])),
2197
(utf8_decode_or_none(result[5][0]),
2198
utf8_decode_or_none(result[5][1])),
2336
2202
block_index +=1
2337
2203
if (block_index < len(state._dirblocks) and
2338
2204
osutils.is_inside(current_root,
2368
2234
elif current_path_info is None:
2369
2235
# no path is fine: the per entry code will handle it.
2370
result = _process_entry(current_entry, current_path_info)
2371
if result is not None:
2372
if result is not uninteresting:
2374
elif (current_entry[0][1] != current_path_info[1]
2375
or current_entry[1][target_index][0] in 'ar'):
2376
# The current path on disk doesn't match the dirblock
2377
# record. Either the dirblock is marked as absent, or
2378
# the file on disk is not present at all in the
2379
# dirblock. Either way, report about the dirblock
2380
# entry, and let other code handle the filesystem one.
2382
# Compare the basename for these files to determine
2236
for result in _process_entry(current_entry, current_path_info):
2237
# this check should probably be outside the loop: one
2238
# 'iterate two trees' api, and then _iter_changes filters
2239
# unchanged pairs. - RBC 20070226
2240
if (include_unchanged
2241
or result[2] # content change
2242
or result[3][0] != result[3][1] # versioned status
2243
or result[4][0] != result[4][1] # parent id
2244
or result[5][0] != result[5][1] # name
2245
or result[6][0] != result[6][1] # kind
2246
or result[7][0] != result[7][1] # executable
2249
(utf8_decode_or_none(result[1][0]),
2250
utf8_decode_or_none(result[1][1])),
2254
(utf8_decode_or_none(result[5][0]),
2255
utf8_decode_or_none(result[5][1])),
2259
elif current_entry[0][1] != current_path_info[1]:
2384
2260
if current_path_info[1] < current_entry[0][1]:
2385
2261
# extra file on disk: pass for now, but only
2386
2262
# increment the path, not the entry
2389
2265
# entry referring to file not present on disk.
2390
2266
# advance the entry only, after processing.
2391
result = _process_entry(current_entry, None)
2392
if result is not None:
2393
if result is not uninteresting:
2267
for result in _process_entry(current_entry, None):
2268
# this check should probably be outside the loop: one
2269
# 'iterate two trees' api, and then _iter_changes filters
2270
# unchanged pairs. - RBC 20070226
2272
if (include_unchanged
2273
or result[2] # content change
2274
or result[3][0] != result[3][1] # versioned status
2275
or result[4][0] != result[4][1] # parent id
2276
or result[5][0] != result[5][1] # name
2277
or result[6][0] != result[6][1] # kind
2278
or result[7][0] != result[7][1] # executable
2281
(utf8_decode_or_none(result[1][0]),
2282
utf8_decode_or_none(result[1][1])),
2286
(utf8_decode_or_none(result[5][0]),
2287
utf8_decode_or_none(result[5][1])),
2395
2291
advance_path = False
2292
elif current_entry[1][target_index][0] in 'ar':
2293
# The path matches, but the current entry is marked as
2294
# not being here. So we don't want to consider this
2295
# as a match. We still need to process the current
2297
advance_path = False
2298
path_handled = False
2299
for result in _process_entry(current_entry, None):
2300
if (include_unchanged
2301
or result[2] # content change
2302
or result[3][0] != result[3][1] # versioned status
2303
or result[4][0] != result[4][1] # parent id
2304
or result[5][0] != result[5][1] # name
2305
or result[6][0] != result[6][1] # kind
2306
or result[7][0] != result[7][1] # executable
2309
(utf8_decode_or_none(result[1][0]),
2310
utf8_decode_or_none(result[1][1])),
2314
(utf8_decode_or_none(result[5][0]),
2315
utf8_decode_or_none(result[5][1])),
2397
result = _process_entry(current_entry, current_path_info)
2398
if result is not None:
2320
for result in _process_entry(current_entry, current_path_info):
2321
# this check should probably be outside the loop: one
2322
# 'iterate two trees' api, and then _iter_changes filters
2323
# unchanged pairs. - RBC 20070226
2399
2324
path_handled = True
2400
if result is not uninteresting:
2325
if (include_unchanged
2326
or result[2] # content change
2327
or result[3][0] != result[3][1] # versioned status
2328
or result[4][0] != result[4][1] # parent id
2329
or result[5][0] != result[5][1] # name
2330
or result[6][0] != result[6][1] # kind
2331
or result[7][0] != result[7][1] # executable
2334
(utf8_decode_or_none(result[1][0]),
2335
utf8_decode_or_none(result[1][1])),
2339
(utf8_decode_or_none(result[5][0]),
2340
utf8_decode_or_none(result[5][1])),
2402
2344
if advance_entry and current_entry is not None:
2403
2345
entry_index += 1
2404
2346
if entry_index < len(current_block[1]):
2415
2357
stat.S_ISREG(current_path_info[3].st_mode)
2416
2358
and stat.S_IEXEC & current_path_info[3].st_mode)
2418
(None, utf8_decode(current_path_info[0])[0]),
2360
(None, utf8_decode_or_none(current_path_info[0])),
2420
2362
(False, False),
2422
(None, utf8_decode(current_path_info[1])[0]),
2364
(None, utf8_decode_or_none(current_path_info[1])),
2423
2365
(None, current_path_info[2]),
2424
2366
(None, new_executable))
2425
2367
# dont descend into this unversioned path if it is