dotman-git 1.3.0__tar.gz → 1.3.1__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.3.1}/PKG-INFO +4 -4
- {dotman_git-1.3.0 → dotman_git-1.3.1}/README.md +2 -1
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/__init__.py +1 -1
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/__init__.py +6 -2
- dotman_git-1.3.1/dot_man/cli/bootstrap_cmd.py +240 -0
- dotman_git-1.3.1/dot_man/cli/config_cmd.py +243 -0
- dotman_git-1.3.0/dot_man/cli/config_cmd.py → dotman_git-1.3.1/dot_man/cli/config_tutorial.py +114 -378
- dotman_git-1.3.1/dot_man/cli/hooks_cmd.py +66 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/main.py +4 -2
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/navigate_cmd.py +14 -286
- dotman_git-1.3.1/dot_man/cli/navigate_preview.py +189 -0
- dotman_git-1.3.1/dot_man/cli/save_cmd.py +188 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/status_cmd.py +43 -6
- dotman_git-1.3.1/dot_man/cli/vault_cmd.py +93 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/core.py +8 -4
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/files.py +4 -4
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/section.py +6 -5
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dotman_git.egg-info/PKG-INFO +4 -4
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dotman_git.egg-info/SOURCES.txt +6 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/pyproject.toml +10 -5
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_completion.py +9 -11
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_config_cmd.py +12 -9
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_shell_completions.py +9 -11
- {dotman_git-1.3.0 → dotman_git-1.3.1}/CHANGELOG.md +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/CONTRIBUTING.md +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/LICENSE +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/MANIFEST.in +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/backups.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/branch_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/add_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/audit_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/backup_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/branch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/clean_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/common.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/completions.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/completions_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/deploy_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/discover_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/doctor_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/edit_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/encrypt_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/export_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/import_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/init_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/interface.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/log_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/onboarding.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/profile_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/remote_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/restore_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/revert_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/rollback_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/show_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/switch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/tag_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/template_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/tui_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/verify_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/cli/watch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/completions/_dot-man.zsh +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/completions/dot-man.bash +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/completions/dot-man.fish +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/completions/install.sh +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/config_detector.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/constants.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/dotman_config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/encryption.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/exceptions.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/global_config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/hooks.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/interactive.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/lock.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/merge.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/operations.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/py.typed +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/save_deploy_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/secrets.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/status_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/tui_log.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/ui.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/utils.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dot_man/vault.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dotman_git.egg-info/dependency_links.txt +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dotman_git.egg-info/entry_points.txt +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dotman_git.egg-info/requires.txt +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/dotman_git.egg-info/top_level.txt +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/setup.cfg +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_add_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_audit_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_backup_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_backups.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_branch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_branch_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_clean.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_cli_commands.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_cli_extra.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_cli_help.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_cli_revert.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_cli_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_common_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_completions_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_comprehensive.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_config_cmd_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_config_ops_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_config_preservation.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_config_section.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_core.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_core_extended.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_core_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_custom_secrets.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_deploy_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_discover_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_doctor_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_dotman_config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_edit_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_encrypt_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_encryption.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_exceptions.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_export_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_files_atomic.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_files_comprehensive.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_files_extended.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_final_push.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_fixtures.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_git_manager.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_git_manager_extended.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_global_config.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_hooks.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_hooks_new.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_import_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_init_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_integration.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_interactive.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_lock.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_log_checkout_tag.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_log_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_log_cmd_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_merge.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_more_integration.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_navigate_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_navigate_helpers.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_navigate_switch_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_onboarding.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_operations.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_ops_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_performance_logic.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_profile_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_profile_cmd_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_profile_extra.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_remote_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_restore_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_rollback_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_save_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_save_deploy_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_secrets.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_section.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_show_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_status_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_status_ops.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_switch_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_switch_enhancements.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_symlink_deploy.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_tag_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_template_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_template_cmd_v1.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_template_extra.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_ui.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_utils.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_vault.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_verify_cmd.py +0 -0
- {dotman_git-1.3.0 → dotman_git-1.3.1}/tests/test_watch_cmd.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dotman-git
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.1
|
|
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
|
|
@@ -70,13 +69,14 @@ Dynamic: license-file
|
|
|
70
69
|
[](https://github.com/astral-sh/ruff)
|
|
71
70
|
[](https://mypy-lang.org/)
|
|
72
71
|
[](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
|
|
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
[](https://github.com/astral-sh/ruff)
|
|
14
14
|
[](https://mypy-lang.org/)
|
|
15
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
|
|
|
@@ -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}")
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"""Config command for dot-man CLI."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from rich.table import Table
|
|
7
|
+
|
|
8
|
+
from .. import ui
|
|
9
|
+
from ..config import GlobalConfig
|
|
10
|
+
from ..exceptions import ConfigurationError
|
|
11
|
+
from .common import complete_config_keys, error, require_init, success
|
|
12
|
+
from .interface import cli as main
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@main.group("config")
|
|
16
|
+
def config():
|
|
17
|
+
"""Manage global configuration."""
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@config.command("defaults")
|
|
22
|
+
def config_defaults():
|
|
23
|
+
"""Show all configurable defaults with descriptions."""
|
|
24
|
+
table = Table(title="Configurable Defaults", show_header=True)
|
|
25
|
+
table.add_column("Setting", style="cyan", no_wrap=True)
|
|
26
|
+
table.add_column("Default Value", style="green")
|
|
27
|
+
table.add_column("Description")
|
|
28
|
+
|
|
29
|
+
defaults = [
|
|
30
|
+
(
|
|
31
|
+
"switch.default_behavior",
|
|
32
|
+
"save",
|
|
33
|
+
"What to do with unsaved changes when switching (save/no-save)",
|
|
34
|
+
),
|
|
35
|
+
(
|
|
36
|
+
"remote.auto_sync",
|
|
37
|
+
"false",
|
|
38
|
+
"Auto push/pull when switching branches (true/false)",
|
|
39
|
+
),
|
|
40
|
+
("remote.url", "", "Remote repository URL for sync"),
|
|
41
|
+
("defaults.secrets_filter", "true", "Redact secrets when saving (true/false)"),
|
|
42
|
+
(
|
|
43
|
+
"defaults.update_strategy",
|
|
44
|
+
"replace",
|
|
45
|
+
"How to deploy: replace/rename_old/ignore",
|
|
46
|
+
),
|
|
47
|
+
(
|
|
48
|
+
"defaults.follow_symlinks",
|
|
49
|
+
"false",
|
|
50
|
+
"Follow symlinks when deploying (true/false)",
|
|
51
|
+
),
|
|
52
|
+
(
|
|
53
|
+
"security.strict_mode",
|
|
54
|
+
"false",
|
|
55
|
+
"Exit with error if secrets detected (true/false)",
|
|
56
|
+
),
|
|
57
|
+
("security.audit_on_commit", "true", "Run audit before commits (true/false)"),
|
|
58
|
+
("backup.max_count", "5", "Maximum number of backups to keep"),
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
for key, default_val, desc in defaults:
|
|
62
|
+
table.add_row(key, str(default_val), desc)
|
|
63
|
+
|
|
64
|
+
ui.console.print(table)
|
|
65
|
+
ui.console.print()
|
|
66
|
+
ui.console.print("[bold]Section-level settings (in dot-man.toml):[/bold]")
|
|
67
|
+
ui.console.print(" [cyan]paths[/cyan] - List of files/dirs to track")
|
|
68
|
+
ui.console.print(" [cyan]secrets_filter[/cyan] - Enable secret detection")
|
|
69
|
+
ui.console.print(" [cyan]update_strategy[/cyan] - How to handle existing files")
|
|
70
|
+
ui.console.print(" [cyan]pre_deploy[/cyan] - Command to run before deploying")
|
|
71
|
+
ui.console.print(" [cyan]post_deploy[/cyan] - Command to run after deploying")
|
|
72
|
+
ui.console.print()
|
|
73
|
+
ui.console.print("[bold]To change a setting:[/bold]")
|
|
74
|
+
ui.console.print(" [cyan]dot-man config set <key> <value>[/cyan]")
|
|
75
|
+
ui.console.print()
|
|
76
|
+
ui.console.print("[dim]Examples:[/dim]")
|
|
77
|
+
ui.console.print(" dot-man config set switch.default_behavior no-save")
|
|
78
|
+
ui.console.print(" dot-man config set remote.auto_sync true")
|
|
79
|
+
ui.console.print(" dot-man config set defaults.update_strategy rename_old")
|
|
80
|
+
ui.console.print()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@config.command("list")
|
|
84
|
+
def config_list():
|
|
85
|
+
"""List all global configuration values."""
|
|
86
|
+
try:
|
|
87
|
+
cfg = GlobalConfig()
|
|
88
|
+
cfg.load()
|
|
89
|
+
|
|
90
|
+
def flatten(d, parent_key="", sep="."):
|
|
91
|
+
items = []
|
|
92
|
+
for k, v in d.items():
|
|
93
|
+
new_key = f"{parent_key}{sep}{k}" if parent_key else k
|
|
94
|
+
if isinstance(v, dict):
|
|
95
|
+
items.extend(flatten(v, new_key, sep=sep).items())
|
|
96
|
+
else:
|
|
97
|
+
items.append((new_key, v))
|
|
98
|
+
return dict(items)
|
|
99
|
+
|
|
100
|
+
flat_data = flatten(cfg._data)
|
|
101
|
+
|
|
102
|
+
table = Table(title="Global Configuration")
|
|
103
|
+
table.add_column("Key", style="cyan")
|
|
104
|
+
table.add_column("Value")
|
|
105
|
+
|
|
106
|
+
for k, v in sorted(flat_data.items()):
|
|
107
|
+
table.add_row(k, str(v))
|
|
108
|
+
|
|
109
|
+
ui.console.print(table)
|
|
110
|
+
|
|
111
|
+
except Exception as e:
|
|
112
|
+
error(f"Failed to list config: {e}")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@config.command("get")
|
|
116
|
+
@click.argument("key", shell_complete=complete_config_keys)
|
|
117
|
+
def config_get(key: str):
|
|
118
|
+
"""Get a configuration value.
|
|
119
|
+
|
|
120
|
+
Example: dot-man config get dot-man.editor
|
|
121
|
+
"""
|
|
122
|
+
try:
|
|
123
|
+
cfg = GlobalConfig()
|
|
124
|
+
cfg.load()
|
|
125
|
+
|
|
126
|
+
parts = key.split(".")
|
|
127
|
+
current = cfg._data
|
|
128
|
+
|
|
129
|
+
for part in parts:
|
|
130
|
+
if isinstance(current, dict) and part in current:
|
|
131
|
+
current = current[part]
|
|
132
|
+
else:
|
|
133
|
+
ui.console.print(f"[red]Key not found:[/red] {key}")
|
|
134
|
+
ui.hint("Run 'dot-man config list' to see all available keys")
|
|
135
|
+
raise SystemExit(1)
|
|
136
|
+
|
|
137
|
+
if isinstance(current, dict):
|
|
138
|
+
ui.console.print(f"[dim]Section '{key}' contains:[/dim]")
|
|
139
|
+
ui.console.print(json.dumps(current, indent=2))
|
|
140
|
+
else:
|
|
141
|
+
ui.console.print(str(current))
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
error(f"Failed to get config: {e}")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@config.command("set")
|
|
148
|
+
@click.argument("key", shell_complete=complete_config_keys)
|
|
149
|
+
@click.argument("value")
|
|
150
|
+
def config_set(key: str, value: str):
|
|
151
|
+
"""Set a configuration value.
|
|
152
|
+
|
|
153
|
+
Example: dot-man config set dot-man.editor nvim
|
|
154
|
+
"""
|
|
155
|
+
try:
|
|
156
|
+
cfg = GlobalConfig()
|
|
157
|
+
try:
|
|
158
|
+
cfg.load()
|
|
159
|
+
except (FileNotFoundError, ConfigurationError):
|
|
160
|
+
cfg.create_default()
|
|
161
|
+
|
|
162
|
+
val: bool | str
|
|
163
|
+
if value.lower() == "true":
|
|
164
|
+
val = True
|
|
165
|
+
elif value.lower() == "false":
|
|
166
|
+
val = False
|
|
167
|
+
else:
|
|
168
|
+
val = value
|
|
169
|
+
|
|
170
|
+
parts = key.split(".")
|
|
171
|
+
current = cfg._data
|
|
172
|
+
|
|
173
|
+
for i, part in enumerate(parts[:-1]):
|
|
174
|
+
if part not in current:
|
|
175
|
+
current[part] = {}
|
|
176
|
+
current = current[part]
|
|
177
|
+
if not isinstance(current, dict):
|
|
178
|
+
error(
|
|
179
|
+
f"Key path conflict: '{'.'.join(parts[: i + 1])}' is not a section"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
current[parts[-1]] = val
|
|
183
|
+
cfg.save()
|
|
184
|
+
|
|
185
|
+
success(f"Set '{key}' to '{val}'")
|
|
186
|
+
ui.console.print(f"[dim] Verified: {key} = {val}[/dim]")
|
|
187
|
+
|
|
188
|
+
except Exception as e:
|
|
189
|
+
error(f"Failed to set config: {e}")
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@config.command("create")
|
|
193
|
+
@click.option(
|
|
194
|
+
"--examples",
|
|
195
|
+
"with_examples",
|
|
196
|
+
is_flag=True,
|
|
197
|
+
default=True,
|
|
198
|
+
help="Include commented examples in the config file (default: True)",
|
|
199
|
+
)
|
|
200
|
+
@click.option(
|
|
201
|
+
"--minimal",
|
|
202
|
+
is_flag=True,
|
|
203
|
+
help="Create a minimal config file without examples or comments",
|
|
204
|
+
)
|
|
205
|
+
@click.option(
|
|
206
|
+
"--force", is_flag=True, help="Overwrite existing config file without prompting"
|
|
207
|
+
)
|
|
208
|
+
@require_init
|
|
209
|
+
def config_create(with_examples: bool, minimal: bool, force: bool):
|
|
210
|
+
"""Create or regenerate the dot-man.toml configuration file."""
|
|
211
|
+
try:
|
|
212
|
+
from ..config import DotManConfig
|
|
213
|
+
from ..constants import DOT_MAN_TOML, REPO_DIR
|
|
214
|
+
|
|
215
|
+
config_path = REPO_DIR / DOT_MAN_TOML
|
|
216
|
+
|
|
217
|
+
if config_path.exists() and not force:
|
|
218
|
+
if not ui.confirm(
|
|
219
|
+
f"Config file already exists at {config_path}. Overwrite?"
|
|
220
|
+
):
|
|
221
|
+
ui.console.print("Cancelled.")
|
|
222
|
+
return
|
|
223
|
+
|
|
224
|
+
dotman_config = DotManConfig()
|
|
225
|
+
|
|
226
|
+
if minimal:
|
|
227
|
+
dotman_config._data = {}
|
|
228
|
+
dotman_config.save()
|
|
229
|
+
ui.console.print(f"Created minimal config at {config_path}")
|
|
230
|
+
else:
|
|
231
|
+
dotman_config.create_default()
|
|
232
|
+
ui.console.print(f"Created config with examples at {config_path}")
|
|
233
|
+
|
|
234
|
+
ui.console.print("Tip: Use 'dot-man edit' to open the config in your editor")
|
|
235
|
+
|
|
236
|
+
except Exception as e:
|
|
237
|
+
error(f"Failed to create config: {e}")
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# Register tutorial subcommand from config_tutorial module
|
|
241
|
+
from .config_tutorial import register as _register_tutorial # noqa: E402
|
|
242
|
+
|
|
243
|
+
_register_tutorial(config)
|