2756
2782
raise errors.ObjectNotLocked(self)
2785
def py_update_entry(state, entry, abspath, stat_value,
2786
_stat_to_minikind=DirState._stat_to_minikind,
2787
_pack_stat=pack_stat):
2788
"""Update the entry based on what is actually on disk.
2790
This function only calculates the sha if it needs to - if the entry is
2791
uncachable, or clearly different to the first parent's entry, no sha
2792
is calculated, and None is returned.
2794
:param state: The dirstate this entry is in.
2795
:param entry: This is the dirblock entry for the file in question.
2796
:param abspath: The path on disk for this file.
2797
:param stat_value: The stat value done on the path.
2798
:return: None, or The sha1 hexdigest of the file (40 bytes) or link
2799
target of a symlink.
2802
minikind = _stat_to_minikind[stat_value.st_mode & 0170000]
2806
packed_stat = _pack_stat(stat_value)
2807
(saved_minikind, saved_link_or_sha1, saved_file_size,
2808
saved_executable, saved_packed_stat) = entry[1][0]
2810
if (minikind == saved_minikind
2811
and packed_stat == saved_packed_stat):
2812
# The stat hasn't changed since we saved, so we can re-use the
2817
# size should also be in packed_stat
2818
if saved_file_size == stat_value.st_size:
2819
return saved_link_or_sha1
2821
# If we have gotten this far, that means that we need to actually
2822
# process this entry.
2825
executable = state._is_executable(stat_value.st_mode,
2827
if state._cutoff_time is None:
2828
state._sha_cutoff_time()
2829
if (stat_value.st_mtime < state._cutoff_time
2830
and stat_value.st_ctime < state._cutoff_time
2831
and len(entry[1]) > 1
2832
and entry[1][1][0] != 'a'):
2833
# Could check for size changes for further optimised
2834
# avoidance of sha1's. However the most prominent case of
2835
# over-shaing is during initial add, which this catches.
2836
link_or_sha1 = state._sha1_file(abspath)
2837
entry[1][0] = ('f', link_or_sha1, stat_value.st_size,
2838
executable, packed_stat)
2840
entry[1][0] = ('f', '', stat_value.st_size,
2841
executable, DirState.NULLSTAT)
2842
elif minikind == 'd':
2844
entry[1][0] = ('d', '', 0, False, packed_stat)
2845
if saved_minikind != 'd':
2846
# This changed from something into a directory. Make sure we
2847
# have a directory block for it. This doesn't happen very
2848
# often, so this doesn't have to be super fast.
2849
block_index, entry_index, dir_present, file_present = \
2850
state._get_block_entry_index(entry[0][0], entry[0][1], 0)
2851
state._ensure_block(block_index, entry_index,
2852
osutils.pathjoin(entry[0][0], entry[0][1]))
2853
elif minikind == 'l':
2854
link_or_sha1 = state._read_link(abspath, saved_link_or_sha1)
2855
if state._cutoff_time is None:
2856
state._sha_cutoff_time()
2857
if (stat_value.st_mtime < state._cutoff_time
2858
and stat_value.st_ctime < state._cutoff_time):
2859
entry[1][0] = ('l', link_or_sha1, stat_value.st_size,
2862
entry[1][0] = ('l', '', stat_value.st_size,
2863
False, DirState.NULLSTAT)
2864
state._dirblock_state = DirState.IN_MEMORY_MODIFIED
2866
update_entry = py_update_entry
2869
class ProcessEntryPython(object):
2871
__slots__ = ["old_dirname_to_file_id", "new_dirname_to_file_id", "uninteresting",
2872
"last_source_parent", "last_target_parent", "include_unchanged",
2873
"use_filesystem_for_exec", "utf8_decode", "searched_specific_files",
2874
"search_specific_files", "state", "source_index", "target_index",
2875
"want_unversioned", "tree"]
2877
def __init__(self, include_unchanged, use_filesystem_for_exec,
2878
search_specific_files, state, source_index, target_index,
2879
want_unversioned, tree):
2880
self.old_dirname_to_file_id = {}
2881
self.new_dirname_to_file_id = {}
2882
# Just a sentry, so that _process_entry can say that this
2883
# record is handled, but isn't interesting to process (unchanged)
2884
self.uninteresting = object()
2885
# Using a list so that we can access the values and change them in
2886
# nested scope. Each one is [path, file_id, entry]
2887
self.last_source_parent = [None, None]
2888
self.last_target_parent = [None, None]
2889
self.include_unchanged = include_unchanged
2890
self.use_filesystem_for_exec = use_filesystem_for_exec
2891
self.utf8_decode = cache_utf8._utf8_decode
2892
# for all search_indexs in each path at or under each element of
2893
# search_specific_files, if the detail is relocated: add the id, and add the
2894
# relocated path as one to search if its not searched already. If the
2895
# detail is not relocated, add the id.
2896
self.searched_specific_files = set()
2897
self.search_specific_files = search_specific_files
2899
self.source_index = source_index
2900
self.target_index = target_index
2901
self.want_unversioned = want_unversioned
2904
def _process_entry(self, entry, path_info, pathjoin=osutils.pathjoin):
2905
"""Compare an entry and real disk to generate delta information.
2907
:param path_info: top_relpath, basename, kind, lstat, abspath for
2908
the path of entry. If None, then the path is considered absent.
2909
(Perhaps we should pass in a concrete entry for this ?)
2910
Basename is returned as a utf8 string because we expect this
2911
tuple will be ignored, and don't want to take the time to
2913
:return: None if these don't match
2914
A tuple of information about the change, or
2915
the object 'uninteresting' if these match, but are
2916
basically identical.
2918
if self.source_index is None:
2919
source_details = DirState.NULL_PARENT_DETAILS
2921
source_details = entry[1][self.source_index]
2922
target_details = entry[1][self.target_index]
2923
target_minikind = target_details[0]
2924
if path_info is not None and target_minikind in 'fdlt':
2925
if not (self.target_index == 0):
2926
raise AssertionError()
2927
link_or_sha1 = update_entry(self.state, entry,
2928
abspath=path_info[4], stat_value=path_info[3])
2929
# The entry may have been modified by update_entry
2930
target_details = entry[1][self.target_index]
2931
target_minikind = target_details[0]
2934
file_id = entry[0][2]
2935
source_minikind = source_details[0]
2936
if source_minikind in 'fdltr' and target_minikind in 'fdlt':
2937
# claimed content in both: diff
2938
# r | fdlt | | add source to search, add id path move and perform
2939
# | | | diff check on source-target
2940
# r | fdlt | a | dangling file that was present in the basis.
2942
if source_minikind in 'r':
2943
# add the source to the search path to find any children it
2944
# has. TODO ? : only add if it is a container ?
2945
if not osutils.is_inside_any(self.searched_specific_files,
2947
self.search_specific_files.add(source_details[1])
2948
# generate the old path; this is needed for stating later
2950
old_path = source_details[1]
2951
old_dirname, old_basename = os.path.split(old_path)
2952
path = pathjoin(entry[0][0], entry[0][1])
2953
old_entry = self.state._get_entry(self.source_index,
2955
# update the source details variable to be the real
2957
if old_entry == (None, None):
2958
raise errors.CorruptDirstate(self.state._filename,
2959
"entry '%s/%s' is considered renamed from %r"
2960
" but source does not exist\n"
2961
"entry: %s" % (entry[0][0], entry[0][1], old_path, entry))
2962
source_details = old_entry[1][self.source_index]
2963
source_minikind = source_details[0]
2965
old_dirname = entry[0][0]
2966
old_basename = entry[0][1]
2967
old_path = path = None
2968
if path_info is None:
2969
# the file is missing on disk, show as removed.
2970
content_change = True
2974
# source and target are both versioned and disk file is present.
2975
target_kind = path_info[2]
2976
if target_kind == 'directory':
2978
old_path = path = pathjoin(old_dirname, old_basename)
2979
self.new_dirname_to_file_id[path] = file_id
2980
if source_minikind != 'd':
2981
content_change = True
2983
# directories have no fingerprint
2984
content_change = False
2986
elif target_kind == 'file':
2987
if source_minikind != 'f':
2988
content_change = True
2990
# If the size is the same, check the sha:
2991
if target_details[2] == source_details[2]:
2992
if link_or_sha1 is None:
2994
file_obj = file(path_info[4], 'rb')
2996
statvalue = os.fstat(file_obj.fileno())
2997
link_or_sha1 = osutils.sha_file(file_obj)
3000
self.state._observed_sha1(entry, link_or_sha1,
3002
content_change = (link_or_sha1 != source_details[1])
3004
# Size changed, so must be different
3005
content_change = True
3006
# Target details is updated at update_entry time
3007
if self.use_filesystem_for_exec:
3008
# We don't need S_ISREG here, because we are sure
3009
# we are dealing with a file.
3010
target_exec = bool(stat.S_IEXEC & path_info[3].st_mode)
3012
target_exec = target_details[3]
3013
elif target_kind == 'symlink':
3014
if source_minikind != 'l':
3015
content_change = True
3017
content_change = (link_or_sha1 != source_details[1])
3019
elif target_kind == 'tree-reference':
3020
if source_minikind != 't':
3021
content_change = True
3023
content_change = False
3026
raise Exception, "unknown kind %s" % path_info[2]
3027
if source_minikind == 'd':
3029
old_path = path = pathjoin(old_dirname, old_basename)
3030
self.old_dirname_to_file_id[old_path] = file_id
3031
# parent id is the entry for the path in the target tree
3032
if old_dirname == self.last_source_parent[0]:
3033
source_parent_id = self.last_source_parent[1]
3036
source_parent_id = self.old_dirname_to_file_id[old_dirname]
3038
source_parent_entry = self.state._get_entry(self.source_index,
3039
path_utf8=old_dirname)
3040
source_parent_id = source_parent_entry[0][2]
3041
if source_parent_id == entry[0][2]:
3042
# This is the root, so the parent is None
3043
source_parent_id = None
3045
self.last_source_parent[0] = old_dirname
3046
self.last_source_parent[1] = source_parent_id
3047
new_dirname = entry[0][0]
3048
if new_dirname == self.last_target_parent[0]:
3049
target_parent_id = self.last_target_parent[1]
3052
target_parent_id = self.new_dirname_to_file_id[new_dirname]
3054
# TODO: We don't always need to do the lookup, because the
3055
# parent entry will be the same as the source entry.
3056
target_parent_entry = self.state._get_entry(self.target_index,
3057
path_utf8=new_dirname)
3058
if target_parent_entry == (None, None):
3059
raise AssertionError(
3060
"Could not find target parent in wt: %s\nparent of: %s"
3061
% (new_dirname, entry))
3062
target_parent_id = target_parent_entry[0][2]
3063
if target_parent_id == entry[0][2]:
3064
# This is the root, so the parent is None
3065
target_parent_id = None
3067
self.last_target_parent[0] = new_dirname
3068
self.last_target_parent[1] = target_parent_id
3070
source_exec = source_details[3]
3071
if (self.include_unchanged
3073
or source_parent_id != target_parent_id
3074
or old_basename != entry[0][1]
3075
or source_exec != target_exec
3077
if old_path is None:
3078
old_path = path = pathjoin(old_dirname, old_basename)
3079
old_path_u = self.utf8_decode(old_path)[0]
3082
old_path_u = self.utf8_decode(old_path)[0]
3083
if old_path == path:
3086
path_u = self.utf8_decode(path)[0]
3087
source_kind = DirState._minikind_to_kind[source_minikind]
3088
return (entry[0][2],
3089
(old_path_u, path_u),
3092
(source_parent_id, target_parent_id),
3093
(self.utf8_decode(old_basename)[0], self.utf8_decode(entry[0][1])[0]),
3094
(source_kind, target_kind),
3095
(source_exec, target_exec))
3097
return self.uninteresting
3098
elif source_minikind in 'a' and target_minikind in 'fdlt':
3099
# looks like a new file
3100
path = pathjoin(entry[0][0], entry[0][1])
3101
# parent id is the entry for the path in the target tree
3102
# TODO: these are the same for an entire directory: cache em.
3103
parent_id = self.state._get_entry(self.target_index,
3104
path_utf8=entry[0][0])[0][2]
3105
if parent_id == entry[0][2]:
3107
if path_info is not None:
3109
if self.use_filesystem_for_exec:
3110
# We need S_ISREG here, because we aren't sure if this
3113
stat.S_ISREG(path_info[3].st_mode)
3114
and stat.S_IEXEC & path_info[3].st_mode)
3116
target_exec = target_details[3]
3117
return (entry[0][2],
3118
(None, self.utf8_decode(path)[0]),
3122
(None, self.utf8_decode(entry[0][1])[0]),
3123
(None, path_info[2]),
3124
(None, target_exec))
3126
# Its a missing file, report it as such.
3127
return (entry[0][2],
3128
(None, self.utf8_decode(path)[0]),
3132
(None, self.utf8_decode(entry[0][1])[0]),
3135
elif source_minikind in 'fdlt' and target_minikind in 'a':
3136
# unversioned, possibly, or possibly not deleted: we dont care.
3137
# if its still on disk, *and* theres no other entry at this
3138
# path [we dont know this in this routine at the moment -
3139
# perhaps we should change this - then it would be an unknown.
3140
old_path = pathjoin(entry[0][0], entry[0][1])
3141
# parent id is the entry for the path in the target tree
3142
parent_id = self.state._get_entry(self.source_index, path_utf8=entry[0][0])[0][2]
3143
if parent_id == entry[0][2]:
3145
return (entry[0][2],
3146
(self.utf8_decode(old_path)[0], None),
3150
(self.utf8_decode(entry[0][1])[0], None),
3151
(DirState._minikind_to_kind[source_minikind], None),
3152
(source_details[3], None))
3153
elif source_minikind in 'fdlt' and target_minikind in 'r':
3154
# a rename; could be a true rename, or a rename inherited from
3155
# a renamed parent. TODO: handle this efficiently. Its not
3156
# common case to rename dirs though, so a correct but slow
3157
# implementation will do.
3158
if not osutils.is_inside_any(self.searched_specific_files, target_details[1]):
3159
self.search_specific_files.add(target_details[1])
3160
elif source_minikind in 'ra' and target_minikind in 'ra':
3161
# neither of the selected trees contain this file,
3162
# so skip over it. This is not currently directly tested, but
3163
# is indirectly via test_too_much.TestCommands.test_conflicts.
3166
raise AssertionError("don't know how to compare "
3167
"source_minikind=%r, target_minikind=%r"
3168
% (source_minikind, target_minikind))
3169
## import pdb;pdb.set_trace()
3175
def iter_changes(self):
3176
"""Iterate over the changes."""
3177
utf8_decode = cache_utf8._utf8_decode
3178
_cmp_by_dirs = cmp_by_dirs
3179
_process_entry = self._process_entry
3180
uninteresting = self.uninteresting
3181
search_specific_files = self.search_specific_files
3182
searched_specific_files = self.searched_specific_files
3183
splitpath = osutils.splitpath
3185
# compare source_index and target_index at or under each element of search_specific_files.
3186
# follow the following comparison table. Note that we only want to do diff operations when
3187
# the target is fdl because thats when the walkdirs logic will have exposed the pathinfo
3191
# Source | Target | disk | action
3192
# r | fdlt | | add source to search, add id path move and perform
3193
# | | | diff check on source-target
3194
# r | fdlt | a | dangling file that was present in the basis.
3196
# r | a | | add source to search
3198
# r | r | | this path is present in a non-examined tree, skip.
3199
# r | r | a | this path is present in a non-examined tree, skip.
3200
# a | fdlt | | add new id
3201
# a | fdlt | a | dangling locally added file, skip
3202
# a | a | | not present in either tree, skip
3203
# a | a | a | not present in any tree, skip
3204
# a | r | | not present in either tree at this path, skip as it
3205
# | | | may not be selected by the users list of paths.
3206
# a | r | a | not present in either tree at this path, skip as it
3207
# | | | may not be selected by the users list of paths.
3208
# fdlt | fdlt | | content in both: diff them
3209
# fdlt | fdlt | a | deleted locally, but not unversioned - show as deleted ?
3210
# fdlt | a | | unversioned: output deleted id for now
3211
# fdlt | a | a | unversioned and deleted: output deleted id
3212
# fdlt | r | | relocated in this tree, so add target to search.
3213
# | | | Dont diff, we will see an r,fd; pair when we reach
3214
# | | | this id at the other path.
3215
# fdlt | r | a | relocated in this tree, so add target to search.
3216
# | | | Dont diff, we will see an r,fd; pair when we reach
3217
# | | | this id at the other path.
3219
# TODO: jam 20070516 - Avoid the _get_entry lookup overhead by
3220
# keeping a cache of directories that we have seen.
3222
while search_specific_files:
3223
# TODO: the pending list should be lexically sorted? the
3224
# interface doesn't require it.
3225
current_root = search_specific_files.pop()
3226
current_root_unicode = current_root.decode('utf8')
3227
searched_specific_files.add(current_root)
3228
# process the entries for this containing directory: the rest will be
3229
# found by their parents recursively.
3230
root_entries = self.state._entries_for_path(current_root)
3231
root_abspath = self.tree.abspath(current_root_unicode)
3233
root_stat = os.lstat(root_abspath)
3235
if e.errno == errno.ENOENT:
3236
# the path does not exist: let _process_entry know that.
3237
root_dir_info = None
3239
# some other random error: hand it up.
3242
root_dir_info = ('', current_root,
3243
osutils.file_kind_from_stat_mode(root_stat.st_mode), root_stat,
3245
if root_dir_info[2] == 'directory':
3246
if self.tree._directory_is_tree_reference(
3247
current_root.decode('utf8')):
3248
root_dir_info = root_dir_info[:2] + \
3249
('tree-reference',) + root_dir_info[3:]
3251
if not root_entries and not root_dir_info:
3252
# this specified path is not present at all, skip it.
3254
path_handled = False
3255
for entry in root_entries:
3256
result = _process_entry(entry, root_dir_info)
3257
if result is not None:
3259
if result is not uninteresting:
3261
if self.want_unversioned and not path_handled and root_dir_info:
3262
new_executable = bool(
3263
stat.S_ISREG(root_dir_info[3].st_mode)
3264
and stat.S_IEXEC & root_dir_info[3].st_mode)
3266
(None, current_root_unicode),
3270
(None, splitpath(current_root_unicode)[-1]),
3271
(None, root_dir_info[2]),
3272
(None, new_executable)
3274
initial_key = (current_root, '', '')
3275
block_index, _ = self.state._find_block_index_from_key(initial_key)
3276
if block_index == 0:
3277
# we have processed the total root already, but because the
3278
# initial key matched it we should skip it here.
3280
if root_dir_info and root_dir_info[2] == 'tree-reference':
3281
current_dir_info = None
3283
dir_iterator = osutils._walkdirs_utf8(root_abspath, prefix=current_root)
3285
current_dir_info = dir_iterator.next()
3287
# on win32, python2.4 has e.errno == ERROR_DIRECTORY, but
3288
# python 2.5 has e.errno == EINVAL,
3289
# and e.winerror == ERROR_DIRECTORY
3290
e_winerror = getattr(e, 'winerror', None)
3291
win_errors = (ERROR_DIRECTORY, ERROR_PATH_NOT_FOUND)
3292
# there may be directories in the inventory even though
3293
# this path is not a file on disk: so mark it as end of
3295
if e.errno in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
3296
current_dir_info = None
3297
elif (sys.platform == 'win32'
3298
and (e.errno in win_errors
3299
or e_winerror in win_errors)):
3300
current_dir_info = None
3304
if current_dir_info[0][0] == '':
3305
# remove .bzr from iteration
3306
bzr_index = bisect.bisect_left(current_dir_info[1], ('.bzr',))
3307
if current_dir_info[1][bzr_index][0] != '.bzr':
3308
raise AssertionError()
3309
del current_dir_info[1][bzr_index]
3310
# walk until both the directory listing and the versioned metadata
3312
if (block_index < len(self.state._dirblocks) and
3313
osutils.is_inside(current_root, self.state._dirblocks[block_index][0])):
3314
current_block = self.state._dirblocks[block_index]
3316
current_block = None
3317
while (current_dir_info is not None or
3318
current_block is not None):
3319
if (current_dir_info and current_block
3320
and current_dir_info[0][0] != current_block[0]):
3321
if _cmp_by_dirs(current_dir_info[0][0], current_block[0]) < 0:
3322
# filesystem data refers to paths not covered by the dirblock.
3323
# this has two possibilities:
3324
# A) it is versioned but empty, so there is no block for it
3325
# B) it is not versioned.
3327
# if (A) then we need to recurse into it to check for
3328
# new unknown files or directories.
3329
# if (B) then we should ignore it, because we don't
3330
# recurse into unknown directories.
3332
while path_index < len(current_dir_info[1]):
3333
current_path_info = current_dir_info[1][path_index]
3334
if self.want_unversioned:
3335
if current_path_info[2] == 'directory':
3336
if self.tree._directory_is_tree_reference(
3337
current_path_info[0].decode('utf8')):
3338
current_path_info = current_path_info[:2] + \
3339
('tree-reference',) + current_path_info[3:]
3340
new_executable = bool(
3341
stat.S_ISREG(current_path_info[3].st_mode)
3342
and stat.S_IEXEC & current_path_info[3].st_mode)
3344
(None, utf8_decode(current_path_info[0])[0]),
3348
(None, utf8_decode(current_path_info[1])[0]),
3349
(None, current_path_info[2]),
3350
(None, new_executable))
3351
# dont descend into this unversioned path if it is
3353
if current_path_info[2] in ('directory',
3355
del current_dir_info[1][path_index]
3359
# This dir info has been handled, go to the next
3361
current_dir_info = dir_iterator.next()
3362
except StopIteration:
3363
current_dir_info = None
3365
# We have a dirblock entry for this location, but there
3366
# is no filesystem path for this. This is most likely
3367
# because a directory was removed from the disk.
3368
# We don't have to report the missing directory,
3369
# because that should have already been handled, but we
3370
# need to handle all of the files that are contained
3372
for current_entry in current_block[1]:
3373
# entry referring to file not present on disk.
3374
# advance the entry only, after processing.
3375
result = _process_entry(current_entry, None)
3376
if result is not None:
3377
if result is not uninteresting:
3380
if (block_index < len(self.state._dirblocks) and
3381
osutils.is_inside(current_root,
3382
self.state._dirblocks[block_index][0])):
3383
current_block = self.state._dirblocks[block_index]
3385
current_block = None
3388
if current_block and entry_index < len(current_block[1]):
3389
current_entry = current_block[1][entry_index]
3391
current_entry = None
3392
advance_entry = True
3394
if current_dir_info and path_index < len(current_dir_info[1]):
3395
current_path_info = current_dir_info[1][path_index]
3396
if current_path_info[2] == 'directory':
3397
if self.tree._directory_is_tree_reference(
3398
current_path_info[0].decode('utf8')):
3399
current_path_info = current_path_info[:2] + \
3400
('tree-reference',) + current_path_info[3:]
3402
current_path_info = None
3404
path_handled = False
3405
while (current_entry is not None or
3406
current_path_info is not None):
3407
if current_entry is None:
3408
# the check for path_handled when the path is adnvaced
3409
# will yield this path if needed.
3411
elif current_path_info is None:
3412
# no path is fine: the per entry code will handle it.
3413
result = _process_entry(current_entry, current_path_info)
3414
if result is not None:
3415
if result is not uninteresting:
3417
elif (current_entry[0][1] != current_path_info[1]
3418
or current_entry[1][self.target_index][0] in 'ar'):
3419
# The current path on disk doesn't match the dirblock
3420
# record. Either the dirblock is marked as absent, or
3421
# the file on disk is not present at all in the
3422
# dirblock. Either way, report about the dirblock
3423
# entry, and let other code handle the filesystem one.
3425
# Compare the basename for these files to determine
3427
if current_path_info[1] < current_entry[0][1]:
3428
# extra file on disk: pass for now, but only
3429
# increment the path, not the entry
3430
advance_entry = False
3432
# entry referring to file not present on disk.
3433
# advance the entry only, after processing.
3434
result = _process_entry(current_entry, None)
3435
if result is not None:
3436
if result is not uninteresting:
3438
advance_path = False
3440
result = _process_entry(current_entry, current_path_info)
3441
if result is not None:
3443
if result is not uninteresting:
3445
if advance_entry and current_entry is not None:
3447
if entry_index < len(current_block[1]):
3448
current_entry = current_block[1][entry_index]
3450
current_entry = None
3452
advance_entry = True # reset the advance flaga
3453
if advance_path and current_path_info is not None:
3454
if not path_handled:
3455
# unversioned in all regards
3456
if self.want_unversioned:
3457
new_executable = bool(
3458
stat.S_ISREG(current_path_info[3].st_mode)
3459
and stat.S_IEXEC & current_path_info[3].st_mode)
3461
relpath_unicode = utf8_decode(current_path_info[0])[0]
3462
except UnicodeDecodeError:
3463
raise errors.BadFilenameEncoding(
3464
current_path_info[0], osutils._fs_enc)
3466
(None, relpath_unicode),
3470
(None, utf8_decode(current_path_info[1])[0]),
3471
(None, current_path_info[2]),
3472
(None, new_executable))
3473
# dont descend into this unversioned path if it is
3475
if current_path_info[2] in ('directory'):
3476
del current_dir_info[1][path_index]
3478
# dont descend the disk iterator into any tree
3480
if current_path_info[2] == 'tree-reference':
3481
del current_dir_info[1][path_index]
3484
if path_index < len(current_dir_info[1]):
3485
current_path_info = current_dir_info[1][path_index]
3486
if current_path_info[2] == 'directory':
3487
if self.tree._directory_is_tree_reference(
3488
current_path_info[0].decode('utf8')):
3489
current_path_info = current_path_info[:2] + \
3490
('tree-reference',) + current_path_info[3:]
3492
current_path_info = None
3493
path_handled = False
3495
advance_path = True # reset the advance flagg.
3496
if current_block is not None:
3498
if (block_index < len(self.state._dirblocks) and
3499
osutils.is_inside(current_root, self.state._dirblocks[block_index][0])):
3500
current_block = self.state._dirblocks[block_index]
3502
current_block = None
3503
if current_dir_info is not None:
3505
current_dir_info = dir_iterator.next()
3506
except StopIteration:
3507
current_dir_info = None
3508
_process_entry = ProcessEntryPython
2759
3511
# Try to load the compiled form if possible
2761
3513
from bzrlib._dirstate_helpers_c import (