#!/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()