123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- #!/usr/bin/env python
- import argparse
- import requests
- REPOS_URL = "https://api.github.com/user/repos"
- def next_link(response):
- if "Link" not in response.headers:
- return None
- links = requests.utils.parse_header_links(response.headers["Link"])
- next = [link for link in links if link["rel"] == "next"]
- if len(next) > 0:
- return next[0]["url"]
- else:
- return None
- def fetch_repos(user, token):
- repos = []
- next_url = REPOS_URL
- while True:
- response = requests.get(next_url, auth=(user, token))
- repos = repos + response.json()
- next_url = next_link(response)
- if not next_url:
- return repos
- class Gogs:
- def __init__(self, base_url, user, token):
- self.base_url = base_url
- self.user = user
- self.token = token
- def user_id(self):
- url = f"{self.base_url}/api/v1/user"
- params = {"token": self.token}
- response = requests.get(url, params=params)
- return response.json()["id"]
- def org_id(self, org_name):
- url = f"{self.base_url}/api/v1/orgs/{org_name}"
- params = {"token": self.token}
- response = requests.get(url, params=params)
- return response.json()["id"]
- def mirror(self, owner_id, repo):
- url = f"{self.base_url}/api/v1/repos/migrate"
- body = {
- "clone_addr": repo["clone_url"],
- "uid": owner_id,
- "repo_name": repo["name"],
- "mirror": True,
- "private": repo["private"],
- "description": repo["description"]
- }
- params = {"token": self.token}
- return requests.post(url, json=body, params=params)
- def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--gh-user", required=True, help="github user")
- parser.add_argument("--gh-token", help="github token")
- parser.add_argument("--gogs-url", required=True, help="gogs server URL")
- parser.add_argument("--gogs-user", required=True, help="gogs user")
- parser.add_argument("--gogs-token", help="gogs token")
- parser.add_argument("--gogs-org", help="Gogs organization to mirror to")
- parser.add_argument("--with-forks", type=bool, help="Mirror forks")
- args = parser.parse_args()
- gh_user = args.gh_user
- gh_token = args.gh_token
- gogs_url = args.gogs_url
- gogs_user = args.gogs_user
- gogs_token = args.gogs_token
- gogs_org = args.gogs_org
- with_forks = args.with_forks
- if not gh_token:
- gh_token = input("Github token: ")
- if not gogs_token:
- gogs_token = input("Gogs token: ")
- # Load repositories
- repos = fetch_repos(gh_user, gh_token)
- # Filter out repos from orgs that the user belongs to
- repos = [r for r in repos if r["owner"]["login"] == gh_user]
- # Filter out forks
- if not with_forks:
- repos = [r for r in repos if not r["fork"]]
- gogs = Gogs(gogs_url, gogs_user, gogs_token)
- if gogs_org:
- print(f"Mirror to organization {gogs_org}")
- gogs_id = gogs.org_id(gogs_org)
- else:
- print(f"Mirror to user {gogs_user}")
- gogs_id = gogs.user_id()
- # Set up the mirrors
- for repo in repos:
- response = gogs.mirror(gogs_id, repo)
- if response.status_code == 201:
- print(f"Mirror for {repo['name']} set up")
- elif response.status_code == 500:
- print(f"Repository {repo['name']} already exists")
- else:
- print(f"Unknown error {response.status_code} for repo {repo['name']}")
- if __name__ == "__main__":
- main()
|