diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4d3fbad --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +/venv +/build +__pycache__ +.mypy_cache +*.xml diff --git a/.gitignore b/.gitignore index 68c1c72..5263a53 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ *.kate-swp -venv/ +/venv +/build __pycache__/ .coverage* *.xml +*.egg-info +dist diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b1c0fa1..5c1feb2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,15 +7,19 @@ format: stage: check image: python before_script: - - pip install yapf autoflake --break-system-packages + - python3 -m venv venv + - venv/bin/pip3 install yapf autoflake script: + - source venv/bin/activate - ./format.sh --check typecheck: stage: check image: python before_script: - - pip install mypy --break-system-packages + - python3 -m venv venv + - source venv/bin/activate + - pip install mypy script: - ./typecheck.sh --non-interactive --junit-xml mypy-report.xml artifacts: @@ -27,12 +31,13 @@ pytest: image: archlinux before_script: - pacman -Sy --noconfirm --needed archlinux-keyring && pacman -Su --noconfirm python python-pip sudo git base-devel arch-install-scripts rsync - - pip install -r test_requirements.txt -r requirements.txt --break-system-packages + - python3 -m venv venv + - venv/bin/pip3 install -r test_requirements.txt -r requirements.txt - 'echo "kupfer ALL = (ALL) NOPASSWD: ALL" > /etc/sudoers.d/kupfer_all' - useradd -m kupfer - chmod 777 . script: - - script -e -c 'su kupfer -s /bin/bash -c "INTEGRATION_TESTS_USE_GLOBAL_CONFIG=TRUE KUPFERBOOTSTRAP_WRAPPED=DOCKER ./pytest.sh --junit-xml=pytest-report.xml --cov-report=xml:coverage.xml integration_tests.py"' + - script -e -c 'su kupfer -s /bin/bash -c ". venv/bin/activate && INTEGRATION_TESTS_USE_GLOBAL_CONFIG=TRUE KUPFERBOOTSTRAP_WRAPPED=DOCKER ./pytest.sh --junit-xml=pytest-report.xml --cov-report=xml:coverage.xml integration_tests.py"' coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/' artifacts: reports: @@ -51,6 +56,7 @@ build_docker: DOCKER_TLS_CERTDIR: "" script: - 'docker build --pull -t "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}" -t "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}" .' + - 'echo "running sanity check" && docker run -it --rm "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}" kupferbootstrap --help' only: - branches except: @@ -77,7 +83,9 @@ push_docker: DOCS_MAKE_TARGET: "html" DOCS_MAKE_THREADS: 6 before_script: &docs_before_script - - pip install -r requirements.txt -r docs/requirements.txt --break-system-packages + - python3 -m venv venv + - source venv/bin/activate + - pip install -r requirements.txt -r docs/requirements.txt script: &docs_script - make -C docs -j$DOCS_MAKE_THREADS SPHINXARGS="$DOCS_SPHINXARGS" $DOCS_MAKE_TARGET - mv "docs/$DOCS_MAKE_TARGET" public diff --git a/Dockerfile b/Dockerfile index 5289aa1..ced9696 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,16 +17,14 @@ RUN yes | pacman -Scc RUN sed -i "s/SigLevel.*/SigLevel = Never/g" /etc/pacman.conf ENV KUPFERBOOTSTRAP_WRAPPED=DOCKER -ENV PATH=/app/bin:/app/local/bin:$PATH +ENV PATH=/app/bin:/app/local/bin:/app/venv/bin:$PATH WORKDIR /app -COPY requirements.txt . -# TODO: pip packaging so we don't need --break-system-packages -RUN pip install -r requirements.txt --break-system-packages - COPY . . +RUN python3 -m venv /app/venv +RUN /app/venv/bin/pip3 install -r requirements.txt -RUN python -c "from distro import distro; distro.get_kupfer_local(arch=None,in_chroot=False).repos_config_snippet()" | tee -a /etc/pacman.conf +RUN /app/venv/bin/python3 -c "from kupferbootstrap.distro import distro; distro.get_kupfer_local(arch=None,in_chroot=False).repos_config_snippet()" | tee -a /etc/pacman.conf RUN useradd -m -g users kupfer RUN echo "kupfer ALL=(ALL) NOPASSWD: ALL" | tee /etc/sudoers.d/kupfer diff --git a/README.md b/README.md index 61e6949..36866f1 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,26 @@ This will run a webserver on localhost:9999. Access it like `firefox http://loca ## Installation -Install Docker, Python 3 with the libraries from `requirements.txt` and put `bin/` into your `PATH`. -Then use `kupferbootstrap`. +0. If you're not on ArchLinux (i.e. don't have `pacman`, `makepkg`, etc. available in your $PATH), install Docker and add yourself to the docker group. +1. Craate a python venv: `python3 -m venv venv` +1. Activate it: `source venv/bin/activate` +1. Install KBS: `pip3 install .` + +Then run `kupferbootstrap`. + +### Pro Tip: + +- You can add a shell alias for `$(PWD)/venv/bin/kupferbootstrap` or create a symlink to it at `/usr/local/bin/kuperbootstrap` for quick access without needing to manually source the venv script every time. +- It is recommended to abbreviate `kupferbootstrap` to `kbs` for even less typing. ## Quickstart 1. Initialize config with defaults, configure your device and flavour: `kupferbootstrap config init` +1. Initialize PKGBUILDs and caches: `kupferbootstrap packages init` 1. Build an image and packages along the way: `kupferbootstrap image build` ## Development -Put `dev` into `version.txt` to always rebuild kupferboostrap from this directory and use `kupferbootstrap` as normal. + +### Docker +Put `BUILD` (the default) into `docker_version.txt` to always rebuild kupferboostrap from this directory; otherwise the image is pulled from `registry.gitlab.com/kupfer/kupferbootstrap:$VERSION`, where `$VERSION` is the contents of `docker_version.txt`. diff --git a/bin/kupferbootstrap b/bin/kupferbootstrap deleted file mode 100755 index 0744f9e..0000000 --- a/bin/kupferbootstrap +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -# shellcheck disable=SC2068 -python3 "$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")/main.py" $@ diff --git a/docker_version.txt b/docker_version.txt new file mode 100644 index 0000000..89620f3 --- /dev/null +++ b/docker_version.txt @@ -0,0 +1 @@ +BUILD diff --git a/docs/.gitignore b/docs/.gitignore index 5d14997..b0fd27d 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -2,6 +2,7 @@ .doctrees html source/cli +source/code checkouts versions archived diff --git a/docs/Makefile b/docs/Makefile index 7255957..48a3aee 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -14,7 +14,7 @@ cleanbuild: @$(MAKE) html clean: - rm -rf html source/cli .buildinfo .doctrees versions checkouts + rm -rf html source/cli source/code .buildinfo .doctrees versions checkouts html: sphinx-build $(SPHINXARGS) $(buildargs) html diff --git a/docs/source/cli.md b/docs/source/cli.md index 53847fb..eb08e1f 100644 --- a/docs/source/cli.md +++ b/docs/source/cli.md @@ -1,7 +1,7 @@ # CLI Interface ```{eval-rst} -.. click:: main:cli +.. click:: kupferbootstrap.main:cli :nested: none :prog: kupferbootstrap diff --git a/docs/source/cmd.md b/docs/source/cmd.md index 646372d..976d4eb 100644 --- a/docs/source/cmd.md +++ b/docs/source/cmd.md @@ -6,6 +6,7 @@ orphan: true only used to trigger builds of the submodule docs! ```{eval-rst} +.. currentmodule:: kupferbootstrap .. autosummary:: :toctree: cli :template: command.rst diff --git a/docs/source/code.md b/docs/source/code.md new file mode 100644 index 0000000..fb15e4a --- /dev/null +++ b/docs/source/code.md @@ -0,0 +1,9 @@ +# Code + +Code documentation is available here + +```{toctree} +:glob: true + +code/kupferbootstrap +``` diff --git a/docs/source/codegen.rst b/docs/source/codegen.rst new file mode 100644 index 0000000..13a4cc5 --- /dev/null +++ b/docs/source/codegen.rst @@ -0,0 +1,8 @@ +:nosearch: +:orphan: + +.. autosummary:: + :toctree: code + :recursive: + + kupferbootstrap diff --git a/docs/source/conf.py b/docs/source/conf.py index fe0dc90..6ab8a57 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,10 +1,14 @@ +import logging import os -import sys +from sphinx.config import getenv +from kupferbootstrap.utils import git -sys.path.insert(0, os.path.abspath('../..')) +#sys.path.insert(0, os.path.abspath('../..')) extensions = [ 'sphinx_click', - 'sphinx.ext.autosummary', # Create neat summary tables + "sphinx.ext.autodoc", + 'sphinx.ext.autosummary', + "sphinx.ext.linkcode", 'myst_parser' ] myst_all_links_external = True @@ -29,4 +33,45 @@ html_theme_options = { "color-brand-content": "#eba38d", "color-problematic": "#ff7564", }, + "source_repository": "https://gitlab.com/kupfer/kupferbootstrap", + "source_directory": "docs/source/", } + + +autosummary_generate = True +autodoc_default_options = { + "members": True, + "undoc-members": True, + "show-inheritance": True, + "inherited-members": True, +} +autodoc_preserve_defaults = True + + +def get_version(): + try: + res = git( + ["rev-parse", "HEAD"], + dir=os.path.join(os.path.dirname(__file__), "../.."), + use_git_dir=True, + capture_output=True, + ) + res.check_returncode() + ver = res.stdout.decode().strip() + logging.info(f"Detected git {ver=}") + return ver + except Exception as ex: + logging.warning("Couldn't get git branch:", exc_info=ex) + return "HEAD" + + +version = getenv("version") or get_version() + + +def linkcode_resolve(domain, info): + if domain != 'py': + return None + if not info['module']: + return None + filename = info['module'].replace('.', '/') + return "%s/-/blob/%s/src/%s.py" % (html_theme_options["source_repository"], version, filename) diff --git a/docs/source/genindex.rst b/docs/source/genindex.rst new file mode 100644 index 0000000..f6c180c --- /dev/null +++ b/docs/source/genindex.rst @@ -0,0 +1,2 @@ +Module Index +============ diff --git a/docs/source/index.md b/docs/source/index.md index 2cde0d6..df03035 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -8,4 +8,6 @@ a tool to build and flash packages and images for the [Kupfer](https://gitlab.co ```{toctree} usage/index cli +code +genindex ``` diff --git a/docs/source/templates/code.rst b/docs/source/templates/code.rst new file mode 100644 index 0000000..fb116ef --- /dev/null +++ b/docs/source/templates/code.rst @@ -0,0 +1,36 @@ +{% set reduced_name = fullname.split(".", 1)[-1] if fullname.startswith("kupferbootstrap.") else fullname %} + +{{ fullname | escape | underline }} + +.. rubric:: Description + +.. automodule:: {{ fullname }} + :members: + :undoc-members: + +.. currentmodule:: {{ fullname }} + + + + +{% if classes %} +.. rubric:: Classes + +.. autosummary:: + :toctree: . + {% for class in classes %} + {{ class }} + {% endfor %} + +{% endif %} + +{% if functions %} +.. rubric:: Functions + +.. autosummary:: + :toctree: . + {% for function in functions %} + {{ function }} + {% endfor %} + +{% endif %} diff --git a/docs/source/templates/command.rst b/docs/source/templates/command.rst index 977c023..da9a9ec 100644 --- a/docs/source/templates/command.rst +++ b/docs/source/templates/command.rst @@ -1,6 +1,9 @@ -.. title: {{fullname}} +{% set reduced_name = fullname.split(".", 1)[-1] if fullname.startswith("kupferbootstrap.") else fullname %} +.. title: {{reduced_name}} -.. click:: {% if fullname == 'main' %}main:cli{% else %}{{fullname}}.cli:cmd_{{fullname}}{% endif %} - :prog: kupferbootstrap {{fullname}} + +.. currentmodule:: {{ fullname }} +.. click:: {% if fullname == 'main' %}kupferbootstrap.main:cli{% else %}{{fullname}}.cli:cmd_{{reduced_name}}{% endif %} + :prog: kupferbootstrap {{reduced_name}} :nested: full diff --git a/format.sh b/format.sh index 6860c4e..9f0fbe9 100755 --- a/format.sh +++ b/format.sh @@ -6,7 +6,7 @@ autoflake_args=('--recursive' '--remove-unused-variables' '--remove-all-unused-i format() { files=("$@") if [[ -z "${files[*]}" ]]; then - files=(".") + files=(*.py "src") fi yapf "${yapf_args[@]}" "${files[@]}" diff --git a/integration_tests.py b/integration_tests.py index bc4eeb7..dd17702 100644 --- a/integration_tests.py +++ b/integration_tests.py @@ -5,13 +5,13 @@ import pytest from glob import glob from subprocess import CompletedProcess -from config.state import config, CONFIG_DEFAULTS -from constants import SRCINFO_METADATA_FILE -from exec.cmd import run_cmd -from exec.file import get_temp_dir -from logger import setup_logging -from packages.cli import SRCINFO_CACHE_FILES, cmd_build, cmd_clean, cmd_init, cmd_update -from utils import git_get_branch +from kupferbootstrap.config.state import config, CONFIG_DEFAULTS +from kupferbootstrap.constants import SRCINFO_METADATA_FILE +from kupferbootstrap.exec.cmd import run_cmd +from kupferbootstrap.exec.file import get_temp_dir +from kupferbootstrap.logger import setup_logging +from kupferbootstrap.packages.cli import SRCINFO_CACHE_FILES, cmd_build, cmd_clean, cmd_init, cmd_update +from kupferbootstrap.utils import git_get_branch tempdir = None config.try_load_file() @@ -38,7 +38,7 @@ def ctx() -> click.Context: def test_main_import(): - from main import cli + from kupferbootstrap.main import cli assert cli @@ -52,7 +52,8 @@ def test_config_load(ctx: click.Context): def test_packages_update(ctx: click.Context): pkgbuilds_path = config.get_path('pkgbuilds') - kbs_branch = git_get_branch(config.runtime.script_source_dir) + assert config.runtime.script_source_dir + kbs_branch = git_get_branch(os.path.join(config.runtime.script_source_dir, "../..")) # Gitlab CI integration: the CI checks out a detached commit, branch comes back empty. if not kbs_branch and os.environ.get('CI', 'false') == 'true': kbs_branch = os.environ.get('CI_COMMIT_BRANCH', '') diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f703eb4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,29 @@ +[project] +name = "kupferbootstrap" +dependencies = [ + "click>=8.0.1", + "appdirs>=1.4.4", + "joblib>=1.0.1", + "toml", + "typing_extensions", + "coloredlogs", + "munch", + "requests", + "python-dateutil", + "enlighten", + "PyYAML", +] +dynamic = ["version"] + +[project.scripts] +kupferbootstrap = "kupferbootstrap.main:main" + +[tool.setuptools.package-data] +"*" = ["version.txt"] + +[build-system] +requires = [ "setuptools>=41", "wheel", "setuptools-git-versioning<2", ] +build-backend = "setuptools.build_meta" + +[tool.setuptools-git-versioning] +enabled = true diff --git a/pytest.sh b/pytest.sh index d305774..544b319 100755 --- a/pytest.sh +++ b/pytest.sh @@ -1,4 +1,4 @@ #!/bin/bash sudo -v -python -m pytest -v --cov=. --cov-branch --cov-report=term "$@" ./*/test_*.py +python -m pytest -v --cov=. --cov-branch --cov-report=term "$@" src/kupferbootstrap diff --git a/requirements.txt b/requirements.txt index df53ed4..d6e1198 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1 @@ -click>=8.0.1 -appdirs>=1.4.4 -joblib>=1.0.1 -toml -typing_extensions -coloredlogs -munch -setuptools # required by munch -requests -python-dateutil -enlighten -PyYAML +-e . diff --git a/binfmt/__init__.py b/src/kupferbootstrap/__init__.py similarity index 100% rename from binfmt/__init__.py rename to src/kupferbootstrap/__init__.py diff --git a/cache/__init__.py b/src/kupferbootstrap/binfmt/__init__.py similarity index 100% rename from cache/__init__.py rename to src/kupferbootstrap/binfmt/__init__.py diff --git a/binfmt/binfmt.py b/src/kupferbootstrap/binfmt/binfmt.py similarity index 95% rename from binfmt/binfmt.py rename to src/kupferbootstrap/binfmt/binfmt.py index bccd93b..d5d263d 100644 --- a/binfmt/binfmt.py +++ b/src/kupferbootstrap/binfmt/binfmt.py @@ -5,10 +5,10 @@ import logging from typing import Optional -from chroot.abstract import Chroot -from constants import Arch, QEMU_ARCHES -from exec.cmd import run_root_cmd, CompletedProcess -from utils import mount +from kupferbootstrap.chroot.abstract import Chroot +from kupferbootstrap.constants import Arch, QEMU_ARCHES +from kupferbootstrap.exec.cmd import run_root_cmd, CompletedProcess +from kupferbootstrap.utils import mount def binfmt_info(chroot: Optional[Chroot] = None): diff --git a/binfmt/cli.py b/src/kupferbootstrap/binfmt/cli.py similarity index 93% rename from binfmt/cli.py rename to src/kupferbootstrap/binfmt/cli.py index 134a966..fd33bbe 100644 --- a/binfmt/cli.py +++ b/src/kupferbootstrap/binfmt/cli.py @@ -3,7 +3,7 @@ import os from typing import Optional -from constants import Arch, ARCHES +from kupferbootstrap.constants import Arch, ARCHES from .binfmt import binfmt_unregister, binfmt_is_registered @@ -15,7 +15,7 @@ arches_arg_optional = click.argument('arches', type=click.Choice(ARCHES), nargs= @cmd_binfmt.command('register', help='Register a binfmt handler with the kernel') @arches_arg def cmd_register(arches: list[Arch], disable_chroot: bool = False): - from packages.build import build_enable_qemu_binfmt + from ..packages.build import build_enable_qemu_binfmt for arch in arches: build_enable_qemu_binfmt(arch) diff --git a/chroot/__init__.py b/src/kupferbootstrap/cache/__init__.py similarity index 100% rename from chroot/__init__.py rename to src/kupferbootstrap/cache/__init__.py diff --git a/cache/cli.py b/src/kupferbootstrap/cache/cli.py similarity index 86% rename from cache/cli.py rename to src/kupferbootstrap/cache/cli.py index 1930a22..1eedc9a 100644 --- a/cache/cli.py +++ b/src/kupferbootstrap/cache/cli.py @@ -2,11 +2,11 @@ import click import os import logging -from config.state import config -from constants import CHROOT_PATHS -from exec.file import remove_file -from packages.cli import cmd_clean as cmd_clean_pkgbuilds -from wrapper import enforce_wrap +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import CHROOT_PATHS +from kupferbootstrap.exec.file import remove_file +from kupferbootstrap.packages.cli import cmd_clean as cmd_clean_pkgbuilds +from kupferbootstrap.wrapper import enforce_wrap PATHS = list(CHROOT_PATHS.keys()) diff --git a/config/__init__.py b/src/kupferbootstrap/chroot/__init__.py similarity index 100% rename from config/__init__.py rename to src/kupferbootstrap/chroot/__init__.py diff --git a/chroot/abstract.py b/src/kupferbootstrap/chroot/abstract.py similarity index 96% rename from chroot/abstract.py rename to src/kupferbootstrap/chroot/abstract.py index ffef4a6..d01db77 100644 --- a/chroot/abstract.py +++ b/src/kupferbootstrap/chroot/abstract.py @@ -9,13 +9,13 @@ from shlex import quote as shell_quote from typing import ClassVar, Iterable, Protocol, Union, Optional, Mapping from uuid import uuid4 -from config.state import config -from constants import Arch, CHROOT_PATHS, GCC_HOSTSPECS -from distro.distro import get_base_distro, get_kupfer_local, RepoInfo -from exec.cmd import FileDescriptor, run_root_cmd, generate_env_cmd, flatten_shell_script, wrap_in_bash, generate_cmd_su -from exec.file import makedir, root_makedir, root_write_file, write_file -from generator import generate_makepkg_conf -from utils import mount, umount, check_findmnt, log_or_exception +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import Arch, CHROOT_PATHS, GCC_HOSTSPECS +from kupferbootstrap.distro.distro import get_base_distro, get_kupfer_local, RepoInfo +from kupferbootstrap.exec.cmd import FileDescriptor, run_root_cmd, generate_env_cmd, flatten_shell_script, wrap_in_bash, generate_cmd_su +from kupferbootstrap.exec.file import makedir, root_makedir, root_write_file, write_file +from kupferbootstrap.generator import generate_makepkg_conf +from kupferbootstrap.utils import mount, umount, check_findmnt, log_or_exception from .helpers import BASE_CHROOT_PREFIX, BASIC_MOUNTS, base_chroot_name, make_abs_path diff --git a/chroot/base.py b/src/kupferbootstrap/chroot/base.py similarity index 88% rename from chroot/base.py rename to src/kupferbootstrap/chroot/base.py index 93b07e7..1d4bedb 100644 --- a/chroot/base.py +++ b/src/kupferbootstrap/chroot/base.py @@ -6,10 +6,10 @@ from glob import glob from shutil import rmtree from typing import ClassVar -from constants import Arch -from exec.cmd import run_root_cmd -from exec.file import makedir, root_makedir -from config.state import config +from kupferbootstrap.constants import Arch +from kupferbootstrap.exec.cmd import run_root_cmd +from kupferbootstrap.exec.file import makedir, root_makedir +from kupferbootstrap.config.state import config from .abstract import Chroot, get_chroot from .helpers import base_chroot_name diff --git a/chroot/build.py b/src/kupferbootstrap/chroot/build.py similarity index 95% rename from chroot/build.py rename to src/kupferbootstrap/chroot/build.py index 40b123d..745dd0c 100644 --- a/chroot/build.py +++ b/src/kupferbootstrap/chroot/build.py @@ -4,11 +4,11 @@ import subprocess from glob import glob from typing import ClassVar, Optional -from config.state import config -from constants import Arch, GCC_HOSTSPECS, CROSSDIRECT_PKGS, CHROOT_PATHS -from distro.distro import get_kupfer_local -from exec.cmd import run_root_cmd -from exec.file import makedir, remove_file, root_makedir, root_write_file, symlink +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import Arch, GCC_HOSTSPECS, CROSSDIRECT_PKGS, CHROOT_PATHS +from kupferbootstrap.distro.distro import get_kupfer_local +from kupferbootstrap.exec.cmd import run_root_cmd +from kupferbootstrap.exec.file import makedir, remove_file, root_makedir, root_write_file, symlink from .abstract import Chroot, get_chroot from .helpers import build_chroot_name diff --git a/chroot/cli.py b/src/kupferbootstrap/chroot/cli.py similarity index 90% rename from chroot/cli.py rename to src/kupferbootstrap/chroot/cli.py index 0a99f48..187cc06 100644 --- a/chroot/cli.py +++ b/src/kupferbootstrap/chroot/cli.py @@ -4,9 +4,9 @@ import os from typing import Optional -from config.state import config -from wrapper import enforce_wrap -from devices.device import get_profile_device +from kupferbootstrap.config.state import config +from kupferbootstrap.wrapper import enforce_wrap +from kupferbootstrap.devices.device import get_profile_device from .abstract import Chroot from .base import get_base_chroot @@ -30,7 +30,7 @@ def cmd_chroot(ctx: click.Context, type: str = 'build', name: Optional[str] = No raise Exception(f'Unknown chroot type: "{type}"') if type == 'rootfs': - from image.image import cmd_inspect + from ..image.image import cmd_inspect assert isinstance(cmd_inspect, click.Command) ctx.invoke(cmd_inspect, profile=name, shell=True) return diff --git a/chroot/device.py b/src/kupferbootstrap/chroot/device.py similarity index 79% rename from chroot/device.py rename to src/kupferbootstrap/chroot/device.py index bd04467..56de30b 100644 --- a/chroot/device.py +++ b/src/kupferbootstrap/chroot/device.py @@ -1,14 +1,14 @@ import atexit import os -from typing import ClassVar, Optional +from typing import ClassVar, Optional, cast -from config.state import config -from constants import Arch, BASE_PACKAGES -from distro.repo import RepoInfo -from distro.distro import get_kupfer_local, get_kupfer_https -from exec.file import get_temp_dir, makedir, root_makedir -from utils import check_findmnt +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import Arch, BASE_PACKAGES +from kupferbootstrap.distro.repo import RepoInfo +from kupferbootstrap.distro.distro import get_kupfer_local, get_kupfer_https +from kupferbootstrap.exec.file import get_temp_dir, makedir, root_makedir +from kupferbootstrap.utils import check_findmnt from .base import BaseChroot from .build import BuildChroot @@ -20,15 +20,14 @@ class DeviceChroot(BuildChroot): _copy_base: ClassVar[bool] = False def create_rootfs(self, reset, pacman_conf_target, active_previously): - clss = BuildChroot if self.copy_base else BaseChroot - makedir(config.get_path('chroots')) root_makedir(self.get_path()) if not self.copy_base: pacman_conf_target = os.path.join(get_temp_dir(register_cleanup=True), f'pacman-{self.name}.conf') self.write_pacman_conf(in_chroot=False, absolute_path=pacman_conf_target) - - clss.create_rootfs(self, reset, pacman_conf_target, active_previously) + BaseChroot.create_rootfs(cast(BaseChroot, self), reset, pacman_conf_target, active_previously) + else: + BuildChroot.create_rootfs(self, reset, pacman_conf_target, active_previously) def mount_rootfs(self, source_path: str, fs_type: Optional[str] = None, options: list[str] = [], allow_overlay: bool = False): if self.active: diff --git a/chroot/helpers.py b/src/kupferbootstrap/chroot/helpers.py similarity index 94% rename from chroot/helpers.py rename to src/kupferbootstrap/chroot/helpers.py index da7b1a1..18bb982 100644 --- a/chroot/helpers.py +++ b/src/kupferbootstrap/chroot/helpers.py @@ -1,8 +1,8 @@ import os from typing import Optional, TypedDict -from config.state import config -from constants import Arch +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import Arch BIND_BUILD_DIRS = 'BINDBUILDDIRS' BASE_CHROOT_PREFIX = 'base_' diff --git a/devices/__init__.py b/src/kupferbootstrap/config/__init__.py similarity index 100% rename from devices/__init__.py rename to src/kupferbootstrap/config/__init__.py diff --git a/config/cli.py b/src/kupferbootstrap/config/cli.py similarity index 97% rename from config/cli.py rename to src/kupferbootstrap/config/cli.py index 740ab17..0204ad3 100644 --- a/config/cli.py +++ b/src/kupferbootstrap/config/cli.py @@ -4,10 +4,10 @@ import logging from copy import deepcopy from typing import Any, Callable, Iterable, Mapping, Optional, Union -from devices.device import get_devices, sanitize_device_name -from flavours.flavour import get_flavours -from utils import color_bold, colors_supported, color_mark_selected -from wrapper import execute_without_exit +from kupferbootstrap.devices.device import get_devices, sanitize_device_name +from kupferbootstrap.flavours.flavour import get_flavours +from kupferbootstrap.utils import color_bold, colors_supported, color_mark_selected +from kupferbootstrap.wrapper import execute_without_exit from .scheme import Profile from .profile import PROFILE_EMPTY, PROFILE_DEFAULTS, resolve_profile_attr, SparseProfile @@ -205,7 +205,7 @@ def prompt_for_save(retry_ctx: Optional[click.Context] = None): If `retry_ctx` is passed, the context's command will be reexecuted with the same arguments if the user chooses to retry. False will still be returned as the retry is expected to either save, perform another retry or arbort. """ - from wrapper import is_wrapped + from ..wrapper import is_wrapped if click.confirm(f'Do you want to save your changes to {config.runtime.config_file}?', default=True): if is_wrapped(): logging.warning("Writing to config file inside wrapper." diff --git a/config/profile.py b/src/kupferbootstrap/config/profile.py similarity index 100% rename from config/profile.py rename to src/kupferbootstrap/config/profile.py diff --git a/config/scheme.py b/src/kupferbootstrap/config/scheme.py similarity index 97% rename from config/scheme.py rename to src/kupferbootstrap/config/scheme.py index a5846ba..1efd474 100644 --- a/config/scheme.py +++ b/src/kupferbootstrap/config/scheme.py @@ -3,8 +3,8 @@ from __future__ import annotations from munch import Munch from typing import Any, Optional, Mapping, Union -from dictscheme import DictScheme -from constants import Arch +from kupferbootstrap.dictscheme import DictScheme +from kupferbootstrap.constants import Arch class SparseProfile(DictScheme): diff --git a/config/state.py b/src/kupferbootstrap/config/state.py similarity index 99% rename from config/state.py rename to src/kupferbootstrap/config/state.py index 2d1ba42..088e3c7 100644 --- a/config/state.py +++ b/src/kupferbootstrap/config/state.py @@ -5,7 +5,7 @@ import toml from copy import deepcopy from typing import Mapping, Optional -from constants import DEFAULT_PACKAGE_BRANCH +from kupferbootstrap.constants import DEFAULT_PACKAGE_BRANCH from .scheme import Config, ConfigLoadState, DictScheme, Profile, RuntimeConfiguration from .profile import PROFILE_DEFAULTS, PROFILE_DEFAULTS_DICT, resolve_profile diff --git a/config/test_config.py b/src/kupferbootstrap/config/test_config.py similarity index 97% rename from config/test_config.py rename to src/kupferbootstrap/config/test_config.py index b97ac1b..373aace 100644 --- a/config/test_config.py +++ b/src/kupferbootstrap/config/test_config.py @@ -7,9 +7,9 @@ import toml from tempfile import mktemp, gettempdir as get_system_tempdir from typing import Any, Optional -from config.profile import PROFILE_DEFAULTS -from config.scheme import Config, Profile -from config.state import CONFIG_DEFAULTS, ConfigStateHolder +from kupferbootstrap.config.profile import PROFILE_DEFAULTS +from kupferbootstrap.config.scheme import Config, Profile +from kupferbootstrap.config.state import CONFIG_DEFAULTS, ConfigStateHolder def get_filename(): diff --git a/constants.py b/src/kupferbootstrap/constants.py similarity index 99% rename from constants.py rename to src/kupferbootstrap/constants.py index 2ddd686..3ce0b50 100644 --- a/constants.py +++ b/src/kupferbootstrap/constants.py @@ -1,4 +1,4 @@ -from typehelpers import TypeAlias +from .typehelpers import TypeAlias FASTBOOT = 'fastboot' FLASH_PARTS = { diff --git a/distro/__init__.py b/src/kupferbootstrap/devices/__init__.py similarity index 100% rename from distro/__init__.py rename to src/kupferbootstrap/devices/__init__.py diff --git a/devices/cli.py b/src/kupferbootstrap/devices/cli.py similarity index 94% rename from devices/cli.py rename to src/kupferbootstrap/devices/cli.py index 56cfd61..124940b 100644 --- a/devices/cli.py +++ b/src/kupferbootstrap/devices/cli.py @@ -4,9 +4,9 @@ import logging from json import dumps as json_dump from typing import Optional -from config.state import config -from config.cli import resolve_profile_field -from utils import color_mark_selected, colors_supported +from kupferbootstrap.config.state import config +from kupferbootstrap.config.cli import resolve_profile_field +from kupferbootstrap.utils import color_mark_selected, colors_supported from .device import get_devices, get_device diff --git a/devices/device.py b/src/kupferbootstrap/devices/device.py similarity index 94% rename from devices/device.py rename to src/kupferbootstrap/devices/device.py index c386053..7b8610e 100644 --- a/devices/device.py +++ b/src/kupferbootstrap/devices/device.py @@ -3,13 +3,13 @@ import os from typing import Optional -from config.state import config -from constants import Arch, ARCHES -from dictscheme import DictScheme -from distro.distro import get_kupfer_local -from distro.package import LocalPackage -from packages.pkgbuild import Pkgbuild, _pkgbuilds_cache, discover_pkgbuilds, get_pkgbuild_by_path, init_pkgbuilds -from utils import read_files_from_tar, color_str +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import Arch, ARCHES +from kupferbootstrap.dictscheme import DictScheme +from kupferbootstrap.distro.distro import get_kupfer_local +from kupferbootstrap.distro.package import LocalPackage +from kupferbootstrap.packages.pkgbuild import Pkgbuild, _pkgbuilds_cache, discover_pkgbuilds, get_pkgbuild_by_path, init_pkgbuilds +from kupferbootstrap.utils import read_files_from_tar, color_str from .deviceinfo import DEFAULT_IMAGE_SECTOR_SIZE, DeviceInfo, parse_deviceinfo @@ -72,7 +72,7 @@ class Device(DictScheme): def parse_deviceinfo(self, try_download: bool = True, lazy: bool = True) -> DeviceInfo: if not lazy or 'deviceinfo' not in self or self.deviceinfo is None: # avoid import loop - from packages.build import check_package_version_built + from kupferbootstrap.packages.build import check_package_version_built is_built = check_package_version_built(self.package, self.arch, try_download=try_download) if not is_built: raise Exception(f"device package {self.package.name} for device {self.name} couldn't be acquired!") diff --git a/devices/deviceinfo.py b/src/kupferbootstrap/devices/deviceinfo.py similarity index 96% rename from devices/deviceinfo.py rename to src/kupferbootstrap/devices/deviceinfo.py index 2a86bf2..b22ee45 100644 --- a/devices/deviceinfo.py +++ b/src/kupferbootstrap/devices/deviceinfo.py @@ -7,9 +7,9 @@ import os from typing import Mapping, Optional -from config.state import config -from constants import Arch -from dictscheme import DictScheme +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import Arch +from kupferbootstrap.dictscheme import DictScheme PMOS_ARCHES_OVERRIDES: dict[str, Arch] = { "armv7": 'armv7h', @@ -205,15 +205,12 @@ def parse_kernel_suffix(deviceinfo: dict[str, Optional[str]], kernel: str = 'mai https://wiki.postmarketos.org/wiki/Device_specific_package#Multiple_kernels :param info: deviceinfo dict, e.g.: - {"a": "first", - "b_mainline": "second", - "b_downstream": "third"} + {"a": "first", "b_mainline": "second", "b_downstream": "third"} :param device: which device info belongs to :param kernel: which kernel suffix to remove (e.g. "mainline") :returns: info, but with the configured kernel suffix removed, e.g: - {"a": "first", - "b": "second", - "b_downstream": "third"} + {"a": "first", "b": "second", "b_downstream": "third"} + """ # Do nothing if the configured kernel isn't available in the kernel (e.g. # after switching from device with multiple kernels to device with only one diff --git a/devices/test_device.py b/src/kupferbootstrap/devices/test_device.py similarity index 94% rename from devices/test_device.py rename to src/kupferbootstrap/devices/test_device.py index 99a2277..d829ffb 100644 --- a/devices/test_device.py +++ b/src/kupferbootstrap/devices/test_device.py @@ -4,8 +4,8 @@ import os from copy import copy -from config.state import ConfigStateHolder, config -from packages.pkgbuild import init_pkgbuilds, discover_pkgbuilds, Pkgbuild, parse_pkgbuild +from kupferbootstrap.config.state import ConfigStateHolder, config +from kupferbootstrap.packages.pkgbuild import init_pkgbuilds, discover_pkgbuilds, Pkgbuild, parse_pkgbuild from .device import Device, DEVICE_DEPRECATIONS, get_device, get_devices, parse_device_pkg, check_devicepkg_name diff --git a/devices/test_deviceinfo.py b/src/kupferbootstrap/devices/test_deviceinfo.py similarity index 98% rename from devices/test_deviceinfo.py rename to src/kupferbootstrap/devices/test_deviceinfo.py index c9866a1..f4f332a 100644 --- a/devices/test_deviceinfo.py +++ b/src/kupferbootstrap/devices/test_deviceinfo.py @@ -1,4 +1,4 @@ -from config.state import config +from kupferbootstrap.config.state import config from .deviceinfo import DeviceInfo, parse_deviceinfo from .device import get_device diff --git a/dictscheme.py b/src/kupferbootstrap/dictscheme.py similarity index 99% rename from dictscheme.py rename to src/kupferbootstrap/dictscheme.py index ca7c12c..272032d 100644 --- a/dictscheme.py +++ b/src/kupferbootstrap/dictscheme.py @@ -7,7 +7,7 @@ from munch import Munch from toml.encoder import TomlEncoder, TomlPreserveInlineDictEncoder from typing import ClassVar, Generator, Optional, Union, Mapping, Any, get_type_hints, get_origin, get_args, Iterable -from typehelpers import UnionType, NoneType +from .typehelpers import UnionType, NoneType def resolve_type_hint(hint: type, ignore_origins: list[type] = []) -> Iterable[type]: diff --git a/exec/__init__.py b/src/kupferbootstrap/distro/__init__.py similarity index 100% rename from exec/__init__.py rename to src/kupferbootstrap/distro/__init__.py diff --git a/distro/distro.py b/src/kupferbootstrap/distro/distro.py similarity index 97% rename from distro/distro.py rename to src/kupferbootstrap/distro/distro.py index bbc6329..268957b 100644 --- a/distro/distro.py +++ b/src/kupferbootstrap/distro/distro.py @@ -3,9 +3,9 @@ import logging from enum import IntFlag from typing import Generic, Mapping, Optional, TypeVar -from constants import Arch, ARCHES, REPOSITORIES, KUPFER_BRANCH_MARKER, KUPFER_HTTPS, CHROOT_PATHS -from generator import generate_pacman_conf_body -from config.state import config +from kupferbootstrap.constants import Arch, ARCHES, REPOSITORIES, KUPFER_BRANCH_MARKER, KUPFER_HTTPS, CHROOT_PATHS +from kupferbootstrap.generator import generate_pacman_conf_body +from kupferbootstrap.config.state import config from .repo import BinaryPackageType, RepoInfo, Repo, LocalRepo, RemoteRepo from .repo_config import AbstrRepoConfig, BaseDistro, ReposConfigFile, REPOS_CONFIG_DEFAULT, get_repo_config as _get_repo_config diff --git a/distro/package.py b/src/kupferbootstrap/distro/package.py similarity index 97% rename from distro/package.py rename to src/kupferbootstrap/distro/package.py index 4a5b5a6..c2dc5c8 100644 --- a/distro/package.py +++ b/src/kupferbootstrap/distro/package.py @@ -5,7 +5,7 @@ from shutil import copyfileobj from typing import Optional, Union from urllib.request import urlopen -from exec.file import get_temp_dir, makedir +from kupferbootstrap.exec.file import get_temp_dir, makedir class PackageInfo: diff --git a/distro/repo.py b/src/kupferbootstrap/distro/repo.py similarity index 96% rename from distro/repo.py rename to src/kupferbootstrap/distro/repo.py index 703d067..1a50fa0 100644 --- a/distro/repo.py +++ b/src/kupferbootstrap/distro/repo.py @@ -5,9 +5,9 @@ import tarfile from typing import Generic, TypeVar -from config.state import config -from exec.file import get_temp_dir -from utils import download_file +from kupferbootstrap.config.state import config +from kupferbootstrap.exec.file import get_temp_dir +from kupferbootstrap.utils import download_file from .package import BinaryPackage, LocalPackage, RemotePackage diff --git a/distro/repo_config.py b/src/kupferbootstrap/distro/repo_config.py similarity index 94% rename from distro/repo_config.py rename to src/kupferbootstrap/distro/repo_config.py index 5f32d2b..90ff908 100644 --- a/distro/repo_config.py +++ b/src/kupferbootstrap/distro/repo_config.py @@ -8,10 +8,10 @@ import yaml from copy import deepcopy from typing import ClassVar, Optional, Mapping, Union -from config.state import config -from constants import Arch, BASE_DISTROS, KUPFER_HTTPS, REPOS_CONFIG_FILE, REPOSITORIES -from dictscheme import DictScheme, toml_inline_dicts, TomlPreserveInlineDictEncoder -from utils import sha256sum +from ..config.state import config +from ..constants import Arch, BASE_DISTROS, KUPFER_HTTPS, REPOS_CONFIG_FILE, REPOSITORIES +from ..dictscheme import DictScheme, toml_inline_dicts, TomlPreserveInlineDictEncoder +from ..utils import sha256sum REPOS_KEY = 'repos' REMOTEURL_KEY = 'remote_url' @@ -142,7 +142,7 @@ def get_repo_config( config_exists = os.path.exists(repo_config_file_path) if not config_exists and _current_config is None: if initialize_pkgbuilds: - from packages.pkgbuild import init_pkgbuilds + from ..packages.pkgbuild import init_pkgbuilds init_pkgbuilds(update=False) return get_repo_config(initialize_pkgbuilds=False, repo_config_file=repo_config_file) if repo_config_file is not None: diff --git a/flavours/__init__.py b/src/kupferbootstrap/exec/__init__.py similarity index 100% rename from flavours/__init__.py rename to src/kupferbootstrap/exec/__init__.py diff --git a/exec/cmd.py b/src/kupferbootstrap/exec/cmd.py similarity index 99% rename from exec/cmd.py rename to src/kupferbootstrap/exec/cmd.py index d653d05..cf2af75 100644 --- a/exec/cmd.py +++ b/src/kupferbootstrap/exec/cmd.py @@ -7,7 +7,7 @@ from subprocess import CompletedProcess # make it easy for users of this module from shlex import quote as shell_quote from typing import IO, Optional, Union -from typehelpers import TypeAlias +from kupferbootstrap.typehelpers import TypeAlias ElevationMethod: TypeAlias = str diff --git a/exec/file.py b/src/kupferbootstrap/exec/file.py similarity index 99% rename from exec/file.py rename to src/kupferbootstrap/exec/file.py index 00653aa..a42ec90 100644 --- a/exec/file.py +++ b/src/kupferbootstrap/exec/file.py @@ -9,7 +9,7 @@ from tempfile import mkdtemp from typing import Optional, Union from .cmd import run_cmd, run_root_cmd, elevation_noop, generate_cmd_su, wrap_in_bash, shell_quote -from utils import get_user_name, get_group_name +from kupferbootstrap.utils import get_user_name, get_group_name def try_native_filewrite(path: str, content: Union[str, bytes], chmod: Optional[str] = None) -> Optional[Exception]: diff --git a/exec/test_cmd.py b/src/kupferbootstrap/exec/test_cmd.py similarity index 100% rename from exec/test_cmd.py rename to src/kupferbootstrap/exec/test_cmd.py diff --git a/exec/test_file.py b/src/kupferbootstrap/exec/test_file.py similarity index 98% rename from exec/test_file.py rename to src/kupferbootstrap/exec/test_file.py index 809d76e..d9bd9bd 100644 --- a/exec/test_file.py +++ b/src/kupferbootstrap/exec/test_file.py @@ -8,7 +8,7 @@ from dataclasses import dataclass from .cmd import run_root_cmd from .file import chmod, chown, get_temp_dir, write_file -from utils import get_gid, get_uid +from kupferbootstrap.utils import get_gid, get_uid TEMPDIR_MODE = 0o755 diff --git a/image/__init__.py b/src/kupferbootstrap/flavours/__init__.py similarity index 100% rename from image/__init__.py rename to src/kupferbootstrap/flavours/__init__.py diff --git a/flavours/cli.py b/src/kupferbootstrap/flavours/cli.py similarity index 94% rename from flavours/cli.py rename to src/kupferbootstrap/flavours/cli.py index a05bf3c..a09ad47 100644 --- a/flavours/cli.py +++ b/src/kupferbootstrap/flavours/cli.py @@ -4,9 +4,9 @@ import logging from json import dumps as json_dump from typing import Optional -from config.cli import resolve_profile_field -from config.state import config -from utils import color_mark_selected, colors_supported +from kupferbootstrap.config.cli import resolve_profile_field +from kupferbootstrap.config.state import config +from kupferbootstrap.utils import color_mark_selected, colors_supported from .flavour import get_flavours, get_flavour diff --git a/flavours/flavour.py b/src/kupferbootstrap/flavours/flavour.py similarity index 93% rename from flavours/flavour.py rename to src/kupferbootstrap/flavours/flavour.py index 4272eca..d3dd89a 100644 --- a/flavours/flavour.py +++ b/src/kupferbootstrap/flavours/flavour.py @@ -6,11 +6,11 @@ import os from typing import Optional -from config.state import config -from constants import FLAVOUR_DESCRIPTION_PREFIX, FLAVOUR_INFO_FILE -from dictscheme import DictScheme -from packages.pkgbuild import discover_pkgbuilds, get_pkgbuild_by_name, init_pkgbuilds, Pkgbuild -from utils import color_str +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import FLAVOUR_DESCRIPTION_PREFIX, FLAVOUR_INFO_FILE +from kupferbootstrap.dictscheme import DictScheme +from kupferbootstrap.packages.pkgbuild import discover_pkgbuilds, get_pkgbuild_by_name, init_pkgbuilds, Pkgbuild +from kupferbootstrap.utils import color_str class FlavourInfo(DictScheme): diff --git a/flavours/test_flavour.py b/src/kupferbootstrap/flavours/test_flavour.py similarity index 100% rename from flavours/test_flavour.py rename to src/kupferbootstrap/flavours/test_flavour.py diff --git a/generator.py b/src/kupferbootstrap/generator.py similarity index 98% rename from generator.py rename to src/kupferbootstrap/generator.py index b96cea3..f936ada 100644 --- a/generator.py +++ b/src/kupferbootstrap/generator.py @@ -1,7 +1,7 @@ from typing import Optional -from constants import Arch, CFLAGS_ARCHES, CFLAGS_GENERAL, COMPILE_ARCHES, GCC_HOSTSPECS -from config.state import config +from .constants import Arch, CFLAGS_ARCHES, CFLAGS_GENERAL, COMPILE_ARCHES, GCC_HOSTSPECS +from .config.state import config def generate_makepkg_conf(arch: Arch, cross: bool = False, chroot: Optional[str] = None) -> str: diff --git a/net/__init__.py b/src/kupferbootstrap/image/__init__.py similarity index 100% rename from net/__init__.py rename to src/kupferbootstrap/image/__init__.py diff --git a/image/boot.py b/src/kupferbootstrap/image/boot.py similarity index 86% rename from image/boot.py rename to src/kupferbootstrap/image/boot.py index 33e1f8b..f7c53c2 100644 --- a/image/boot.py +++ b/src/kupferbootstrap/image/boot.py @@ -4,13 +4,13 @@ import click from typing import Optional -from config.state import config -from constants import FLASH_PARTS, FASTBOOT, JUMPDRIVE, JUMPDRIVE_VERSION -from exec.file import makedir -from devices.device import get_profile_device -from flavours.flavour import get_profile_flavour -from flavours.cli import profile_option -from wrapper import enforce_wrap +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import FLASH_PARTS, FASTBOOT, JUMPDRIVE, JUMPDRIVE_VERSION +from kupferbootstrap.exec.file import makedir +from kupferbootstrap.devices.device import get_profile_device +from kupferbootstrap.flavours.flavour import get_profile_flavour +from kupferbootstrap.flavours.cli import profile_option +from kupferbootstrap.wrapper import enforce_wrap from .fastboot import fastboot_boot, fastboot_erase from .image import get_device_name, losetup_rootfs_image, get_image_path, dump_aboot, dump_lk2nd diff --git a/image/cli.py b/src/kupferbootstrap/image/cli.py similarity index 100% rename from image/cli.py rename to src/kupferbootstrap/image/cli.py diff --git a/image/fastboot.py b/src/kupferbootstrap/image/fastboot.py similarity index 96% rename from image/fastboot.py rename to src/kupferbootstrap/image/fastboot.py index cbe7ec6..165fcbc 100644 --- a/image/fastboot.py +++ b/src/kupferbootstrap/image/fastboot.py @@ -1,7 +1,7 @@ import click import logging -from exec.cmd import run_cmd, CompletedProcess +from kupferbootstrap.exec.cmd import run_cmd, CompletedProcess from typing import Optional diff --git a/image/flash.py b/src/kupferbootstrap/image/flash.py similarity index 93% rename from image/flash.py rename to src/kupferbootstrap/image/flash.py index 5def17c..b85e166 100644 --- a/image/flash.py +++ b/src/kupferbootstrap/image/flash.py @@ -5,13 +5,13 @@ import logging from typing import Optional -from constants import FLASH_PARTS, LOCATIONS, FASTBOOT, JUMPDRIVE -from exec.cmd import run_root_cmd -from exec.file import get_temp_dir -from devices.device import get_profile_device -from flavours.flavour import get_profile_flavour -from flavours.cli import profile_option -from wrapper import enforce_wrap +from kupferbootstrap.constants import FLASH_PARTS, LOCATIONS, FASTBOOT, JUMPDRIVE +from kupferbootstrap.exec.cmd import run_root_cmd +from kupferbootstrap.exec.file import get_temp_dir +from kupferbootstrap.devices.device import get_profile_device +from kupferbootstrap.flavours.flavour import get_profile_flavour +from kupferbootstrap.flavours.cli import profile_option +from kupferbootstrap.wrapper import enforce_wrap from .fastboot import fastboot_flash from .image import dd_image, dump_aboot, dump_lk2nd, dump_qhypstub, get_image_path, losetup_destroy, losetup_rootfs_image, partprobe, shrink_fs diff --git a/image/image.py b/src/kupferbootstrap/image/image.py similarity index 95% rename from image/image.py rename to src/kupferbootstrap/image/image.py index 6532af7..a82203d 100644 --- a/image/image.py +++ b/src/kupferbootstrap/image/image.py @@ -9,17 +9,17 @@ from signal import pause from subprocess import CompletedProcess from typing import Optional, Union -from config.state import config, Profile -from chroot.device import DeviceChroot, get_device_chroot -from constants import Arch, BASE_LOCAL_PACKAGES, BASE_PACKAGES, POST_INSTALL_CMDS -from distro.distro import get_base_distro, get_kupfer_https -from devices.device import Device, get_profile_device -from exec.cmd import run_root_cmd, generate_cmd_su -from exec.file import get_temp_dir, root_write_file, root_makedir, makedir -from flavours.flavour import Flavour, get_profile_flavour -from net.ssh import copy_ssh_keys -from packages.build import build_enable_qemu_binfmt, build_packages, filter_pkgbuilds -from wrapper import enforce_wrap +from kupferbootstrap.config.state import config, Profile +from kupferbootstrap.chroot.device import DeviceChroot, get_device_chroot +from kupferbootstrap.constants import Arch, BASE_LOCAL_PACKAGES, BASE_PACKAGES, POST_INSTALL_CMDS +from kupferbootstrap.distro.distro import get_base_distro, get_kupfer_https +from kupferbootstrap.devices.device import Device, get_profile_device +from kupferbootstrap.exec.cmd import run_root_cmd, generate_cmd_su +from kupferbootstrap.exec.file import get_temp_dir, root_write_file, root_makedir, makedir +from kupferbootstrap.flavours.flavour import Flavour, get_profile_flavour +from kupferbootstrap.net.ssh import copy_ssh_keys +from kupferbootstrap.packages.build import build_enable_qemu_binfmt, build_packages, filter_pkgbuilds +from kupferbootstrap.wrapper import enforce_wrap # image files need to be slightly smaller than partitions to fit IMG_FILE_ROOT_DEFAULT_SIZE = "1800M" diff --git a/logger.py b/src/kupferbootstrap/logger.py similarity index 100% rename from logger.py rename to src/kupferbootstrap/logger.py diff --git a/main.py b/src/kupferbootstrap/main.py similarity index 81% rename from main.py rename to src/kupferbootstrap/main.py index f212197..c3dbdb9 100755 --- a/main.py +++ b/src/kupferbootstrap/main.py @@ -7,19 +7,19 @@ from os import isatty from traceback import format_exc, format_exception_only, format_tb from typing import Optional -from logger import color_option, logging, quiet_option, setup_logging, verbose_option -from wrapper import get_wrapper_type, enforce_wrap, nowrapper_option -from progressbar import progress_bars_option +from .logger import color_option, logging, quiet_option, setup_logging, verbose_option +from .wrapper import get_wrapper_type, enforce_wrap, nowrapper_option +from .progressbar import progress_bars_option -from binfmt.cli import cmd_binfmt -from config.cli import config, config_option, cmd_config -from packages.cli import cmd_packages -from flavours.cli import cmd_flavours -from devices.cli import cmd_devices -from net.cli import cmd_net -from chroot.cli import cmd_chroot -from cache.cli import cmd_cache -from image.cli import cmd_image +from .binfmt.cli import cmd_binfmt +from .config.cli import config, config_option, cmd_config +from .packages.cli import cmd_packages +from .flavours.cli import cmd_flavours +from .devices.cli import cmd_devices +from .net.cli import cmd_net +from .chroot.cli import cmd_chroot +from .cache.cli import cmd_cache +from .image.cli import cmd_image @click.group() diff --git a/packages/__init__.py b/src/kupferbootstrap/net/__init__.py similarity index 100% rename from packages/__init__.py rename to src/kupferbootstrap/net/__init__.py diff --git a/net/cli.py b/src/kupferbootstrap/net/cli.py similarity index 100% rename from net/cli.py rename to src/kupferbootstrap/net/cli.py diff --git a/net/forwarding.py b/src/kupferbootstrap/net/forwarding.py similarity index 92% rename from net/forwarding.py rename to src/kupferbootstrap/net/forwarding.py index 5089c42..3dc4171 100644 --- a/net/forwarding.py +++ b/src/kupferbootstrap/net/forwarding.py @@ -1,8 +1,8 @@ import click import logging -from exec.cmd import run_root_cmd -from wrapper import check_programs_wrap +from kupferbootstrap.exec.cmd import run_root_cmd +from kupferbootstrap.wrapper import check_programs_wrap from .ssh import run_ssh_command diff --git a/net/ssh.py b/src/kupferbootstrap/net/ssh.py similarity index 93% rename from net/ssh.py rename to src/kupferbootstrap/net/ssh.py index 6eb7294..82501b0 100644 --- a/net/ssh.py +++ b/src/kupferbootstrap/net/ssh.py @@ -4,12 +4,12 @@ import os import pathlib import click -from config.state import config -from constants import SSH_COMMON_OPTIONS, SSH_DEFAULT_HOST, SSH_DEFAULT_PORT -from chroot.abstract import Chroot -from exec.cmd import run_cmd -from exec.file import write_file -from wrapper import check_programs_wrap +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import SSH_COMMON_OPTIONS, SSH_DEFAULT_HOST, SSH_DEFAULT_PORT +from kupferbootstrap.exec.cmd import run_cmd +from kupferbootstrap.exec.file import write_file +from kupferbootstrap.chroot.abstract import Chroot +from kupferbootstrap.wrapper import check_programs_wrap @click.command(name='ssh') diff --git a/net/telnet.py b/src/kupferbootstrap/net/telnet.py similarity index 83% rename from net/telnet.py rename to src/kupferbootstrap/net/telnet.py index d7097fd..17e8985 100644 --- a/net/telnet.py +++ b/src/kupferbootstrap/net/telnet.py @@ -1,6 +1,6 @@ import subprocess import click -from wrapper import check_programs_wrap +from kupferbootstrap.wrapper import check_programs_wrap @click.command(name='telnet') diff --git a/src/kupferbootstrap/packages/__init__.py b/src/kupferbootstrap/packages/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/packages/build.py b/src/kupferbootstrap/packages/build.py similarity index 97% rename from packages/build.py rename to src/kupferbootstrap/packages/build.py index b388221..4274abf 100644 --- a/packages/build.py +++ b/src/kupferbootstrap/packages/build.py @@ -9,18 +9,18 @@ from copy import deepcopy from urllib.error import HTTPError from typing import Iterable, Iterator, Optional -from binfmt.binfmt import binfmt_is_registered, binfmt_register -from constants import CROSSDIRECT_PKGS, QEMU_BINFMT_PKGS, GCC_HOSTSPECS, ARCHES, Arch, CHROOT_PATHS, MAKEPKG_CMD -from config.state import config -from exec.cmd import run_cmd, run_root_cmd -from exec.file import makedir, remove_file, symlink -from chroot.build import get_build_chroot, BuildChroot -from distro.distro import get_kupfer_https, get_kupfer_local, get_kupfer_repo_names -from distro.package import RemotePackage, LocalPackage -from distro.repo import LocalRepo -from progressbar import BAR_PADDING, get_levels_bar -from wrapper import check_programs_wrap, is_wrapped -from utils import ellipsize, sha256sum +from kupferbootstrap.binfmt.binfmt import binfmt_is_registered, binfmt_register +from kupferbootstrap.constants import CROSSDIRECT_PKGS, QEMU_BINFMT_PKGS, GCC_HOSTSPECS, ARCHES, Arch, CHROOT_PATHS, MAKEPKG_CMD +from kupferbootstrap.config.state import config +from kupferbootstrap.exec.cmd import run_cmd, run_root_cmd +from kupferbootstrap.exec.file import makedir, remove_file, symlink +from kupferbootstrap.chroot.build import get_build_chroot, BuildChroot +from kupferbootstrap.distro.distro import get_kupfer_https, get_kupfer_local, get_kupfer_repo_names +from kupferbootstrap.distro.package import RemotePackage, LocalPackage +from kupferbootstrap.distro.repo import LocalRepo +from kupferbootstrap.progressbar import BAR_PADDING, get_levels_bar +from kupferbootstrap.wrapper import check_programs_wrap, is_wrapped +from kupferbootstrap.utils import ellipsize, sha256sum from .pkgbuild import discover_pkgbuilds, filter_pkgbuilds, Pkgbase, Pkgbuild, SubPkgbuild diff --git a/packages/cli.py b/src/kupferbootstrap/packages/cli.py similarity index 96% rename from packages/cli.py rename to src/kupferbootstrap/packages/cli.py index 3878ba4..3fdcae3 100644 --- a/packages/cli.py +++ b/src/kupferbootstrap/packages/cli.py @@ -6,16 +6,16 @@ import os from glob import glob from typing import Iterable, Optional -from config.state import config -from constants import Arch, ARCHES, SRCINFO_FILE, SRCINFO_INITIALISED_FILE, SRCINFO_METADATA_FILE, SRCINFO_TARBALL_FILE, SRCINFO_TARBALL_URL -from exec.cmd import run_cmd, shell_quote, CompletedProcess -from exec.file import get_temp_dir, makedir, remove_file -from devices.device import get_profile_device -from distro.distro import get_kupfer_local, get_kupfer_url, get_kupfer_repo_names -from distro.package import LocalPackage -from net.ssh import run_ssh_command, scp_put_files -from utils import download_file, git, sha256sum -from wrapper import check_programs_wrap, enforce_wrap +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import Arch, ARCHES, SRCINFO_FILE, SRCINFO_INITIALISED_FILE, SRCINFO_METADATA_FILE, SRCINFO_TARBALL_FILE, SRCINFO_TARBALL_URL +from kupferbootstrap.exec.cmd import run_cmd, shell_quote, CompletedProcess +from kupferbootstrap.exec.file import get_temp_dir, makedir, remove_file +from kupferbootstrap.devices.device import get_profile_device +from kupferbootstrap.distro.distro import get_kupfer_local, get_kupfer_url, get_kupfer_repo_names +from kupferbootstrap.distro.package import LocalPackage +from kupferbootstrap.net.ssh import run_ssh_command, scp_put_files +from kupferbootstrap.utils import download_file, git, sha256sum +from kupferbootstrap.wrapper import check_programs_wrap, enforce_wrap from .build import build_packages_by_paths, init_prebuilts from .pkgbuild import discover_pkgbuilds, filter_pkgbuilds, get_pkgbuild_dirs, init_pkgbuilds diff --git a/packages/pkgbuild.py b/src/kupferbootstrap/packages/pkgbuild.py similarity index 97% rename from packages/pkgbuild.py rename to src/kupferbootstrap/packages/pkgbuild.py index 9be89c3..e634d2e 100644 --- a/packages/pkgbuild.py +++ b/src/kupferbootstrap/packages/pkgbuild.py @@ -8,15 +8,15 @@ import os from joblib import Parallel, delayed from typing import Iterable, Optional -from config.state import config, ConfigStateHolder -from constants import Arch -from distro.distro import get_kupfer_repo_names -from distro.package import PackageInfo -from exec.file import remove_file -from logger import setup_logging -from utils import git, git_get_branch -from wrapper import check_programs_wrap -from typehelpers import TypeAlias +from kupferbootstrap.config.state import config, ConfigStateHolder +from kupferbootstrap.constants import Arch +from kupferbootstrap.distro.distro import get_kupfer_repo_names +from kupferbootstrap.distro.package import PackageInfo +from kupferbootstrap.exec.file import remove_file +from kupferbootstrap.logger import setup_logging +from kupferbootstrap.utils import git, git_get_branch +from kupferbootstrap.wrapper import check_programs_wrap +from kupferbootstrap.typehelpers import TypeAlias from .srcinfo_cache import SrcinfoMetaFile diff --git a/packages/srcinfo_cache.py b/src/kupferbootstrap/packages/srcinfo_cache.py similarity index 96% rename from packages/srcinfo_cache.py rename to src/kupferbootstrap/packages/srcinfo_cache.py index 3d9737b..4fe4792 100644 --- a/packages/srcinfo_cache.py +++ b/src/kupferbootstrap/packages/srcinfo_cache.py @@ -7,11 +7,11 @@ import subprocess from typing import Any, ClassVar, Optional -from config.state import config -from constants import MAKEPKG_CMD, SRCINFO_FILE, SRCINFO_METADATA_FILE, SRCINFO_INITIALISED_FILE -from dictscheme import DictScheme -from exec.cmd import run_cmd -from utils import sha256sum +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import MAKEPKG_CMD, SRCINFO_FILE, SRCINFO_METADATA_FILE, SRCINFO_INITIALISED_FILE +from kupferbootstrap.dictscheme import DictScheme +from kupferbootstrap.exec.cmd import run_cmd +from kupferbootstrap.utils import sha256sum SRCINFO_CHECKSUM_FILES = ['PKGBUILD', SRCINFO_FILE] diff --git a/progressbar.py b/src/kupferbootstrap/progressbar.py similarity index 97% rename from progressbar.py rename to src/kupferbootstrap/progressbar.py index bfb450a..8899da8 100644 --- a/progressbar.py +++ b/src/kupferbootstrap/progressbar.py @@ -4,7 +4,7 @@ import sys from enlighten import Counter, Manager, get_manager as _getmanager from typing import Hashable, Optional -from config.state import config +from .config.state import config BAR_PADDING = 25 DEFAULT_OUTPUT = sys.stderr diff --git a/src/kupferbootstrap/py.typed b/src/kupferbootstrap/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/typehelpers.py b/src/kupferbootstrap/typehelpers.py similarity index 100% rename from typehelpers.py rename to src/kupferbootstrap/typehelpers.py diff --git a/utils.py b/src/kupferbootstrap/utils.py similarity index 99% rename from utils.py rename to src/kupferbootstrap/utils.py index df40a97..1de8ca6 100644 --- a/utils.py +++ b/src/kupferbootstrap/utils.py @@ -14,7 +14,7 @@ from dateutil.parser import parse as parsedate from shutil import which from typing import Any, Generator, IO, Optional, Union, Sequence -from exec.cmd import run_cmd, run_root_cmd +from .exec.cmd import run_cmd, run_root_cmd _programs_available = dict[str, bool]() diff --git a/wrapper/__init__.py b/src/kupferbootstrap/wrapper/__init__.py similarity index 89% rename from wrapper/__init__.py rename to src/kupferbootstrap/wrapper/__init__.py index a86f879..1a7156e 100644 --- a/wrapper/__init__.py +++ b/src/kupferbootstrap/wrapper/__init__.py @@ -3,9 +3,9 @@ import logging from typing import Optional, Sequence, Union -from config.state import config -from constants import Arch -from utils import programs_available +from kupferbootstrap.config.state import config +from kupferbootstrap.constants import Arch +from kupferbootstrap.utils import programs_available from .docker import DockerWrapper from .wrapper import Wrapper @@ -57,10 +57,12 @@ def wrap_if_foreign_arch(arch: Arch): def execute_without_exit(f, argv_override: Optional[list[str]], *args, **kwargs): - """If no wrap is needed, executes and returns f(*args, **kwargs). + """ + If no wrap is needed, executes and returns `f(*args, **kwargs)`. If a wrap is determined to be necessary, force a wrap with argv_override applied. If a wrap was forced, None is returned. - WARNING: No protection against f() returning None is taken.""" + WARNING: No protection against f() returning None is taken. + """ if not needs_wrap(): return f(*args, **kwargs) assert get_wrapper_type() != 'none', "needs_wrap() should've returned False" diff --git a/wrapper/docker.py b/src/kupferbootstrap/wrapper/docker.py similarity index 60% rename from wrapper/docker.py rename to src/kupferbootstrap/wrapper/docker.py index 13c0bde..d3fe799 100644 --- a/wrapper/docker.py +++ b/src/kupferbootstrap/wrapper/docker.py @@ -4,11 +4,13 @@ import pathlib import subprocess import sys -from config.state import config -from exec.file import makedir +from kupferbootstrap.config.state import config +from kupferbootstrap.exec.file import makedir from .wrapper import Wrapper, WRAPPER_PATHS +VERSION_FILE = "docker_version.txt" +DOCKER_FILE = "Dockerfile" DOCKER_PATHS = WRAPPER_PATHS.copy() @@ -26,10 +28,39 @@ class DockerWrapper(Wrapper): super().wrap() script_path = config.runtime.script_source_dir assert script_path - with open(os.path.join(script_path, 'version.txt')) as version_file: - version = version_file.read().replace('\n', '') + docker_path = script_path + tried = [docker_path] + if not os.path.exists(os.path.join(docker_path, DOCKER_FILE)): + docker_path = os.path.realpath(os.path.join(script_path, "../..")) + tried.append(docker_path) + if not os.path.exists(os.path.join(docker_path, DOCKER_FILE)): + _par_dir = os.path.dirname(script_path) + # handle venv + if os.path.basename(_par_dir) == "site-packages": + _path = os.path.join(_par_dir, "../../../..") + docker_path = os.path.realpath(_path) + tried.append(f"{_path} => {docker_path}") + logging.debug(f"{DOCKER_FILE!r} not found at {script_path!r}, trying {docker_path!r}") + version_file = os.path.join(script_path, '../..', VERSION_FILE) + if not os.path.exists(version_file): + _vfile = os.path.join(docker_path, VERSION_FILE) + logging.warning(f"{VERSION_FILE} not found at {version_file!r}." + f"\nTrying {_vfile!r}" + "\nDid you use `pip install .` instead of `pip install -e .`?") + if os.path.exists(_vfile): + version_file = _vfile + if os.path.exists(version_file): + with open(version_file) as fd: + version = fd.read().replace('\n', '').strip() + logging.debug(f"Read docker tag {version} from {version_file}") + else: + version = "BUILD" + logging.error(f"'{script_path}/{VERSION_FILE}' doesn't exist, defaulting docker tag to {version}!" + "\nThis installation is potentially broken!" + "\nDid you use `pip install .` instead of `pip install -e .` to install kupferboostrap?" + f"Tried locations: {[version_file, _vfile]}") tag = f'registry.gitlab.com/kupfer/kupferbootstrap:{version}' - if version == 'dev': + if version == 'BUILD': logging.info(f'Building docker image "{tag}"') cmd = [ 'docker', @@ -38,11 +69,15 @@ class DockerWrapper(Wrapper): '-t', tag, ] + (['-q'] if not config.runtime.verbose else []) - logging.debug('Running docker cmd: ' + ' '.join(cmd)) + _dfile = os.path.join(docker_path, DOCKER_FILE) + if not os.path.exists(_dfile): + _sep = "\n -" + raise Exception(f'{DOCKER_FILE!r} not found. Tried locations:' + (_sep.join(["", *[repr(f"{p}/{DOCKER_FILE}") for p in tried]]))) + logging.debug(f'Running docker cmd (chdir={script_path!r}) : ' + ' '.join(cmd)) mute_docker = not config.runtime.verbose result = subprocess.run( cmd, - cwd=script_path, + cwd=docker_path, capture_output=mute_docker, ) if result.returncode != 0: diff --git a/wrapper/wrapper.py b/src/kupferbootstrap/wrapper/wrapper.py similarity index 95% rename from wrapper/wrapper.py rename to src/kupferbootstrap/wrapper/wrapper.py index 7f00eca..5f40a61 100644 --- a/wrapper/wrapper.py +++ b/src/kupferbootstrap/wrapper/wrapper.py @@ -5,9 +5,9 @@ import pathlib from typing import Optional, Protocol -from config.state import config -from config.state import dump_file as dump_config_file -from constants import CHROOT_PATHS, WRAPPER_ENV_VAR +from kupferbootstrap.config.state import config +from kupferbootstrap.config.state import dump_file as dump_config_file +from kupferbootstrap.constants import CHROOT_PATHS, WRAPPER_ENV_VAR WRAPPER_PATHS = CHROOT_PATHS | { 'ccache': '/ccache', diff --git a/version.txt b/version.txt deleted file mode 100644 index 38f8e88..0000000 --- a/version.txt +++ /dev/null @@ -1 +0,0 @@ -dev diff --git a/wrapper_su_helper.py b/wrapper_su_helper.py index 7f8426c..9c9afcb 100755 --- a/wrapper_su_helper.py +++ b/wrapper_su_helper.py @@ -1,14 +1,14 @@ -#!/bin/python3 +#!/usr/bin/env python3 import click import pwd import os -from logger import logging, setup_logging +from kupferbootstrap.logger import logging, setup_logging -from constants import WRAPPER_ENV_VAR -from exec.cmd import run_cmd, flatten_shell_script -from exec.file import chown +from kupferbootstrap.constants import WRAPPER_ENV_VAR +from kupferbootstrap.exec.cmd import run_cmd, flatten_shell_script +from kupferbootstrap.exec.file import chown @click.command('kupferbootstrap_su')