diff options
| author | huker667 <huker@tuta.io> | 2026-05-10 09:51:20 +0300 |
|---|---|---|
| committer | huker667 <huker@tuta.io> | 2026-05-10 09:51:20 +0300 |
| commit | e9046a96f1edd2d52594785998d90a14d10a5803 (patch) | |
| tree | b2a0119be219839dff66d07e638a6775a568b0eb /package.py | |
| download | qulay-master.tar.gz qulay-master.tar.bz2 qulay-master.zip | |
init commit v0.7master
Diffstat (limited to 'package.py')
| -rw-r--r-- | package.py | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/package.py b/package.py new file mode 100644 index 0000000..2667c7d --- /dev/null +++ b/package.py @@ -0,0 +1,249 @@ +import os +import sys +import tarfile +import shutil +import tempfile +import subprocess +import urllib.request +from urllib.parse import urlsplit, urlunsplit + +from logs import info, warn, error +from paths import TMP_DIR, CACHE_DIR, REPOS_DIR +from pathlib import Path +from uzbekdb import database +from database import ( + download_repos, + get_repos_urls, + install_package, + remove_package, + is_installed, +) + + +_NAME = os.path.basename(sys.argv[0]) + + +def _random_tmp_dir(tmp_dir=TMP_DIR): + return tempfile.mkdtemp(prefix="qulay_", dir=tmp_dir) + + +def _download(url, dest): + try: + urllib.request.urlretrieve(url, dest) + except Exception as e: + return e + else: + return 1 + return 0 + + +def _extract(archive, dest): + with tarfile.open(archive) as tar: + tar.extractall(dest) + + +def _read_depends(path): + depends_file = os.path.join(path, "depends.uz") + if not os.path.exists(depends_file): + return [] + with open(depends_file) as f: + return [line.strip() for line in f if line.strip()] + + +def _check_pkg_structure(path): + required = ["install.sh", "remove.sh"] + for file in required: + if not os.path.exists(os.path.join(path, file)): + error("!! package is corrupted", True) + + +def _get_packages(dest_dir="/"): + found = [] + packages_path = os.path.join(dest_dir, REPOS_DIR.lstrip(os.sep)) + for repo_name in os.listdir(packages_path): + repo_path = os.path.join(packages_path, repo_name) + if os.path.isdir(repo_path): + pkgs_file = os.path.join(repo_path, "pkgs.uz") + if os.path.exists(pkgs_file): + try: + with open(pkgs_file, "r", encoding="utf-8") as f: + pkgs_data = database.loads(f.read()) + for name, data in pkgs_data.items(): + found.append({ + "name": name, + "repo": repo_name, + "data": data + }) + except Exception: + continue + return found + + +def _find_package(name, dest_dir="/"): + found = [] + packages_path = os.path.join(dest_dir, REPOS_DIR.lstrip(os.sep)) + + if not os.path.exists(packages_path): + return "-n" + + for repo_name in os.listdir(packages_path): + repo_path = os.path.join(packages_path, repo_name) + if os.path.isdir(repo_path): + pkgs_file = os.path.join(repo_path, "pkgs.uz") + if os.path.exists(pkgs_file): + try: + with open(pkgs_file, "r", encoding="utf-8") as f: + pkgs_data = database.loads(f.read()) + + if isinstance(pkgs_data, dict) and name in pkgs_data: + found.append({ + "name": name, + "repo": repo_name, + "data": pkgs_data[name] + }) + except Exception: + continue + + if not found: + return None + # if len(found) > 1: + # return "-r" + + return found + + +def _find_repo_package(result, repo, name): + for pkg in result: + if pkg["repo"] == repo: + return pkg + return None + + +def install(name, args=[], dest_dir="/"): + # verbose=False, ask=False, reinstall=False, disable_logs=False, disable_deps=False + verbose = ":v" in args + ask = ":a" in args + reinstall = ":r" in args + disable_logs = ":nl" in args + disable_deps = ":nd" in args + + if "/" in name: + parts = name.split("/", 1) + repo_name = parts[0] + name = parts[1] + + pkg = _find_repo_package(_find_package(name), repo_name, name) + + if not pkg: + error(f"!! package {name} not found in {repo_name}", True, disable_logs) + return 1 + + pkg_data = pkg["data"] + version = pkg_data[1] + else: + result = _find_package(name) + if not result: + error(f"!! package {name} not found", True, disable_logs) + return 1 + + if len(result) > 1: + error(f"!! {len(result)} same pkgs found in different repos:", True, disable_logs) + for pkg in result: + print(f" {pkg['repo']}/{pkg['name']} - {pkg['data'][0]} - {pkg['data'][1]}") + return 1 + + repo_name = result[0]["repo"] + pkg_data = result[0]["data"] + + version = pkg_data[1] + + pkg_path = os.path.join(dest_dir, REPOS_DIR.lstrip(os.sep), f"{repo_name}/packages/{name}") + + if ask: + download_answer = input( + f"-> confirm installing '{name}' with version {version} [Y/n]: " + ).strip().lower() + + if download_answer not in ("y", "yes", ""): + sys.exit(0) + + # -- install depends -- + depends = _read_depends(pkg_path) + if not disable_deps: + for dep in depends: + if not is_installed(dep) or reinstall: + # -- copy args to dep install -- + install(dep, args, dest_dir=dest_dir) + + # -- run install.sh -- + try: + subprocess.run( + ["sh", "install.sh"], + cwd=pkg_path, + check=True, + env=os.environ + ) + except Exception as e: + error(f"!! {e}", True, disable_logs) + return 0 + + if not disable_logs: + install_package(f"{repo_name}/{name}", version, dest_dir=dest_dir) + + info(f":: {name} installed successfully", True, disable_logs) + + +def remove(name, args=[], dest_dir="/"): + verbose = ":v" in args + ask = ":a" in args + disable_logs = ":nl" in args + # disable_deps = "/nd" in args + + if "/" in name: + parts = name.split("/", 1) + repo_name = parts[0] + name = parts[1] + + pkg = _find_repo_package(_find_package(name), repo_name, name) + + if not pkg: + error(f"!! package {name} not found in {repo_name}", True, disable_logs) + return 1 + + pkg_data = pkg["data"] + version = pkg_data[1] + else: + result = _find_package(name) + if not result: + error(f"!! package {name} not found", True, disable_logs) + return 1 + + if len(result) > 1: + error(f"!! {len(result)} same pkgs found in different repos:", True, disable_logs) + for pkg in result: + print(f" {pkg['repo']}/{pkg['name']} - {pkg['data'][0]} - {pkg['data'][1]}") + return 1 + + repo_name = result[0]["repo"] + pkg_data = result[0]["data"] + + version = pkg_data[1] + + # -- super uzbek package remover da -- + pkg_path = os.path.join(dest_dir, REPOS_DIR.lstrip(os.sep), f"{repo_name}/packages/{name}") + + try: + subprocess.run( + ["sh", "remove.sh"], + cwd=pkg_path, + check=True, + env=os.environ + ) + except Exception as e: + error(f"!! {e}", True, disable_logs) + return 0 + + if not disable_logs: + remove_package(f"{repo_name}/{name}", dest_dir=dest_dir) + + info(f":: {name} removed successfully", True, disable_logs) |