summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node/FS.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons/Node/FS.py')
-rw-r--r--src/engine/SCons/Node/FS.py87
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: