|
46 | 46 | pass |
47 | 47 |
|
48 | 48 | # program constants |
| 49 | + |
49 | 50 | APPLICATIONS_URL = "https://raw.githubusercontent.com/relic-se/Fruit_Jam_Library/refs/heads/main/database/applications.json" |
50 | 51 | METADATA_URL = "https://raw.githubusercontent.com/{:s}/refs/heads/main/metadata.json" |
51 | 52 | REPO_URL = "https://api.github.com/repos/{:s}" |
52 | 53 | ICON_URL = "https://raw.githubusercontent.com/{:s}/{:s}/{:s}" |
53 | 54 | RELEASE_URL = "https://api.github.com/repos/{:s}/releases/latest" |
54 | 55 |
|
| 56 | +MAJOR_VERSION = int(os.uname().release.split(".")[0]) |
| 57 | +VERSION_NAME = "CircuitPython {:d}.x".format(MAJOR_VERSION) |
| 58 | + |
55 | 59 | # file operations |
56 | 60 |
|
57 | 61 | def exists(path: str) -> bool: |
@@ -82,12 +86,13 @@ def rmtree(dirpath: str) -> None: |
82 | 86 | os.rmdir(dirpath) |
83 | 87 |
|
84 | 88 | def extractall(zf: ZipFile, destination: str, source: str = "") -> None: |
85 | | - for srcpath in zf: |
86 | | - if srcpath.startswith(source + "/"): |
87 | | - destpath = destination + "/" + srcpath[len(source) + 1:] |
| 89 | + for srcinfo in zf.infolist(): |
| 90 | + if not srcinfo.filename.endswith("/") and srcinfo.filename.startswith(source + "/"): |
| 91 | + destpath = destination + "/" + srcinfo.filename[len(source) + 1:] |
88 | 92 | mkdir(destpath, True) |
89 | | - with open(destpath, "wb") as f: |
90 | | - f.write(zf.read(zf[srcpath])) |
| 93 | + with open(destpath, "wb") as destfile: |
| 94 | + with zf.open(srcinfo.filename) as srcfile: |
| 95 | + destfile.write(srcfile.read()) |
91 | 96 |
|
92 | 97 | def is_app_installed(name: str) -> bool: |
93 | 98 | return exists("/sd/apps/{:s}".format(name)) |
@@ -730,33 +735,36 @@ def download_application(full_name: str = None) -> bool: |
730 | 735 | log("Installing application...") |
731 | 736 | result = False |
732 | 737 | try: |
733 | | - with open(zip_path, "rb") as f: |
734 | | - zf = ZipFile(f) |
| 738 | + with ZipFile(zip_path, "r") as zf: |
735 | 739 |
|
736 | 740 | # determine correct inner path based on CP version |
737 | | - major_version = int(os.uname().release.split(".")[0]) |
738 | | - version_name = "CircuitPython {:d}.x".format(major_version) |
739 | | - for dirpath in (repo_name + "/" + version_name, version_name, repo_name, ""): |
740 | | - try: |
741 | | - zf[(dirpath + "/code.py").strip("/")] |
742 | | - except KeyError: |
743 | | - pass |
744 | | - else: |
745 | | - break |
| 741 | + for dirpath in (repo_name + "/" + VERSION_NAME, VERSION_NAME, repo_name, "", None): |
| 742 | + if dirpath is not None: |
| 743 | + try: |
| 744 | + zf.getinfo((dirpath + "/code.py").strip("/")) |
| 745 | + except KeyError: |
| 746 | + pass |
| 747 | + else: |
| 748 | + break |
| 749 | + |
| 750 | + if dirpath is None: |
| 751 | + # try searching for code.py |
| 752 | + for info in zf.infolist(): |
| 753 | + if info.filename.split("/")[-1] == "code.py": |
| 754 | + dirpath = info.filename[:-len("code.py")].strip("/") |
| 755 | + break |
746 | 756 |
|
747 | 757 | # make sure we found code.py |
748 | | - try: |
749 | | - zf[(dirpath + "/code.py").strip("/")] |
750 | | - except KeyError: |
| 758 | + if dirpath is None: |
751 | 759 | log("Could not locate application files within release!") |
752 | 760 | else: |
753 | 761 | # extract files |
754 | 762 | extractall(zf, path, dirpath) |
755 | 763 | log("Successfully installed {:s}!".format(full_name)) |
756 | 764 | result = True |
| 765 | + |
757 | 766 | except BadZipFile as e: |
758 | 767 | log("Unable to extract and install application! {:s}".format(str(e))) |
759 | | - return False |
760 | 768 |
|
761 | 769 | # remove zip file |
762 | 770 | os.remove(zip_path) |
|
0 commit comments