E321 Refactor cross-platform installers for isolated and reliable setup by Napreth · Pull Request #833 · bkerler/edl · GitHub
[go: up one dir, main page]

Skip to content
10000

Refactor cross-platform installers for isolated and reliable setup - #833

Open
Napreth wants to merge 11 commits into
bkerler:masterfrom
Napreth:refactor/install-scripts
Open

Napreth wants to merge 11 commits into
bkerler:masterfrom
Napreth:refactor/install-scripts

Conversation

@Napreth
@Napreth Napreth commented Oct 22, 2026
Copy link
Copy Markdown

⚠️ Dependency notice

This PR depends on #831 and #832 and should be reviewed/merged after both.

The current branch is based on changes from both PRs, so its diff against upstream master also includes their commits. Once they are merged, this branch may need to be rebased, and only the installer-specific commits may need to be replayed.

Summary

Refactor the Windows and Unix installers to provide an isolated, user-level installation process without unnecessarily modifying the system environment.

The previous installers required elevated privileges, installed Python dependencies into the system environment, and modified system-wide configuration even when those changes were not needed.

This PR separates Python application setup from system-level prerequisites, adds installation recovery and concurrency protection, and preserves the existing USB driver setup workflows.

Changes

Isolated Python installation

  • Detect an existing compatible Python 3.10+ interpreter before offering to install one.
  • Create or reuse a project-local .venv for EDL and its dependencies.
  • Add local edl / edl.bat launchers, avoiding system-wide PATH modifications.
  • Support optional features through the asm and qrcode extras.
  • Allow users to select an interpreter explicitly.
  • Require confirmation before installing Python globally.
  • Support non-interactive installation without implicitly approving system changes.
  • Validate virtual environments before reuse and avoid inherited pip configuration interfering with installation.

Source checkout and Loader management

  • Support installation directly from a downloaded installer script, without requiring Git.
  • Prefer Git when available, falling back to GitHub source archives.
  • Download and initialize Loaders separately when needed.
  • Detect incomplete Loader downloads and retry them.
  • Preserve existing local files, with documented behavior for conflicting paths.
  • Validate the installation target before downloading source or offering to install Python.

Installation recovery and concurrency

  • Stage source downloads before publishing them to the installation directory.
  • Record a persistent publication plan to recover from failed or interrupted file moves.
  • Roll back incomplete source publication on the next run.
  • Preserve successfully published source when only cleanup was interrupted.
  • Use per-target OS-level locks to prevent concurrent installers from interfering with an active installation.
  • Keep locks effective across child processes, including when the parent process terminates unexpectedly.

USB driver setup

  • Separate USB driver configuration from Python application installation.
  • On Windows, detect Zadig and offer to install it through WinGet when needed.
  • Preserve the existing OnePlus 9008 driver installer.
  • On Linux, check USB prerequisites and configuration before requesting system-level changes.
  • Avoid requesting elevated privileges for the entire installation process.
  • Allow USB setup to be skipped or performed separately.

Documentation and tests

  • Update the README with the new installation workflows and command-line options.
  • Add installation tests covering source checkout, environment isolation, interpreter selection, failure handling, and recovery.
  • Add subprocess tests for interrupted installations and concurrent installer execution.
  • Add CI coverage for Windows and Linux installation workflows.

Testing

The following checks passed locally:

Environment Tests Result
Windows / Python 3.14 21 Passed
Linux / Python 3.10 (act) 16 Passed
Wheel, sdist, and CLI checks 4 Passed
Total 41 Passed

The tests cover:

  • Isolated virtual environment creation and reuse.
  • Source installation through Git and archive fallback.
  • Python selection, confirmation, and unattended behavior.
  • Target validation and preservation of existing files.
  • Loader download recovery.
  • Failed and interrupted source publication.
  • Concurrent installers and lock lifetime across child processes.
  • Packaging and CLI entry-point verification.

USB driver operations were tested through mocks and control-flow checks; actual driver installation and physical device communication were not tested.

Related to #830.

Move the EDL implementation into the package, retain the source launcher, and remove tool import symlinks. Make CLI entry points safe to import and callable without arguments. Restrict package discovery and add wheel/sdist installation checks for Windows and Unix.

Refs: bkerler#830 (Python packaging stage)
Run source launchers in a dependency-only virtual environment and assert edlclient is not importable before execution. Keep wheel installation checks in a separate environment, and add the source root for qc_diag only during direct script execution.
Generate legacy requirements from pyproject.toml, declare required cryptography support, and separate assembly and QR image extras. Add independent dependency resolution and optional-feature checks on the upstream package layout.

Refs: bkerler#830 (dependency management stage)
# Conflicts:
#	MANIFEST.in
Write a persistent move plan before publishing fresh source entries. Roll back
failed moves and recover interrupted publication before validating the target
or selecting Python. Keep a commit record through cleanup so a completed
checkout is retained when only cleanup was interrupted.

Validated with Windows Python 3.14 (20 tests), Linux act Python 3.10 (14 tests),
and wheel/sdist/CLI checks (4 tests). Fault cases include failed moves, killed
publisher processes, valid-looking partial checkouts and committed cleanup.
Windows tests used a temporary wheelhouse after a transient PyPI timeout.

Live WinGet 1.29.380 detected installed Zadig 2.9.788 with exit 0, including
Test-Zadig with its PATH shortcut excluded. The same package's absent user
scope returned -1978335212. Existing machine-scope Zadig was not uninstalled.
Hold a per-target kernel lock before recovering pending source state and keep
it through environment setup and cleanup. Competing installers fail without
modifying the active checkout. Windows uses an exclusive inheritable handle
with DeleteOnClose; Unix uses flock or native Perl flock on an inherited fd.
Keep and ignore the empty Unix lock file to avoid inode replacement races.

Real subprocess tests cover normal completion, forced parent termination,
continued protection while an orphaned native writer remains alive, and recovery
after all writers exit. Both Unix flock backends retain the same lock inode.

Validated with Windows Python 3.14 (21 tests), Linux act Python 3.10 (16 tests),
and wheel/sdist/CLI checks (4 tests). Existing driver scripts are unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0