483
473
return path_utf8.decode('utf8')
485
475
if not osutils.supports_executable():
486
477
def is_executable(self, file_id, path=None):
487
"""Test if a file is executable or not.
489
Note: The caller is expected to take a read-lock before calling this.
491
478
file_id = osutils.safe_file_id(file_id)
492
479
entry = self._get_entry(file_id=file_id, path=path)
493
480
if entry == (None, None):
495
482
return entry[1][0][3]
497
485
def is_executable(self, file_id, path=None):
498
"""Test if a file is executable or not.
500
Note: The caller is expected to take a read-lock before calling this.
503
487
file_id = osutils.safe_file_id(file_id)
504
488
path = self.id2path(file_id)
1090
1076
# missing on access.
1091
1077
for rev_id, tree in parents_list:
1092
1078
rev_id = osutils.safe_revision_id(rev_id)
1093
_mod_revision.check_not_reserved_id(rev_id)
1094
1079
if tree is not None:
1095
1080
real_trees.append((rev_id, tree))
1097
1082
real_trees.append((rev_id,
1098
1083
self.branch.repository.revision_tree(None)))
1099
1084
ghosts.append(rev_id)
1085
dirstate._validate()
1100
1086
dirstate.set_parent_trees(real_trees, ghosts=ghosts)
1087
dirstate._validate()
1101
1088
self._make_dirty(reset_inventory=False)
1089
dirstate._validate()
1103
1091
def _set_root_id(self, file_id):
1104
1092
"""See WorkingTree.set_root_id."""
1814
1800
NULL_PARENT_DETAILS = dirstate.DirState.NULL_PARENT_DETAILS
1815
1801
# Using a list so that we can access the values and change them in
1816
1802
# nested scope. Each one is [path, file_id, entry]
1817
last_source_parent = [None, None]
1818
last_target_parent = [None, None]
1803
last_source_parent = [None, None, None]
1804
last_target_parent = [None, None, None]
1820
1806
use_filesystem_for_exec = (sys.platform != 'win32')
1822
# Just a sentry, so that _process_entry can say that this
1823
# record is handled, but isn't interesting to process (unchanged)
1824
uninteresting = object()
1827
old_dirname_to_file_id = {}
1828
new_dirname_to_file_id = {}
1829
# TODO: jam 20070516 - Avoid the _get_entry lookup overhead by
1830
# keeping a cache of directories that we have seen.
1832
1808
def _process_entry(entry, path_info):
1833
1809
"""Compare an entry and real disk to generate delta information.
1933
1901
target_exec = False
1935
1903
raise Exception, "unknown kind %s" % path_info[2]
1936
if source_minikind == 'd':
1938
old_path = path = pathjoin(old_dirname, old_basename)
1939
old_dirname_to_file_id[old_path] = file_id
1940
1904
# parent id is the entry for the path in the target tree
1941
1905
if old_dirname == last_source_parent[0]:
1942
1906
source_parent_id = last_source_parent[1]
1945
source_parent_id = old_dirname_to_file_id[old_dirname]
1947
source_parent_entry = state._get_entry(source_index,
1948
path_utf8=old_dirname)
1949
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]
1950
1911
if source_parent_id == entry[0][2]:
1951
1912
# This is the root, so the parent is None
1952
1913
source_parent_id = None
1954
1915
last_source_parent[0] = old_dirname
1955
1916
last_source_parent[1] = source_parent_id
1917
last_source_parent[2] = source_parent_entry
1956
1918
new_dirname = entry[0][0]
1957
1919
if new_dirname == last_target_parent[0]:
1958
1920
target_parent_id = last_target_parent[1]
1961
target_parent_id = new_dirname_to_file_id[new_dirname]
1963
# TODO: We don't always need to do the lookup, because the
1964
# parent entry will be the same as the source entry.
1965
target_parent_entry = state._get_entry(target_index,
1966
path_utf8=new_dirname)
1967
assert target_parent_entry != (None, None), (
1968
"Could not find target parent in wt: %s\nparent of: %s"
1969
% (new_dirname, entry))
1970
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]
1971
1930
if target_parent_id == entry[0][2]:
1972
1931
# This is the root, so the parent is None
1973
1932
target_parent_id = None
1975
1934
last_target_parent[0] = new_dirname
1976
1935
last_target_parent[1] = target_parent_id
1936
last_target_parent[2] = target_parent_entry
1978
1938
source_exec = source_details[3]
1979
if (include_unchanged
1981
or source_parent_id != target_parent_id
1982
or old_basename != entry[0][1]
1983
or source_exec != target_exec
1985
if old_path is None:
1986
old_path = path = pathjoin(old_dirname, old_basename)
1987
old_path_u = utf8_decode(old_path)[0]
1990
old_path_u = utf8_decode(old_path)[0]
1991
if old_path == path:
1994
path_u = utf8_decode(path)[0]
1995
source_kind = _minikind_to_kind[source_minikind]
1996
return (entry[0][2],
1997
(old_path_u, path_u),
2000
(source_parent_id, target_parent_id),
2001
(utf8_decode(old_basename)[0], utf8_decode(entry[0][1])[0]),
2002
(source_kind, target_kind),
2003
(source_exec, target_exec))
2005
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)),)
2006
1945
elif source_minikind in 'a' and target_minikind in 'fdlt':
2007
1946
# looks like a new file
2008
1947
if path_info is not None:
2043
1980
parent_id = state._get_entry(source_index, path_utf8=entry[0][0])[0][2]
2044
1981
if parent_id == entry[0][2]:
2045
1982
parent_id = None
2046
return (entry[0][2],
2047
(utf8_decode(old_path)[0], None),
2051
(utf8_decode(entry[0][1])[0], None),
2052
(_minikind_to_kind[source_minikind], None),
2053
(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)),)
2054
1989
elif source_minikind in 'fdlt' and target_minikind in 'r':
2055
1990
# a rename; could be a true rename, or a rename inherited from
2056
1991
# a renamed parent. TODO: handle this efficiently. Its not
2105
2040
path_handled = False
2106
2041
for entry in root_entries:
2107
result = _process_entry(entry, root_dir_info)
2108
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
2109
2046
path_handled = True
2110
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])),
2112
2066
if want_unversioned and not path_handled and root_dir_info:
2113
2067
new_executable = bool(
2114
2068
stat.S_ISREG(root_dir_info[3].st_mode)
2191
2145
stat.S_ISREG(current_path_info[3].st_mode)
2192
2146
and stat.S_IEXEC & current_path_info[3].st_mode)
2194
(None, utf8_decode(current_path_info[0])[0]),
2148
(None, utf8_decode_or_none(current_path_info[0])),
2196
2150
(False, False),
2198
(None, utf8_decode(current_path_info[1])[0]),
2152
(None, utf8_decode_or_none(current_path_info[1])),
2199
2153
(None, current_path_info[2]),
2200
2154
(None, new_executable))
2201
# dont descend into this unversioned path if it is
2203
if current_path_info[2] in ('directory',
2205
del current_dir_info[1][path_index]
2155
# dont descend into this unversioned path if it is
2157
if current_path_info[2] in ('directory',
2159
del current_dir_info[1][path_index]
2209
2163
# This dir info has been handled, go to the next
2222
2176
for current_entry in current_block[1]:
2223
2177
# entry referring to file not present on disk.
2224
2178
# advance the entry only, after processing.
2225
result = _process_entry(current_entry, None)
2226
if result is not None:
2227
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])),
2229
2202
block_index +=1
2230
2203
if (block_index < len(state._dirblocks) and
2231
2204
osutils.is_inside(current_root,
2261
2234
elif current_path_info is None:
2262
2235
# no path is fine: the per entry code will handle it.
2263
result = _process_entry(current_entry, current_path_info)
2264
if result is not None:
2265
if result is not uninteresting:
2267
elif (current_entry[0][1] != current_path_info[1]
2268
or current_entry[1][target_index][0] in 'ar'):
2269
# The current path on disk doesn't match the dirblock
2270
# record. Either the dirblock is marked as absent, or
2271
# the file on disk is not present at all in the
2272
# dirblock. Either way, report about the dirblock
2273
# entry, and let other code handle the filesystem one.
2275
# 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]:
2277
2260
if current_path_info[1] < current_entry[0][1]:
2278
2261
# extra file on disk: pass for now, but only
2279
2262
# increment the path, not the entry
2282
2265
# entry referring to file not present on disk.
2283
2266
# advance the entry only, after processing.
2284
result = _process_entry(current_entry, None)
2285
if result is not None:
2286
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])),
2288
2291
advance_path = False
2290
result = _process_entry(current_entry, current_path_info)
2291
if result is not None:
2293
if result is not uninteresting:
2293
for result in _process_entry(current_entry, current_path_info):
2294
# this check should probably be outside the loop: one
2295
# 'iterate two trees' api, and then _iter_changes filters
2296
# unchanged pairs. - RBC 20070226
2297
if current_entry[1][target_index][0] == 'a':
2298
advance_path = False
2299
path_handled = False
2302
if (include_unchanged
2303
or result[2] # content change
2304
or result[3][0] != result[3][1] # versioned status
2305
or result[4][0] != result[4][1] # parent id
2306
or result[5][0] != result[5][1] # name
2307
or result[6][0] != result[6][1] # kind
2308
or result[7][0] != result[7][1] # executable
2311
(utf8_decode_or_none(result[1][0]),
2312
utf8_decode_or_none(result[1][1])),
2316
(utf8_decode_or_none(result[5][0]),
2317
utf8_decode_or_none(result[5][1])),
2295
2321
if advance_entry and current_entry is not None:
2296
2322
entry_index += 1
2297
2323
if entry_index < len(current_block[1]):
2308
2334
stat.S_ISREG(current_path_info[3].st_mode)
2309
2335
and stat.S_IEXEC & current_path_info[3].st_mode)
2311
(None, utf8_decode(current_path_info[0])[0]),
2337
(None, utf8_decode_or_none(current_path_info[0])),
2313
2339
(False, False),
2315
(None, utf8_decode(current_path_info[1])[0]),
2341
(None, utf8_decode_or_none(current_path_info[1])),
2316
2342
(None, current_path_info[2]),
2317
2343
(None, new_executable))
2318
2344
# dont descend into this unversioned path if it is