Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@SpotlightKid
Last active April 11, 2024 15:31
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save SpotlightKid/042491a9a2987af04a5a to your computer and use it in GitHub Desktop.
Save SpotlightKid/042491a9a2987af04a5a to your computer and use it in GitHub Desktop.
Clone all gists of GitHub username given on the command line.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Clone all gists of GitHub user with given username.
Clones all gist repos into the current directory, using the gist id as the
directory name. If the directory already exists as a git repo, try to perform a
'git pull' in it.
"""
import argparse
import sys
from os.path import exists, join
from subprocess import CalledProcessError, check_call
import requests
def main(args=None):
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument(
"-p", "--page", type=int, metavar="PAGE", help="Fetch only page PAGE from list of Gists"
)
ap.add_argument(
"--per-page", type=int, metavar="NUM", default=100, help="Fetch NUM gists per page"
)
ap.add_argument(
"-s", "--ssh-url", action="store_true", help="Clone gists using SSH URL instead of HTTPS"
)
ap.add_argument(
"-v", "--verbose", action="store_true", help="Run git commands with verbose messages"
)
ap.add_argument("username", help="GitHub username")
ap.add_argument("token", nargs="?", help="GitHub auth token")
args = ap.parse_args(args)
page = args.page
while True:
if page is None:
page = 1
print(f"Fetching page {page} of list of Gists of user {args.username}...")
url = "https://api.github.com/users/{}/gists".format(args.username)
headers = {"Authorization": "token " + args.token} if args.token else {}
resp = requests.get(url, headers=headers, params={"per_page": args.per_page, "page": page})
if resp.status_code == 200:
for gist in resp.json():
gistid = gist["id"]
try:
if exists(join(gist["id"], ".git")):
print(f"Updating gist {gistid} via 'git pull'...")
check_call(["git", "pull", "-v" if args.verbose else "-q"], cwd=gistid)
else:
url = gist["git_pull_url"]
if args.ssh_url:
url = url.replace("https://gist.github.com/", "git@gist.github.com:")
print(f"Cloning Gist from {url}...")
check_call(["git", "clone", "-v" if args.verbose else "-q", url])
except CalledProcessError:
print(f"*** ERROR cloning/updating gist {gistid}. Please check output.")
except KeyboardInterrupt:
break
if 'rel="next"' in resp.headers.get("link", ""):
page += 1
else:
break
else:
return "Error reponse: {}".format(req.json().get("message"))
if args.page:
break
if __name__ == "__main__":
sys.exit(main() or 0)
#!/bin/bash
#
# replace gist git repo remote origin https URL with SSH one.
#
if [[ "$1" = "-p" ]]; then
pull=1
shift
fi
for d in *; do
if [ -d "$d/.git" ]; then
pushd "$d"
url="$(git remote get-url origin)"
newurl="$(echo $url | sed -e 's|https://|git@|;s|\.com/|.com:|')"
if [ "x$url" != "x$newurl" ]; then
git remote set-url origin "$newurl"
fi
branch="$(git branch --show-current)"
tracking="$(git config branch.$branch.merge)"
if [ -z "$tracking" ]; then
git branch --set-upstream-to=origin/$branch $branch
fi
if [[ "$pull" -eq 1 ]]; then
git pull
fi
popd
fi
done
@daephx
Copy link

daephx commented Apr 16, 2020

I don't think gists have pull requests.
Added the ability to pass an access token to download private gists, so far it's worked for me.
https://gist.github.com/DaemonPhenex/4ed066e04022ec374a16cb995091d64c

@SpotlightKid
Copy link
Author

@DaemonPhenex Passing the auth token via an URL param is deprecated. I changed the script to pass the token via the HTTP headers instead.

You can create a personal token via "Settings / Developer settings / Personal access tokens". The token needs no special OAuth scopes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment