|
|
|
|
|
import logging |
|
|
import re |
|
|
import sys |
|
|
|
|
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") |
|
|
|
|
|
|
|
|
def process_changelog(file_path, release_pr_number): |
|
|
|
|
|
try: |
|
|
with open(file_path) as file: |
|
|
lines = file.readlines() |
|
|
except OSError as e: |
|
|
logging.error(f"Failed to open or read file: {e}") |
|
|
return |
|
|
|
|
|
pr_occurrences = {} |
|
|
|
|
|
|
|
|
for i, line in enumerate(lines): |
|
|
match = re.search(r"\(#(\d+)\)", line) |
|
|
if match: |
|
|
pr_number = int(match.group(1)) |
|
|
|
|
|
if pr_number not in pr_occurrences: |
|
|
pr_occurrences[pr_number] = [] |
|
|
pr_occurrences[pr_number].append(i) |
|
|
|
|
|
|
|
|
to_remove = { |
|
|
i |
|
|
for pr, indices in pr_occurrences.items() |
|
|
if len(indices) > 1 |
|
|
for i in indices[:-1] |
|
|
} |
|
|
|
|
|
to_remove.update( |
|
|
i |
|
|
for pr, indices in pr_occurrences.items() |
|
|
for i in indices |
|
|
if pr <= release_pr_number |
|
|
) |
|
|
|
|
|
|
|
|
processed_lines = [line for i, line in enumerate(lines) if i not in to_remove] |
|
|
|
|
|
|
|
|
final_lines = [] |
|
|
seen_pr_numbers = set() |
|
|
for line in reversed( |
|
|
processed_lines |
|
|
): |
|
|
match = re.search(r"\(#(\d+)\)", line) |
|
|
if match: |
|
|
pr_number = int(match.group(1)) |
|
|
if pr_number in seen_pr_numbers: |
|
|
continue |
|
|
seen_pr_numbers.add(pr_number) |
|
|
final_lines.append(line) |
|
|
final_lines.reverse() |
|
|
|
|
|
|
|
|
try: |
|
|
with open(file_path, "w") as file: |
|
|
file.writelines(final_lines) |
|
|
except OSError as e: |
|
|
logging.error(f"Failed to write to file: {e}") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
if len(sys.argv) < 3: |
|
|
logging.error( |
|
|
"Usage: python process_changelog.py <changelog_file> <release_pr_number>" |
|
|
) |
|
|
sys.exit(1) |
|
|
|
|
|
file_path = sys.argv[1] |
|
|
release_pr_number = int(sys.argv[2]) |
|
|
process_changelog(file_path, release_pr_number) |
|
|
|