setup_mirror.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #!/usr/bin/env python
  2. import argparse
  3. import requests
  4. REPOS_URL = "https://api.github.com/user/repos"
  5. def next_link(response):
  6. if "Link" not in response.headers:
  7. return None
  8. links = requests.utils.parse_header_links(response.headers["Link"])
  9. next = [link for link in links if link["rel"] == "next"]
  10. if len(next) > 0:
  11. return next[0]["url"]
  12. else:
  13. return None
  14. def fetch_repos(user, token):
  15. repos = []
  16. next_url = REPOS_URL
  17. while True:
  18. response = requests.get(next_url, auth=(user, token))
  19. repos = repos + response.json()
  20. next_url = next_link(response)
  21. if not next_url:
  22. return repos
  23. class Gogs:
  24. def __init__(self, base_url, user, token):
  25. self.base_url = base_url
  26. self.user = user
  27. self.token = token
  28. def user_id(self):
  29. url = f"{self.base_url}/api/v1/user"
  30. params = {"token": self.token}
  31. response = requests.get(url, params=params)
  32. return response.json()["id"]
  33. def org_id(self, org_name):
  34. url = f"{self.base_url}/api/v1/orgs/{org_name}"
  35. params = {"token": self.token}
  36. response = requests.get(url, params=params)
  37. return response.json()["id"]
  38. def mirror(self, owner_id, repo):
  39. url = f"{self.base_url}/api/v1/repos/migrate"
  40. body = {
  41. "clone_addr": repo["clone_url"],
  42. "uid": owner_id,
  43. "repo_name": repo["name"],
  44. "mirror": True,
  45. "private": repo["private"],
  46. "description": repo["description"]
  47. }
  48. params = {"token": self.token}
  49. return requests.post(url, json=body, params=params)
  50. def main():
  51. parser = argparse.ArgumentParser()
  52. parser.add_argument("--gh-user", required=True, help="github user")
  53. parser.add_argument("--gh-token", help="github token")
  54. parser.add_argument("--gogs-url", required=True, help="gogs server URL")
  55. parser.add_argument("--gogs-user", required=True, help="gogs user")
  56. parser.add_argument("--gogs-token", help="gogs token")
  57. parser.add_argument("--gogs-org", help="Gogs organization to mirror to")
  58. parser.add_argument("--with-forks", type=bool, help="Mirror forks")
  59. args = parser.parse_args()
  60. gh_user = args.gh_user
  61. gh_token = args.gh_token
  62. gogs_url = args.gogs_url
  63. gogs_user = args.gogs_user
  64. gogs_token = args.gogs_token
  65. gogs_org = args.gogs_org
  66. with_forks = args.with_forks
  67. if not gh_token:
  68. gh_token = input("Github token: ")
  69. if not gogs_token:
  70. gogs_token = input("Gogs token: ")
  71. # Load repositories
  72. repos = fetch_repos(gh_user, gh_token)
  73. # Filter out repos from orgs that the user belongs to
  74. repos = [r for r in repos if r["owner"]["login"] == gh_user]
  75. # Filter out forks
  76. if not with_forks:
  77. repos = [r for r in repos if not r["fork"]]
  78. gogs = Gogs(gogs_url, gogs_user, gogs_token)
  79. if gogs_org:
  80. print(f"Mirror to organization {gogs_org}")
  81. gogs_id = gogs.org_id(gogs_org)
  82. else:
  83. print(f"Mirror to user {gogs_user}")
  84. gogs_id = gogs.user_id()
  85. # Set up the mirrors
  86. for repo in repos:
  87. response = gogs.mirror(gogs_id, repo)
  88. if response.status_code == 201:
  89. print(f"Mirror for {repo['name']} set up")
  90. elif response.status_code == 500:
  91. print(f"Repository {repo['name']} already exists")
  92. else:
  93. print(f"Unknown error {response.status_code} for repo {repo['name']}")
  94. if __name__ == "__main__":
  95. main()