473
483
return path_utf8.decode('utf8')
475
485
if not osutils.supports_executable():
477
486
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.
478
491
file_id = osutils.safe_file_id(file_id)
479
492
entry = self._get_entry(file_id=file_id, path=path)
480
493
if entry == (None, None):
482
495
return entry[1][0][3]
485
497
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.
487
503
file_id = osutils.safe_file_id(file_id)
488
504
path = self.id2path(file_id)
1076
1090
# missing on access.
1077
1091
for rev_id, tree in parents_list:
1078
1092
rev_id = osutils.safe_revision_id(rev_id)
1093
_mod_revision.check_not_reserved_id(rev_id)
1079
1094
if tree is not None:
1080
1095
real_trees.append((rev_id, tree))
1082
1097
real_trees.append((rev_id,
1083
1098
self.branch.repository.revision_tree(None)))
1084
1099
ghosts.append(rev_id)
1085
dirstate._validate()
1086
1100
dirstate.set_parent_trees(real_trees, ghosts=ghosts)
1087
dirstate._validate()
1088
1101
self._make_dirty(reset_inventory=False)
1089
dirstate._validate()
1091
1103
def _set_root_id(self, file_id):
1092
1104
"""See WorkingTree.set_root_id."""
1800
1814
NULL_PARENT_DETAILS = dirstate.DirState.NULL_PARENT_DETAILS
1801
1815
# Using a list so that we can access the values and change them in
1802
1816
# nested scope. Each one is [path, file_id, entry]
1803
last_source_parent = [None, None, None]
1804
last_target_parent = [None, None, None]
1817
last_source_parent = [None, None]
1818
last_target_parent = [None, None]
1806
1820
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.
1808
1832
def _process_entry(entry, path_info):
1809
1833
"""Compare an entry and real disk to generate delta information.
1901
1933
target_exec = False
1903
1935
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
1904
1940
# parent id is the entry for the path in the target tree
1905
1941
if old_dirname == last_source_parent[0]:
1906
1942
source_parent_id = last_source_parent[1]
1908
source_parent_entry = state._get_entry(source_index,
1909
path_utf8=old_dirname)
1910
source_parent_id = source_parent_entry[0][2]
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]
1911
1950
if source_parent_id == entry[0][2]:
1912
1951
# This is the root, so the parent is None
1913
1952
source_parent_id = None
1915
1954
last_source_parent[0] = old_dirname
1916
1955
last_source_parent[1] = source_parent_id
1917
last_source_parent[2] = source_parent_entry
1918
1956
new_dirname = entry[0][0]
1919
1957
if new_dirname == last_target_parent[0]:
1920
1958
target_parent_id = last_target_parent[1]
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]
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]
1930
1971
if target_parent_id == entry[0][2]:
1931
1972
# This is the root, so the parent is None
1932
1973
target_parent_id = None
1934
1975
last_target_parent[0] = new_dirname
1935
1976
last_target_parent[1] = target_parent_id
1936
last_target_parent[2] = target_parent_entry
1938
1978
source_exec = source_details[3]
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)),)
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
1945
2006
elif source_minikind in 'a' and target_minikind in 'fdlt':
1946
2007
# looks like a new file
1947
2008
if path_info is not None:
1980
2043
parent_id = state._get_entry(source_index, path_utf8=entry[0][0])[0][2]
1981
2044
if parent_id == entry[0][2]:
1982
2045
parent_id = 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)),)
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))
1989
2054
elif source_minikind in 'fdlt' and target_minikind in 'r':
1990
2055
# a rename; could be a true rename, or a rename inherited from
1991
2056
# a renamed parent. TODO: handle this efficiently. Its not
2040
2105
path_handled = False
2041
2106
for entry in root_entries:
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
2107
result = _process_entry(entry, root_dir_info)
2108
if result is not None:
2046
2109
path_handled = True
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])),
2110
if result is not uninteresting:
2066
2112
if want_unversioned and not path_handled and root_dir_info:
2067
2113
new_executable = bool(
2068
2114
stat.S_ISREG(root_dir_info[3].st_mode)
2145
2191
stat.S_ISREG(current_path_info[3].st_mode)
2146
2192
and stat.S_IEXEC & current_path_info[3].st_mode)
2148
(None, utf8_decode_or_none(current_path_info[0])),
2194
(None, utf8_decode(current_path_info[0])[0]),
2150
2196
(False, False),
2152
(None, utf8_decode_or_none(current_path_info[1])),
2198
(None, utf8_decode(current_path_info[1])[0]),
2153
2199
(None, current_path_info[2]),
2154
2200
(None, new_executable))
2155
2201
# dont descend into this unversioned path if it is
2176
2222
for current_entry in current_block[1]:
2177
2223
# entry referring to file not present on disk.
2178
2224
# advance the entry only, after processing.
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])),
2225
result = _process_entry(current_entry, None)
2226
if result is not None:
2227
if result is not uninteresting:
2202
2229
block_index +=1
2203
2230
if (block_index < len(state._dirblocks) and
2204
2231
osutils.is_inside(current_root,
2234
2261
elif current_path_info is None:
2235
2262
# no path is fine: the per entry code will handle it.
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])),
2263
result = _process_entry(current_entry, current_path_info)
2264
if result is not None:
2265
if result is not uninteresting:
2259
2267
elif (current_entry[0][1] != current_path_info[1]
2260
2268
or current_entry[1][target_index][0] in 'ar'):
2261
2269
# The current path on disk doesn't match the dirblock
2263
2271
# the file on disk is not present at all in the
2264
2272
# dirblock. Either way, report about the dirblock
2265
2273
# entry, and let other code handle the filesystem one.
2266
if current_path_info[1].split('/') < current_entry[0][1].split('/'):
2275
# Compare the basename for these files to determine
2277
if current_path_info[1] < current_entry[0][1]:
2267
2278
# extra file on disk: pass for now, but only
2268
2279
# increment the path, not the entry
2269
2280
advance_entry = False
2271
2282
# entry referring to file not present on disk.
2272
2283
# advance the entry only, after processing.
2273
for result in _process_entry(current_entry, None):
2274
# this check should probably be outside the loop: one
2275
# 'iterate two trees' api, and then _iter_changes filters
2276
# unchanged pairs. - RBC 20070226
2277
if (include_unchanged
2278
or result[2] # content change
2279
or result[3][0] != result[3][1] # versioned status
2280
or result[4][0] != result[4][1] # parent id
2281
or result[5][0] != result[5][1] # name
2282
or result[6][0] != result[6][1] # kind
2283
or result[7][0] != result[7][1] # executable
2286
(utf8_decode_or_none(result[1][0]),
2287
utf8_decode_or_none(result[1][1])),
2291
(utf8_decode_or_none(result[5][0]),
2292
utf8_decode_or_none(result[5][1])),
2284
result = _process_entry(current_entry, None)
2285
if result is not None:
2286
if result is not uninteresting:
2296
2288
advance_path = False
2298
for result in _process_entry(current_entry, current_path_info):
2299
# this check should probably be outside the loop: one
2300
# 'iterate two trees' api, and then _iter_changes filters
2301
# unchanged pairs. - RBC 20070226
2290
result = _process_entry(current_entry, current_path_info)
2291
if result is not None:
2302
2292
path_handled = True
2303
if (include_unchanged
2304
or result[2] # content change
2305
or result[3][0] != result[3][1] # versioned status
2306
or result[4][0] != result[4][1] # parent id
2307
or result[5][0] != result[5][1] # name
2308
or result[6][0] != result[6][1] # kind
2309
or result[7][0] != result[7][1] # executable
2312
(utf8_decode_or_none(result[1][0]),
2313
utf8_decode_or_none(result[1][1])),
2317
(utf8_decode_or_none(result[5][0]),
2318
utf8_decode_or_none(result[5][1])),
2293
if result is not uninteresting:
2322
2295
if advance_entry and current_entry is not None:
2323
2296
entry_index += 1
2324
2297
if entry_index < len(current_block[1]):
2335
2308
stat.S_ISREG(current_path_info[3].st_mode)
2336
2309
and stat.S_IEXEC & current_path_info[3].st_mode)
2338
(None, utf8_decode_or_none(current_path_info[0])),
2311
(None, utf8_decode(current_path_info[0])[0]),
2340
2313
(False, False),
2342
(None, utf8_decode_or_none(current_path_info[1])),
2315
(None, utf8_decode(current_path_info[1])[0]),
2343
2316
(None, current_path_info[2]),
2344
2317
(None, new_executable))
2345
2318
# dont descend into this unversioned path if it is