Files
Sankofa/scripts/update-markdown-links.py

130 lines
5.2 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""
Update Markdown Links After Reorganization
Updates links to moved files in documentation.
"""
import os
import re
from pathlib import Path
# Mapping of old paths to new paths (relative to docs/)
FILE_MOVES = {
'AUDIT_SUMMARY.md': 'reports/AUDIT_SUMMARY.md',
'COMPREHENSIVE_AUDIT_REPORT.md': 'reports/COMPREHENSIVE_AUDIT_REPORT.md',
'PROXMOX_COMPREHENSIVE_AUDIT_REPORT.md': 'reports/PROXMOX_COMPREHENSIVE_AUDIT_REPORT.md',
'REPOSITORY_AUDIT_REPORT.md': 'reports/REPOSITORY_AUDIT_REPORT.md',
'PROJECT_COMPREHENSIVE_REVIEW.md': 'reports/PROJECT_COMPREHENSIVE_REVIEW.md',
'REVIEW_ITEMS_COMPLETED.md': 'reports/REVIEW_ITEMS_COMPLETED.md',
'DOCUMENTATION_DEEP_DIVE_ANALYSIS.md': 'reports/DOCUMENTATION_DEEP_DIVE_ANALYSIS.md',
'DOCUMENTATION_FIXES_APPLIED.md': 'reports/DOCUMENTATION_FIXES_APPLIED.md',
'DOCUMENTATION_COMPLETE_SUMMARY.md': 'summaries/DOCUMENTATION_COMPLETE_SUMMARY.md',
'IMPLEMENTATION_SUMMARY.md': 'summaries/IMPLEMENTATION_SUMMARY.md',
'BUILD_AND_DEPLOY_INSTRUCTIONS.md': 'guides/BUILD_AND_DEPLOY_INSTRUCTIONS.md',
'FORCE_UNLOCK_INSTRUCTIONS.md': 'guides/FORCE_UNLOCK_INSTRUCTIONS.md',
'QUICK_INSTALL_GUEST_AGENT.md': 'guides/QUICK_INSTALL_GUEST_AGENT.md',
'enable-guest-agent-manual.md': 'guides/enable-guest-agent-manual.md',
'GUEST_AGENT_CHECKLIST.md': 'guest-agent/GUEST_AGENT_CHECKLIST.md',
'GUEST_AGENT_CONFIGURATION_ANALYSIS.md': 'guest-agent/GUEST_AGENT_CONFIGURATION_ANALYSIS.md',
'VM_CREATION_PROCEDURE.md': 'vm/VM_CREATION_PROCEDURE.md',
'VM_DEPLOYMENT_CHECKLIST.md': 'vm/VM_DEPLOYMENT_CHECKLIST.md',
'VM_SPECIFICATIONS.md': 'vm/VM_SPECIFICATIONS.md',
'COPY_SCRIPT_TO_PROXMOX_NODES.md': 'reference/COPY_SCRIPT_TO_PROXMOX_NODES.md',
'SCRIPT_COPIED_TO_PROXMOX_NODES.md': 'reference/SCRIPT_COPIED_TO_PROXMOX_NODES.md',
'CODE_INCONSISTENCIES.md': 'reference/CODE_INCONSISTENCIES.md',
'DEPLOYMENT_NEXT_STEPS.md': 'deployment/DEPLOYMENT_NEXT_STEPS.md',
'DEPLOYMENT_READY.md': 'deployment/DEPLOYMENT_READY.md',
'PRE_DEPLOYMENT_CHECKLIST.md': 'deployment/PRE_DEPLOYMENT_CHECKLIST.md',
}
def calculate_relative_path(from_file: Path, to_file: str) -> str:
"""Calculate relative path from one file to another."""
from_dir = from_file.parent
to_path = Path('docs') / to_file
try:
rel_path = os.path.relpath(to_path, from_dir)
# Normalize path separators for markdown
return rel_path.replace('\\', '/')
except:
return to_file
def update_links_in_file(file_path: Path, dry_run: bool = True):
"""Update links in a single file."""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
original_content = content
updated = False
for old_file, new_file in FILE_MOVES.items():
# Pattern 1: [text](./FILE.md) or [text](FILE.md)
pattern1 = rf'(\[[^\]]+\]\()\.?/?{re.escape(old_file)}(#[^\)]+)?(\))'
def replace1(match):
new_path = calculate_relative_path(file_path, new_file)
anchor = match.group(2) or ''
return f"{match.group(1)}{new_path}{anchor}{match.group(3)}"
if re.search(pattern1, content):
content = re.sub(pattern1, replace1, content)
updated = True
# Pattern 2: [text](./FILE.md#anchor)
pattern2 = rf'(\[[^\]]+\]\(\./){re.escape(old_file)}(#[^\)]+)?(\))'
def replace2(match):
new_path = calculate_relative_path(file_path, new_file)
anchor = match.group(2) or ''
return f"{match.group(1)}{new_path}{anchor}{match.group(3)}"
if re.search(pattern2, content):
content = re.sub(pattern2, replace2, content)
updated = True
if updated and content != original_content:
if not dry_run:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
return True
return False
except Exception as e:
print(f"Error processing {file_path}: {e}")
return False
def main():
import sys
dry_run = '--dry-run' in sys.argv or '-n' in sys.argv
if not dry_run:
response = input("This will modify files. Continue? (yes/no): ")
if response.lower() != 'yes':
print("Aborted.")
return
docs_dir = Path('docs')
md_files = list(docs_dir.rglob('*.md'))
updated_count = 0
for md_file in md_files:
# Skip the moved files themselves
if any(md_file.name == old_file for old_file in FILE_MOVES.keys()):
continue
if update_links_in_file(md_file, dry_run=dry_run):
updated_count += 1
if dry_run:
print(f"Would update: {md_file}")
else:
print(f"Updated: {md_file}")
if dry_run:
print(f"\nDry run complete. {updated_count} files would be updated.")
print("Run without --dry-run to apply changes.")
else:
print(f"\nUpdated {updated_count} files.")
if __name__ == '__main__':
main()