diff options
Diffstat (limited to 'src/engine/SCons/Node/FS.py')
-rw-r--r-- | src/engine/SCons/Node/FS.py | 87 |
1 files changed, 62 insertions, 25 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 91d349d..ac85638 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -2635,6 +2635,7 @@ class File(Base): if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS.File') Base.__init__(self, name, directory, fs) self._morph() + self.attributes.changed_timestamp_then_content = None def Entry(self, name): """Create an entry node named 'name' relative to @@ -3283,14 +3284,14 @@ class File(Base): self._memo['changed'] = has_changed return has_changed - def changed_content(self, target, prev_ni): + def changed_content(self, target, prev_ni, repo_node=None): cur_csig = self.get_csig() try: return cur_csig != prev_ni.csig except AttributeError: return 1 - def changed_state(self, target, prev_ni): + def changed_state(self, target, prev_ni, repo_node=None): return self.state != SCons.Node.up_to_date @@ -3324,6 +3325,21 @@ class File(Base): return binfo.dependency_map + # @profile + def _add_strings_to_dependency_map(self, dmap): + """ + In the case comparing node objects isn't sufficient, we'll add the strings for the nodes to the dependency map + :return: + """ + + first_string = str(next(iter(dmap))) + + # print("DMAP:%s"%id(dmap)) + if first_string not in dmap: + string_dict = {str(child): signature for child, signature in dmap.items()} + dmap.update(string_dict) + return dmap + def _get_previous_signatures(self, dmap): """ Return a list of corresponding csigs from previous @@ -3342,37 +3358,62 @@ class File(Base): if len(dmap) == 0: if MD5_TIMESTAMP_DEBUG: print("Nothing dmap shortcutting") return None + elif MD5_TIMESTAMP_DEBUG: print("len(dmap):%d"%len(dmap)) + - if MD5_TIMESTAMP_DEBUG: print("len(dmap):%d"%len(dmap)) - # First try the simple name for node - c_str = str(self) - if MD5_TIMESTAMP_DEBUG: print("Checking :%s"%c_str) - df = dmap.get(c_str, None) + # First try retrieving via Node + if MD5_TIMESTAMP_DEBUG: print("Checking if self is in map:%s id:%s type:%s"%(str(self), id(self), type(self))) + df = dmap.get(self, False) if df: return df + # Now check if self's repository file is in map. + rf = self.rfile() + if MD5_TIMESTAMP_DEBUG: print("Checking if self.rfile is in map:%s id:%s type:%s"%(str(rf), id(rf), type(rf))) + rfm = dmap.get(rf, False) + if rfm: + return rfm + + # get default string for node and then also string swapping os.altsep for os.sep (/ for \) + c_strs = [str(self)] + if os.altsep: - c_str = c_str.replace(os.sep, os.altsep) - df = dmap.get(c_str, None) - if MD5_TIMESTAMP_DEBUG: print("-->%s"%df) + c_strs.append(c_strs[0].replace(os.sep, os.altsep)) + + # In some cases the dependency_maps' keys are already strings check. + # Check if either string is now in dmap. + for s in c_strs: + if MD5_TIMESTAMP_DEBUG: print("Checking if str(self) is in map :%s" % s) + df = dmap.get(s, False) if df: return df + # Strings didn't existing in map, add them and try again + # If there are no strings in this dmap, then add them. + # This may not be necessary, we could walk the nodes in the dmap and check each string + # rather than adding ALL the strings to dmap. In theory that would be n/2 vs 2n str() calls on node + # if not dmap.has_strings: + dmap = self._add_strings_to_dependency_map(dmap) + + # In some cases the dependency_maps' keys are already strings check. + # Check if either string is now in dmap. + for s in c_strs: + if MD5_TIMESTAMP_DEBUG: print("Checking if str(self) is in map (now with strings) :%s" % s) + df = dmap.get(s, False) + if df: + return df + + # Lastly use nodes get_path() to generate string and see if that's in dmap if not df: try: # this should yield a path which matches what's in the sconsign c_str = self.get_path() - df = dmap.get(c_str, None) - if MD5_TIMESTAMP_DEBUG: print("-->%s"%df) - if df: - return df - if os.altsep: c_str = c_str.replace(os.sep, os.altsep) - df = dmap.get(c_str, None) - if MD5_TIMESTAMP_DEBUG: print("-->%s"%df) - if df: - return df + + if MD5_TIMESTAMP_DEBUG: print("Checking if self.get_path is in map (now with strings) :%s" % s) + + df = dmap.get(c_str, None) except AttributeError as e: raise FileBuildInfoFileToCsigMappingError("No mapping from file name to content signature for :%s"%c_str) @@ -3399,9 +3440,6 @@ class File(Base): Returns: Boolean - Indicates if node(File) has changed. """ - if node is None: - # We need required node argument to get BuildInfo to function - raise DeciderNeedsNode(self.changed_timestamp_then_content) # Now get sconsign name -> csig map and then get proper prev_ni if possible bi = node.get_stored_info().binfo @@ -3433,7 +3471,6 @@ class File(Base): print("Mismatch self.changed_timestamp_match(%s, prev_ni) old:%s new:%s"%(str(target), old, new)) new_prev_ni = self._get_previous_signatures(dependency_map) - if not new: try: # NOTE: We're modifying the current node's csig in a query. @@ -3443,13 +3480,13 @@ class File(Base): return False return self.changed_content(target, new_prev_ni) - def changed_timestamp_newer(self, target, prev_ni): + def changed_timestamp_newer(self, target, prev_ni, repo_node=None): try: return self.get_timestamp() > target.get_timestamp() except AttributeError: return 1 - def changed_timestamp_match(self, target, prev_ni): + def changed_timestamp_match(self, target, prev_ni, repo_node=None): """ Return True if the timestamps don't match or if there is no previous timestamp :param target: |