This commit removes the `run_command`-based execution model for Nix flake
installations and replaces it with a direct `os.system` invocation.
This ensures that *all* Nix diagnostics (stdout/stderr) are fully visible and
no longer suppressed by wrapper logic.
Key changes:
* Directly run `nix profile install` via `os.system` for full error output
* Correctly decode real exit codes via `os.WIFEXITED` / `os.WEXITSTATUS`
* Preserve mandatory/optional behavior for flake outputs
* Update unit tests to the new execution model using `unittest`
* Add complete coverage for:
* successful installs
* mandatory failures → raise SystemExit(code)
* optional failures → warn and continue
* environment-based disabling via `PKGMGR_DISABLE_NIX_FLAKE_INSTALLER`
* Remove obsolete mocks and legacy test logic that assumed `run_command`
Overall, this improves transparency, debuggability, and correctness of the
Nix flake installer while maintaining full backward compatibility at the
interface level.
https://chatgpt.com/share/693b0a20-99f4-800f-b789-b00a50413612
- Implement new mirror actions:
- list_mirrors: show mirrors from config, MIRRORS file, or merged view
- diff_mirrors: compare config mirrors with MIRRORS file (ONLY IN CONFIG,
ONLY IN FILE, URL MISMATCH, OK)
- merge_mirrors: merge mirrors between config and MIRRORS file in both
directions, with preview mode and user config writing via save_user_config
- setup_mirrors: prepare local Git remotes (ensure origin) and print
provider-URL suggestions for remote repositories
- Introduce mirror utilities:
- RepoMirrorContext with resolved_mirrors (config + file, file wins)
- load_config_mirrors supporting dict and list-of-dicts shapes
- read/write MIRRORS file with simple "name url" format and preview mode
- helper for building default SSH URLs from provider/account/repository
- Wire mirror commands into CLI:
- Add handle_mirror_command and integrate "mirror" into dispatch
- Add dedicated CLI parser modules under pkgmgr.cli.parser:
* common, install_update, config_cmd, navigation_cmd,
branch_cmd, release_cmd, version_cmd, changelog_cmd,
list_cmd, make_cmd, mirror_cmd
- Replace old flat cli/parser.py with modular parser package and
SortedSubParsersAction in common.py
- Update TODO.md to mark MIRROR as implemented
- Add E2E tests for mirror commands:
- test_mirror_help
- test_mirror_list_preview_all
- test_mirror_diff_preview_all
- test_mirror_merge_config_to_file_preview_all
- test_mirror_setup_preview_all
https://chatgpt.com/share/693adee0-aa3c-800f-b72a-98473fdaf760
- Update test_nix_build_pkgmgr.py to invoke
nix --option sandbox false build .#pkgmgr -L
to avoid sandbox/permission issues in Debian and Ubuntu containers.
- Keeps the test logic identical across all distros while ensuring
consistent flake build behaviour during E2E runs.
https://chatgpt.com/share/693aa33f-4e3c-800f-86ec-99c38a07eacb
- Introduce tests/e2e/test_nix_build_pkgmgr.py to inspect the Nix environment
and build the pkgmgr flake inside the container started by test-e2e.sh
- Run the same commands in every distro container: nix --version, sandbox
config, id, and nix build .#pkgmgr -L
- Print stdout/stderr and assert the flake build succeeds for easier
cross-distro Nix debugging
https://chatgpt.com/share/693aa33f-4e3c-800f-86ec-99c38a07eacb
- Adjust install_repos integration test to patch resolve_command_for_repo
in the pipeline module and tighten DummyInstaller overrides
- Rewrite recursive capability integration tests to focus on layer
ordering and capability shadowing across Makefile, Python, Nix
and OS-package installers
- Extend recursive capabilities markdown with hierarchy diagram,
capability matrix, scenario matrix and link to the external
setup controller schema
https://chatgpt.com/share/69399857-4d84-800f-a636-6bcd1ab5e192
- Introduce explicit CLI layer model (os-packages, nix, python, makefile)
and central InstallationPipeline to orchestrate installers.
- Move installer orchestration out of install_repos() into
pkgmgr.actions.repository.install.pipeline, using layer precedence and
capability tracking.
- Add pkgmgr.actions.repository.install.layers to classify commands into
layers and compare priorities.
- Rework PythonInstaller to always use isolated environments:
PKGMGR_PIP override → active venv → per-repo venv under ~/.venvs/<identifier>,
avoiding system Python and PEP 668 conflicts.
- Adjust NixFlakeInstaller to install flake outputs based on repository
identity: pkgmgr/package-manager → pkgmgr (mandatory) + default (optional),
all other repos → default (mandatory).
- Tighten MakefileInstaller behaviour, add global
PKGMGR_DISABLE_MAKEFILE_INSTALLER switch, and simplify install target
detection.
- Rewrite resolve_command_for_repo() with explicit Repository typing,
better Python package detection, Nix/PATH resolution, and a
library-only fallback instead of raising on missing CLI.
- Update flake.nix devShell to provide python3 with pip and add pip as a
propagated build input.
- Remove deprecated/wip repository entries from config defaults and drop
the unused config/wip.yml.
https://chatgpt.com/share/69399157-86d8-800f-9935-1a820893e908
This update introduces Variant B behavior in the command resolver:
- If a repository explicitly defines the key \"command\" (even if its value is None),
resolve_command_for_repo() treats it as authoritative and returns immediately.
This allows library-only repositories to declare:
command: null
which disables CLI resolution entirely.
- As a result, Python package repositories without installed CLI entry points
no longer trigger SystemExit during update/install flows, as long as they set
command: null in their repo configuration.
The resolution logic is now bypassed for such repositories, skipping:
- Python package detection (src/*/__main__.py)
- PATH/Nix/venv binary lookup
- main.sh/main.py fallback evaluation
A new unit test suite has been added under
tests/unit/pkgmgr/core/command/test_resolve.py
covering:
1) Python package without installed command → SystemExit
2) Python package with installed command → returned correctly
3) Script repository fallback to main.py
4) Explicit command overrides all logic
This commit stabilizes update/install flows and ensures library-only
repositories behave as intended when no CLI command is provided.
https://chatgpt.com/share/69394a53-bc78-800f-995d-21099a68dd60
The pkgmgr proxy layer may intentionally terminate the process via
SystemExit(0). The previous test logic interpreted any SystemExit as a failure,
causing false negatives during `pkgmgr clone --all` E2E runs.
This patch updates `test_clone_all.py` to:
- accept SystemExit(0) as a successful run,
- only fail on non-zero exit codes,
- preserve diagnostic output for real failures.
This stabilizes the clone-all E2E test across proxy-triggered exits.
https://chatgpt.com/share/69393f6b-b854-800f-aabb-25811bbb8c74
- Use _resolve_repository_path() for explore, terminal and code commands
so tools no longer rely on a 'directory' key in the repository dict.
- Fall back to repositories_base_dir/repositories_dir via get_repo_dir()
when no explicit path-like key is present.
- Make VS Code workspace creation more robust (safe default for
directories.workspaces and UTF-8 when writing JSON).
- Add unit tests for handle_tools_command (explore, terminal, code) under
tests/unit/pkgmgr/cli/commands/test_tools.py.
- Add E2E/integration-style tests for the tools subcommands' --help
output under tests/e2e/test_tools_help.py, treating SystemExit(0) as
success.
This change fixes the KeyError: 'directory' when running 'pkgmgr code'
and verifies the behavior via unit and integration tests.
https://chatgpt.com/share/69393ca1-b554-800f-9967-abf8c4e3fea3
This commit introduces two new end-to-end integration tests:
• tests/e2e/test_clone_all.py
Runs: pkgmgr clone --all --clone-mode https --no-verification
Verifies that full HTTPS cloning of all configured repositories
works inside the test container environment.
• tests/e2e/test_update_all.py
Runs: pkgmgr update --all --clone-mode https --no-verification
Ensures that updating all repositories with HTTPS mode completes
successfully without raising exceptions.
Both tests:
- Provide extended diagnostics on SystemExit
- Reuse nix-profile cleanup helpers for consistent test environments
- Validate that `pkgmgr --help` works after execution
These tests complement the existing shallow-install integration test
and improve overall reliability of HTTPS clone/update workflows.
This commit adds a safety guard to create_ink() to prevent creation of
self-referential symlinks when the resolved command already lives at the
intended link target (e.g. ~/.local/bin/package-manager). Such a situation
previously resulted in broken shells with the error:
"zsh: too many levels of symbolic links"
Key changes:
- create_ink():
• Introduce early-abort guard when command == link_path
• Improve function signature and formatting
• Enhance alias creation messaging
- Added comprehensive unit tests under:
tests/unit/pkgmgr/core/command/test_ink.py
Tests cover:
• Self-referential command path → skip symlink creation
• Standard symlink + alias creation behaviour
This prevents pkgmgr from overwriting user-managed binaries inside ~/.local/bin
and ensures predictable, safe behaviour across all installer layers.
https://chatgpt.com/share/6938a43b-0eb8-800f-9545-6cb555ab406d
Update Debian, RPM, Nix flake, and Python installer unit tests to match the current
installer behavior and to run correctly inside the Nix development shell.
- DebianControlInstaller:
- Add clearer docstrings for supports() behavior.
- Relax final install assertion to accept dpkg -i, sudo dpkg -i, or
sudo apt-get install -y.
- Keep checks for apt-get update, apt-get build-dep, and dpkg-buildpackage.
- RpmSpecInstaller:
- Add docstrings for supports() conditions.
- Mock _prepare_source_tarball() to avoid touching the filesystem.
- Assert builddep, rpmbuild -ba, and sudo dnf install -y commands.
- NixFlakeInstaller:
- Ensure supports() and run() tests simulate a non-Nix-shell environment
via IN_NIX_SHELL and PKGMGR_DISABLE_NIX_FLAKE_INSTALLER.
- Verify that the old profile entry is removed and both pkgmgr and default
flake outputs are installed.
- Confirm _ensure_old_profile_removed() swallows SystemExit.
- PythonInstaller:
- Make supports() and run() tests ignore the real IN_NIX_SHELL environment.
- Assert that pip install . is invoked with cwd set to the repository
directory.
These changes make the unit tests stable in the Nix dev shell and align them
with the current installer implementations.
- Update pkgmgr.actions.branch.open_branch() to resolve the base branch
via _resolve_base_branch(), preferring 'main' and falling back to
'master' when the preferred branch does not exist.
- Adjust the open_branch logic to:
- fetch from origin
- checkout the resolved base branch
- pull the resolved base branch
- create the feature branch
- push the new branch with upstream tracking
- Add and refine unit tests in tests/unit/pkgmgr/actions/test_branch.py
to cover:
- normal branch creation with explicit name and default base
- interactive name prompting when no name is provided
- error handling when fetch fails after successful base resolution
- fallback to 'master' when 'main' is missing.
- Clean up and clarify docstrings and comments for open_branch(),
close_branch(), and _resolve_base_branch(), and fix the module header
comment to match the new package path.
This fixes branch opening in repositories that still use 'master' as
their primary branch while keeping the default behavior for 'main'.
https://chatgpt.com/share/6938838f-7aac-800f-b130-924e07ef48b9
- Updated update_pyproject_version() to gracefully skip missing or unreadable pyproject.toml
- Added corresponding unit test ensuring missing file triggers no exception and no file creation
- Updated test wording for spec changelog section
- Ref: adjustments discussed in ChatGPT conversation (2025-12-09) - https://chatgpt.com/share/69388024-93e4-800f-a09f-bf78a6b9a53f
This commit enhances the behaviour of pull_with_verification() and adds a
comprehensive unit test suite covering all control flows.
Changes:
- Added `preview` parameter to fully disable interaction and execution.
- Improved verification logic:
* Prompt only when not in preview, verification is enabled,
verification info exists, and verification failed.
* Skip prompts entirely when --no-verification is set.
- More explicit construction of `git pull` command with optional extra args.
- Improved messaging and formatting for clarity.
- Ensured directory existence is checked before any verification logic.
- Added detailed comments explaining logic and conditions.
Tests:
- New file tests/unit/pkgmgr/actions/repos/test_pull_with_verification.py
- Covers:
* Preview mode (no input, no subprocess)
* Verification failure – user rejects
* Verification failure – user accepts
* Verification success – immediate git call
* Missing repository directory – skip silently
* --no-verification flag bypasses prompts
* Command formatting with extra args
- Uses systematic mocking for identifier, repo-dir, verify_repository(),
subprocess.run(), and user input.
This significantly strengthens correctness, UX, and test coverage of the
repository pull workflow.
https://chatgpt.com/share/69384aaa-0c80-800f-b4b4-64e6fbdebd3b
This commit introduces proper handling of the `ignore: true` flag in the
repository selection mechanism and adds comprehensive unit tests for both
`ignored.py` and `selected.py`.
- `get_selected_repos()` now filters ignored repositories in all implicit
selection modes:
• filter-only mode (string/category/tag)
• `--all` mode
• CWD-based selection
- Explicit identifiers (e.g. `pkgmgr install ignored-repo`) **bypass**
ignore filtering, so the user can still operate directly on ignored
repositories if they ask for them explicitly.
- Added `_maybe_filter_ignored()` helper to handle logic cleanly and allow
future extension (e.g. integrating a CLI flag `--include-ignored`).
Under `tests/unit/pkgmgr/core/repository`:
1. **test_ignored.py**
• Ensures `filter_ignored()` removes repos with `ignore: true`
• Ensures empty lists are handled correctly
2. **test_selected.py**
Comprehensive coverage of the selection logic:
• Explicit identifiers bypass ignore filtering
• Filter-only mode excludes ignored repos unless `include_ignored=True`
• `--all` mode excludes ignored repos unless explicitly overridden
• CWD-based detection filters ignored repos unless explicitly overridden
Before this change, ignored repositories still appeared in `pkgmgr list`,
`pkgmgr status`, and other commands using `get_selected_repos()`.
This was unintuitive and broke the expected semantics of the `ignore`
attribute.
The new logic ensures ignored repositories are truly invisible unless
explicitly requested.
https://chatgpt.com/share/69383b41-50a0-800f-a2b9-c680cd96d9e9
- Move the monolithic pkgmgr/actions/release.py implementation into the
pkgmgr.actions.release package, splitting concerns into versioning,
git_ops and files helpers.
- Extend the release orchestration to update Fedora/RPM %changelog
entries via update_spec_changelog(), reusing the same effective
release message as for CHANGELOG.md and debian/changelog.
- Wire the new update_spec_changelog() helper into _release_impl() so
every release keeps project, Debian and RPM metadata in sync.
- Add unit tests for update_spec_changelog() and for the updated release
orchestration behaviour in preview and real modes.
- Remove the deprecated pkgmgr/actions/release.py module.
See ChatGPT discussion: https://chatgpt.com/share/6938368e-0940-800f-92d3-f2ccfddab794
This commit introduces a large-scale structural refactor of the pkgmgr
codebase. All functionality has been moved from the previous flat
top-level layout into three clearly separated namespaces:
• pkgmgr.actions – high-level operations invoked by the CLI
• pkgmgr.core – pure logic, helpers, repository utilities,
versioning, git helpers, config IO, and
command resolution
• pkgmgr.cli – parser, dispatch, context, and command
handlers
Key improvements:
- Moved all “branch”, “release”, “changelog”, repo-management
actions, installer pipelines, and proxy execution logic into
pkgmgr.actions.<domain>.
- Reworked installer structure under
pkgmgr.actions.repository.install.installers
including OS-package installers, Nix, Python, and Makefile.
- Consolidated all low-level functionality under pkgmgr.core:
• git helpers → core/git
• config load/save → core/config
• repository helpers → core/repository
• versioning & semver → core/version
• command helpers (alias, resolve, run, ink) → core/command
- Replaced pkgmgr.cli_core with pkgmgr.cli and updated all imports.
- Added minimal __init__.py files for clean package exposure.
- Updated all E2E, integration, and unit tests with new module paths.
- Fixed patch targets so mocks point to the new structure.
- Ensured backward compatibility at the CLI boundary (pkgmgr entry point unchanged).
This refactor produces a cleaner, layered architecture:
- `core` = logic
- `actions` = orchestrated behaviour
- `cli` = user interface
Reference: ChatGPT-assisted refactor discussion
https://chatgpt.com/share/6938221c-e24c-800f-8317-7732cedf39b9
- Added rich error reporting to install_repos() for clearer installer failure context
(repository identifier, repo directory, installer name, exit code).
- Updated E2E test 'install_all_shallow' to show additional diagnostics,
including Nix profile dumps and contextual SystemExit handling.
- Removed outdated/deactivated test file.
- New test now mirrors the robust debugging flow of the pkgmgr-only test.
See conversation for full context:
https://chatgpt.com/share/6936241b-52ec-800f-9859-1734a581c002
References:
- Current ChatGPT conversation: https://chatgpt.com/share/6935d6d7-0ae4-800f-988a-44a50c17ba48
- Extended discussion: https://chatgpt.com/share/6935d734-fd84-800f-9755-290902b8cee8
Summary:
This commit performs a major cleanup and modernization of the installation pipeline:
1. Introduced a new capability-detection subsystem:
- Capabilities (python-runtime, make-install, nix-flake) are detected per installer/layer.
- Installers run only when they add new capabilities.
- Prevents duplicated work such as Python installers running when Nix already provides the runtime.
2. Removed deprecated pkgmgr.yml manifest installer:
- Dependency resolution is now delegated entirely to real package managers (Nix, pip, make, distro build tools).
- Simplifies layering and avoids unnecessary recursion.
3. Reworked OS-specific installers:
- Arch PKGBUILD now uses 'makepkg --syncdeps --cleanbuild --install --noconfirm'.
- Debian installer now builds proper .deb packages via dpkg-buildpackage + installs them.
- RPM installer now builds packages using rpmbuild and installs them via rpm.
4. Switched from remote GitHub flakes to local-flake execution:
- Wrapper now executes: nix run /usr/lib/package-manager#pkgmgr
- Avoids lock-file write attempts and improves reliability in CI.
5. Added bash -i based integration test:
- Correctly sources ~/.bashrc and evaluates alias + venv activation.
- ‘pkgmgr --help’ is now printed for debugging without failing tests.
6. Updated unit tests across all installers:
- Removed references to manifest installer.
- Adjusted expectations for new behaviors (makepkg, dpkg-buildpackage, rpmbuild).
- Added capability subsystem tests.
7. Improved flake.nix packaging logic:
- The entire project source tree is copied into the runtime closure.
- pkgmgr wrapper now executes runpy inside the packaged directory.
Together, these changes create a predictable, layered, capability-driven installer pipeline with consistent behavior across Arch, Debian, RPM, Nix, and Python layers.