titan-cli 0.1.5__tar.gz → 0.1.7__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.
- {titan_cli-0.1.5 → titan_cli-0.1.7}/PKG-INFO +5 -10
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/clients/git_client.py +59 -2
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/plugin.py +10 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/ai_commit_message_step.py +8 -8
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/branch_steps.py +6 -6
- titan_cli-0.1.7/plugins/titan-plugin-git/titan_plugin_git/steps/checkout_step.py +66 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/commit_step.py +3 -3
- titan_cli-0.1.7/plugins/titan-plugin-git/titan_plugin_git/steps/create_branch_step.py +131 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/diff_summary_step.py +11 -13
- titan_cli-0.1.7/plugins/titan-plugin-git/titan_plugin_git/steps/pull_step.py +70 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/push_step.py +3 -3
- titan_cli-0.1.7/plugins/titan-plugin-git/titan_plugin_git/steps/restore_original_branch_step.py +97 -0
- titan_cli-0.1.7/plugins/titan-plugin-git/titan_plugin_git/steps/save_current_branch_step.py +82 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/status_step.py +23 -13
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/workflows/commit-ai.yaml +4 -3
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/steps/ai_pr_step.py +90 -22
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/steps/create_pr_step.py +8 -8
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/steps/github_prompt_steps.py +13 -13
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/steps/issue_steps.py +14 -15
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/steps/preview_step.py +8 -8
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/workflows/create-pr-ai.yaml +1 -11
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/messages.py +12 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/plugin.py +4 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/steps/ai_analyze_issue_step.py +6 -6
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/steps/get_issue_step.py +7 -7
- titan_cli-0.1.7/plugins/titan-plugin-jira/titan_plugin_jira/steps/list_versions_step.py +133 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/steps/prompt_select_issue_step.py +8 -9
- titan_cli-0.1.7/plugins/titan-plugin-jira/titan_plugin_jira/steps/search_jql_step.py +191 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/steps/search_saved_query_step.py +13 -13
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/utils/__init__.py +1 -1
- {titan_cli-0.1.5 → titan_cli-0.1.7}/pyproject.toml +9 -9
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/workflows/project_step_source.py +52 -7
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/workflows/workflow_filter_service.py +6 -4
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/__init__.py +5 -1
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/results.py +31 -1
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/steps/ai_assistant_step.py +18 -18
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/workflow_executor.py +7 -2
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/plugin_config_wizard.py +16 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/workflow_execution.py +22 -24
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/workflows.py +8 -4
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/textual_components.py +293 -189
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/textual_workflow_executor.py +30 -2
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/theme.py +34 -5
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/widgets/__init__.py +15 -0
- titan_cli-0.1.7/titan_cli/ui/tui/widgets/multiline_input.py +32 -0
- titan_cli-0.1.7/titan_cli/ui/tui/widgets/prompt_choice.py +138 -0
- titan_cli-0.1.7/titan_cli/ui/tui/widgets/prompt_input.py +74 -0
- titan_cli-0.1.7/titan_cli/ui/tui/widgets/prompt_selection_list.py +150 -0
- titan_cli-0.1.7/titan_cli/ui/tui/widgets/prompt_textarea.py +87 -0
- titan_cli-0.1.7/titan_cli/ui/tui/widgets/styled_option_list.py +107 -0
- titan_cli-0.1.7/titan_cli/ui/tui/widgets/text.py +98 -0
- titan_cli-0.1.5/titan_cli/ui/tui/widgets/text.py +0 -177
- {titan_cli-0.1.5 → titan_cli-0.1.7}/LICENSE +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/README.md +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/clients/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/exceptions.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/messages.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/models.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/workflows/__previews__/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/workflows/__previews__/commit_ai_preview.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/agents/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/agents/config_loader.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/agents/issue_generator.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/agents/pr_agent.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/clients/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/clients/github_client.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/config/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/config/pr_agent.toml +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/exceptions.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/messages.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/models.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/plugin.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/steps/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/utils.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/workflows/__previews__/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/workflows/__previews__/create_pr_ai_preview.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-github/titan_plugin_github/workflows/create-issue-ai.yaml +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/agents/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/agents/config_loader.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/agents/jira_agent.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/agents/prompts.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/agents/response_parser.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/agents/token_tracker.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/agents/validators.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/clients/jira_client.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/config/jira_agent.toml +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/config/templates/issue_analysis.md.j2 +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/exceptions.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/formatters/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/formatters/markdown_formatter.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/models.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/utils/issue_sorter.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/utils/saved_queries.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-jira/titan_plugin_jira/workflows/analyze-jira-issues.yaml +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/__main__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/agents/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/agents/base.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/client.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/constants.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/exceptions.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/models.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/oauth_helper.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/providers/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/providers/anthropic.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/providers/base.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ai/providers/gemini.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/cli.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/clients/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/clients/gcloud_client.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/config.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/discovery.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/errors.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/models.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/plugins/available.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/plugins/models.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/plugins/plugin_base.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/plugins/plugin_registry.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/secrets.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/workflows/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/workflows/models.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/workflows/workflow_exceptions.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/workflows/workflow_registry.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/core/workflows/workflow_sources.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/builder.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/context.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/mock_context.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/steps/command_step.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/utils/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/engine/utils/venv.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/external_cli/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/external_cli/configs.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/external_cli/launcher.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/messages.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/__previews__/statusbar_preview.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/app.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/icons.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/ai_config.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/ai_config_wizard.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/base.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/cli_launcher.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/global_setup_wizard.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/main_menu.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/plugin_management.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/screens/project_setup_wizard.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/widgets/button.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/widgets/header.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/widgets/panel.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/widgets/status_bar.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/widgets/step_container.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/ui/tui/widgets/table.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/utils/__init__.py +0 -0
- {titan_cli-0.1.5 → titan_cli-0.1.7}/titan_cli/utils/autoupdate.py +0 -0
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: titan-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: Modular development tools orchestrator - Streamline your workflows with AI integration and intuitive terminal UI
|
|
5
|
+
Home-page: https://github.com/masmovil/titan-cli
|
|
5
6
|
License: MIT
|
|
6
|
-
License-File: LICENSE
|
|
7
7
|
Keywords: cli,workflow,orchestrator,automation,devtools,ai
|
|
8
|
-
Author:
|
|
9
|
-
Author-email:
|
|
10
|
-
Maintainer: r-pedraza
|
|
11
|
-
Maintainer-email: raulpedrazaleon@gmail.com
|
|
8
|
+
Author: MasOrange Apps Team
|
|
9
|
+
Author-email: apps-management-stores@masorange.es
|
|
12
10
|
Requires-Python: >=3.10,<4.0.0
|
|
13
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
12
|
Classifier: Environment :: Console
|
|
@@ -19,8 +17,6 @@ Classifier: Programming Language :: Python :: 3
|
|
|
19
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
24
20
|
Requires-Dist: anthropic (>=0.75.0,<0.76.0)
|
|
25
21
|
Requires-Dist: google-auth (>=2.43.0,<3.0.0)
|
|
26
22
|
Requires-Dist: google-genai (>=1.58.0,<2.0.0)
|
|
@@ -36,7 +32,6 @@ Requires-Dist: tomli (>=2.0.0,<3.0.0)
|
|
|
36
32
|
Requires-Dist: tomli-w (>=1.0.0,<2.0.0)
|
|
37
33
|
Requires-Dist: typer (>=0.20.0,<1.0.0)
|
|
38
34
|
Project-URL: Documentation, https://github.com/masmovil/titan-cli
|
|
39
|
-
Project-URL: Homepage, https://github.com/masmovil/titan-cli
|
|
40
35
|
Project-URL: Repository, https://github.com/masmovil/titan-cli
|
|
41
36
|
Description-Content-Type: text/markdown
|
|
42
37
|
|
{titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/clients/git_client.py
RENAMED
|
@@ -109,6 +109,27 @@ class GitClient:
|
|
|
109
109
|
"""
|
|
110
110
|
return self._run_command(["git", "rev-parse", "--abbrev-ref", "HEAD"])
|
|
111
111
|
|
|
112
|
+
def get_current_commit(self) -> str:
|
|
113
|
+
"""
|
|
114
|
+
Get current commit SHA (HEAD)
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
Full SHA of current commit
|
|
118
|
+
"""
|
|
119
|
+
return self._run_command(["git", "rev-parse", "HEAD"])
|
|
120
|
+
|
|
121
|
+
def get_commit_sha(self, ref: str) -> str:
|
|
122
|
+
"""
|
|
123
|
+
Get commit SHA for any git ref (branch, tag, remote branch, etc.)
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
ref: Git reference (e.g., "HEAD", "develop", "origin/main", "v1.0.0")
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Full SHA of the commit
|
|
130
|
+
"""
|
|
131
|
+
return self._run_command(["git", "rev-parse", ref])
|
|
132
|
+
|
|
112
133
|
def get_status(self) -> GitStatus:
|
|
113
134
|
"""
|
|
114
135
|
Get repository status
|
|
@@ -282,7 +303,7 @@ class GitClient:
|
|
|
282
303
|
"""
|
|
283
304
|
self._run_command(["git", "branch", branch_name, start_point])
|
|
284
305
|
|
|
285
|
-
def commit(self, message: str, all: bool = False, no_verify: bool =
|
|
306
|
+
def commit(self, message: str, all: bool = False, no_verify: bool = True) -> str:
|
|
286
307
|
"""
|
|
287
308
|
Create a commit
|
|
288
309
|
|
|
@@ -390,12 +411,13 @@ class GitClient:
|
|
|
390
411
|
|
|
391
412
|
self._run_command(args)
|
|
392
413
|
|
|
393
|
-
def fetch(self, remote: str = "origin", all: bool = False) -> None:
|
|
414
|
+
def fetch(self, remote: str = "origin", branch: Optional[str] = None, all: bool = False) -> None:
|
|
394
415
|
"""
|
|
395
416
|
Fetch from remote
|
|
396
417
|
|
|
397
418
|
Args:
|
|
398
419
|
remote: Remote name
|
|
420
|
+
branch: Specific branch to fetch (optional)
|
|
399
421
|
all: Fetch from all remotes
|
|
400
422
|
"""
|
|
401
423
|
args = ["git", "fetch"]
|
|
@@ -404,6 +426,8 @@ class GitClient:
|
|
|
404
426
|
args.append("--all")
|
|
405
427
|
else:
|
|
406
428
|
args.append(remote)
|
|
429
|
+
if branch:
|
|
430
|
+
args.append(branch)
|
|
407
431
|
|
|
408
432
|
self._run_command(args)
|
|
409
433
|
|
|
@@ -736,6 +760,39 @@ class GitClient:
|
|
|
736
760
|
except GitCommandError:
|
|
737
761
|
return ""
|
|
738
762
|
|
|
763
|
+
def get_uncommitted_diff_stat(self) -> str:
|
|
764
|
+
"""
|
|
765
|
+
Get diff stat summary of uncommitted changes (git diff --stat HEAD).
|
|
766
|
+
|
|
767
|
+
Returns a summary showing files changed, insertions, and deletions.
|
|
768
|
+
|
|
769
|
+
Returns:
|
|
770
|
+
Diff stat output as string
|
|
771
|
+
"""
|
|
772
|
+
try:
|
|
773
|
+
return self._run_command(["git", "diff", "--stat", "HEAD"], check=False)
|
|
774
|
+
except GitCommandError:
|
|
775
|
+
return ""
|
|
776
|
+
|
|
777
|
+
def get_branch_diff_stat(self, base_branch: str, head_branch: str) -> str:
|
|
778
|
+
"""
|
|
779
|
+
Get diff stat summary between two branches.
|
|
780
|
+
|
|
781
|
+
Args:
|
|
782
|
+
base_branch: Base branch name
|
|
783
|
+
head_branch: Head branch name
|
|
784
|
+
|
|
785
|
+
Returns:
|
|
786
|
+
Diff stat output as string
|
|
787
|
+
"""
|
|
788
|
+
try:
|
|
789
|
+
return self._run_command(
|
|
790
|
+
["git", "diff", "--stat", f"{base_branch}...{head_branch}"],
|
|
791
|
+
check=False
|
|
792
|
+
)
|
|
793
|
+
except GitCommandError:
|
|
794
|
+
return ""
|
|
795
|
+
|
|
739
796
|
def get_branch_commits(self, base_branch: str, head_branch: str) -> list[str]:
|
|
740
797
|
"""
|
|
741
798
|
Get list of commits in head_branch that are not in base_branch.
|
|
@@ -101,6 +101,11 @@ class GitPlugin(TitanPlugin):
|
|
|
101
101
|
from .steps.branch_steps import get_current_branch_step, get_base_branch_step
|
|
102
102
|
from .steps.ai_commit_message_step import ai_generate_commit_message
|
|
103
103
|
from .steps.diff_summary_step import show_uncommitted_diff_summary, show_branch_diff_summary
|
|
104
|
+
from .steps.save_current_branch_step import save_current_branch_step
|
|
105
|
+
from .steps.restore_original_branch_step import restore_original_branch_step
|
|
106
|
+
from .steps.checkout_step import checkout_branch_step
|
|
107
|
+
from .steps.pull_step import pull_step
|
|
108
|
+
from .steps.create_branch_step import create_branch_step
|
|
104
109
|
|
|
105
110
|
return {
|
|
106
111
|
"get_status": get_git_status_step,
|
|
@@ -111,6 +116,11 @@ class GitPlugin(TitanPlugin):
|
|
|
111
116
|
"ai_generate_commit_message": ai_generate_commit_message,
|
|
112
117
|
"show_uncommitted_diff_summary": show_uncommitted_diff_summary,
|
|
113
118
|
"show_branch_diff_summary": show_branch_diff_summary,
|
|
119
|
+
"save_current_branch": save_current_branch_step,
|
|
120
|
+
"restore_original_branch": restore_original_branch_step,
|
|
121
|
+
"checkout": checkout_branch_step,
|
|
122
|
+
"pull": pull_step,
|
|
123
|
+
"create_branch": create_branch_step,
|
|
114
124
|
}
|
|
115
125
|
|
|
116
126
|
@property
|
|
@@ -33,7 +33,7 @@ def ai_generate_commit_message(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
33
33
|
|
|
34
34
|
# Check if AI is configured
|
|
35
35
|
if not ctx.ai or not ctx.ai.is_available():
|
|
36
|
-
ctx.textual.
|
|
36
|
+
ctx.textual.dim_text(msg.Steps.AICommitMessage.AI_NOT_CONFIGURED)
|
|
37
37
|
ctx.textual.end_step("skip")
|
|
38
38
|
return Skip(msg.Steps.AICommitMessage.AI_NOT_CONFIGURED)
|
|
39
39
|
|
|
@@ -45,13 +45,13 @@ def ai_generate_commit_message(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
45
45
|
# Get git status
|
|
46
46
|
git_status = ctx.get('git_status')
|
|
47
47
|
if not git_status or git_status.is_clean:
|
|
48
|
-
ctx.textual.
|
|
48
|
+
ctx.textual.dim_text(msg.Steps.AICommitMessage.NO_CHANGES_TO_COMMIT)
|
|
49
49
|
ctx.textual.end_step("skip")
|
|
50
50
|
return Skip(msg.Steps.AICommitMessage.NO_CHANGES_TO_COMMIT)
|
|
51
51
|
|
|
52
52
|
try:
|
|
53
53
|
# Get diff of uncommitted changes
|
|
54
|
-
ctx.textual.
|
|
54
|
+
ctx.textual.dim_text(msg.Steps.AICommitMessage.ANALYZING_CHANGES)
|
|
55
55
|
|
|
56
56
|
# Get diff of all uncommitted changes
|
|
57
57
|
diff_text = ctx.git.get_uncommitted_diff()
|
|
@@ -125,12 +125,12 @@ Return ONLY the single-line commit message, absolutely nothing else."""
|
|
|
125
125
|
|
|
126
126
|
# Show preview to user
|
|
127
127
|
ctx.textual.text("") # spacing
|
|
128
|
-
ctx.textual.
|
|
129
|
-
ctx.textual.
|
|
128
|
+
ctx.textual.bold_text(msg.Steps.AICommitMessage.GENERATED_MESSAGE_TITLE)
|
|
129
|
+
ctx.textual.bold_primary_text(f" {commit_message}")
|
|
130
130
|
|
|
131
131
|
# Warn if message is too long
|
|
132
132
|
if len(commit_message) > 72:
|
|
133
|
-
ctx.textual.
|
|
133
|
+
ctx.textual.warning_text(msg.Steps.AICommitMessage.MESSAGE_LENGTH_WARNING.format(length=len(commit_message)))
|
|
134
134
|
|
|
135
135
|
ctx.textual.text("") # spacing
|
|
136
136
|
|
|
@@ -165,8 +165,8 @@ Return ONLY the single-line commit message, absolutely nothing else."""
|
|
|
165
165
|
)
|
|
166
166
|
|
|
167
167
|
except Exception as e:
|
|
168
|
-
ctx.textual.
|
|
169
|
-
ctx.textual.
|
|
168
|
+
ctx.textual.warning_text(msg.Steps.AICommitMessage.GENERATION_FAILED.format(e=e))
|
|
169
|
+
ctx.textual.dim_text(msg.Steps.AICommitMessage.FALLBACK_TO_MANUAL)
|
|
170
170
|
|
|
171
171
|
ctx.textual.end_step("skip")
|
|
172
172
|
return Skip(msg.Steps.AICommitMessage.GENERATION_FAILED.format(e=e))
|
{titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/branch_steps.py
RENAMED
|
@@ -24,14 +24,14 @@ def get_current_branch_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
24
24
|
|
|
25
25
|
if not ctx.git:
|
|
26
26
|
error_msg = msg.Steps.Status.GIT_CLIENT_NOT_AVAILABLE
|
|
27
|
-
ctx.textual.
|
|
27
|
+
ctx.textual.error_text(error_msg)
|
|
28
28
|
ctx.textual.end_step("error")
|
|
29
29
|
return Error(error_msg)
|
|
30
30
|
|
|
31
31
|
try:
|
|
32
32
|
current_branch = ctx.git.get_current_branch()
|
|
33
33
|
success_msg = msg.Steps.Branch.GET_CURRENT_BRANCH_SUCCESS.format(branch=current_branch)
|
|
34
|
-
ctx.textual.
|
|
34
|
+
ctx.textual.success_text(success_msg)
|
|
35
35
|
ctx.textual.end_step("success")
|
|
36
36
|
return Success(
|
|
37
37
|
success_msg,
|
|
@@ -39,7 +39,7 @@ def get_current_branch_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
39
39
|
)
|
|
40
40
|
except Exception as e:
|
|
41
41
|
error_msg = msg.Steps.Branch.GET_CURRENT_BRANCH_FAILED.format(e=e)
|
|
42
|
-
ctx.textual.
|
|
42
|
+
ctx.textual.error_text(error_msg)
|
|
43
43
|
ctx.textual.end_step("error")
|
|
44
44
|
return Error(error_msg, exception=e)
|
|
45
45
|
|
|
@@ -65,14 +65,14 @@ def get_base_branch_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
65
65
|
|
|
66
66
|
if not ctx.git:
|
|
67
67
|
error_msg = msg.Steps.Status.GIT_CLIENT_NOT_AVAILABLE
|
|
68
|
-
ctx.textual.
|
|
68
|
+
ctx.textual.error_text(error_msg)
|
|
69
69
|
ctx.textual.end_step("error")
|
|
70
70
|
return Error(error_msg)
|
|
71
71
|
|
|
72
72
|
try:
|
|
73
73
|
base_branch = ctx.git.main_branch
|
|
74
74
|
success_msg = msg.Steps.Branch.GET_BASE_BRANCH_SUCCESS.format(branch=base_branch)
|
|
75
|
-
ctx.textual.
|
|
75
|
+
ctx.textual.success_text(success_msg)
|
|
76
76
|
ctx.textual.end_step("success")
|
|
77
77
|
return Success(
|
|
78
78
|
success_msg,
|
|
@@ -80,6 +80,6 @@ def get_base_branch_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
80
80
|
)
|
|
81
81
|
except Exception as e:
|
|
82
82
|
error_msg = msg.Steps.Branch.GET_BASE_BRANCH_FAILED.format(e=e)
|
|
83
|
-
ctx.textual.
|
|
83
|
+
ctx.textual.error_text(error_msg)
|
|
84
84
|
ctx.textual.end_step("error")
|
|
85
85
|
return Error(error_msg, exception=e)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Checkout a Git branch.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from titan_cli.engine import WorkflowContext, WorkflowResult, Success, Error
|
|
6
|
+
from titan_plugin_git.exceptions import GitError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def checkout_branch_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
10
|
+
"""
|
|
11
|
+
Checkout a Git branch.
|
|
12
|
+
|
|
13
|
+
Inputs (from ctx.data):
|
|
14
|
+
branch (str): Branch name to checkout
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
Success: Branch checked out successfully
|
|
18
|
+
Error: Git operation failed
|
|
19
|
+
"""
|
|
20
|
+
if ctx.textual:
|
|
21
|
+
ctx.textual.begin_step("Checkout Branch")
|
|
22
|
+
|
|
23
|
+
if not ctx.textual:
|
|
24
|
+
return Error("Textual UI context is not available for this step.")
|
|
25
|
+
|
|
26
|
+
if not ctx.git:
|
|
27
|
+
ctx.textual.error_text("Git client not available in context")
|
|
28
|
+
ctx.textual.end_step("error")
|
|
29
|
+
return Error("Git client not available in context")
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
# Get branch from params, or use main_branch from git config
|
|
33
|
+
branch = ctx.get("branch")
|
|
34
|
+
if not branch:
|
|
35
|
+
branch = ctx.git.main_branch
|
|
36
|
+
ctx.textual.dim_text(f"Using main branch from config: {branch}")
|
|
37
|
+
|
|
38
|
+
ctx.textual.text("")
|
|
39
|
+
ctx.textual.dim_text(f"Checking out: {branch}")
|
|
40
|
+
|
|
41
|
+
# Checkout branch
|
|
42
|
+
try:
|
|
43
|
+
ctx.git.checkout(branch)
|
|
44
|
+
ctx.textual.success_text(f"✓ Checked out {branch}")
|
|
45
|
+
except GitError as e:
|
|
46
|
+
ctx.textual.text("")
|
|
47
|
+
ctx.textual.error_text(f"Failed to checkout {branch}: {str(e)}")
|
|
48
|
+
ctx.textual.end_step("error")
|
|
49
|
+
return Error(f"Failed to checkout: {str(e)}")
|
|
50
|
+
|
|
51
|
+
ctx.textual.text("")
|
|
52
|
+
ctx.textual.end_step("success")
|
|
53
|
+
return Success(
|
|
54
|
+
f"Checked out {branch}",
|
|
55
|
+
metadata={"branch": branch}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
except Exception as e:
|
|
59
|
+
ctx.textual.text("")
|
|
60
|
+
ctx.textual.error_text(f"Failed to checkout branch: {str(e)}")
|
|
61
|
+
ctx.textual.text("")
|
|
62
|
+
ctx.textual.end_step("error")
|
|
63
|
+
return Error(f"Failed to checkout: {str(e)}")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
__all__ = ["checkout_branch_step"]
|
{titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/commit_step.py
RENAMED
|
@@ -37,7 +37,7 @@ def create_git_commit_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
37
37
|
# Skip if there's nothing to commit
|
|
38
38
|
git_status = ctx.data.get("git_status")
|
|
39
39
|
if git_status and git_status.is_clean:
|
|
40
|
-
ctx.textual.
|
|
40
|
+
ctx.textual.dim_text(msg.Steps.Commit.WORKING_DIRECTORY_CLEAN)
|
|
41
41
|
ctx.textual.end_step("skip")
|
|
42
42
|
return Skip(msg.Steps.Commit.WORKING_DIRECTORY_CLEAN)
|
|
43
43
|
|
|
@@ -47,7 +47,7 @@ def create_git_commit_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
47
47
|
|
|
48
48
|
commit_message = ctx.get('commit_message')
|
|
49
49
|
if not commit_message:
|
|
50
|
-
ctx.textual.
|
|
50
|
+
ctx.textual.dim_text(msg.Steps.Commit.NO_COMMIT_MESSAGE)
|
|
51
51
|
ctx.textual.end_step("skip")
|
|
52
52
|
return Skip(msg.Steps.Commit.NO_COMMIT_MESSAGE)
|
|
53
53
|
|
|
@@ -58,7 +58,7 @@ def create_git_commit_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
58
58
|
commit_hash = ctx.git.commit(message=commit_message, all=all_files, no_verify=no_verify)
|
|
59
59
|
|
|
60
60
|
# Show success message
|
|
61
|
-
ctx.textual.
|
|
61
|
+
ctx.textual.success_text(f"Commit created: {commit_hash[:7]}")
|
|
62
62
|
|
|
63
63
|
ctx.textual.end_step("success")
|
|
64
64
|
return Success(
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Create a new Git branch.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from titan_cli.engine import WorkflowContext, WorkflowResult, Success, Error
|
|
6
|
+
from titan_plugin_git.exceptions import GitError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def create_branch_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
10
|
+
"""
|
|
11
|
+
Create a new Git branch.
|
|
12
|
+
|
|
13
|
+
Inputs (from ctx.data):
|
|
14
|
+
new_branch (str): Name of the branch to create
|
|
15
|
+
start_point (str, optional): Starting point for the branch (defaults to HEAD)
|
|
16
|
+
delete_if_exists (bool, optional): Delete the branch if it already exists (default: False)
|
|
17
|
+
checkout (bool, optional): Checkout the new branch after creation (default: True)
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Success: Branch created successfully
|
|
21
|
+
Error: Git operation failed
|
|
22
|
+
"""
|
|
23
|
+
if ctx.textual:
|
|
24
|
+
ctx.textual.begin_step("Create Branch")
|
|
25
|
+
|
|
26
|
+
if not ctx.textual:
|
|
27
|
+
return Error("Textual UI context is not available for this step.")
|
|
28
|
+
|
|
29
|
+
if not ctx.git:
|
|
30
|
+
ctx.textual.error_text("Git client not available in context")
|
|
31
|
+
ctx.textual.end_step("error")
|
|
32
|
+
return Error("Git client not available in context")
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
# Get params from context
|
|
36
|
+
new_branch = ctx.get("new_branch")
|
|
37
|
+
if not new_branch:
|
|
38
|
+
ctx.textual.error_text("No branch name specified")
|
|
39
|
+
ctx.textual.dim_text("Set 'new_branch' in workflow params or previous step")
|
|
40
|
+
ctx.textual.end_step("error")
|
|
41
|
+
return Error("No branch name specified")
|
|
42
|
+
|
|
43
|
+
start_point = ctx.get("start_point", "HEAD")
|
|
44
|
+
delete_if_exists = ctx.get("delete_if_exists", False)
|
|
45
|
+
checkout = ctx.get("checkout", True)
|
|
46
|
+
|
|
47
|
+
ctx.textual.text("")
|
|
48
|
+
ctx.textual.dim_text(f"Creating branch: {new_branch}")
|
|
49
|
+
ctx.textual.dim_text(f"From: {start_point}")
|
|
50
|
+
|
|
51
|
+
# Check if branch exists
|
|
52
|
+
all_branches = ctx.git.get_branches()
|
|
53
|
+
branch_names = [b.name for b in all_branches]
|
|
54
|
+
branch_exists = new_branch in branch_names
|
|
55
|
+
|
|
56
|
+
# Delete if exists and requested
|
|
57
|
+
if branch_exists and delete_if_exists:
|
|
58
|
+
ctx.textual.text("")
|
|
59
|
+
ctx.textual.warning_text(f"Branch {new_branch} exists, deleting...")
|
|
60
|
+
|
|
61
|
+
# If we're on the branch, checkout another one first
|
|
62
|
+
current_branch = ctx.git.get_current_branch()
|
|
63
|
+
if current_branch == new_branch:
|
|
64
|
+
# Checkout main branch before deleting
|
|
65
|
+
main_branch = ctx.git.main_branch
|
|
66
|
+
if main_branch in branch_names and main_branch != new_branch:
|
|
67
|
+
try:
|
|
68
|
+
ctx.git.checkout(main_branch)
|
|
69
|
+
ctx.textual.dim_text(f"Switched to {main_branch}")
|
|
70
|
+
except GitError as e:
|
|
71
|
+
ctx.textual.error_text(f"Failed to checkout {main_branch}: {str(e)}")
|
|
72
|
+
ctx.textual.end_step("error")
|
|
73
|
+
return Error(f"Cannot checkout {main_branch}: {str(e)}")
|
|
74
|
+
else:
|
|
75
|
+
ctx.textual.error_text(f"Cannot delete current branch {new_branch}")
|
|
76
|
+
ctx.textual.end_step("error")
|
|
77
|
+
return Error("Cannot delete current branch")
|
|
78
|
+
|
|
79
|
+
# Delete the branch
|
|
80
|
+
try:
|
|
81
|
+
ctx.git.safe_delete_branch(new_branch, force=True)
|
|
82
|
+
ctx.textual.success_text(f"✓ Deleted existing branch {new_branch}")
|
|
83
|
+
except GitError as e:
|
|
84
|
+
ctx.textual.error_text(f"Failed to delete {new_branch}: {str(e)}")
|
|
85
|
+
ctx.textual.end_step("error")
|
|
86
|
+
return Error(f"Failed to delete branch: {str(e)}")
|
|
87
|
+
|
|
88
|
+
elif branch_exists:
|
|
89
|
+
ctx.textual.error_text(f"Branch {new_branch} already exists")
|
|
90
|
+
ctx.textual.dim_text("Set 'delete_if_exists: true' to recreate it")
|
|
91
|
+
ctx.textual.end_step("error")
|
|
92
|
+
return Error(f"Branch {new_branch} already exists")
|
|
93
|
+
|
|
94
|
+
# Create the branch
|
|
95
|
+
ctx.textual.text("")
|
|
96
|
+
try:
|
|
97
|
+
ctx.git.create_branch(new_branch, start_point=start_point)
|
|
98
|
+
ctx.textual.success_text(f"✓ Created branch {new_branch}")
|
|
99
|
+
except GitError as e:
|
|
100
|
+
ctx.textual.error_text(f"Failed to create {new_branch}: {str(e)}")
|
|
101
|
+
ctx.textual.end_step("error")
|
|
102
|
+
return Error(f"Failed to create branch: {str(e)}")
|
|
103
|
+
|
|
104
|
+
# Checkout if requested
|
|
105
|
+
if checkout:
|
|
106
|
+
try:
|
|
107
|
+
ctx.git.checkout(new_branch)
|
|
108
|
+
ctx.textual.success_text(f"✓ Checked out {new_branch}")
|
|
109
|
+
except GitError as e:
|
|
110
|
+
ctx.textual.warning_text(f"Branch created but failed to checkout: {str(e)}")
|
|
111
|
+
|
|
112
|
+
ctx.textual.text("")
|
|
113
|
+
ctx.textual.end_step("success")
|
|
114
|
+
return Success(
|
|
115
|
+
f"Created branch {new_branch}",
|
|
116
|
+
metadata={
|
|
117
|
+
"new_branch": new_branch,
|
|
118
|
+
"start_point": start_point,
|
|
119
|
+
"checked_out": checkout
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
except Exception as e:
|
|
124
|
+
ctx.textual.text("")
|
|
125
|
+
ctx.textual.error_text(f"Failed to create branch: {str(e)}")
|
|
126
|
+
ctx.textual.text("")
|
|
127
|
+
ctx.textual.end_step("error")
|
|
128
|
+
return Error(f"Failed to create branch: {str(e)}")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
__all__ = ["create_branch_step"]
|
|
@@ -24,16 +24,16 @@ def show_uncommitted_diff_summary(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
24
24
|
|
|
25
25
|
try:
|
|
26
26
|
# Get diff stat for uncommitted changes
|
|
27
|
-
stat_output = ctx.git.
|
|
27
|
+
stat_output = ctx.git.get_uncommitted_diff_stat()
|
|
28
28
|
|
|
29
29
|
if not stat_output or not stat_output.strip():
|
|
30
|
-
ctx.textual.
|
|
30
|
+
ctx.textual.dim_text("No uncommitted changes to show")
|
|
31
31
|
ctx.textual.end_step("success")
|
|
32
32
|
return Success("No changes")
|
|
33
33
|
|
|
34
34
|
# Show the stat summary with colors
|
|
35
35
|
ctx.textual.text("") # spacing
|
|
36
|
-
ctx.textual.
|
|
36
|
+
ctx.textual.bold_text("Changes summary:")
|
|
37
37
|
ctx.textual.text("") # spacing
|
|
38
38
|
|
|
39
39
|
# Parse lines to find max filename length for alignment
|
|
@@ -69,7 +69,7 @@ def show_uncommitted_diff_summary(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
69
69
|
for line in summary_lines:
|
|
70
70
|
colored_line = line.replace('(+)', '[green](+)[/green]')
|
|
71
71
|
colored_line = colored_line.replace('(-)', '[red](-)[/red]')
|
|
72
|
-
ctx.textual.
|
|
72
|
+
ctx.textual.dim_text(f" {colored_line}")
|
|
73
73
|
|
|
74
74
|
ctx.textual.text("") # spacing
|
|
75
75
|
|
|
@@ -104,13 +104,13 @@ def show_branch_diff_summary(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
104
104
|
ctx.textual.begin_step("Show Branch Changes Summary")
|
|
105
105
|
|
|
106
106
|
if not ctx.git:
|
|
107
|
-
ctx.textual.
|
|
107
|
+
ctx.textual.error_text(msg.Steps.Push.GIT_CLIENT_NOT_AVAILABLE)
|
|
108
108
|
ctx.textual.end_step("error")
|
|
109
109
|
return Error(msg.Steps.Push.GIT_CLIENT_NOT_AVAILABLE)
|
|
110
110
|
|
|
111
111
|
head_branch = ctx.get("pr_head_branch")
|
|
112
112
|
if not head_branch:
|
|
113
|
-
ctx.textual.
|
|
113
|
+
ctx.textual.dim_text("No head branch specified")
|
|
114
114
|
ctx.textual.end_step("skip")
|
|
115
115
|
return Skip("No head branch specified")
|
|
116
116
|
|
|
@@ -118,18 +118,16 @@ def show_branch_diff_summary(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
118
118
|
|
|
119
119
|
try:
|
|
120
120
|
# Get diff stat between branches
|
|
121
|
-
stat_output = ctx.git.
|
|
122
|
-
"git", "diff", "--stat", f"{base_branch}...{head_branch}"
|
|
123
|
-
])
|
|
121
|
+
stat_output = ctx.git.get_branch_diff_stat(base_branch, head_branch)
|
|
124
122
|
|
|
125
123
|
if not stat_output or not stat_output.strip():
|
|
126
|
-
ctx.textual.
|
|
124
|
+
ctx.textual.dim_text(f"No changes between {base_branch} and {head_branch}")
|
|
127
125
|
ctx.textual.end_step("success")
|
|
128
126
|
return Success("No changes")
|
|
129
127
|
|
|
130
128
|
# Show the stat summary with colors
|
|
131
129
|
ctx.textual.text("") # spacing
|
|
132
|
-
ctx.textual.
|
|
130
|
+
ctx.textual.bold_text(f"Changes in {head_branch} vs {base_branch}:")
|
|
133
131
|
ctx.textual.text("") # spacing
|
|
134
132
|
|
|
135
133
|
# Parse lines to find max filename length for alignment
|
|
@@ -165,7 +163,7 @@ def show_branch_diff_summary(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
165
163
|
for line in summary_lines:
|
|
166
164
|
colored_line = line.replace('(+)', '[green](+)[/green]')
|
|
167
165
|
colored_line = colored_line.replace('(-)', '[red](-)[/red]')
|
|
168
|
-
ctx.textual.
|
|
166
|
+
ctx.textual.dim_text(f" {colored_line}")
|
|
169
167
|
|
|
170
168
|
ctx.textual.text("") # spacing
|
|
171
169
|
|
|
@@ -174,7 +172,7 @@ def show_branch_diff_summary(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
174
172
|
|
|
175
173
|
except Exception as e:
|
|
176
174
|
# Don't fail the workflow, just skip
|
|
177
|
-
ctx.textual.
|
|
175
|
+
ctx.textual.warning_text(f"Could not show branch diff summary: {e}")
|
|
178
176
|
ctx.textual.end_step("skip")
|
|
179
177
|
return Skip(f"Could not show branch diff summary: {e}")
|
|
180
178
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pull from Git remote.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from titan_cli.engine import WorkflowContext, WorkflowResult, Success, Error
|
|
7
|
+
from titan_plugin_git.exceptions import GitError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def pull_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
11
|
+
"""
|
|
12
|
+
Pull from Git remote.
|
|
13
|
+
|
|
14
|
+
Inputs (from ctx.data):
|
|
15
|
+
remote (str, optional): Remote name (defaults to "origin")
|
|
16
|
+
branch (str, optional): Branch name (defaults to current branch)
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
Success: Pull completed successfully
|
|
20
|
+
Error: Git operation failed
|
|
21
|
+
"""
|
|
22
|
+
if ctx.textual:
|
|
23
|
+
ctx.textual.begin_step("Pull from Remote")
|
|
24
|
+
|
|
25
|
+
if not ctx.textual:
|
|
26
|
+
return Error("Textual UI context is not available for this step.")
|
|
27
|
+
|
|
28
|
+
if not ctx.git:
|
|
29
|
+
ctx.textual.error_text("Git client not available in context")
|
|
30
|
+
ctx.textual.end_step("error")
|
|
31
|
+
return Error("Git client not available in context")
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
# Get params from context (optional)
|
|
35
|
+
remote = ctx.get("remote", "origin")
|
|
36
|
+
branch: Optional[str] = ctx.get("pull_branch") # Optional, defaults to current
|
|
37
|
+
|
|
38
|
+
ctx.textual.text("")
|
|
39
|
+
if branch:
|
|
40
|
+
ctx.textual.dim_text(f"Pulling {remote}/{branch}...")
|
|
41
|
+
else:
|
|
42
|
+
ctx.textual.dim_text(f"Pulling from {remote}...")
|
|
43
|
+
|
|
44
|
+
# Pull
|
|
45
|
+
try:
|
|
46
|
+
with ctx.textual.loading("Pulling from remote..."):
|
|
47
|
+
ctx.git.pull(remote=remote, branch=branch)
|
|
48
|
+
ctx.textual.success_text(f"✓ Pulled from {remote}")
|
|
49
|
+
except GitError as e:
|
|
50
|
+
ctx.textual.text("")
|
|
51
|
+
ctx.textual.error_text(f"Failed to pull: {str(e)}")
|
|
52
|
+
ctx.textual.end_step("error")
|
|
53
|
+
return Error(f"Failed to pull: {str(e)}")
|
|
54
|
+
|
|
55
|
+
ctx.textual.text("")
|
|
56
|
+
ctx.textual.end_step("success")
|
|
57
|
+
return Success(
|
|
58
|
+
f"Pulled from {remote}",
|
|
59
|
+
metadata={"remote": remote, "branch": branch}
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
except Exception as e:
|
|
63
|
+
ctx.textual.text("")
|
|
64
|
+
ctx.textual.error_text(f"Failed to pull: {str(e)}")
|
|
65
|
+
ctx.textual.text("")
|
|
66
|
+
ctx.textual.end_step("error")
|
|
67
|
+
return Error(f"Failed to pull: {str(e)}")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
__all__ = ["pull_step"]
|
{titan_cli-0.1.5 → titan_cli-0.1.7}/plugins/titan-plugin-git/titan_plugin_git/steps/push_step.py
RENAMED
|
@@ -60,7 +60,7 @@ def create_git_push_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
60
60
|
if push_tags:
|
|
61
61
|
success_msg += " (with tags)"
|
|
62
62
|
|
|
63
|
-
ctx.textual.
|
|
63
|
+
ctx.textual.success_text(success_msg)
|
|
64
64
|
|
|
65
65
|
ctx.textual.end_step("success")
|
|
66
66
|
return Success(
|
|
@@ -69,11 +69,11 @@ def create_git_push_step(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
69
69
|
)
|
|
70
70
|
except GitCommandError as e:
|
|
71
71
|
error_msg = msg.Steps.Push.PUSH_FAILED.format(e=e)
|
|
72
|
-
ctx.textual.
|
|
72
|
+
ctx.textual.error_text(error_msg)
|
|
73
73
|
ctx.textual.end_step("error")
|
|
74
74
|
return Error(error_msg)
|
|
75
75
|
except Exception as e:
|
|
76
76
|
error_msg = msg.Git.UNEXPECTED_ERROR.format(e=e)
|
|
77
|
-
ctx.textual.
|
|
77
|
+
ctx.textual.error_text(error_msg)
|
|
78
78
|
ctx.textual.end_step("error")
|
|
79
79
|
return Error(error_msg)
|