Rev 4571: Refactoring of dirstate iter_changes to make it possible to tell changed vs unchanged results internally. in http://bazaar.launchpad.net/~lifeless/bzr/refactor-dirstate
Robert Collins
robertc at robertcollins.net
Mon Jul 27 06:44:32 BST 2009
At http://bazaar.launchpad.net/~lifeless/bzr/refactor-dirstate
------------------------------------------------------------
revno: 4571
revision-id: robertc at robertcollins.net-20090727054419-d50zguhycqlutib8
parent: pqm at pqm.ubuntu.com-20090726170411-dyeth9vnxeslqows
committer: Robert Collins <robertc at robertcollins.net>
branch nick: refactor-dirstate
timestamp: Mon 2009-07-27 15:44:19 +1000
message:
Refactoring of dirstate iter_changes to make it possible to tell changed vs unchanged results internally.
=== modified file 'bzrlib/_dirstate_helpers_pyx.pyx'
--- a/bzrlib/_dirstate_helpers_pyx.pyx 2009-06-23 06:58:24 +0000
+++ b/bzrlib/_dirstate_helpers_pyx.pyx 2009-07-27 05:44:19 +0000
@@ -965,7 +965,6 @@
cdef object old_dirname_to_file_id # dict
cdef object new_dirname_to_file_id # dict
- cdef readonly object uninteresting
cdef object last_source_parent
cdef object last_target_parent
cdef object include_unchanged
@@ -1002,9 +1001,6 @@
want_unversioned, tree):
self.old_dirname_to_file_id = {}
self.new_dirname_to_file_id = {}
- # Just a sentry, so that _process_entry can say that this
- # record is handled, but isn't interesting to process (unchanged)
- self.uninteresting = object()
# Using a list so that we can access the values and change them in
# nested scope. Each one is [path, file_id, entry]
self.last_source_parent = [None, None]
@@ -1055,10 +1051,13 @@
Basename is returned as a utf8 string because we expect this
tuple will be ignored, and don't want to take the time to
decode.
- :return: None if the these don't match
- A tuple of information about the change, or
- the object 'uninteresting' if these match, but are
- basically identical.
+ :return: (iter_changes_result, changed). If the entry has not been
+ handled then changed is None. Otherwise it is False if no content
+ or metadata changes have occured, and None if any content or
+ metadata change has occured. If self.include_unchanged is True then
+ if changed is not None, iter_changes_result will always be a result
+ tuple. Otherwise, iter_changes_result is None unless changed is
+ True.
"""
cdef char target_minikind
cdef char source_minikind
@@ -1220,12 +1219,14 @@
self.last_target_parent[1] = target_parent_id
source_exec = source_details[3]
- if (self.include_unchanged
- or content_change
+ changed = (content_change
or source_parent_id != target_parent_id
or old_basename != entry[0][1]
or source_exec != target_exec
- ):
+ )
+ if not changed and not self.include_unchanged:
+ return None, False
+ else:
if old_path is None:
path = self.pathjoin(old_dirname, old_basename)
old_path = path
@@ -1245,9 +1246,7 @@
(source_parent_id, target_parent_id),
(self.utf8_decode(old_basename)[0], self.utf8_decode(entry[0][1])[0]),
(source_kind, target_kind),
- (source_exec, target_exec))
- else:
- return self.uninteresting
+ (source_exec, target_exec)), changed
elif source_minikind == c'a' and _versioned_minikind(target_minikind):
# looks like a new file
path = self.pathjoin(entry[0][0], entry[0][1])
@@ -1280,7 +1279,7 @@
(None, parent_id),
(None, self.utf8_decode(entry[0][1])[0]),
(None, path_info[2]),
- (None, target_exec))
+ (None, target_exec)), True
else:
# Its a missing file, report it as such.
return (entry[0][2],
@@ -1290,7 +1289,7 @@
(None, parent_id),
(None, self.utf8_decode(entry[0][1])[0]),
(None, None),
- (None, False))
+ (None, False)), True
elif _versioned_minikind(source_minikind) and target_minikind == c'a':
# unversioned, possibly, or possibly not deleted: we dont care.
# if its still on disk, *and* theres no other entry at this
@@ -1308,7 +1307,7 @@
(parent_id, None),
(self.utf8_decode(entry[0][1])[0], None),
(_minikind_to_kind(source_minikind), None),
- (source_details[3], None))
+ (source_details[3], None)), True
elif _versioned_minikind(source_minikind) and target_minikind == c'r':
# a rename; could be a true rename, or a rename inherited from
# a renamed parent. TODO: handle this efficiently. Its not
@@ -1327,7 +1326,7 @@
"source_minikind=%r, target_minikind=%r"
% (source_minikind, target_minikind))
## import pdb;pdb.set_trace()
- return None
+ return None, None
def __iter__(self):
return self
@@ -1401,14 +1400,13 @@
cdef char * current_dirname_c, * current_blockname_c
cdef int advance_entry, advance_path
cdef int path_handled
- uninteresting = self.uninteresting
searched_specific_files = self.searched_specific_files
# Are we walking a root?
while self.root_entries_pos < self.root_entries_len:
entry = self.root_entries[self.root_entries_pos]
self.root_entries_pos = self.root_entries_pos + 1
- result = self._process_entry(entry, self.root_dir_info)
- if result is not None and result is not self.uninteresting:
+ result, changed = self._process_entry(entry, self.root_dir_info)
+ if changed is not None and changed or self.include_unchanged:
return result
# Have we finished the prior root, or never started one ?
if self.current_root is None:
@@ -1457,10 +1455,10 @@
while self.root_entries_pos < self.root_entries_len:
entry = self.root_entries[self.root_entries_pos]
self.root_entries_pos = self.root_entries_pos + 1
- result = self._process_entry(entry, self.root_dir_info)
- if result is not None:
+ result, changed = self._process_entry(entry, self.root_dir_info)
+ if changed is not None:
path_handled = -1
- if result is not self.uninteresting:
+ if changed or self.include_unchanged:
return result
# handle unversioned specified paths:
if self.want_unversioned and not path_handled and self.root_dir_info:
@@ -1606,9 +1604,9 @@
self.current_block_pos = self.current_block_pos + 1
# entry referring to file not present on disk.
# advance the entry only, after processing.
- result = self._process_entry(current_entry, None)
- if result is not None:
- if result is not self.uninteresting:
+ result, changed = self._process_entry(current_entry, None)
+ if changed is not None:
+ if changed or self.include_unchanged:
return result
self.block_index = self.block_index + 1
self._update_current_block()
@@ -1675,10 +1673,8 @@
pass
elif current_path_info is None:
# no path is fine: the per entry code will handle it.
- result = self._process_entry(current_entry, current_path_info)
- if result is not None:
- if result is self.uninteresting:
- result = None
+ result, changed = self._process_entry(current_entry,
+ current_path_info)
else:
minikind = _minikind_from_string(
current_entry[1][self.target_index][0])
@@ -1699,19 +1695,16 @@
else:
# entry referring to file not present on disk.
# advance the entry only, after processing.
- result = self._process_entry(current_entry, None)
- if result is not None:
- if result is self.uninteresting:
- result = None
+ result, changed = self._process_entry(current_entry,
+ None)
advance_path = 0
else:
# paths are the same,and the dirstate entry is not
# absent or renamed.
- result = self._process_entry(current_entry, current_path_info)
- if result is not None:
+ result, changed = self._process_entry(current_entry,
+ current_path_info)
+ if changed is not None:
path_handled = -1
- if result is self.uninteresting:
- result = None
# >- loop control starts here:
# >- entry
if advance_entry and current_entry is not None:
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py 2009-07-20 08:56:45 +0000
+++ b/bzrlib/dirstate.py 2009-07-27 05:44:19 +0000
@@ -3164,7 +3164,7 @@
class ProcessEntryPython(object):
- __slots__ = ["old_dirname_to_file_id", "new_dirname_to_file_id", "uninteresting",
+ __slots__ = ["old_dirname_to_file_id", "new_dirname_to_file_id",
"last_source_parent", "last_target_parent", "include_unchanged",
"use_filesystem_for_exec", "utf8_decode", "searched_specific_files",
"search_specific_files", "state", "source_index", "target_index",
@@ -3175,9 +3175,6 @@
want_unversioned, tree):
self.old_dirname_to_file_id = {}
self.new_dirname_to_file_id = {}
- # Just a sentry, so that _process_entry can say that this
- # record is handled, but isn't interesting to process (unchanged)
- self.uninteresting = object()
# Using a list so that we can access the values and change them in
# nested scope. Each one is [path, file_id, entry]
self.last_source_parent = [None, None]
@@ -3206,10 +3203,13 @@
Basename is returned as a utf8 string because we expect this
tuple will be ignored, and don't want to take the time to
decode.
- :return: None if these don't match
- A tuple of information about the change, or
- the object 'uninteresting' if these match, but are
- basically identical.
+ :return: (iter_changes_result, changed). If the entry has not been
+ handled then changed is None. Otherwise it is False if no content
+ or metadata changes have occured, and None if any content or
+ metadata change has occured. If self.include_unchanged is True then
+ if changed is not None, iter_changes_result will always be a result
+ tuple. Otherwise, iter_changes_result is None unless changed is
+ True.
"""
if self.source_index is None:
source_details = DirState.NULL_PARENT_DETAILS
@@ -3320,7 +3320,7 @@
old_path = path = pathjoin(old_dirname, old_basename)
self.old_dirname_to_file_id[old_path] = file_id
# parent id is the entry for the path in the target tree
- if old_dirname == self.last_source_parent[0]:
+ if old_basename and old_dirname == self.last_source_parent[0]:
source_parent_id = self.last_source_parent[1]
else:
try:
@@ -3336,7 +3336,7 @@
self.last_source_parent[0] = old_dirname
self.last_source_parent[1] = source_parent_id
new_dirname = entry[0][0]
- if new_dirname == self.last_target_parent[0]:
+ if entry[0][1] and new_dirname == self.last_target_parent[0]:
target_parent_id = self.last_target_parent[1]
else:
try:
@@ -3359,12 +3359,14 @@
self.last_target_parent[1] = target_parent_id
source_exec = source_details[3]
- if (self.include_unchanged
- or content_change
+ changed = (content_change
or source_parent_id != target_parent_id
or old_basename != entry[0][1]
or source_exec != target_exec
- ):
+ )
+ if not changed and not self.include_unchanged:
+ return None, False
+ else:
if old_path is None:
old_path = path = pathjoin(old_dirname, old_basename)
old_path_u = self.utf8_decode(old_path)[0]
@@ -3383,9 +3385,7 @@
(source_parent_id, target_parent_id),
(self.utf8_decode(old_basename)[0], self.utf8_decode(entry[0][1])[0]),
(source_kind, target_kind),
- (source_exec, target_exec))
- else:
- return self.uninteresting
+ (source_exec, target_exec)), changed
elif source_minikind in 'a' and target_minikind in 'fdlt':
# looks like a new file
path = pathjoin(entry[0][0], entry[0][1])
@@ -3412,7 +3412,7 @@
(None, parent_id),
(None, self.utf8_decode(entry[0][1])[0]),
(None, path_info[2]),
- (None, target_exec))
+ (None, target_exec)), True
else:
# Its a missing file, report it as such.
return (entry[0][2],
@@ -3422,7 +3422,7 @@
(None, parent_id),
(None, self.utf8_decode(entry[0][1])[0]),
(None, None),
- (None, False))
+ (None, False)), True
elif source_minikind in 'fdlt' and target_minikind in 'a':
# unversioned, possibly, or possibly not deleted: we dont care.
# if its still on disk, *and* theres no other entry at this
@@ -3440,7 +3440,7 @@
(parent_id, None),
(self.utf8_decode(entry[0][1])[0], None),
(DirState._minikind_to_kind[source_minikind], None),
- (source_details[3], None))
+ (source_details[3], None)), True
elif source_minikind in 'fdlt' and target_minikind in 'r':
# a rename; could be a true rename, or a rename inherited from
# a renamed parent. TODO: handle this efficiently. Its not
@@ -3458,7 +3458,7 @@
"source_minikind=%r, target_minikind=%r"
% (source_minikind, target_minikind))
## import pdb;pdb.set_trace()
- return None
+ return None, None
def __iter__(self):
return self
@@ -3468,7 +3468,6 @@
utf8_decode = cache_utf8._utf8_decode
_cmp_by_dirs = cmp_by_dirs
_process_entry = self._process_entry
- uninteresting = self.uninteresting
search_specific_files = self.search_specific_files
searched_specific_files = self.searched_specific_files
splitpath = osutils.splitpath
@@ -3544,10 +3543,10 @@
continue
path_handled = False
for entry in root_entries:
- result = _process_entry(entry, root_dir_info)
- if result is not None:
+ result, changed = _process_entry(entry, root_dir_info)
+ if changed is not None:
path_handled = True
- if result is not uninteresting:
+ if changed or self.include_unchanged:
yield result
if self.want_unversioned and not path_handled and root_dir_info:
new_executable = bool(
@@ -3663,9 +3662,9 @@
for current_entry in current_block[1]:
# entry referring to file not present on disk.
# advance the entry only, after processing.
- result = _process_entry(current_entry, None)
- if result is not None:
- if result is not uninteresting:
+ result, changed = _process_entry(current_entry, None)
+ if changed is not None:
+ if changed or self.include_unchanged:
yield result
block_index +=1
if (block_index < len(self.state._dirblocks) and
@@ -3701,9 +3700,9 @@
pass
elif current_path_info is None:
# no path is fine: the per entry code will handle it.
- result = _process_entry(current_entry, current_path_info)
- if result is not None:
- if result is not uninteresting:
+ result, changed = _process_entry(current_entry, current_path_info)
+ if changed is not None:
+ if changed or self.include_unchanged:
yield result
elif (current_entry[0][1] != current_path_info[1]
or current_entry[1][self.target_index][0] in 'ar'):
@@ -3722,16 +3721,16 @@
else:
# entry referring to file not present on disk.
# advance the entry only, after processing.
- result = _process_entry(current_entry, None)
- if result is not None:
- if result is not uninteresting:
+ result, changed = _process_entry(current_entry, None)
+ if changed is not None:
+ if changed or self.include_unchanged:
yield result
advance_path = False
else:
- result = _process_entry(current_entry, current_path_info)
- if result is not None:
+ result, changed = _process_entry(current_entry, current_path_info)
+ if changed is not None:
path_handled = True
- if result is not uninteresting:
+ if changed or self.include_unchanged:
yield result
if advance_entry and current_entry is not None:
entry_index += 1
More information about the bazaar-commits
mailing list