dotman-git 1.3.0__tar.gz → 1.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dotman_git-1.3.0 → dotman_git-1.4.0}/CHANGELOG.md +44 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/PKG-INFO +9 -10
- {dotman_git-1.3.0 → dotman_git-1.4.0}/README.md +7 -7
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/__init__.py +1 -1
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/__init__.py +6 -2
- dotman_git-1.4.0/dot_man/cli/bootstrap_cmd.py +240 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/common.py +22 -0
- dotman_git-1.4.0/dot_man/cli/completion_engine.py +445 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/completions_cmd.py +36 -21
- dotman_git-1.4.0/dot_man/cli/config_cmd.py +243 -0
- dotman_git-1.3.0/dot_man/cli/config_cmd.py → dotman_git-1.4.0/dot_man/cli/config_tutorial.py +114 -378
- dotman_git-1.4.0/dot_man/cli/hooks_cmd.py +66 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/main.py +7 -2
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/navigate_cmd.py +16 -286
- dotman_git-1.4.0/dot_man/cli/navigate_preview.py +189 -0
- dotman_git-1.4.0/dot_man/cli/save_cmd.py +190 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/status_cmd.py +43 -6
- dotman_git-1.4.0/dot_man/cli/vault_cmd.py +93 -0
- dotman_git-1.4.0/dot_man/completions/dot-man.fish +13 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/core.py +8 -4
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/dotman_config.py +2 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/files.py +4 -4
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/section.py +13 -5
- dotman_git-1.4.0/dot_man/shared_sync.py +301 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dotman_git.egg-info/PKG-INFO +9 -10
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dotman_git.egg-info/SOURCES.txt +14 -1
- {dotman_git-1.3.0 → dotman_git-1.4.0}/pyproject.toml +10 -5
- dotman_git-1.4.0/tests/test_audit_cmd_extended.py +217 -0
- dotman_git-1.4.0/tests/test_bootstrap_cmd.py +269 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_completion.py +9 -11
- dotman_git-1.4.0/tests/test_completion_engine.py +333 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_completions_cmd.py +33 -3
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_config_cmd.py +12 -9
- dotman_git-1.4.0/tests/test_export_cmd.py +184 -0
- dotman_git-1.4.0/tests/test_revert_cmd_extended.py +106 -0
- dotman_git-1.4.0/tests/test_shared_sync.py +330 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_shell_completions.py +9 -11
- dotman_git-1.4.0/tests/test_tag_cmd.py +205 -0
- dotman_git-1.4.0/tests/test_vault.py +281 -0
- dotman_git-1.4.0/tests/test_vault_cmd.py +165 -0
- dotman_git-1.4.0/tests/test_verify_cmd.py +276 -0
- dotman_git-1.3.0/dot_man/completions/dot-man.fish +0 -58
- dotman_git-1.3.0/dot_man/completions/install.sh +0 -26
- dotman_git-1.3.0/tests/test_export_cmd.py +0 -94
- dotman_git-1.3.0/tests/test_tag_cmd.py +0 -105
- dotman_git-1.3.0/tests/test_vault.py +0 -148
- dotman_git-1.3.0/tests/test_verify_cmd.py +0 -93
- {dotman_git-1.3.0 → dotman_git-1.4.0}/CONTRIBUTING.md +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/LICENSE +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/MANIFEST.in +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/backups.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/branch_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/add_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/audit_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/backup_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/branch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/clean_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/completions.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/deploy_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/discover_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/doctor_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/edit_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/encrypt_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/export_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/import_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/init_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/interface.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/log_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/onboarding.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/profile_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/remote_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/restore_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/revert_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/rollback_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/show_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/switch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/tag_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/template_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/tui_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/verify_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/cli/watch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/completions/_dot-man.zsh +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/completions/dot-man.bash +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/config_detector.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/constants.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/encryption.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/exceptions.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/global_config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/hooks.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/interactive.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/lock.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/merge.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/operations.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/py.typed +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/save_deploy_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/secrets.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/status_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/tui_log.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/ui.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/utils.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dot_man/vault.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dotman_git.egg-info/dependency_links.txt +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dotman_git.egg-info/entry_points.txt +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dotman_git.egg-info/requires.txt +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/dotman_git.egg-info/top_level.txt +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/setup.cfg +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_add_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_audit_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_backup_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_backups.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_branch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_branch_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_clean.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_cli_commands.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_cli_extra.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_cli_help.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_cli_revert.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_cli_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_common_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_comprehensive.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_config_cmd_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_config_ops_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_config_preservation.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_config_section.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_core.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_core_extended.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_core_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_custom_secrets.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_deploy_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_discover_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_doctor_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_dotman_config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_edit_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_encrypt_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_encryption.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_exceptions.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_files_atomic.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_files_comprehensive.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_files_extended.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_final_push.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_fixtures.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_git_manager.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_git_manager_extended.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_global_config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_hooks.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_hooks_new.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_import_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_init_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_integration.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_interactive.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_lock.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_log_checkout_tag.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_log_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_log_cmd_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_merge.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_more_integration.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_navigate_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_navigate_helpers.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_navigate_switch_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_onboarding.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_operations.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_ops_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_performance_logic.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_profile_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_profile_cmd_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_profile_extra.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_remote_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_restore_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_rollback_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_save_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_save_deploy_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_secrets.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_section.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_show_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_status_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_status_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_switch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_switch_enhancements.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_symlink_deploy.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_template_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_template_cmd_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_template_extra.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_ui.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_utils.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.4.0}/tests/test_watch_cmd.py +0 -0
|
@@ -7,6 +7,50 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Shell completions for `add` command** — file/directory path completion using `@completes("add", param="path")` decorator
|
|
13
|
+
- **Shell completions for `bootstrap` command** — package manager name completion (`brew`, `apt`, `dnf`, `pacman`, etc.) via `@completes("bootstrap", param="pm")` decorator
|
|
14
|
+
- **19 new documentation pages** — dedicated pages for `init`, `add`, `deploy`, `tag`, `log`, `diff`, `revert`, `import`, `export`, `discover`, `encrypt`, `hooks`, `template`, `profile`, `watch`, `rollback`, `backup`, `verify`, `completions` commands
|
|
15
|
+
- **Docs navigation restructured** — commands grouped by category (Core, Configuration, Inspection, Tags, Encryption, Import/Export, Hooks, Shell)
|
|
16
|
+
- **Roadmap updated** — consistent with v1.4.0 state, removed stale duplicate sections
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **`save_cmd.py`** — fixed `_sync_shared_sections` → `sync_shared_sections` name mismatch that caused `NameError` on `--commit` flag
|
|
21
|
+
- **`shared_sync.py`** — `_sync_branch` now records overridden sections in `report.skipped` even when other shared sections are still wanted (partial overrides)
|
|
22
|
+
- **`test_shared_sync.py`** — fixed test expectations for `test_edits_reach_non_overriding_branches` (work overrides fish, so only server gets propagated), `test_unparsable_target_config_is_skipped_safely` (fixed `run_git()` call to use `subprocess.run` with `input=`), `test_source_branch_never_modified` (fixed log assertion to use `-1` flag)
|
|
23
|
+
- **Tests** — all 1700 tests passing (up from 1691), 1 skipped
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **Repository cleanup** — single source of truth for completion scripts (`dot_man/completions/`); removed the duplicated `scripts/completions/` copies and the unused packaged `install.sh`. `install.sh` now installs completions via the built-in `dot-man completions` command. Removed the stale `docs/development/roadmap.md` duplicate and surfaced `docs/roadmap.md` in the docs site nav.
|
|
28
|
+
|
|
29
|
+
### Removed
|
|
30
|
+
|
|
31
|
+
- **Tracked artifacts** — dropped `coverage.json` (256 KB CI artifact) and the author's personal `config.toml` from version control; both now gitignored along with benchmark output.
|
|
32
|
+
- **Local clutter** — `.gitignore` fixed (broken merged pattern) and extended: coverage reports, benchmarks, stale build/dist/site outputs no longer pollute the working tree.
|
|
33
|
+
|
|
34
|
+
## [1.4.0] - 2026-08-25
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **Decorator-driven completion engine** — new `dot_man/cli/completion_engine.py` gathers commands, subcommands, options, accepted values (static or dynamic) and defaults from the Click CLI definition itself. Extended via the `@completes(path, param=...)` decorator registry; a `(path, param)` registration wins over the generic one.
|
|
39
|
+
- **`dot-man --complete <shell>` protocol** — handled before onboarding/git/side effects in `main()`. Fish output uses `value<TAB>description` lines so descriptions render natively.
|
|
40
|
+
- **Defaults & choices surfaced** — option completions now show `[choices: bash|zsh|fish|all]` and `[default: all]` inline (e.g. `dot-man completions --s<TAB>`).
|
|
41
|
+
- **Alias labeling** — shell shortcuts like `nav`, `cpl`, `aud` are listed as `(alias)` entries instead of indistinguishable duplicates.
|
|
42
|
+
- **`--option=<TAB>` form** — completing after `=` emits full tokens (`--shell=fish`).
|
|
43
|
+
- **Static choice provider** — `config set KEY <TAB>` suggests `true`/`false`.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- **Fish completions showed invalid/stale choices** — the hand-written `dot-man.fish` listed missing commands (`backup`, `tag`, `template`, `profile`, `doctor`, ...), treated navigate options as subcommands, and kept deprecated `switch` prominent. It is now a tiny delegating script calling `dot-man --complete fish` on every TAB (wifi-tracker style), so completions can never go stale.
|
|
48
|
+
- **Unformatted fish output** — the old script's naive `string split ","` broke on help text containing commas and dropped descriptions. Tab-separated engine output renders descriptions natively in fish.
|
|
49
|
+
|
|
50
|
+
### Tests
|
|
51
|
+
|
|
52
|
+
- 37 new tests in `tests/test_completion_engine.py` (registry priority, root/subcommand listing, static choices, defaults display, alias labeling, eq-form values, dynamic git-backed callbacks, request parsing, formatting, entry safety). Suite: 1682 passed, coverage 84% (up from 81%).
|
|
53
|
+
|
|
10
54
|
## [1.3.0] - 2026-06-27
|
|
11
55
|
|
|
12
56
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dotman-git
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Dotfile manager with git-powered branching
|
|
5
5
|
Author-email: Bishoy Ehab <beshoyehabhhmm@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -18,7 +18,6 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
18
18
|
Classifier: Operating System :: POSIX :: Linux
|
|
19
19
|
Classifier: Operating System :: MacOS
|
|
20
20
|
Classifier: Programming Language :: Python :: 3
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.10
|
|
23
22
|
Classifier: Programming Language :: Python :: 3.11
|
|
24
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -26,7 +25,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
26
25
|
Classifier: Topic :: System :: Systems Administration
|
|
27
26
|
Classifier: Topic :: Utilities
|
|
28
27
|
Classifier: Typing :: Typed
|
|
29
|
-
Requires-Python: >=3.
|
|
28
|
+
Requires-Python: >=3.10
|
|
30
29
|
Description-Content-Type: text/markdown
|
|
31
30
|
License-File: LICENSE
|
|
32
31
|
Requires-Dist: click>=8.0
|
|
@@ -64,19 +63,20 @@ Dynamic: license-file
|
|
|
64
63
|
[](https://github.com/BeshoyEhab/dot-man/actions/workflows/ci.yml)
|
|
65
64
|
[](https://pypi.org/project/dotman-git/)
|
|
66
65
|
[](https://pypi.org/project/dotman-git/)
|
|
67
|
-
[](https://pypi.org/project/dotman-git/)
|
|
66
|
+
[](https://pypi.org/project/dotman-git/)
|
|
68
67
|
[](https://opensource.org/licenses/MIT)
|
|
69
68
|
[](https://github.com/psf/black)
|
|
70
69
|
[](https://github.com/astral-sh/ruff)
|
|
71
70
|
[](https://mypy-lang.org/)
|
|
72
|
-
[](https://github.com/BeshoyEhab/dot-man)
|
|
72
|
+
[](https://beshoyehab.github.io/dot-man/)
|
|
73
73
|
[](https://github.com/BeshoyEhab/dot-man/pulls)
|
|
74
74
|
|
|
75
75
|
---
|
|
76
76
|
|
|
77
77
|
*Switch your entire development environment in one command.*
|
|
78
78
|
|
|
79
|
-
[**Install**](#installation) · [**Quick Start**](#quick-start) · [**Commands**](#commands) · [**Config**](#configuration) · [**Docs**](
|
|
79
|
+
[**Install**](https://github.com/BeshoyEhab/dot-man#installation) · [**Quick Start**](https://github.com/BeshoyEhab/dot-man#quick-start) · [**Commands**](https://github.com/BeshoyEhab/dot-man#commands) · [**Config**](https://github.com/BeshoyEhab/dot-man#configuration) · [**Docs**](https://beshoyehab.github.io/dot-man/)
|
|
80
80
|
|
|
81
81
|
</div>
|
|
82
82
|
|
|
@@ -125,7 +125,7 @@ Your Machine dot-man Repo Any Machine
|
|
|
125
125
|
<td>
|
|
126
126
|
|
|
127
127
|
**Developer**
|
|
128
|
-
- 🐚 Shell completions (bash/zsh/fish)
|
|
128
|
+
- 🐚 Shell completions (bash/zsh/fish) — decorator-driven engine, always in sync with the CLI
|
|
129
129
|
- 🎨 Syntax-highlighted rich diffs
|
|
130
130
|
- 🩺 `doctor` and `verify` diagnostics
|
|
131
131
|
- 📦 PyPI — `pip install dotman-git`
|
|
@@ -181,7 +181,6 @@ dot-man add ~/.config/nvim
|
|
|
181
181
|
|
|
182
182
|
# 3. Create a "work" profile (branch)
|
|
183
183
|
dot-man navigate work
|
|
184
|
-
# btw it was "switch" instead of "navigate" untill Bishoy decided to change it to "navigate" for some silly reasons and push that changes so as community help us to make it "switch" again.
|
|
185
184
|
|
|
186
185
|
# 4. Edit your work-specific configs, then switch back — changes are saved automatically
|
|
187
186
|
dot-man navigate main
|
|
@@ -480,10 +479,10 @@ System variables (`{{HOSTNAME}}`, `{{USER}}`, `{{SHELL}}`, etc.) are auto-popula
|
|
|
480
479
|
|
|
481
480
|
| Metric | Value |
|
|
482
481
|
|--------|-------|
|
|
483
|
-
| Version | `1.
|
|
482
|
+
| Version | `1.4.0` |
|
|
484
483
|
| Python | `3.10 · 3.11 · 3.12 · 3.13` |
|
|
485
484
|
| Platforms | Linux, macOS |
|
|
486
|
-
| Test Coverage |
|
|
485
|
+
| Test Coverage | 84% (1682 tests) |
|
|
487
486
|
| Commands | 30+ |
|
|
488
487
|
| PyPI | [`dotman-git`](https://pypi.org/project/dotman-git/) |
|
|
489
488
|
|
|
@@ -7,19 +7,20 @@
|
|
|
7
7
|
[](https://github.com/BeshoyEhab/dot-man/actions/workflows/ci.yml)
|
|
8
8
|
[](https://pypi.org/project/dotman-git/)
|
|
9
9
|
[](https://pypi.org/project/dotman-git/)
|
|
10
|
-
[](https://pypi.org/project/dotman-git/)
|
|
10
|
+
[](https://pypi.org/project/dotman-git/)
|
|
11
11
|
[](https://opensource.org/licenses/MIT)
|
|
12
12
|
[](https://github.com/psf/black)
|
|
13
13
|
[](https://github.com/astral-sh/ruff)
|
|
14
14
|
[](https://mypy-lang.org/)
|
|
15
|
-
[](https://github.com/BeshoyEhab/dot-man)
|
|
16
|
+
[](https://beshoyehab.github.io/dot-man/)
|
|
16
17
|
[](https://github.com/BeshoyEhab/dot-man/pulls)
|
|
17
18
|
|
|
18
19
|
---
|
|
19
20
|
|
|
20
21
|
*Switch your entire development environment in one command.*
|
|
21
22
|
|
|
22
|
-
[**Install**](#installation) · [**Quick Start**](#quick-start) · [**Commands**](#commands) · [**Config**](#configuration) · [**Docs**](
|
|
23
|
+
[**Install**](https://github.com/BeshoyEhab/dot-man#installation) · [**Quick Start**](https://github.com/BeshoyEhab/dot-man#quick-start) · [**Commands**](https://github.com/BeshoyEhab/dot-man#commands) · [**Config**](https://github.com/BeshoyEhab/dot-man#configuration) · [**Docs**](https://beshoyehab.github.io/dot-man/)
|
|
23
24
|
|
|
24
25
|
</div>
|
|
25
26
|
|
|
@@ -68,7 +69,7 @@ Your Machine dot-man Repo Any Machine
|
|
|
68
69
|
<td>
|
|
69
70
|
|
|
70
71
|
**Developer**
|
|
71
|
-
- 🐚 Shell completions (bash/zsh/fish)
|
|
72
|
+
- 🐚 Shell completions (bash/zsh/fish) — decorator-driven engine, always in sync with the CLI
|
|
72
73
|
- 🎨 Syntax-highlighted rich diffs
|
|
73
74
|
- 🩺 `doctor` and `verify` diagnostics
|
|
74
75
|
- 📦 PyPI — `pip install dotman-git`
|
|
@@ -124,7 +125,6 @@ dot-man add ~/.config/nvim
|
|
|
124
125
|
|
|
125
126
|
# 3. Create a "work" profile (branch)
|
|
126
127
|
dot-man navigate work
|
|
127
|
-
# btw it was "switch" instead of "navigate" untill Bishoy decided to change it to "navigate" for some silly reasons and push that changes so as community help us to make it "switch" again.
|
|
128
128
|
|
|
129
129
|
# 4. Edit your work-specific configs, then switch back — changes are saved automatically
|
|
130
130
|
dot-man navigate main
|
|
@@ -423,10 +423,10 @@ System variables (`{{HOSTNAME}}`, `{{USER}}`, `{{SHELL}}`, etc.) are auto-popula
|
|
|
423
423
|
|
|
424
424
|
| Metric | Value |
|
|
425
425
|
|--------|-------|
|
|
426
|
-
| Version | `1.
|
|
426
|
+
| Version | `1.4.0` |
|
|
427
427
|
| Python | `3.10 · 3.11 · 3.12 · 3.13` |
|
|
428
428
|
| Platforms | Linux, macOS |
|
|
429
|
-
| Test Coverage |
|
|
429
|
+
| Test Coverage | 84% (1682 tests) |
|
|
430
430
|
| Commands | 30+ |
|
|
431
431
|
| PyPI | [`dotman-git`](https://pypi.org/project/dotman-git/) |
|
|
432
432
|
|
|
@@ -4,7 +4,7 @@ This package provides the CLI entry point for dot-man.
|
|
|
4
4
|
It exposes the modular CLI implementation.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from . import discover_cmd, encrypt_cmd, export_cmd, import_cmd
|
|
7
|
+
from . import bootstrap_cmd, discover_cmd, encrypt_cmd, export_cmd, import_cmd
|
|
8
8
|
from .add_cmd import add
|
|
9
9
|
from .audit_cmd import audit
|
|
10
10
|
from .backup_cmd import backup
|
|
@@ -35,19 +35,21 @@ from .config_cmd import config
|
|
|
35
35
|
from .deploy_cmd import deploy
|
|
36
36
|
from .doctor_cmd import doctor
|
|
37
37
|
from .edit_cmd import edit
|
|
38
|
+
from .hooks_cmd import hooks
|
|
38
39
|
|
|
39
40
|
# Import commands for easier access and backward compatibility
|
|
40
41
|
from .init_cmd import init
|
|
41
42
|
from .interface import cli
|
|
42
43
|
from .log_cmd import checkout, diff, log
|
|
43
44
|
from .main import main
|
|
44
|
-
from .navigate_cmd import
|
|
45
|
+
from .navigate_cmd import navigate
|
|
45
46
|
from .onboarding import is_first_run, mark_onboarded, run_onboarding
|
|
46
47
|
from .profile_cmd import profile
|
|
47
48
|
from .remote_cmd import remote, sync
|
|
48
49
|
from .restore_cmd import restore
|
|
49
50
|
from .revert_cmd import revert
|
|
50
51
|
from .rollback_cmd import rollback
|
|
52
|
+
from .save_cmd import save
|
|
51
53
|
from .show_cmd import show
|
|
52
54
|
from .status_cmd import status
|
|
53
55
|
from .switch_cmd import switch
|
|
@@ -96,6 +98,7 @@ __all__ = [
|
|
|
96
98
|
"config",
|
|
97
99
|
"revert",
|
|
98
100
|
"restore",
|
|
101
|
+
"save",
|
|
99
102
|
"clean",
|
|
100
103
|
"doctor",
|
|
101
104
|
"verify",
|
|
@@ -112,6 +115,7 @@ __all__ = [
|
|
|
112
115
|
"export_cmd",
|
|
113
116
|
"encrypt_cmd",
|
|
114
117
|
"discover_cmd",
|
|
118
|
+
"bootstrap_cmd",
|
|
115
119
|
"completions",
|
|
116
120
|
"watch",
|
|
117
121
|
"rollback",
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""Bootstrap command for dot-man — install packages via system package managers."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import shutil
|
|
5
|
+
import subprocess
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
from .. import ui
|
|
10
|
+
from .common import require_init, success, warn
|
|
11
|
+
from .interface import cli as main
|
|
12
|
+
|
|
13
|
+
# Package manager detection: command → (install_cmd, update_cmd)
|
|
14
|
+
PACKAGE_MANAGERS = {
|
|
15
|
+
"brew": {
|
|
16
|
+
"install": "brew install {package}",
|
|
17
|
+
"update": "brew update",
|
|
18
|
+
"detect": "brew",
|
|
19
|
+
},
|
|
20
|
+
"apt": {
|
|
21
|
+
"install": "sudo apt-get install -y {package}",
|
|
22
|
+
"update": "sudo apt-get update",
|
|
23
|
+
"detect": "apt-get",
|
|
24
|
+
},
|
|
25
|
+
"dnf": {
|
|
26
|
+
"install": "sudo dnf install -y {package}",
|
|
27
|
+
"update": "sudo dnf check-update",
|
|
28
|
+
"detect": "dnf",
|
|
29
|
+
},
|
|
30
|
+
"pacman": {
|
|
31
|
+
"install": "sudo pacman -S --noconfirm {package}",
|
|
32
|
+
"update": "sudo pacman -Sy",
|
|
33
|
+
"detect": "pacman",
|
|
34
|
+
},
|
|
35
|
+
"zypper": {
|
|
36
|
+
"install": "sudo zypper install -y {package}",
|
|
37
|
+
"update": "sudo zypper refresh",
|
|
38
|
+
"detect": "zypper",
|
|
39
|
+
},
|
|
40
|
+
"nix-env": {
|
|
41
|
+
"install": "nix-env -iA nixpkgs.{package}",
|
|
42
|
+
"update": "nix-channel --update",
|
|
43
|
+
"detect": "nix-env",
|
|
44
|
+
},
|
|
45
|
+
"xbps-install": {
|
|
46
|
+
"install": "sudo xbps-install -y {package}",
|
|
47
|
+
"update": "sudo xbps-install -Su",
|
|
48
|
+
"detect": "xbps-install",
|
|
49
|
+
},
|
|
50
|
+
"pkg": {
|
|
51
|
+
"install": "pkg install -y {package}",
|
|
52
|
+
"update": "pkg update",
|
|
53
|
+
"detect": "pkg",
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _detect_package_manager() -> str | None:
|
|
59
|
+
"""Detect the available package manager on this system."""
|
|
60
|
+
import platform
|
|
61
|
+
|
|
62
|
+
os_name = platform.system().lower()
|
|
63
|
+
|
|
64
|
+
# Preferred order by OS
|
|
65
|
+
if os_name == "darwin":
|
|
66
|
+
preferred = ["brew"]
|
|
67
|
+
elif os_name == "linux":
|
|
68
|
+
preferred = ["apt", "dnf", "pacman", "zypper", "xbps-install", "nix-env"]
|
|
69
|
+
elif os_name == "freebsd":
|
|
70
|
+
preferred = ["pkg"]
|
|
71
|
+
else:
|
|
72
|
+
preferred = list(PACKAGE_MANAGERS.keys())
|
|
73
|
+
|
|
74
|
+
for pm in preferred:
|
|
75
|
+
if shutil.which(PACKAGE_MANAGERS[pm]["detect"]):
|
|
76
|
+
return pm
|
|
77
|
+
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _load_bootstrap_packages() -> dict[str, list[str]]:
|
|
82
|
+
"""Load packages from dot-man config or bootstrap.toml."""
|
|
83
|
+
try:
|
|
84
|
+
from ..config import DotManConfig
|
|
85
|
+
|
|
86
|
+
config = DotManConfig()
|
|
87
|
+
config.load()
|
|
88
|
+
|
|
89
|
+
# Check for [bootstrap] section in config
|
|
90
|
+
bootstrap = config._data.get("bootstrap", {})
|
|
91
|
+
if bootstrap:
|
|
92
|
+
packages = {}
|
|
93
|
+
# Support both flat list and grouped format
|
|
94
|
+
if isinstance(bootstrap, dict):
|
|
95
|
+
for key, value in bootstrap.items():
|
|
96
|
+
if key == "packages" and isinstance(value, list):
|
|
97
|
+
packages["default"] = value
|
|
98
|
+
elif isinstance(value, list):
|
|
99
|
+
packages[key] = value
|
|
100
|
+
return packages
|
|
101
|
+
|
|
102
|
+
except Exception as e:
|
|
103
|
+
logging.debug(f"Failed to load bootstrap config: {e}")
|
|
104
|
+
|
|
105
|
+
return {}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _run_with_pm(pm: str, command_template: str, package: str) -> bool:
|
|
109
|
+
"""Run a package manager command. Returns True on success."""
|
|
110
|
+
cmd = command_template.format(package=package)
|
|
111
|
+
ui.console.print(f" [cyan]$ {cmd}[/cyan]")
|
|
112
|
+
try:
|
|
113
|
+
result = subprocess.run(
|
|
114
|
+
cmd, shell=True, capture_output=True, text=True, timeout=300
|
|
115
|
+
)
|
|
116
|
+
if result.returncode == 0:
|
|
117
|
+
return True
|
|
118
|
+
else:
|
|
119
|
+
warn(f"Failed to install {package} (exit code {result.returncode})")
|
|
120
|
+
if result.stderr:
|
|
121
|
+
for line in result.stderr.splitlines()[:3]:
|
|
122
|
+
ui.console.print(f" [dim]{line}[/dim]")
|
|
123
|
+
return False
|
|
124
|
+
except subprocess.TimeoutExpired:
|
|
125
|
+
warn(f"Timeout installing {package}")
|
|
126
|
+
return False
|
|
127
|
+
except Exception as e:
|
|
128
|
+
warn(f"Error installing {package}: {e}")
|
|
129
|
+
return False
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@main.command("bootstrap")
|
|
133
|
+
@click.option(
|
|
134
|
+
"--list",
|
|
135
|
+
"list_only",
|
|
136
|
+
is_flag=True,
|
|
137
|
+
help="List packages that would be installed without installing",
|
|
138
|
+
)
|
|
139
|
+
@click.option("--pm", help="Package manager to use (auto-detected if not specified)")
|
|
140
|
+
@click.option("--update", is_flag=True, help="Update package manager first")
|
|
141
|
+
@click.argument("packages", nargs=-1)
|
|
142
|
+
@require_init
|
|
143
|
+
def bootstrap(list_only: bool, pm: str | None, update: bool, packages: tuple[str, ...]):
|
|
144
|
+
"""Install system packages via package managers.
|
|
145
|
+
|
|
146
|
+
Detects your system package manager (brew, apt, dnf, pacman, etc.)
|
|
147
|
+
and installs the specified packages. Packages can also be defined
|
|
148
|
+
in your dot-man config under [bootstrap].
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
# Install specific packages
|
|
152
|
+
dot-man bootstrap neovim tmux git
|
|
153
|
+
|
|
154
|
+
# List what would be installed from config
|
|
155
|
+
dot-man bootstrap --list
|
|
156
|
+
|
|
157
|
+
# Use a specific package manager
|
|
158
|
+
dot-man bootstrap --pm brew neovim
|
|
159
|
+
|
|
160
|
+
# Update package manager first
|
|
161
|
+
dot-man bootstrap --update neovim
|
|
162
|
+
"""
|
|
163
|
+
# Detect package manager
|
|
164
|
+
if not pm:
|
|
165
|
+
pm = _detect_package_manager()
|
|
166
|
+
if not pm:
|
|
167
|
+
ui.console.print("[red]No supported package manager found.[/red]")
|
|
168
|
+
ui.console.print(
|
|
169
|
+
"Supported: brew, apt, dnf, pacman, zypper, nix-env, xbps-install, pkg"
|
|
170
|
+
)
|
|
171
|
+
ui.console.print("Use --pm to specify one manually.")
|
|
172
|
+
raise SystemExit(1)
|
|
173
|
+
|
|
174
|
+
if pm not in PACKAGE_MANAGERS:
|
|
175
|
+
ui.console.print(f"[red]Unknown package manager: {pm}[/red]")
|
|
176
|
+
raise SystemExit(1)
|
|
177
|
+
|
|
178
|
+
pm_info = PACKAGE_MANAGERS[pm]
|
|
179
|
+
ui.console.print(f"[bold]Using package manager:[/bold] [cyan]{pm}[/cyan]")
|
|
180
|
+
|
|
181
|
+
# Collect packages from args and config
|
|
182
|
+
all_packages: dict[str, list[str]] = {}
|
|
183
|
+
|
|
184
|
+
if packages:
|
|
185
|
+
all_packages["command-line"] = list(packages)
|
|
186
|
+
|
|
187
|
+
config_packages = _load_bootstrap_packages()
|
|
188
|
+
all_packages.update(config_packages)
|
|
189
|
+
|
|
190
|
+
if not all_packages:
|
|
191
|
+
ui.console.print("[yellow]No packages specified.[/yellow]")
|
|
192
|
+
ui.console.print("Usage: dot-man bootstrap <package1> <package2> ...")
|
|
193
|
+
ui.console.print("Or add [bootstrap] section to your dot-man.toml:")
|
|
194
|
+
ui.console.print(' [bootstrap]\n packages = ["neovim", "tmux", "git"]')
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
# List mode
|
|
198
|
+
if list_only:
|
|
199
|
+
ui.console.print()
|
|
200
|
+
ui.console.print("[bold]Packages to install:[/bold]")
|
|
201
|
+
for group, pkgs in all_packages.items():
|
|
202
|
+
ui.console.print(f" [cyan]{group}:[/cyan]")
|
|
203
|
+
for pkg in pkgs:
|
|
204
|
+
ui.console.print(f" • {pkg}")
|
|
205
|
+
ui.console.print()
|
|
206
|
+
total = sum(len(pkgs) for pkgs in all_packages.values())
|
|
207
|
+
ui.console.print(f" [dim]{total} package(s) total[/dim]")
|
|
208
|
+
return
|
|
209
|
+
|
|
210
|
+
# Update package manager if requested
|
|
211
|
+
if update:
|
|
212
|
+
ui.console.print()
|
|
213
|
+
ui.console.print("[bold]Updating package manager...[/bold]")
|
|
214
|
+
_run_with_pm(pm, pm_info["update"], "")
|
|
215
|
+
|
|
216
|
+
# Install packages
|
|
217
|
+
installed = 0
|
|
218
|
+
failed = 0
|
|
219
|
+
|
|
220
|
+
for group, pkgs in all_packages.items():
|
|
221
|
+
ui.console.print()
|
|
222
|
+
ui.console.print(f"[bold]Installing {group}:[/bold]")
|
|
223
|
+
for pkg in pkgs:
|
|
224
|
+
ui.console.print(f"\n[bold]→ {pkg}[/bold]")
|
|
225
|
+
result = _run_with_pm(pm, pm_info["install"], pkg)
|
|
226
|
+
if result:
|
|
227
|
+
installed += 1
|
|
228
|
+
else:
|
|
229
|
+
failed += 1
|
|
230
|
+
|
|
231
|
+
# Summary
|
|
232
|
+
ui.console.print()
|
|
233
|
+
ui.console.print("[bold]Bootstrap complete:[/bold]")
|
|
234
|
+
ui.console.print(f" [green]✓ {installed} installed[/green]")
|
|
235
|
+
if failed:
|
|
236
|
+
ui.console.print(f" [red]✗ {failed} failed[/red]")
|
|
237
|
+
ui.console.print()
|
|
238
|
+
|
|
239
|
+
if installed > 0:
|
|
240
|
+
success(f"Installed {installed} package(s) via {pm}")
|
|
@@ -111,6 +111,28 @@ class DotManGroup(click.Group):
|
|
|
111
111
|
ctx.exit(2)
|
|
112
112
|
|
|
113
113
|
|
|
114
|
+
def sync_shared_sections(ops) -> None:
|
|
115
|
+
"""Propagate ``shared = true`` sections to non-overriding branches.
|
|
116
|
+
|
|
117
|
+
Called after a commit was created on the current branch. Failures
|
|
118
|
+
are reported but never abort the surrounding command.
|
|
119
|
+
"""
|
|
120
|
+
try:
|
|
121
|
+
from ..shared_sync import SharedSectionSync
|
|
122
|
+
|
|
123
|
+
report = SharedSectionSync(ops).sync()
|
|
124
|
+
if not report.shared_sections:
|
|
125
|
+
return
|
|
126
|
+
for branch, sections in report.propagated.items():
|
|
127
|
+
ui.console.print(
|
|
128
|
+
f" [dim]↔ shared → '{branch}': {', '.join(sections)}[/dim]"
|
|
129
|
+
)
|
|
130
|
+
for branch, reason in report.errors.items():
|
|
131
|
+
warn(f"Shared-section sync failed for '{branch}': {reason}")
|
|
132
|
+
except Exception as e:
|
|
133
|
+
logging.debug("Shared-section sync skipped: %s", e)
|
|
134
|
+
|
|
135
|
+
|
|
114
136
|
def require_init(func):
|
|
115
137
|
"""Decorator to require initialization before running command."""
|
|
116
138
|
|