Skip to content

Commit

Permalink
updater ready
Browse files Browse the repository at this point in the history
  • Loading branch information
Muddyblack committed Jan 13, 2024
1 parent 7ce4dac commit 4976dac
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 124 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ Ensure you have Python version ``3.9.2`` or higher installed.
- Execute: the ``initialize.sh`` inside the projectfolder using ``cd path/to/this_repo``

#### Update
**!!! Currently under dev and not stable yet!!!**
- To get newest repo version: ``python -m update.py --update``

#### Manual-Way-Install:
Expand Down
256 changes: 133 additions & 123 deletions update.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import os
import sys
import json
from shutil import rmtree, copy
import logging
from shutil import rmtree, move
from subprocess import call
from typing import Union
from argparse import ArgumentParser
from requests import get, exceptions


# get args
parser = ArgumentParser(description="TerminalSlideShow, use '--update'.")
parser.add_argument("--update", action="store_true", help="Update.", required=False)
Expand All @@ -19,18 +19,24 @@
)
args = parser.parse_args()

# setup
if args.debug:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)

# important settings
TEMP_FOLDER = "temp//"
dir_path = os.path.join(__file__.replace(os.path.basename(__file__), ""))
PROJECT_PATH = os.path.join(__file__.replace(os.path.basename(__file__), ""))
TEMP_DIR = PROJECT_PATH + "/" + "temp"
ignore_files = [
"LICENSE",
".gitignore",
".github",
".github/workflows",
".github/workflows/update-version-file.yml",
".pylintrc",
".unittests",
"app_config.json",
"update.py",
"black.png",
"LOGO.png",
]
repository = {
Expand All @@ -40,13 +46,55 @@
}


def download(url, action, json_decode=True) -> str:
def create_dir(path: str) -> str:
"""Create directory"""
os.mkdir(path)
logging.info(f"Directory created: {path}")

return path


def delete_dir(path: str) -> None:
"""Delete directory"""
rmtree(path)
logging.info(f"Directory deleted: {path}")


def user_permissions() -> Union[str, bool]:
"""Ask user if he wants to continue with the update."""
if not args.y:
rights = input(
"Automatic installer will download and update your program files. If you have the appropriate file, and download rights please continue by entering 'Y'. [y/N] "
)
if rights.lower() not in ["y", "yes"]:
logging.info("Exiting script...")
sys.exit(1)
return rights
return args.y


def validate(repo, specific_file="", api=False) -> str:
"""Create a link to the file in the repo.
example.com (repo) + directory = example.com/directory if API then
https://api.github.com/repos/USER/REPO/git/trees/BRANCH?recursive=1
"""
if api:
return rf'https://api.github.com/repos/{repo["name"]}/{repo["repo"]}/git/trees/{repo["branch"]}?recursive=1'
repo_link = rf'https://raw.githubusercontent.com/{repo["name"]}/{repo["repo"]}/{repo["branch"]}'
return (
f"{repo_link}{specific_file}"
if repo_link[-1] == "/"
else f"{repo_link}/{specific_file}"
)


def fetch_and_decode(url, action, json_decode=True) -> str:
"""return GET of url. action is only for exit() not anything important"""
# Attempt to downloaded_file
try:
downloaded_file = get(url, timeout=10)
except exceptions.RequestException as exc:
print(f"[UPDATER] Unable to {action}. ")
logging.info(f"[UPDATER] Unable to {action}. ")
sys.exit(exc)

# Error handling
Expand All @@ -65,186 +113,148 @@ def download(url, action, json_decode=True) -> str:
return downloaded_file.text


def validate(repo, specific_file="", api=False) -> str:
"""
example.com (repo) + directory = example.com/directory if API then
https://api.github.com/repos/USER/REPO/git/trees/BRANCH?recursive=1
"""
if api:
return rf'https://api.github.com/repos/{repo["name"]}/{repo["repo"]}/git/trees/{repo["branch"]}?recursive=1'
repo_link = rf'https://raw.githubusercontent.com/{repo["name"]}/{repo["repo"]}/{repo["branch"]}'
return (
f"{repo_link}{specific_file}"
if repo_link[-1] == "/"
else f"{repo_link}/{specific_file}"
)


def api_to_list(data) -> list:
"""GitHub API file paths to dictionary"""
stripped, files = [], []
def extract_file_paths(data) -> list:
"""Appends GitHub API file paths to dictionary if not in ignore_files"""
stripped, files, dirs = [], [], []

# strip unnecessary data
for file_path in data["tree"]:
if file_path["path"] not in ignore_files:
if not any(file_path["path"].startswith(ignore) for ignore in ignore_files):
stripped.append(file_path)

# convert useful file paths to list
# separate files and directories
for _, value in enumerate(stripped):
files.append(value["path"])

return sorted(files)


def create_dir(dir_name: str) -> str:
"""Create directory"""
path = dir_path + dir_name

# check if folder exists, if so deleted L
if os.path.isdir(path):
delete_dir(dir_name)

os.mkdir(path)
print(f"Directory created: {path}")

return path


def delete_dir(dir_name: str) -> None:
"""Delete directory"""
path = dir_path + dir_name
rmtree(path)
print(f"Directory deleted: {path}")


def user_permissions() -> Union[str, bool]:
"""Ask user if Yes or No"""
if not args.y:
rights = input(
"Automatic installer will download and update your program files. If you have the appropriate file, and download rights please continue by entering 'Y'. [y/N] "
)
if rights.lower() not in ["y", "yes"]:
print("Exiting script...")
sys.exit(1)
return rights
return args.y


def debug(statement) -> None:
"""send debug info if --debug"""
if args.debug:
print(statement)


def download_online_files(path) -> list:
"""download files from the internet superhighway"""
files = []
for file in online_files:
files.append(file)
if value["type"] == "blob":
files.append(value["path"])
elif value["type"] == "tree":
dirs.append(value["path"])

return {"files": sorted(files), "directories": sorted(dirs)}


def download_online_files(online_files, path) -> list:
"""download files from the internet world-wide-web"""
downloaded_file = []
files = online_files["files"]
folders = online_files["directories"]
for folder in folders:
os.mkdir(path + "/" + folder)
for file in files:
downloaded_file.append(file)
print(f"Attempting to download {file}.")

try:
downloaded_text = download(
downloaded_text = fetch_and_decode(
validate(repository, file), f"downloading {file}", False
)
with open(rf"{path}/{file}", "wb") as temp_file:
temp_file.write(
downloaded_text.encode(sys.stdout.encoding, errors="replace")
)
except Exception as exc: # skipcq
debug(exc)
print(
locals.debug(exc)
logging.info(
f"Failed to download {file}.\nError occurred whilst downloading files.\n"
"Before reporting this as an issue on github please run --debug and report the result."
)
delete_dir("temp")
delete_dir(TEMP_DIR)
sys.exit(1)
print(f"Successfully downloaded {file}.")
return files
logging.info(f"Successfully downloaded {file}.")
return downloaded_file


def delete_files():
def delete_files(online_files, dir_path: str = "./"):
"""Delete files"""
for file in online_files:
files = online_files["files"]
folders = online_files["directories"]
for file in files:
try:
os.remove(dir_path + file)
except FileNotFoundError:
continue


def move_temp_files():
"""move files from /temp to working directory"""
for file in online_files:
copy(dir_path + TEMP_FOLDER + file, dir_path)
def move_files_and_folders(src_dir: str, dest_dir: str):
"""Move files and folders from src_dir to dest_dir."""
for item in os.listdir(src_dir):
try:
s = os.path.join(src_dir, item)
d = os.path.join(dest_dir, item)
move(s, d)
except Exception as exc:
logging.error(exc)


def pip_install():
"""runs: pip install -r requirements.txt"""
try:
call("pip install -r requirements.txt", shell=True)
except Exception as exc: # skipcq
debug(exc)
print(
logging.debug(exc)
logging.warning(
"Pip was unable to automatically update your modules."
"\nPlease manually update your modules by using: 'pip install -r requirements.txt'."
)
return
print("Updated pip modules.")
logging.info("Updated pip modules.")


if __name__ == "__main__":
# Force users to use --update
if not args.update:
print(f"Use 'py {os.path.basename(__file__)} --update'")
logging.info("Use 'py %s --update' to update.", os.path.basename(__file__))
sys.exit(0)

# Check latest version
print("Checking latest version online.")
check_version = download(
# Check for the latest version
logging.info("Checking latest version online.")
check_version = fetch_and_decode(
validate(repository, "version.json"), "check latest version"
)
print(
f"Found a version online! Attempting to update to {check_version['version']}."
logging.info(
"Found a version online! Attempting to update to %s.", check_version["version"]
)
debug(check_version)
logging.debug(check_version)

# Get online files
print("Finding list of online files.")
online_files = api_to_list(
download(validate(repository, api=True), "check file directory")
logging.info("Finding list of online files.")
online_files = extract_file_paths(
fetch_and_decode(validate(repository, api=True), "check file directory")
)
print("Found list of online files.")
debug(online_files)
logging.info("Found list of online files.")
logging.debug(online_files)

# Check for user permissions
user_perm = user_permissions()
debug(user_perm)
logging.debug(user_perm)

# Create directory
temp_path = create_dir("temp")
# Create temp directory
# check if folder exists, if so deleted L
if os.path.isdir(TEMP_DIR):
delete_dir(TEMP_DIR)
create_dir(TEMP_DIR)

# Download all files to local device
print("Attempting to download files.")
download_online_files(temp_path)
print("Successfully downloaded files")
logging.info("Attempting to download files.")
download_online_files(online_files, TEMP_DIR)
logging.info("Successfully downloaded files")

# Delete local files
print("Deleting local files.")
delete_files()
print("Deleted local files.")
logging.info("Deleting local files.")
delete_files(online_files, PROJECT_PATH)
logging.info("Deleted local files.")

# Move files in temp to main directory
print("Moving downloaded files to local directory.")
move_temp_files()
print("Moved downloaded files to local directory.")
logging.info("Moving downloaded files to local directory.")
move_files_and_folders(TEMP_DIR, PROJECT_PATH)
logging.info("Moved downloaded files to local directory.")

# Delete downloaded/temp folder
print("Deleting temp folder.")
delete_dir("temp")
print("Deleted temp folder.")
logging.info("Deleting temp folder.")
delete_dir(TEMP_DIR)
logging.info("Deleted temp folder.")

# Updating pip
print("Updating pip modules.")
logging.info("Updating pip modules.")
pip_install()

# Finishing message
print(f"Successfully updated your script to {check_version['version']}.")
logging.info(f"Successfully updated your script to {check_version['version']}.")

0 comments on commit 4976dac

Please sign in to comment.