update-supported-devices.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #!/usr/bin/env python3
  2. """Update docs/supported-devices.md from a device-support issue."""
  3. import re, sys, datetime, pathlib
  4. ISSUE_BODY = pathlib.Path(sys.argv[1]).read_text() if len(sys.argv) > 1 else sys.stdin.read()
  5. MD = pathlib.Path("docs/supported-devices.md")
  6. def field(id):
  7. # issue form bodies render as "### <Label>\n\nvalue"
  8. # we match by id label text variations
  9. labels = {
  10. "manufacturer": "Manufacturer",
  11. "custom_manufacturer": "Custom manufacturer (if Other)",
  12. "device": "Device",
  13. "codename": "Codename",
  14. "gki_kernel": "GKI Kernel",
  15. "firmware": "Firmware",
  16. "status": "Status",
  17. }
  18. label = labels.get(id, id)
  19. m = re.search(rf"### {re.escape(label)}\s*\n+([^\n#]+)", ISSUE_BODY)
  20. if m:
  21. return m.group(1).strip()
  22. # fallback: try id
  23. m = re.search(rf"### {re.escape(id)}\s*\n+([^\n#]+)", ISSUE_BODY)
  24. return m.group(1).strip() if m else ""
  25. heading_map = {
  26. "Google Pixel": "## Google Pixel",
  27. "Samsung": "## Samsung",
  28. "OnePlus": "## OnePlus",
  29. "OPPO": "## OPPO",
  30. "Realme": "## Realme",
  31. "Xiaomi": "## Xiaomi",
  32. "POCO": "## POCO",
  33. "Redmi": "## Redmi",
  34. "Nothing": "## Nothing",
  35. "Other": "## Other",
  36. }
  37. manufacturer = field("manufacturer") or "Other"
  38. device = field("device").strip()
  39. codename = field("codename").strip()
  40. gki = field("gki_kernel").strip()
  41. firmware = field("firmware").strip() or "stock"
  42. status = field("status").strip() or "Supported"
  43. custom_oem = field("custom_manufacturer").strip()
  44. # handle custom OEM when Other is selected
  45. if manufacturer == "Other" and custom_oem and custom_oem.lower() not in ("none", "_no response_", ""):
  46. manufacturer = custom_oem.strip().title()
  47. heading_map[manufacturer] = f"## {manufacturer}"
  48. if not device or not codename or not gki:
  49. print("missing required fields", file=sys.stderr)
  50. sys.exit(0)
  51. heading = heading_map.get(manufacturer, f"## {manufacturer}")
  52. # Xiaomi/POCO/Redmi share same file section expansion if not present -> create heading
  53. text = MD.read_text()
  54. if heading not in text and manufacturer in ("Xiaomi", "POCO", "Redmi"):
  55. # ensure sections exist (already added as separate? current file has Xiaomi / POCO / Redmi combined? we split?)
  56. # if missing, append before end
  57. pass
  58. today = datetime.date.today().isoformat()
  59. status_cell = f"{status} · {today}"
  60. row = f"| {device} | {codename} | {gki} | {firmware} | {status_cell} |"
  61. if heading not in text:
  62. # append new section at end before source
  63. text = text.rstrip() + f"\n\n{heading}\n\n| Device | Codename | GKI Kernel | Firmware | Status |\n|--------|----------|------------|----------|--------|\n{row}\n"
  64. MD.write_text(text)
  65. print(f"added new heading {heading}")
  66. sys.exit(0)
  67. # find table under heading
  68. # split by headings
  69. parts = re.split(r"(^## .+$)", text, flags=re.MULTILINE)
  70. out = []
  71. for i, part in enumerate(parts):
  72. if part.strip() == heading:
  73. # next part is body until next heading
  74. body = parts[i+1] if i+1 < len(parts) else ""
  75. # check duplicate codename
  76. if re.search(rf"\|\s*{re.escape(device)}\s*\|", body) or re.search(rf"\|\s*[^|]*\|\s*{re.escape(codename)}\s*\|", body):
  77. print("device already listed, updating not duplicating")
  78. # replace existing row's status/gki if needed? skip for now
  79. out.append(part)
  80. out.append(body)
  81. continue
  82. # replace placeholder row if present
  83. placeholder = "| — | — | — | — | Placeholder — add entries |"
  84. if placeholder in body:
  85. new_body = body.replace(placeholder, row, 1)
  86. else:
  87. # append row before next heading or at end of table (before blank line + ##)
  88. # find last table row line
  89. lines = body.splitlines()
  90. insert_idx = None
  91. for idx, line in enumerate(lines):
  92. if line.startswith("|") and "Device | Codename" in line:
  93. # header, continue
  94. continue
  95. if line.startswith("|") and "--------" in line:
  96. continue
  97. # find last row that starts with |
  98. last = -1
  99. for idx, line in enumerate(lines):
  100. if line.startswith("| "):
  101. last = idx
  102. if last >= 0:
  103. lines.insert(last+1, row)
  104. else:
  105. lines.append(row)
  106. new_body = "\n".join(lines)
  107. out.append(part)
  108. out.append(new_body)
  109. else:
  110. # already handled body as part of heading case? avoid double
  111. if i>0 and parts[i-1].strip() == heading:
  112. continue
  113. out.append(part)
  114. MD.write_text("".join(out))
  115. print(f"inserted {device} into {heading}")