From 329497ace1259aca5c2860bb3becfefbfb2dd143 Mon Sep 17 00:00:00 2001 From: Grumpy Coder Date: Mon, 8 Jan 2024 09:02:47 +0000 Subject: [PATCH 1/8] Initial commit --- .gitignore | 15 +++++++++++++++ LICENSE | 9 +++++++++ README.md | 2 ++ 3 files changed, 26 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce8d4d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# ---> ArchLinuxPackages +*.tar +*.tar.* +*.jar +*.exe +*.msi +*.zip +*.tgz +*.log +*.log.* +*.sig + +pkg/ +src/ + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f4384ec --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2024 wonky + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e22b09c --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# manjaro-get-iso + From c96b1d3b6b91ce4fa35b306591e8cc49a7b4021f Mon Sep 17 00:00:00 2001 From: Frede Hundewadt Date: Mon, 8 Jan 2024 10:07:08 +0100 Subject: [PATCH 2/8] update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ce8d4d7..0566191 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ *.log *.log.* *.sig - +.idea/ pkg/ src/ From 70829f5d67189f280f7e60d7852e617dab790a9e Mon Sep 17 00:00:00 2001 From: Frede Hundewadt Date: Mon, 8 Jan 2024 10:12:10 +0100 Subject: [PATCH 3/8] merge development into wonky main --- PKGBUILD | 17 +++ get-iso | 321 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + 3 files changed, 339 insertions(+) create mode 100644 PKGBUILD create mode 100755 get-iso create mode 100644 requirements.txt diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..0d06ae7 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,17 @@ +# Maintainer: linux-aarhus + +pkgname='manjaro-get-iso' +pkgver=0.9 +pkgrel=1 +pkgdesc='A tool to download Manjaro ISO' +arch=('any') +url='https://scm.nix.dk/root/manjaro-get-iso' +licnse=('GPL') +depends=('python-requests' 'p7zip') +source=("${url}/archive/v${pkgver}.tar.gz") + +package() { + install -d m755 "$pkgdir/usr/bin" + install -m755 "$srcdir/$pkgname/get-iso" "$pkgdir/usr/bin" +} +sha256sums=('64703dadb058cdb9dc6bfa847259ad42a85a408755352e3837eb6d8187647451') diff --git a/get-iso b/get-iso new file mode 100755 index 0000000..f4ef3b5 --- /dev/null +++ b/get-iso @@ -0,0 +1,321 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# @linux-aarhus - root.nix.dk +# License: GNU GPL, version 3 or later; +import argparse +import os +import requests +import subprocess +import sys +import requests.exceptions +from pathlib import Path + +PROG_VERSION = "0.9" +PROG_NAME = os.path.basename(__file__) +ISO_RELEASE_URL = \ + "https://gitlab.manjaro.org/webpage/iso-info/-/raw/master/file-info.json" +GNU_URL = "https://www.gnu.org/licenses/gpl.html" +REL_REVIEW_URL = \ + "https://api.github.com/repos/manjaro/release-review/releases/latest" +DEV_PREVIEW_URL = \ + "https://api.github.com/repos/manjaro-edition/download/releases/latest" +review_editions = ["gnome", "plasma", "xfce"] +FOLDER = Path.home() + + +def download_file(url: str, folder_name: str) -> bool: + filename: str = url.split("/")[-1] + path = os.path.join("/{}/{}".format(folder_name, filename)) + try: + response = requests.get(url, stream=True) + total_size_in_bytes = int(response.headers.get("content-length", 0)) + block_size = 1024 + if total_size_in_bytes < block_size: + block_size = total_size_in_bytes + with open(path, "wb") as f: + progress = 0 + for data in response.iter_content(block_size): + f.write(data) + if len(data) < block_size: + progress += len(data) + else: + progress += block_size + print(f"Downloading {round(progress/1024/1024)}MiB of " + f"{round(total_size_in_bytes/1024/1024)}MiB", end="\r") + except Exception as e: + print(f"{e}") + return False + return True + + +def get_definitions(url: str) -> dict: + try: + resp = requests.get(url=url, timeout=10) + resp.raise_for_status() + return resp.json() + except Exception as e: + print("Download error", e) + print("Terminated") + sys.exit(1) + + +def init_iso_list(url: str, review: bool = False, preview: bool = False) -> list: + if preview: + return init_developer_preview_list(url) + + if review: + return init_release_review_list(url) + + return init_official_iso_list(url) + + +def init_official_iso_list(url: str) -> list: + data = get_definitions(url) + data_official: dict = data.get("official") + data_community: dict = data.get("community") + init_iso_result = [] + for ok, ov in data_official.items(): + try: + init_iso_result.append({"name": ok, + "full": { + "img": ov["image"], + "sig": ov["signature"] + }, + "minimal": { + "img": ov["minimal"]["image"], + "sig": ov["minimal"]["signature"] + } + }) + except KeyError: + continue + for ck, cv in data_community.items(): + try: + init_iso_result.append({"name": ck, + "full": { + "img": cv["image"], + "sig": cv["signature"] + }, + "minimal": { + "img": cv["minimal"]["image"], + "sig": cv["minimal"]["signature"] + }}) + except KeyError: + continue + return init_iso_result + + +def init_release_review_list(url: str) -> list: + """ + Get data from review endpoint + :param url: + :return: + """ + # from the assets list we want to extract + # the browser_download_url propoerty for each asset + init_review_result = [] + data = get_definitions(url) + data_assets: dict = data.get("assets") + review_list = [] + for asset in data_assets: + review_list.append(asset["browser_download_url"]) + + minimal = "minimal" + sha256sum = ".iso.sha256" + part = ".iso.z" + for edition in review_editions: + if edition == "plasma": + urls = [x for x in review_list if "kde" in x] + else: + urls = [x for x in review_list if edition in x] + + full_iso = [x for x in urls if minimal not in x] + minimal_iso = [x for x in urls if minimal in x] + + f_part = [x for x in full_iso if part in x] + f_256sum = [x for x in full_iso if sha256sum in x] + + m_part = [x for x in minimal_iso if part in x] + m_256sum = [x for x in minimal_iso if sha256sum in x] + + init_review_result.append({"name": edition, + "full": { + "parts": f_part, + "sha": f_256sum[0]}, + "minimal": { + "parts": m_part, + "sha": m_256sum[0]} + }) + + return init_review_result + + +def init_developer_preview_list(url: str) -> list: + """ + Get data from review endpoint + :param url: + :return: + """ + # from the assets list we want to extract + # the browser_download_url propoerty for each asset + init_devel_result = [] + + for edition in review_editions: + # replace edition in generic url + edition_url = url.replace("edition", edition) + data = get_definitions(edition_url) + data_assets: dict = data.get("assets") + dev_list = [] + for asset in data_assets: + dev_list.append(asset["browser_download_url"]) + minimal = "minimal" + sha256sum = ".iso.sha256" + part = ".iso.z" + + full_iso = [x for x in dev_list if minimal not in x] + minimal_iso = [x for x in dev_list if minimal in x] + + f_part = [x for x in full_iso if part in x] + f_256sum = [x for x in full_iso if sha256sum in x] + + m_part = [x for x in minimal_iso if part in x] + m_256sum = [x for x in minimal_iso if sha256sum in x] + + init_devel_result.append({"name": edition, + "full": { + "parts": f_part, + "sha": f_256sum[0]}, + "minimal": { + "parts": m_part, + "sha": m_256sum[0]} + }) + + return init_devel_result + + +def download(url: str, out_dir: str) -> bool: + print(f'Download: {url.split("/")[-1]}') + success = download_file(url, f"{out_dir}") + return success + + +def dir_path(path: str) -> str: + if os.path.isdir(path): + return path + else: + raise NotADirectoryError(path) + + +def main(): + out_dir = FOLDER + iso_files = init_iso_list(ISO_RELEASE_URL, review=False) + choices = [] + for c in iso_files: + choices.append(c["name"]) + parser = argparse.ArgumentParser( + prog=f"{PROG_NAME}", + description="This tool will download a named Manjaro ISO", + epilog=f"{PROG_NAME} v. {PROG_VERSION} - GPL v3 or later <{GNU_URL}>") + parser.add_argument("edition", + type=str, + help="Edition e.g. plasma or xfce.", + choices=choices) + parser.add_argument("-f", "--full", + required=False, + action="store_true", + help="Download full ISO") + parser.add_argument("-o", "--out-dir", + nargs='?', + type=dir_path, + default=FOLDER, + help="Folder to store dowloaded ISO files.") + previews = parser.add_argument_group("Previews") + preview = previews.add_mutually_exclusive_group() + preview.add_argument("-r", "--review", + required=False, + action="store_true", + help="Get Latest Release Review ISO") + preview.add_argument("-p", "--preview", + required=False, + action="store_true", + help="Get Latest Developer Preview ISO") + + args = parser.parse_args() + + if args.out_dir is not None: + out_dir = args.out_dir + + if args.review: + if args.edition in review_editions: + iso_files = init_iso_list(REL_REVIEW_URL, review=True) + else: + print("Invalid review edition. Valid editions: " + + ", ".join(review_editions)) + sys.exit(1) + + if args.preview: + if args.edition in review_editions: + iso_files = init_iso_list(DEV_PREVIEW_URL, preview=True) + else: + print("Invalid review edition. Valid editions: " + + ", ".join(review_editions)) + sys.exit(1) + + if len(iso_files) == 0: + print("Could not get iso file list") + sys.exit(1) + + try: + result = [x for x in iso_files if args.edition == x["name"]] + if args.full: + iso = result[0]["full"] + else: + iso = result[0]["minimal"] + except IndexError: + print("Could not extract edition from data") + sys.exit(1) + + if args.review or args.preview: + sha_result = download(iso["sha"], out_dir=out_dir) + shafile = iso["sha"].split("/")[-1] + isozip = [x for x in iso["parts"] if ".iso.zip" in x] + zipfile = isozip[0].split("/")[-1] + zip_result = False + for part in iso["parts"]: + zip_result = download(part, out_dir=out_dir) + if not zip_result: + break + + if zip_result and sha_result: + subprocess.run(["7z", "-y", "t", f"{zipfile}"], + cwd=f"{out_dir}") + subprocess.run(["7z", "-y", "x", f"{zipfile}"], + cwd=f"{out_dir}") + print("\nWait for checksum to complete ...") + subprocess.run(["sha256sum", "-c", f"{shafile}"], + cwd=f"{out_dir}") + else: + print("Download failied") + sys.exit(1) + + else: + iso_result = download(iso["img"], out_dir=out_dir) + sig_result = download(iso["sig"], out_dir=out_dir) + + if sig_result and iso_result: + print("Wait for verification to complete ...") + subprocess.run(["gpg", "--verify", f'{iso["sig"].split("/")[-1]}'], + cwd=f"{out_dir}") + else: + print("Download failed") + sys.exit(1) + print("Finished downloading ISO to '{}'".format(out_dir)) + sys.exit(0) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + print("\n" + "Exit: interrupted by the user.") + sys.exit(1) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..663bd1f --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +requests \ No newline at end of file From 5aad676e28906058e057bc6076a2dc528a98c109 Mon Sep 17 00:00:00 2001 From: Frede Hundewadt Date: Mon, 8 Jan 2024 10:13:58 +0100 Subject: [PATCH 4/8] updated README.md --- README.md | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e22b09c..0d99a64 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,128 @@ -# manjaro-get-iso +## Download and verify a Manjaro ISO. +The tool is a command line tool and is limited to x86 ISO but it provides a convenient way of downloading and verifying an ISO as they are listed on https://manjaro.org/download. + +Neither Sway nor ARM is supported, sway because the files is located elsewhere and ARM because there is no signature. + +The script has options to fetch the latest stable release review ISO or unstable developer previews from [Manjaro Github][github]. + +The [source][1] is free to use, and you are encouraged to clone my repo at [scm.nix.dk][2]. + +## Get started +Besides the basic Python modules - the script relies on the [Python requests][5] module and p7zip. You can check if you have p7zip installed using + + which 7z + +### Manjaro +On Manjaro you don't need to install the requests module - it is present as a dependency of pacman-mirrors. + +You may need to install p7zip depending on the result of above check + + sudo pacman -Syu p7zip + +### Other Linux +If you are using another Linux you can use requirements.txt to install the necessary dependency. + +You will also need to fetch the public key for Manjaro Build Server + + gpg --recv-keys 3B794DE6D4320FCE594F4171279E7CF5D8D56EC8 + +Use your systems package manager to install p7zip. + +### Setup +Create the folder **~/.local/bin** + + mkdir -p ~/.local/bin + +Then create a new file in this bin folder - name the file **get-iso** - then use your favorite text editor to copy paste [the code][1] into the new file. + +Make the file executable + + chmod +x ~/.local/bin/get-iso + +## Usage +``` + $ get-iso -h +usage: get-iso [-h] [-f] [-r | -d] {plasma,xfce,gnome,budgie,cinnamon,i3,mate} + +This tool will download a named Manjaro ISO + +positional arguments: + {plasma,xfce,gnome,budgie,cinnamon,i3,mate} + Edition e.g. plasma or xfce. + +options: + -h, --help show this help message and exit + -f, --full Download full ISO + -o [OUT_DIR], --out-dir [OUT_DIR] + Folder to store dowloaded ISO files. + +Previews: + -r, --review Get Latest Release Review ISO + -p, --preview Get Latest Developer Preview ISO + +get-iso v. 0.9 - GPL v3 or later + +``` +### Examples +The script defaults to pull the minimal ISO and downloaded files is placed your home folder. + +Example downloading **full mate** edition +``` +get-iso mate -f +``` +``` +Downloading: manjaro-mate-22.0-230104-linux61.iso +Downloading: manjaro-mate-22.0-230104-linux61.iso.sig +Wait for verification ... +gpg: assuming signed data in 'manjaro-mate-22.0-230104-linux61.iso' +gpg: Signature made ons 04 jan 2023 12:48:04 CET +gpg: using RSA key 3B794DE6D4320FCE594F4171279E7CF5D8D56EC8 +gpg: Good signature from "Manjaro Build Server " [unknown] +gpg: WARNING: This key is not certified with a trusted signature! +gpg: There is no indication that the signature belongs to the owner. +Primary key fingerprint: 3B79 4DE6 D432 0FCE 594F 4171 279E 7CF5 D8D5 6EC8 +``` + +Another example downloading **minimal plasma** +``` +get-iso plasma +``` +``` + $ get-iso plasma +Downloading: manjaro-kde-22.1.3-minimal-230529-linux61.iso +Downloading: manjaro-kde-22.1.3-minimal-230529-linux61.iso.sig +Wait for verification ... +gpg: assuming signed data in 'manjaro-kde-22.1.3-minimal-230529-linux61.iso' +gpg: Signature made man 29 maj 2023 11:46:55 CEST +gpg: using RSA key 3B794DE6D4320FCE594F4171279E7CF5D8D56EC8 +gpg: Good signature from "Manjaro Build Server " [unknown] +gpg: WARNING: This key is not certified with a trusted signature! +gpg: There is no indication that the signature belongs to the owner. +Primary key fingerprint: 3B79 4DE6 D432 0FCE 594F 4171 279E 7CF5 D8D5 6EC8 +``` + +## Similar tool +There is a similar tool (without release-review ISO) in the repo [**manjaro-iso-downloader**][6] with a small GUI created using yad. + +So if you are the point and click user, you can install it from the repo + + sudo pacman -Syu manjaro-iso-downloader + + +## Revision +* [date=2024-01-05 time=14:37:00 timezone="Europe/Copenhagen"] Added optional -o/--out-dir to store downloaded ISO (default is **$HOME**) +* [date=2023-12-17 time=09:17:00 timezone="Europe/Copenhagen"] Change to -p/--preview for developer preview ISO +* [date=2023-12-07 time=15:30:00 timezone="Europe/Copenhagen"] Fix plasma download +* [date=2023-12-07 time=11:00:00 timezone="Europe/Copenhagen"] Added -d/--developer for developer preview ISO +* [date=2023-12-07 time=09:00:00 timezone="Europe/Copenhagen"] Added PKGBUILD +* [date=2023-12-07 time=07:32:00 timezone="Europe/Copenhagen"] Added -r/--review for release-review + +Crossposted at https://root.nix.dk/en/utility-scripts/use-python-to-download-and-verify-manjaro-iso + + +[1]: https://forum.manjaro.org/t/root-tip-utility-script-using-python-to-download-and-verify-a-manjaro-iso/146703#the-complete-script-8 +[2]: https://scm.nix.dk/root/manjaro-get-iso +[5]: https://pypi.org/project/requests/ +[6]: https://packages.manjaro.org/?query=manjaro-iso-downloader +[github]: https://github.com/manjaro/release-review/releases/latest \ No newline at end of file From ac704e39dcd2d20544b53f2362153a495768c14a Mon Sep 17 00:00:00 2001 From: Frede Hundewadt Date: Mon, 8 Jan 2024 10:16:10 +0100 Subject: [PATCH 5/8] update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0566191..83b4436 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.log *.log.* *.sig +manjaro* .idea/ pkg/ src/ From 5a216b89e6bf5d73d2f5051cf6fb36ccd7d9931a Mon Sep 17 00:00:00 2001 From: Frede Hundewadt Date: Mon, 8 Jan 2024 10:17:19 +0100 Subject: [PATCH 6/8] update README --- README.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/README.md b/README.md index 0d99a64..eafafdc 100644 --- a/README.md +++ b/README.md @@ -109,18 +109,6 @@ So if you are the point and click user, you can install it from the repo sudo pacman -Syu manjaro-iso-downloader - -## Revision -* [date=2024-01-05 time=14:37:00 timezone="Europe/Copenhagen"] Added optional -o/--out-dir to store downloaded ISO (default is **$HOME**) -* [date=2023-12-17 time=09:17:00 timezone="Europe/Copenhagen"] Change to -p/--preview for developer preview ISO -* [date=2023-12-07 time=15:30:00 timezone="Europe/Copenhagen"] Fix plasma download -* [date=2023-12-07 time=11:00:00 timezone="Europe/Copenhagen"] Added -d/--developer for developer preview ISO -* [date=2023-12-07 time=09:00:00 timezone="Europe/Copenhagen"] Added PKGBUILD -* [date=2023-12-07 time=07:32:00 timezone="Europe/Copenhagen"] Added -r/--review for release-review - -Crossposted at https://root.nix.dk/en/utility-scripts/use-python-to-download-and-verify-manjaro-iso - - [1]: https://forum.manjaro.org/t/root-tip-utility-script-using-python-to-download-and-verify-a-manjaro-iso/146703#the-complete-script-8 [2]: https://scm.nix.dk/root/manjaro-get-iso [5]: https://pypi.org/project/requests/ From 613c367441b8ecbf7d852588fda10bc2d7503ef0 Mon Sep 17 00:00:00 2001 From: Frede Hundewadt Date: Mon, 8 Jan 2024 10:34:01 +0100 Subject: [PATCH 7/8] update PKGBUILD --- PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 0d06ae7..2567222 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -5,7 +5,7 @@ pkgver=0.9 pkgrel=1 pkgdesc='A tool to download Manjaro ISO' arch=('any') -url='https://scm.nix.dk/root/manjaro-get-iso' +url='https://codeberg.org/wonky/manjaro-get-iso' licnse=('GPL') depends=('python-requests' 'p7zip') source=("${url}/archive/v${pkgver}.tar.gz") @@ -14,4 +14,4 @@ package() { install -d m755 "$pkgdir/usr/bin" install -m755 "$srcdir/$pkgname/get-iso" "$pkgdir/usr/bin" } -sha256sums=('64703dadb058cdb9dc6bfa847259ad42a85a408755352e3837eb6d8187647451') +sha256sums=('db5322f6dbc86cbe0139deb6c232c7054385d0ebd2d22708eeceb818718b5dad') From 516894a57dbcc3d88e35dd53e7560a09d671a515 Mon Sep 17 00:00:00 2001 From: Frede Hundewadt Date: Thu, 22 Feb 2024 07:06:46 +0100 Subject: [PATCH 8/8] change url to manjaro gitlab --- PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKGBUILD b/PKGBUILD index 2567222..d8ec7cd 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -5,7 +5,7 @@ pkgver=0.9 pkgrel=1 pkgdesc='A tool to download Manjaro ISO' arch=('any') -url='https://codeberg.org/wonky/manjaro-get-iso' +url='https://gitlab.manjaro.org/manjaro-get-iso' licnse=('GPL') depends=('python-requests' 'p7zip') source=("${url}/archive/v${pkgver}.tar.gz")