Skip to content

Instantly share code, notes, and snippets.

@pdashford
Created January 18, 2017 04:01
Show Gist options
  • Save pdashford/2e4bcd4fc2343e2fd03efe4da17f577d to your computer and use it in GitHub Desktop.
Save pdashford/2e4bcd4fc2343e2fd03efe4da17f577d to your computer and use it in GitHub Desktop.
Python script to download folders from Github repo
"""
Downloads folders from github repo
Requires PyGithub
pip install PyGithub
"""
import os
import sys
import base64
import shutil
import getopt
from github import Github
from github import GithubException
def get_sha_for_tag(repository, tag):
"""
Returns a commit PyGithub object for the specified repository and tag.
"""
branches = repository.get_branches()
matched_branches = [match for match in branches if match.name == tag]
if matched_branches:
return matched_branches[0].commit.sha
tags = repository.get_tags()
matched_tags = [match for match in tags if match.name == tag]
if not matched_tags:
raise ValueError('No Tag or Branch exists with that name')
return matched_tags[0].commit.sha
def download_directory(repository, sha, server_path):
"""
Download all contents at server_path with commit tag sha in
the repository.
"""
if os.path.exists(server_path):
shutil.rmtree(server_path)
os.makedirs(server_path)
contents = repository.get_dir_contents(server_path, ref=sha)
for content in contents:
print "Processing %s" % content.path
if content.type == 'dir':
os.makedirs(content.path)
download_directory(repository, sha, content.path)
else:
try:
path = content.path
file_content = repository.get_contents(path, ref=sha)
file_data = base64.b64decode(file_content.content)
file_out = open(content.path, "w+")
file_out.write(file_data)
file_out.close()
except (GithubException, IOError) as exc:
print('Error processing %s: %s', content.path, exc)
def usage():
"""
Prints the usage command lines
"""
print "usage: gh-download --token=token --org=org --repo=repo --branch=branch --folder=folder"
def main(argv):
"""
Main function block
"""
try:
opts, args = getopt.getopt(argv, "t:o:r:b:f:", ["token=", "org=", "repo=", "branch=", "folder="])
except getopt.GetoptError as err:
print str(err)
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-t", "--token"):
token = arg
elif opt in ("-o", "--org"):
org = arg
elif opt in ("-r", "--repo"):
repo = arg
elif opt in ("-b", "--branch"):
branch = arg
elif opt in ("-f", "--folder"):
folder = arg
github = Github(token)
organization = github.get_organization(org)
repository = organization.get_repo(repo)
sha = get_sha_for_tag(repository, branch)
download_directory(repository, sha, folder)
if __name__ == "__main__":
"""
Entry point
"""
main(sys.argv[1:])
@Gkquic
Copy link

Gkquic commented Apr 3, 2023

Hey here is short version of this code
import os
import sys
import base64
import shutil
import argparse
from github import Github

def get_sha_for_tag(repository, tag):
"""
Returns a commit PyGithub object for the specified repository and tag.
"""
branches = repository.get_branches()
matched_branches = [match for match in branches if match.name == tag]
if matched_branches:
return matched_branches[0].commit.sha

tags = repository.get_tags()
matched_tags = [match for match in tags if match.name == tag]
if not matched_tags:
    raise ValueError('No Tag or Branch exists with that name')
return matched_tags[0].commit.sha

def download_directory(repository, sha, server_path):
"""
Download all contents at server_path with commit tag sha in
the repository.
"""
if os.path.exists(server_path):
shutil.rmtree(server_path)

os.makedirs(server_path)
contents = repository.get_dir_contents(server_path, ref=sha)

for content in contents:
    print(f"Processing {content.path}")
    if content.type == 'dir':
        os.makedirs(content.path)
        download_directory(repository, sha, content.path)
    else:
        try:
            path = content.path
            file_content = repository.get_contents(path, ref=sha)
            file_data = base64.b64decode(file_content.content)
            with open(content.path, "w+") as file_out:
                file_out.write(file_data)
        except Exception as exc:
            print(f"Error processing {content.path}: {exc}")

def parse_args():
"""
Parses command line arguments.
"""
parser = argparse.ArgumentParser(description='Download a directory from a Github repo.')
parser.add_argument('--token', required=True, help='Github API token')
parser.add_argument('--org', required=True, help='Github organization')
parser.add_argument('--repo', required=True, help='Github repository')
parser.add_argument('--branch', required=True, help='Github branch or tag')
parser.add_argument('--folder', required=True, help='Folder to download')
return parser.parse_args()

def main():
"""
Main function block
"""
args = parse_args()
github = Github(args.token)
organization = github.get_organization(args.org)
repository = organization.get_repo(args.repo)
sha = get_sha_for_tag(repository, args.branch)
download_directory(repository, sha, args.folder)

if name == "main":
"""
Entry point
"""
main()

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