Skip to content

Commit

Permalink
improve script with filters
Browse files Browse the repository at this point in the history
  • Loading branch information
raynaudoe committed Jul 3, 2024
1 parent 1303278 commit 066652d
Showing 1 changed file with 122 additions and 50 deletions.
172 changes: 122 additions & 50 deletions scripts/apply_runtime_patch.py
Original file line number Diff line number Diff line change
@@ -1,69 +1,141 @@
import sys
import os
import subprocess
from unidiff import PatchSet
import re

def usage():
print("Usage: {} [--check] <patch_file_path>".format(sys.argv[0]))
sys.exit(1)
def paseo_to_polkadot_filter(file_path, hunk):
"""
Filter to skip hunks that replace "Paseo" with "Polkadot".
"""
for line in hunk:
if line.is_removed:
removed_line = line.value
for added_line in hunk:
if added_line.is_added:
if re.search(r'[Pp]aseo', removed_line) and re.search(r'[Pp]olkadot', added_line.value):
if re.sub(r'[Pp]aseo', 'Polkadot', removed_line).strip() == added_line.value.strip():
print(f" Skipping hunk in {file_path}: Contains Paseo to Polkadot replacement")
return False
# Check for case-sensitive replacements
if 'Paseo' in removed_line and 'Polkadot' in added_line.value:
if removed_line.replace('Paseo', 'Polkadot') == added_line.value:
print(f" Skipping hunk in {file_path}: Contains Paseo to Polkadot replacement")
return False
# Check for case-insensitive replacements
elif 'paseo' in removed_line.lower() and 'polkadot' in added_line.value.lower():
if re.sub(r'(?i)paseo', lambda m: 'Polkadot' if m.group(0)[0].isupper() else 'polkadot', removed_line) == added_line.value:
print(f" Skipping hunk in {file_path}: Contains paseo to polkadot replacement")
return False
return True

def preprocessPatch(patch_file):
def keep_sudo_filter(file_path, hunk):
"""
Filter to keep files and lines related to sudo.
- Ignores deletion of files with 'sudo' in their name.
- Prevents deletion of lines containing 'sudo'.
"""
# Check if the file is being deleted and contains 'sudo' in its name
if hunk.source_start == 0 and hunk.source_length == 0 and 'sudo' in file_path.lower():
print(f" Keeping file {file_path}: Contains 'sudo' in filename")
return False

# Check for lines containing 'sudo'
for line in hunk:
if line.is_removed and 'sudo' in line.value.lower():
print(f" Keeping line in {file_path}: Contains 'sudo'")
return False

return True

def filter_hunk(file_path, hunk):
"""
Main filter function that applies all individual filters.
"""
# List of filters to apply
filters = [
paseo_to_polkadot_filter,
keep_sudo_filter,
# Add more filters here
]

# Apply all filters
for filter_func in filters:
if not filter_func(file_path, hunk):
return False

return True

def apply_patch_line_by_line(patch_file, check_only=False, hunk_filter=filter_hunk):
try:
with open(patch_file, 'r') as file:
content = file.read()
with open(patch_file, 'r') as pf:
patch = PatchSet(pf)

# Replace "Polkadot" with "Paseo" and "polkadot" with "paseo"
modified_content = re.sub(r'Polkadot', 'Paseo', content)
modified_content = re.sub(r'polkadot', 'paseo', modified_content)
for patched_file in patch:
file_path = patched_file.path
try:
with open(file_path, 'r') as tf:
target_lines = tf.readlines()
except FileNotFoundError:
print(f"Warning: File {file_path} not found. Skipping.")
continue

if modified_content != content:
with open(patch_file, 'w') as file:
file.write(modified_content)
print("Patch preprocessed successfully!")
modified = False
for hunk in patched_file:
try:
# Apply the hunk filter
if not hunk_filter(file_path, hunk):
print(f"Skipping hunk in {file_path} due to filter")
continue

for line in hunk:
try:
if line.is_added:
target_lines.insert(line.target_line_no - 1, line.value)
modified = True
elif line.is_removed:
if line.source_line_no <= len(target_lines) and target_lines[line.source_line_no - 1] == line.value:
target_lines.pop(line.source_line_no - 1)
modified = True
else:
print(f"Warning: Line to remove not found or mismatch in {file_path} at line {line.source_line_no}")
except IndexError:
print(f"Error: Index out of range in {file_path} at line {line.source_line_no or line.target_line_no}")
if not check_only:
return False
except Exception as e:
print(f"Error processing hunk in {file_path}: {e}")
if not check_only:
return False

if modified and not check_only:
with open(file_path, 'w') as tf:
tf.writelines(target_lines)

if not check_only:
print("Patch applied successfully!")
else:
print("No changes were necessary in the patch file.")
print("Patch can be applied successfully.")
return True
except Exception as e:
print(f"Failed to preprocess patch: {e}")
sys.exit(1)
print(f"Failed to apply patch: {e}")
return False

def main():
# Check if the correct number of arguments is provided
if len(sys.argv) < 2 or len(sys.argv) > 3:
usage()

# Initialize variables
check_flag = ""
patch_file = ""
print("Usage: python apply_runtime_patch.py [--check] <patch_file>")
sys.exit(1)

# Parse arguments
check_flag = False
if len(sys.argv) == 3:
if sys.argv[1] == "--check":
check_flag = "--check"
patch_file = sys.argv[2]
else:
usage()
if sys.argv[1] != "--check":
print("Invalid argument. Use --check for check mode.")
sys.exit(1)
check_flag = True
patch_file = sys.argv[2]
else:
patch_file = sys.argv[1]

# Check if the patch file exists
if not os.path.isfile(patch_file):
print(f"Error: Patch file '{patch_file}' does not exist.")
sys.exit(1)

# Preprocess the patch
preprocessPatch(patch_file)

# Apply the patch
try:
command = ["git", "apply", "--reject"]
if check_flag:
command.append(check_flag)
command.append(patch_file)
subprocess.run(command, check=True)
print("Patch applied successfully!")
except subprocess.CalledProcessError:
print("Failed to apply patch.")
sys.exit(1)
success = apply_patch_line_by_line(patch_file, check_flag, hunk_filter=filter_hunk)
sys.exit(0 if success else 1)

if __name__ == "__main__":
main()
main()

0 comments on commit 066652d

Please sign in to comment.