/ tools / r-wrapper / 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()