Last active
February 26, 2024 05:32
-
-
Save YuriyGuts/f13383478d8bad9ac148 to your computer and use it in GitHub Desktop.
Clones all GitHub Gists for the specified user.
This file contains hidden or 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
#!/usr/bin/env python | |
""" | |
Clone all GitHub Gists for the specified user. | |
Copyright (c) 2018 Yuriy Guts | |
usage: gist-clone-all.py [-h] user token | |
positional arguments: | |
user Which user's Gists to clone. | |
token Command line token for GitHub authentication. | |
optional arguments: | |
-h, --help show this help message and exit | |
""" | |
from __future__ import division, print_function | |
import argparse | |
import os | |
import requests | |
import subprocess | |
import sys | |
import traceback | |
class HelpOnFailArgumentParser(argparse.ArgumentParser): | |
""" | |
Prints help whenever the command-line arguments could not be parsed. | |
""" | |
def error(self, message): | |
sys.stderr.write('error: %s\n\n' % message) | |
self.print_help() | |
sys.exit(2) | |
class RepoEnumerationException(Exception): | |
pass | |
def parse_command_line_args(args): | |
""" | |
Parse command-line arguments and organize them into a single structured object. | |
""" | |
program_desc = 'Clone all GitHub Gists for the specified user.' | |
parser = HelpOnFailArgumentParser(description=program_desc) | |
parser.add_argument('user', help="Which user's Gists to clone.") | |
parser.add_argument('token', help='Command line token for GitHub authentication.') | |
# Try parsing the arguments and fail properly if that didn't succeed. | |
return parser.parse_args(args) | |
def fetch_json(url, auth_token): | |
print('> HTTP fetch:', url) | |
headers = { | |
'Accept': 'application/vnd.github.v3+json', | |
'Authorization': "token " + auth_token, | |
'User-Agent': "YuriyGuts/gist-clone-all.py" | |
} | |
response = requests.get(url, headers=headers) | |
return response.json() | |
def get_command_output(command): | |
print('> Running:', command) | |
return subprocess.check_output(command, shell=True).decode('utf-8') | |
def is_repo_already_cloned(repo_name): | |
return os.path.exists(repo_name) and os.path.exists(os.path.join(repo_name, '.git')) | |
def clone_gist(gist): | |
""" | |
Clone a single Gist. | |
""" | |
gist_id = gist['id'] | |
gist_name = gist['name'] | |
repo_url = 'https://gist.github.com/{}.git'.format(gist_id) | |
# Clone the Gist. | |
print() | |
print('-------- Cloning {} [{}] --------'.format(gist_name, gist_id)) | |
if is_repo_already_cloned(gist_name): | |
print('SKIP: repo already cloned') | |
return | |
clone_path = '{}-{}'.format(gist_name, gist_id) | |
get_command_output('git clone {} "{}"'.format(repo_url, clone_path)) | |
def clone_all_gists(args): | |
""" | |
Discover all Gists for the user and clone them. | |
""" | |
print('Querying GitHub API...') | |
list_repos_url = 'https://api.github.com/users/{}/gists?per_page=200'.format(args.user) | |
gists = fetch_json(list_repos_url, args.token) | |
if not isinstance(gists, list): | |
raise RepoEnumerationException(gists) | |
# Print out all Gists. | |
print() | |
print('Will clone the following Gists:') | |
for gist in gists: | |
gist['name'] = list(gist['files'].values())[0]['filename'] | |
print(' * {}'.format(gist['name'])) | |
for gist in gists: | |
try: | |
clone_gist(gist) | |
except Exception: | |
print() | |
print('ERROR while cloning a repo.') | |
print() | |
traceback.print_exc() | |
def main(): | |
parsed_args = parse_command_line_args(sys.argv[1:]) | |
try: | |
clone_all_gists(parsed_args) | |
except RepoEnumerationException as e: | |
print('ERROR enumerating the gists (an incorrect GitHub username/password?).') | |
print('GitHub response:', e) | |
sys.exit(1) | |
except Exception: | |
traceback.print_exc() | |
sys.exit(1) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment