update_contributors.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #!/usr/bin/env python3
  2. import subprocess
  3. import datetime
  4. from collections import defaultdict
  5. from pathlib import Path
  6. # Path to CONTRIBUTORS.md
  7. contributors_file = Path(__file__).parent / "CONTRIBUTORS.md"
  8. def run_git(command):
  9. """Run a git command and return the output as a list of lines."""
  10. result = subprocess.run(
  11. ["git"] + command, capture_output=True, text=True, check=True
  12. )
  13. return result.stdout.strip().split("\n")
  14. def get_contributors():
  15. """Extract contributors from git log."""
  16. log_lines = run_git(["log", "--format=%aN|%aE|%ad", "--date=short"])
  17. contributors = defaultdict(lambda: {"emails": set(), "first": None, "last": None, "count": 0})
  18. for line in log_lines:
  19. if "|" not in line:
  20. continue
  21. name, email, date = line.split("|")
  22. name, email = name.strip(), email.strip()
  23. info = contributors[name]
  24. info["emails"].add(email)
  25. info["count"] += 1
  26. if not info["first"] or date < info["first"]:
  27. info["first"] = date
  28. if not info["last"] or date > info["last"]:
  29. info["last"] = date
  30. return contributors
  31. def generate_table(contributors):
  32. """Generate markdown table."""
  33. header = [
  34. "# 🌍 Project Contributors",
  35. "",
  36. "This file lists all contributors automatically extracted from Git commit history.",
  37. "Do not edit manually — run `python scripts/update_contributors.py` to refresh.",
  38. "",
  39. "| Name | Email | Contributions | First Commit | Last Commit | Reference |",
  40. "|------|--------|----------------|---------------|--------------|-----------|",
  41. ]
  42. rows = []
  43. for name, info in sorted(contributors.items(), key=lambda x: x[0].lower()):
  44. emails = ", ".join(sorted(info["emails"]))
  45. # Default empty reference link
  46. reference = ""
  47. rows.append(f"| {name} | {emails} | {info['count']} commits | {info['first']} | {info['last']} | {reference} |")
  48. return "\n".join(header + rows) + "\n"
  49. def main():
  50. contributors = get_contributors()
  51. md = generate_table(contributors)
  52. contributors_file.write_text(md, encoding="utf-8")
  53. print(f"✅ Updated {contributors_file} with {len(contributors)} contributors.")
  54. if __name__ == "__main__":
  55. main()