aboutsummaryrefslogtreecommitdiffstats
path: root/file_cmds/mtree/fix_failure_locations.py
diff options
context:
space:
mode:
Diffstat (limited to 'file_cmds/mtree/fix_failure_locations.py')
-rwxr-xr-xfile_cmds/mtree/fix_failure_locations.py77
1 files changed, 77 insertions, 0 deletions
diff --git a/file_cmds/mtree/fix_failure_locations.py b/file_cmds/mtree/fix_failure_locations.py
new file mode 100755
index 0000000..a49906e
--- /dev/null
+++ b/file_cmds/mtree/fix_failure_locations.py
@@ -0,0 +1,77 @@
+#!/usr/bin/python
+
+#
+# This script is used to automatically fix up the location numbers in
+# calls to RECORD_FAILURE(). When adding a new call to RECORD_FAILURE,
+# write it like:
+# RECORD_FAILURE(0, ...);
+# Don't put any white space between the open parenthesis, zero and comma.
+# Once you have added the new calls to RECORD_FAILURE, then run this script,
+# passing it the path to the directory, like this:
+# python3 mtree/fix_failure_locations.py mtree/
+#
+# This script will edit the files, changing the "0" to the next available
+# location number. It will also detect and complain if you have duplicate
+# location numbers.
+#
+# DO NOT reuse location numbers! It is best if locations are consistent across
+# all versions that have that RECORD_FAILURE call.
+#
+
+import sys
+import os
+import re
+from collections import defaultdict
+from datetime import datetime,timezone
+
+class LocationUpdater(object):
+ epoch = datetime(2020, 6, 17, 23, 22, 46, 562458, tzinfo=timezone.utc)
+ location_base = int((datetime.now(timezone.utc) - epoch).total_seconds() / 60)
+ # Match the number in "RECORD_FAILURE(<number>,"
+ fail_re = (re.compile('(?<=\\bRECORD_FAILURE\\()\\d+(?=,)'),re.compile('(?<=\\bRECORD_FAILURE_MSG\\()\\d+(?=,)'))
+
+ def __init__(self, path):
+ self.location = self.location_base
+ self.path = path
+ # Counters for how often each location number was found
+ self.counts = defaultdict(int)
+ self.locations_changed = 0
+
+ # Replace the "0" in "RECORD_FAILURE(0," with next location number, in *.c
+ def fixLocations(self):
+ def replace_loc(match):
+ location = int(match.group(0))
+ if location == 0:
+ # Replace location 0 with the next available location
+ self.location += 1
+ self.locations_changed += 1
+ location = self.location
+ # Count the number of times this location number was used
+ self.counts[location] += 1
+ # Return the (possibly updated) location number
+ return str(location)
+ rootpath = self.path
+ for dirpath, dirnames, filenames in os.walk(rootpath):
+ for filename in filenames:
+ if filename.endswith(".c") or filename.endswith(".cpp"):
+ path = os.path.join(dirpath, filename)
+ content = open(path, "r").read()
+ for fail_re in self.fail_re:
+ if fail_re.search(content):
+ locations_changed_before = self.locations_changed
+ content = fail_re.sub(replace_loc, content)
+ if self.locations_changed != locations_changed_before:
+ # We updated a location number, so write the changed file
+ print("Updating file {}".format(path))
+ open(path,"w").write(content)
+
+ def duplicates(self):
+ # Return the list of keys whose count is greater than 1
+ return [k for (k,v) in iter(self.counts.items()) if v > 1]
+
+updater = LocationUpdater(sys.argv[1])
+updater.fixLocations()
+dups = updater.duplicates()
+if len(dups):
+ print("WARNING! Duplicate location numbers: {}".format(dups))
+ sys.exit(1)