Skip to content

Instantly share code, notes, and snippets.

@megat69
Last active May 21, 2024 07:42
Show Gist options
  • Save megat69/173594870a63a4374605b5fb98ce7426 to your computer and use it in GitHub Desktop.
Save megat69/173594870a63a4374605b5fb98ce7426 to your computer and use it in GitHub Desktop.
Download GitHub repository

Repository downloader

This Python script allows you to download a public GitHub repository extremely quickly.

Usage

download_repo()

This function is the function that will download the repository.

Parameters

URL

This is required parameter.

It is basically the repository main zip URL, which can be obtained through the get_zip_link() function (see below).

folder

A required parameter.

This is the folder you want the repository to be placed in. It is just a string.

files_to_delete

This is a non-required argument, which defines the files to delete after the download. By default, it will delete the ".gitattributes" file and the "README.md" file.

log

A non-required boolean (set to True by default) which controls whether or not you want to enable the logging.

If True, the notify_function() (see below) will be called every time a log is required.

notify_function

A non-required callback function. By default, the print method.

This argument is the name of the function to call when logging is wanted.

When called, the function will receive as first argument the logging string, followed by the other given positional arguments, and the other given keyword arguments.

get_zip_link()

This function is used to get the link of a repository main ZIP file, which will be returned as a string.

Usage

Parameters

username

A required string. This is the username of the repository owner.

repository

Another required string. This is the repository name.

branch

A non-required string. This is the branch you want to download, by default the main branch.

Examples

Example 1

Simple repository download : The repository is megat69's ACPL, and we download the master branch.

The downloaded repository will be stored in the ACPL folder.

download_repo(get_zip_link("megat69", "ACPL", branch="master"), "ACPL")

Example 2

The repository is megat69's ACPL, and we download the master branch.

The downloaded repository will be stored in the ACPL folder.

But in this case, we want the user to be capable to see the ".gitattributes" and "README.md" file, so we pass in an empty tuple to the files_to_delete argument.

download_repo(get_zip_link("megat69", "ACPL", branch="master"), "ACPL", files_to_delete=tuple())

Example 3

Background download : We don't want the user to see that we are downloading. Therefore, the log parameter is set to False.

The repository is megat69's ACPL, and we download the master branch.

The downloaded repository will be stored in the ACPL folder.

download_repo(get_zip_link("megat69", "ACPL", branch="master"), "ACPL", log=False)

Example 4

GUI popup (tkinter) : We want the user to be notified through the GUI of our app.

The repository is megat69's ACPL, and we download the master branch.

The downloaded repository will be stored in the ACPL folder.

from repository_downloader import *
import tkinter as tk

window = tk.Tk()
window.geometry("500x500")

def notify(log_string:str):
  """
  Notifies the user through the app GUI.
  """
  notification = tk.Label(window, text=log_string).pack()

def download():
  download_repo(get_zip_link("megat69", "ACPL", branch="master"), "ACPL", notify_function=notify)

window.after(16, download)
window.mainloop()
import requests
import os
import zipfile
import shutil
def download_repo(URL:str, folder:str, files_to_delete:(list, tuple)=(".gitattributes", "README.md"), log:bool=True, notify_function=print, *args, **kwargs):
"""
Downloads the specified repository into the specified folder.
:param URL: The URL of the repository main archive.
:param folder: The folder to place the repository in.
:param files_to_delete: The files to delete after downloading the repository. DEFAULT : '.gitattributes', 'README.md'
:param log: Log the informations in the console. DEFAULT : True
:param notify_function: The function that will get the log as argument. DEFAULT : print()
"""
if log: notify_function("Downloading... This might take a while.", *args, **kwargs)
r = requests.get(URL)
assert r.status_code == 200, "Something happened.\nStatus code : " + str(r.status_code)
if log: notify_function("Writing the zip...", *args, **kwargs)
# Writing the zip
with open(f"{folder}.zip", "wb") as code:
code.write(r.content)
code.close()
# Creating a folder for the zip content
if not os.path.exists(folder):
os.mkdir(folder)
if log: notify_function("Extracting...", *args, **kwargs)
# Extracting the zip
with zipfile.ZipFile(f"{folder}.zip", "r") as zip_ref:
zip_ref.extractall(folder)
if log: notify_function("Moving the files...", *args, **kwargs)
suffix = URL.split("/")[-1].replace(".zip", "", 1)
repo_name = URL.split("/")[4]
# Moving the file to parent
for filename in os.listdir(os.path.join(folder, f'{repo_name}-{suffix}')):
shutil.move(os.path.join(folder, f'{repo_name}-{suffix}', filename), os.path.join(folder, filename))
# Deleting unnecessary files
shutil.rmtree(f"{folder}/{repo_name}-{suffix}")
os.remove(f"{folder}.zip")
for file in files_to_delete:
try:
os.remove(f"{folder}/{file}")
except FileNotFoundError:
pass
if log: notify_function("Download complete !", *args, **kwargs)
def get_zip_link(username:str, repository:str, branch:str="main"):
"""
Gets the link to the main zip of a repository.
:param username: The username of the repository owner.
:param repository: The repository name.
:param branch: The branch to download. Default : 'main'.
:return: The link to the zip.
"""
return f"https://github.com/{username}/{repository}/archive/refs/heads/{branch}.zip"
if __name__ == "__main__":
download_repo(get_zip_link("megat69", "ACPL", branch="master"), "ACPL")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment