/ map_arch_to_repo.py
map_arch_to_repo.py
1 #!/usr/bin/env python3 2 """ 3 Dependency graph generator. 4 Parses Cargo.toml/requirements.txt to build cross-repo dependency map. 5 """ 6 import os 7 import json 8 import re 9 import sys 10 11 from config import WORKSPACE_ROOT, WORKSPACE_MAP_PATH, REPO_DEPENDENCIES_PATH 12 13 14 def parse_cargo_toml(repo_path): 15 """Extract dependency info from Cargo.toml.""" 16 cargo_path = os.path.join(repo_path, 'Cargo.toml') 17 if not os.path.exists(cargo_path): 18 return None 19 20 try: 21 with open(cargo_path, 'r') as f: 22 content = f.read() 23 24 # Extract name 25 name_match = re.search(r'^name\s*=\s*"([^"]+)"', content, re.MULTILINE) 26 name = name_match.group(1) if name_match else os.path.basename(repo_path) 27 28 # Extract workspace members 29 members = [] 30 members_match = re.search(r'members\s*=\s*\[(.*?)(\s*\])?', content, re.DOTALL) 31 if members_match: 32 raw_members = members_match.group(1) 33 members = [m.strip().strip('"').strip("'") for m in raw_members.split(',') if m.strip()] 34 35 # Extract path dependencies 36 deps = set() 37 path_matches = re.findall(r'path\s*=\s*"(\.\.[^\\"]+)"', content) 38 for path in path_matches: 39 norm_path = os.path.normpath(os.path.join(repo_path, path)) 40 repo_name = os.path.basename(norm_path) 41 deps.add(repo_name) 42 43 return { 44 "type": "rust", 45 "name": name, 46 "members": members, 47 "local_dependencies": list(deps) 48 } 49 except Exception as e: 50 sys.stderr.write(f"!ERR:PARSE Cargo.toml in {repo_path}: {e}\n") 51 return None 52 53 54 def parse_python_deps(repo_path): 55 """Extract dependency info from requirements.txt.""" 56 req_path = os.path.join(repo_path, 'requirements.txt') 57 deps = [] 58 59 if os.path.exists(req_path): 60 try: 61 with open(req_path, 'r') as f: 62 for line in f: 63 line = line.strip() 64 if line and not line.startswith('#'): 65 deps.append(re.split(r'[=<>]', line)[0]) 66 except Exception as e: 67 sys.stderr.write(f"!ERR:PARSE requirements.txt in {repo_path}: {e}\n") 68 69 return { 70 "type": "python", 71 "local_dependencies": [], 72 "packages": deps 73 } 74 75 76 def main(): 77 if not os.path.exists(WORKSPACE_MAP_PATH): 78 sys.stderr.write(f"!ERR:MISSING {WORKSPACE_MAP_PATH} not found. Run bootstrap.py first.\n") 79 sys.exit(1) 80 81 try: 82 with open(WORKSPACE_MAP_PATH, 'r') as f: 83 ws_map = json.load(f) 84 except Exception as e: 85 sys.stderr.write(f"!ERR:READ Cannot load workspace map: {e}\n") 86 sys.exit(1) 87 88 repo_graph = {} 89 90 for key, path in ws_map.items(): 91 if '::' in key: 92 namespace, repo_name = key.split('::', 1) 93 else: 94 namespace = "UNKNOWN" 95 repo_name = key 96 97 info = None 98 if os.path.exists(os.path.join(path, 'Cargo.toml')): 99 info = parse_cargo_toml(path) 100 elif os.path.exists(os.path.join(path, 'requirements.txt')) or \ 101 os.path.exists(os.path.join(path, 'pyproject.toml')): 102 info = parse_python_deps(path) 103 104 if info: 105 info['path'] = path 106 info['namespace'] = namespace 107 repo_graph[repo_name] = info 108 else: 109 repo_graph[repo_name] = { 110 "path": path, 111 "namespace": namespace, 112 "type": "unknown" 113 } 114 115 print(f"Generating dependency map at {REPO_DEPENDENCIES_PATH}...") 116 117 try: 118 with open(REPO_DEPENDENCIES_PATH, 'w') as f: 119 json.dump(repo_graph, f, indent=2) 120 except Exception as e: 121 sys.stderr.write(f"!ERR:WRITE Cannot write dependencies: {e}\n") 122 sys.exit(1) 123 124 print(f"[S:PASS] Mapped {len(repo_graph)} repositories.") 125 126 127 if __name__ == "__main__": 128 main()