Created
July 18, 2023 02:38
-
-
Save cassc/169c81133b4ac3d96348c171f9fae353 to your computer and use it in GitHub Desktop.
Clone all github repos
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# python github-clone-by-user.py username --skip-forks --excluded project1 project2 | |
import requests | |
import subprocess | |
import argparse | |
import os | |
def clone_or_fetch_repo(username, token, skip_forks): | |
headers = {'Authorization': f'token {token}'} if token else {} | |
# First, clone or fetch the public repositories of the specified user | |
base_url = f"https://api.github.com/users/{username}/repos" | |
clone_or_fetch(base_url, headers, username, skip_forks) | |
if not token: | |
return | |
# Then, clone or fetch the repositories that the authenticated user has access to | |
base_url = "https://api.github.com/user/repos" | |
clone_or_fetch(base_url, headers, username, skip_forks) | |
def clone_or_fetch(base_url, headers, username, skip_forks): | |
page = 1 | |
while True: | |
# Add the page and per_page parameters to the URL | |
url = f"{base_url}?page={page}&per_page=100" | |
# Send a GET request to the GitHub API | |
response = requests.get(url, headers=headers) | |
# If the request was successful | |
if response.status_code == 200: | |
# Get the JSON data from the response | |
repos = response.json() | |
# If there are no repositories in the response, we've reached the end of the list | |
if not repos: | |
break | |
# For each repository | |
for repo in repos: | |
if skip_forks and repo.get('fork'): | |
print(f"Skipping forked repo {repo['name']}") | |
continue | |
# Get the SSH URL | |
clone_url = repo["ssh_url"] | |
# Get the repository name | |
repo_name = repo["name"] | |
repo_owner = repo["owner"]["login"] | |
if repo_owner != username: | |
continue | |
if repo_name in excluded: | |
continue | |
# Check if the repository already exists | |
if os.path.exists(repo_name): | |
# If it does, fetch the updates | |
subprocess.run(["git", "-C", repo_name, "fetch"]) | |
else: | |
# If it doesn't, clone the repository | |
subprocess.run(["git", "clone", clone_url]) | |
# Go to the next page | |
page += 1 | |
else: | |
print(f"Failed to get repositories. Status code: {response.status_code}") | |
break | |
# Create the parser | |
parser = argparse.ArgumentParser(description="Clone all repositories that the authenticated user has access to, from a specific GitHub user") | |
# Add the arguments | |
parser.add_argument('username', type=str, help="The GitHub username") | |
parser.add_argument('token', type=str, nargs='?', default=None, help="The GitHub personal access token (optional)") | |
parser.add_argument('--skip-forks', action='store_true', help="Whether to skip forked repositories (optional)") | |
parser.add_argument('--excluded', nargs='*', default=[], help="List of repository names to be excluded (optional)") | |
# Parse the arguments | |
args = parser.parse_args() | |
excluded = set(args.excluded) | |
# Call the function with the username and token arguments | |
clone_or_fetch_repo(args.username, args.token, args.skip_forks) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment