gitpane 1.0.0__py3-none-any.whl
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.
- gitpane/__init__.py +0 -0
- gitpane/account/__init__.py +0 -0
- gitpane/account/account_choice.py +297 -0
- gitpane/account/address_owner.py +67 -0
- gitpane/account/authentication.py +1811 -0
- gitpane/account/authentication_worker.py +836 -0
- gitpane/account/credential_manager.py +480 -0
- gitpane/account/credential_manager_install.py +171 -0
- gitpane/account/keyring_reader.py +135 -0
- gitpane/account/keyring_state.py +158 -0
- gitpane/account/ssh.py +312 -0
- gitpane/account/ssh_askpass.py +216 -0
- gitpane/account/ssh_prompt.py +222 -0
- gitpane/application.py +684 -0
- gitpane/commit/__init__.py +0 -0
- gitpane/commit/commit_metadata.py +88 -0
- gitpane/commit/commit_push.py +276 -0
- gitpane/commit/commit_write.py +830 -0
- gitpane/config.py +1066 -0
- gitpane/controller/__init__.py +0 -0
- gitpane/controller/account_controller.py +677 -0
- gitpane/controller/clone_controller.py +776 -0
- gitpane/controller/close_readiness.py +212 -0
- gitpane/controller/commit_timing_controller.py +566 -0
- gitpane/controller/conflict_controller.py +885 -0
- gitpane/controller/console_registry.py +38 -0
- gitpane/controller/emoji_window_controller.py +95 -0
- gitpane/controller/file_action_controller.py +479 -0
- gitpane/controller/history_read_controller.py +671 -0
- gitpane/controller/history_rewrite_controller.py +739 -0
- gitpane/controller/navigation_controller.py +658 -0
- gitpane/controller/opening_controller.py +375 -0
- gitpane/controller/operation_policy.py +76 -0
- gitpane/controller/rebase_controller.py +797 -0
- gitpane/controller/rebase_editor_controller.py +309 -0
- gitpane/controller/reference_form_controller.py +1677 -0
- gitpane/controller/reference_read_controller.py +242 -0
- gitpane/controller/refresh_controller.py +477 -0
- gitpane/controller/replay_controller.py +805 -0
- gitpane/controller/session_registry.py +337 -0
- gitpane/controller/setting_controller.py +592 -0
- gitpane/controller/shutdown_controller.py +345 -0
- gitpane/controller/staging_controller.py +199 -0
- gitpane/controller/staging_session_registry.py +47 -0
- gitpane/controller/stash_controller.py +367 -0
- gitpane/controller/transport_controller.py +813 -0
- gitpane/controller/welcome_controller.py +102 -0
- gitpane/controller/window_activation.py +116 -0
- gitpane/controller/worktree_state_controller.py +169 -0
- gitpane/emoji/__init__.py +0 -0
- gitpane/emoji/emoji_catalogue.py +156 -0
- gitpane/git_config/__init__.py +0 -0
- gitpane/git_config/git_setting.py +441 -0
- gitpane/history/__init__.py +0 -0
- gitpane/history/avatar.py +241 -0
- gitpane/history/file_history.py +359 -0
- gitpane/history/graph.py +145 -0
- gitpane/history/history_filter.py +31 -0
- gitpane/history/history_parse.py +605 -0
- gitpane/history/repository.py +1600 -0
- gitpane/history/repository_value.py +341 -0
- gitpane/history/revision.py +180 -0
- gitpane/history/revision_file.py +182 -0
- gitpane/history_rewrite/__init__.py +0 -0
- gitpane/history_rewrite/graph.py +210 -0
- gitpane/history_rewrite/guard.py +288 -0
- gitpane/history_rewrite/index.py +125 -0
- gitpane/history_rewrite/prepare.py +378 -0
- gitpane/history_rewrite/protocol.py +320 -0
- gitpane/history_rewrite/publish.py +444 -0
- gitpane/history_rewrite/recovery.py +481 -0
- gitpane/history_rewrite/value.py +229 -0
- gitpane/operation/__init__.py +0 -0
- gitpane/operation/console_line.py +313 -0
- gitpane/operation/console_tone.py +76 -0
- gitpane/operation/diagnostic.py +954 -0
- gitpane/operation/launch_signature.py +254 -0
- gitpane/operation/operation_status.py +87 -0
- gitpane/operation/operation_trace.py +766 -0
- gitpane/operation/repository_operation.py +781 -0
- gitpane/preference/__init__.py +0 -0
- gitpane/preference/preference_location.py +40 -0
- gitpane/preference/preference_store.py +590 -0
- gitpane/process/__init__.py +0 -0
- gitpane/process/exact_arguments.py +77 -0
- gitpane/process/git_output_text.py +20 -0
- gitpane/process/process_group.py +851 -0
- gitpane/process/process_log.py +114 -0
- gitpane/process/process_runner.py +1033 -0
- gitpane/process/released_child_watch.py +138 -0
- gitpane/recent/__init__.py +0 -0
- gitpane/recent/mount_table.py +422 -0
- gitpane/recent/recent_availability.py +414 -0
- gitpane/recent/recent_name.py +11 -0
- gitpane/recent/recent_search.py +114 -0
- gitpane/reference/__init__.py +0 -0
- gitpane/reference/reference_edit.py +2030 -0
- gitpane/reference/reference_snapshot.py +196 -0
- gitpane/reference/stash.py +730 -0
- gitpane/reference/stash_list.py +164 -0
- gitpane/sequencer/__init__.py +0 -0
- gitpane/sequencer/commit_message_rule.py +154 -0
- gitpane/sequencer/conflict.py +506 -0
- gitpane/sequencer/merge_recovery.py +163 -0
- gitpane/sequencer/merge_state.py +166 -0
- gitpane/sequencer/mergetool.py +856 -0
- gitpane/sequencer/rebase.py +750 -0
- gitpane/sequencer/rebase_edit_file.py +224 -0
- gitpane/sequencer/rebase_state.py +523 -0
- gitpane/sequencer/replay.py +1435 -0
- gitpane/sequencer/replay_legacy.py +253 -0
- gitpane/sequencer/replay_state.py +747 -0
- gitpane/submodule/__init__.py +0 -0
- gitpane/submodule/checkout_refusal.py +102 -0
- gitpane/submodule/checkout_refusal_notice.py +111 -0
- gitpane/submodule/cloned_without_checkout.py +65 -0
- gitpane/submodule/submodule_discovery.py +1180 -0
- gitpane/submodule/submodule_loss.py +218 -0
- gitpane/system/__init__.py +0 -0
- gitpane/system/appearance_portal.py +125 -0
- gitpane/system/application_identity.py +48 -0
- gitpane/system/command_line.py +36 -0
- gitpane/system/desktop_icon_fact.py +128 -0
- gitpane/system/desktop_icon_support.py +270 -0
- gitpane/system/desktop_shortcut.py +536 -0
- gitpane/system/icns_image.py +35 -0
- gitpane/system/installed_launcher.py +136 -0
- gitpane/system/linux_distribution.py +151 -0
- gitpane/system/network_folder.py +46 -0
- gitpane/system/path_identity.py +95 -0
- gitpane/system/private_tree_removal.py +47 -0
- gitpane/system/process_program.py +63 -0
- gitpane/system/qt_folder.py +38 -0
- gitpane/system/ready_channel_watch.py +67 -0
- gitpane/system/startup_activation.py +65 -0
- gitpane/system/terminal_detach.py +384 -0
- gitpane/system/xdg_session.py +85 -0
- gitpane/text/__init__.py +0 -0
- gitpane/text/text_query.py +97 -0
- gitpane/text/typed_path.py +75 -0
- gitpane/text/typed_text.py +17 -0
- gitpane/thread/__init__.py +0 -0
- gitpane/thread/weak_signal.py +93 -0
- gitpane/tool/__init__.py +0 -0
- gitpane/tool/app_bundle.py +164 -0
- gitpane/tool/desktop_text_editor.py +156 -0
- gitpane/tool/difftool.py +429 -0
- gitpane/tool/editor.py +445 -0
- gitpane/tool/editor_bridge.py +193 -0
- gitpane/tool/editor_recipe.py +481 -0
- gitpane/tool/file_reveal.py +94 -0
- gitpane/tool/git_executable.py +264 -0
- gitpane/tool/git_version.py +62 -0
- gitpane/tool/kdiff3.py +41 -0
- gitpane/tool/kdiff3_install.py +162 -0
- gitpane/tool/launch_services_text_editor.py +104 -0
- gitpane/tool/mergetool_recipe.py +84 -0
- gitpane/tool/system_editor_default.py +80 -0
- gitpane/tool/system_text_editor.py +44 -0
- gitpane/tool/system_tool.py +816 -0
- gitpane/tool/terminal_recipe.py +390 -0
- gitpane/transport/__init__.py +0 -0
- gitpane/transport/branch_exchange.py +1690 -0
- gitpane/transport/clone.py +1273 -0
- gitpane/transport/credential_read_retry.py +35 -0
- gitpane/transport/git_refusal.py +207 -0
- gitpane/transport/push_tracking.py +121 -0
- gitpane/transport/refusal_notice.py +225 -0
- gitpane/transport/remote.py +747 -0
- gitpane/transport/remote_config.py +544 -0
- gitpane/ui/__init__.py +0 -0
- gitpane/ui/console/__init__.py +0 -0
- gitpane/ui/console/error_dialog.py +332 -0
- gitpane/ui/console/operation_dialog.py +408 -0
- gitpane/ui/console/operation_output.py +91 -0
- gitpane/ui/console/operation_output_view.py +373 -0
- gitpane/ui/emoji/__init__.py +0 -0
- gitpane/ui/emoji/emoji_font.py +257 -0
- gitpane/ui/emoji/emoji_grid.py +125 -0
- gitpane/ui/emoji/emoji_window.py +154 -0
- gitpane/ui/emoji/file_action_icon.py +131 -0
- gitpane/ui/emoji/opentype_family_name.py +182 -0
- gitpane/ui/history_rewrite/__init__.py +0 -0
- gitpane/ui/history_rewrite/details.py +78 -0
- gitpane/ui/history_rewrite/preview.py +565 -0
- gitpane/ui/history_rewrite/preview_model.py +291 -0
- gitpane/ui/history_rewrite/question.py +87 -0
- gitpane/ui/history_rewrite/recovery_dialog.py +262 -0
- gitpane/ui/look/__init__.py +0 -0
- gitpane/ui/look/action_icon.py +504 -0
- gitpane/ui/look/application_icon.py +78 -0
- gitpane/ui/look/application_style.py +317 -0
- gitpane/ui/look/avatar_label.py +53 -0
- gitpane/ui/look/color_contrast.py +43 -0
- gitpane/ui/look/desktop_appearance_follower.py +118 -0
- gitpane/ui/look/fixed_font.py +21 -0
- gitpane/ui/look/gtk_settings.py +116 -0
- gitpane/ui/look/icon_density.py +16 -0
- gitpane/ui/look/reference_font.py +19 -0
- gitpane/ui/look/theme_color.py +63 -0
- gitpane/ui/look/theme_look.py +95 -0
- gitpane/ui/look/theme_palette.py +173 -0
- gitpane/ui/look/warning_icon.py +86 -0
- gitpane/ui/look/windows_control_look.py +250 -0
- gitpane/ui/reader/__init__.py +0 -0
- gitpane/ui/reader/commit_message.py +129 -0
- gitpane/ui/reader/commit_panel.py +378 -0
- gitpane/ui/reader/diff_panel.py +626 -0
- gitpane/ui/reader/file_action.py +138 -0
- gitpane/ui/reader/file_tree_panel.py +235 -0
- gitpane/ui/reader/reader_toolbar.py +56 -0
- gitpane/ui/reader/revision_tree.py +80 -0
- gitpane/ui/reader/search_result.py +165 -0
- gitpane/ui/reader/source_text.py +134 -0
- gitpane/ui/reader/source_view.py +151 -0
- gitpane/ui/reader/syntax_span.py +67 -0
- gitpane/ui/reference/__init__.py +0 -0
- gitpane/ui/reference/branch_selector.py +106 -0
- gitpane/ui/reference/checkout_dialog.py +419 -0
- gitpane/ui/reference/checkout_revision_dialog.py +182 -0
- gitpane/ui/reference/commit_summary.py +339 -0
- gitpane/ui/reference/create_branch_dialog.py +346 -0
- gitpane/ui/reference/create_tag_dialog.py +283 -0
- gitpane/ui/reference/delete_local_branch_dialog.py +323 -0
- gitpane/ui/reference/delete_tag_dialog.py +394 -0
- gitpane/ui/reference/form_opening.py +53 -0
- gitpane/ui/reference/reference_dialog.py +417 -0
- gitpane/ui/reference/reference_feedback.py +62 -0
- gitpane/ui/reference/reference_form.py +139 -0
- gitpane/ui/reference/rename_branch_dialog.py +179 -0
- gitpane/ui/reference/reset_branch_dialog.py +430 -0
- gitpane/ui/reference/reset_dialog.py +263 -0
- gitpane/ui/reference/revision_dialog.py +121 -0
- gitpane/ui/reference/revision_picker.py +227 -0
- gitpane/ui/reference/select_branches_dialog.py +199 -0
- gitpane/ui/reference/stash_dialog.py +171 -0
- gitpane/ui/repository/__init__.py +0 -0
- gitpane/ui/repository/graph_delegate.py +298 -0
- gitpane/ui/repository/history_avatar.py +130 -0
- gitpane/ui/repository/history_model.py +179 -0
- gitpane/ui/repository/repository_list_popup.py +319 -0
- gitpane/ui/repository/repository_window.py +2580 -0
- gitpane/ui/resource/ArrowDown.png +0 -0
- gitpane/ui/resource/ArrowUp.png +0 -0
- gitpane/ui/resource/BranchCheckout.png +0 -0
- gitpane/ui/resource/BranchCreate.png +0 -0
- gitpane/ui/resource/BranchDelete.png +0 -0
- gitpane/ui/resource/CopyToClipboard.png +0 -0
- gitpane/ui/resource/GitPane-16.png +0 -0
- gitpane/ui/resource/GitPane-24.png +0 -0
- gitpane/ui/resource/GitPane-256.png +0 -0
- gitpane/ui/resource/GitPane-32.png +0 -0
- gitpane/ui/resource/GitPane-48.png +0 -0
- gitpane/ui/resource/GitPane-64.png +0 -0
- gitpane/ui/resource/GitPane.ico +0 -0
- gitpane/ui/resource/NotoColorEmoji-OFL.txt +92 -0
- gitpane/ui/resource/NotoColorEmoji_WindowsCompatible.ttf +0 -0
- gitpane/ui/resource/Renamed.png +0 -0
- gitpane/ui/resource/ResetAnotherBranchToHere.png +0 -0
- gitpane/ui/resource/ResetCurrentBranchToHere.png +0 -0
- gitpane/ui/resource/Stash.png +0 -0
- gitpane/ui/resource/Tag.png +0 -0
- gitpane/ui/resource/TagCreate.png +0 -0
- gitpane/ui/resource/TagDelete.png +0 -0
- gitpane/ui/resource/Unmerged.png +0 -0
- gitpane/ui/resource/checkout.png +0 -0
- gitpane/ui/sequencer/__init__.py +0 -0
- gitpane/ui/sequencer/conflict_dialog.py +532 -0
- gitpane/ui/sequencer/merge_recovery_dialog.py +67 -0
- gitpane/ui/sequencer/rebase_dialog.py +461 -0
- gitpane/ui/sequencer/rebase_editor_window.py +220 -0
- gitpane/ui/sequencer/replay_conflict_prompt.py +105 -0
- gitpane/ui/sequencer/replay_dialog.py +501 -0
- gitpane/ui/setting/__init__.py +0 -0
- gitpane/ui/setting/account_page.py +724 -0
- gitpane/ui/setting/add_account_dialog.py +1005 -0
- gitpane/ui/setting/credential_manager_dialog.py +151 -0
- gitpane/ui/setting/git_setting_widget.py +388 -0
- gitpane/ui/setting/setting_block.py +19 -0
- gitpane/ui/setting/setting_dialog.py +750 -0
- gitpane/ui/setting/ssh_widget.py +232 -0
- gitpane/ui/setting/utility_page.py +240 -0
- gitpane/ui/staging/__init__.py +0 -0
- gitpane/ui/staging/staging_action.py +356 -0
- gitpane/ui/staging/staging_window.py +745 -0
- gitpane/ui/transport/__init__.py +0 -0
- gitpane/ui/transport/clone_dialog.py +879 -0
- gitpane/ui/transport/push_dialog.py +580 -0
- gitpane/ui/transport/push_rejection_prompt.py +100 -0
- gitpane/ui/transport/push_tracking_question.py +88 -0
- gitpane/ui/transport/remote_dialog.py +943 -0
- gitpane/ui/welcome/__init__.py +0 -0
- gitpane/ui/welcome/invalid_repository_prompt.py +114 -0
- gitpane/ui/welcome/welcome_window.py +1137 -0
- gitpane/ui/widget/__init__.py +0 -0
- gitpane/ui/widget/busy_indicator.py +106 -0
- gitpane/ui/widget/commit_date_text.py +55 -0
- gitpane/ui/widget/content_growth.py +262 -0
- gitpane/ui/widget/content_measure.py +99 -0
- gitpane/ui/widget/dialog_layout.py +668 -0
- gitpane/ui/widget/drop_down_wheel_filter.py +32 -0
- gitpane/ui/widget/flow_layout.py +110 -0
- gitpane/ui/widget/long_text.py +542 -0
- gitpane/ui/widget/mnemonic.py +13 -0
- gitpane/ui/widget/numbered_text_edit.py +127 -0
- gitpane/ui/widget/plain_label.py +15 -0
- gitpane/ui/widget/plain_tooltip.py +19 -0
- gitpane/ui/widget/refresh_advice.py +25 -0
- gitpane/ui/widget/result_label.py +227 -0
- gitpane/ui/widget/result_status_bar.py +53 -0
- gitpane/ui/widget/scrolled_text.py +69 -0
- gitpane/ui/widget/shortcut_text.py +31 -0
- gitpane/ui/widget/standard_icon_label.py +55 -0
- gitpane/ui/widget/system_shortcut.py +75 -0
- gitpane/ui/widget/unavailable_reason.py +29 -0
- gitpane/ui/widget/wheel_safe_drop_down.py +24 -0
- gitpane/ui/window_control/__init__.py +0 -0
- gitpane/ui/window_control/button_focus.py +42 -0
- gitpane/ui/window_control/compositor_answer.py +152 -0
- gitpane/ui/window_control/compositor_growth_cap.py +73 -0
- gitpane/ui/window_control/desktop_activation.py +203 -0
- gitpane/ui/window_control/dialog_modality.py +122 -0
- gitpane/ui/window_control/item_activation.py +42 -0
- gitpane/ui/window_control/modal_focus_relay.py +124 -0
- gitpane/ui/window_control/wayland_activation.py +695 -0
- gitpane/ui/window_control/window_placement.py +305 -0
- gitpane/vendor/DISTLIB-LICENSE.txt +284 -0
- gitpane/vendor/w32.exe +0 -0
- gitpane/vendor/w64-arm.exe +0 -0
- gitpane/vendor/w64.exe +0 -0
- gitpane/worktree/__init__.py +0 -0
- gitpane/worktree/command_sequence.py +110 -0
- gitpane/worktree/file_action_target.py +61 -0
- gitpane/worktree/file_menu_action.py +52 -0
- gitpane/worktree/historical_restore.py +361 -0
- gitpane/worktree/ignore_rule.py +266 -0
- gitpane/worktree/mutation.py +1539 -0
- gitpane/worktree/partial_patch.py +435 -0
- gitpane/worktree/staged_reset.py +447 -0
- gitpane/worktree/staging.py +1418 -0
- gitpane/worktree/trash.py +302 -0
- gitpane/worktree/worktree_file.py +406 -0
- gitpane/worktree/worktree_service.py +584 -0
- gitpane/worktree/worktree_snapshot.py +630 -0
- gitpane-1.0.0.dist-info/METADATA +141 -0
- gitpane-1.0.0.dist-info/RECORD +353 -0
- gitpane-1.0.0.dist-info/WHEEL +5 -0
- gitpane-1.0.0.dist-info/entry_points.txt +2 -0
- gitpane-1.0.0.dist-info/licenses/LICENSE +21 -0
- gitpane-1.0.0.dist-info/licenses/THIRD_PARTY_NOTICES.md +109 -0
- gitpane-1.0.0.dist-info/licenses/src/gitpane/ui/resource/NotoColorEmoji-OFL.txt +92 -0
- gitpane-1.0.0.dist-info/licenses/src/gitpane/vendor/DISTLIB-LICENSE.txt +284 -0
- gitpane-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""Tell whether a repository window may close or change repository now."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from PySide6.QtCore import QObject, QTimer
|
|
8
|
+
from shiboken6 import isValid
|
|
9
|
+
|
|
10
|
+
from gitpane.config import REBASE_CLOSE_REREAD_ATTEMPTS, REBASE_REFRESH_INTERVAL_MS, SharedText
|
|
11
|
+
from gitpane.sequencer.replay_state import replay_may_be_present
|
|
12
|
+
from gitpane.worktree.worktree_snapshot import WorktreeKey
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from gitpane.controller.console_registry import ConsoleRegistry
|
|
16
|
+
from gitpane.controller.rebase_controller import RebaseController
|
|
17
|
+
from gitpane.controller.rebase_editor_controller import RebaseEditorController
|
|
18
|
+
from gitpane.controller.reference_form_controller import ReferenceFormController
|
|
19
|
+
from gitpane.controller.replay_controller import ReplayController
|
|
20
|
+
from gitpane.controller.session_registry import SessionRegistry
|
|
21
|
+
from gitpane.operation.repository_operation import RepositoryOperationService
|
|
22
|
+
from gitpane.sequencer.mergetool import MergetoolService
|
|
23
|
+
from gitpane.sequencer.rebase import RebaseService
|
|
24
|
+
from gitpane.sequencer.replay import ReplayService
|
|
25
|
+
from gitpane.tool.editor import EditorService
|
|
26
|
+
from gitpane.worktree.mutation import MutationService
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class CloseReadiness(QObject):
|
|
30
|
+
"""The wait of a repository window that closes or changes repository while Git still works in it: the decision, the explanation shown in its banner, the bounded rereads of the native state, the timer that tries again."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, *, session_registry_controller: SessionRegistry, console_registry_controller: ConsoleRegistry, reference_form_controller: ReferenceFormController, replay_controller: ReplayController, rebase_controller: RebaseController,
|
|
33
|
+
rebase_editor_controller: RebaseEditorController, editor: EditorService, repository_operation: RepositoryOperationService, rebase: RebaseService, replay: ReplayService, mutation: MutationService, mergetool: MergetoolService,
|
|
34
|
+
parent: QObject | None = None) -> None:
|
|
35
|
+
"""Receive the services and the lower controllers the decision reads, then set the interval of the timer; the wiring builds it after the conflict controller and connects the timer to the resumption of the pending closes.
|
|
36
|
+
|
|
37
|
+
The rebase editor controller brings its windows forward when a close waits for an edit Git asked for.
|
|
38
|
+
"""
|
|
39
|
+
super().__init__(parent)
|
|
40
|
+
self.session_registry_controller = session_registry_controller
|
|
41
|
+
self.console_registry_controller = console_registry_controller
|
|
42
|
+
self.reference_form_controller = reference_form_controller
|
|
43
|
+
self.replay_controller = replay_controller
|
|
44
|
+
self.rebase_controller = rebase_controller
|
|
45
|
+
self.rebase_editor_controller = rebase_editor_controller
|
|
46
|
+
self.editor = editor
|
|
47
|
+
self.repository_operation = repository_operation
|
|
48
|
+
self.rebase = rebase
|
|
49
|
+
self.replay = replay
|
|
50
|
+
self.mutation = mutation
|
|
51
|
+
self.mergetool = mergetool
|
|
52
|
+
self.close_timer = QTimer(self)
|
|
53
|
+
self.close_timer.setInterval(REBASE_REFRESH_INTERVAL_MS)
|
|
54
|
+
|
|
55
|
+
def _close_busy(self, session_id: str | None = None) -> bool:
|
|
56
|
+
"""Retain authority until reference forms, output, editing and reconciliation finish."""
|
|
57
|
+
session = self.session_registry_controller.session_by_id.get(session_id)
|
|
58
|
+
if session_id is not None and session is None:
|
|
59
|
+
return False
|
|
60
|
+
key = WorktreeKey.from_context(session.repository_context) if session is not None else None
|
|
61
|
+
if key is None:
|
|
62
|
+
return bool(self.editor.active_by_id or self.rebase_controller.rebase_intent_by_id or any(self._close_busy(identity) for identity in self.session_registry_controller.session_by_id))
|
|
63
|
+
for dialog_by_session in (self.replay_controller.replay_dialog_by_session, self.reference_form_controller.checkout_dialog_by_session,
|
|
64
|
+
self.reference_form_controller.checkout_revision_dialog_by_session, self.reference_form_controller.branch_dialog_by_session,
|
|
65
|
+
self.reference_form_controller.tag_dialog_by_session):
|
|
66
|
+
dialog = dialog_by_session.get(session_id)
|
|
67
|
+
if dialog is not None and isValid(dialog) and dialog.busy:
|
|
68
|
+
return True
|
|
69
|
+
window = self.session_registry_controller.window_by_session.get(session_id)
|
|
70
|
+
for output in self.console_registry_controller.reference_output_by_id.values():
|
|
71
|
+
if isValid(output) and output.running and output.parent() is window:
|
|
72
|
+
return True
|
|
73
|
+
for intent in self.rebase_controller.rebase_intent_by_id.values():
|
|
74
|
+
if intent.operation.key == key:
|
|
75
|
+
return True
|
|
76
|
+
for context in self.editor.context_by_id.values():
|
|
77
|
+
if context.worktree_key == key and not context.closed:
|
|
78
|
+
return True
|
|
79
|
+
if any(intent.operation.key == key for intent in self.replay_controller.replay_intent_by_id.values()):
|
|
80
|
+
return True
|
|
81
|
+
if replay_may_be_present(self.replay.state_by_key.get(key)):
|
|
82
|
+
if any(operation.key == key for operation in self.repository_operation.active_by_id.values()):
|
|
83
|
+
return True
|
|
84
|
+
if self.mergetool.owns_repository(session.repository_context.common_git_dir):
|
|
85
|
+
return True
|
|
86
|
+
state = self.rebase.state_by_key.get(key)
|
|
87
|
+
if state is None or state.identity is None:
|
|
88
|
+
return False
|
|
89
|
+
for operation in self.repository_operation.active_by_id.values():
|
|
90
|
+
if operation.key == key:
|
|
91
|
+
return True
|
|
92
|
+
return self.mergetool.owns_repository(session.repository_context.common_git_dir)
|
|
93
|
+
|
|
94
|
+
def close_ready(self, session_id: str | None = None) -> bool:
|
|
95
|
+
"""Require a fresh reread only after a command left its native result uncertain, and give up after a bounded number of failed rereads.
|
|
96
|
+
|
|
97
|
+
A state that stays unreadable (todo saved in another encoding, metadata removed externally) would otherwise keep the window,
|
|
98
|
+
Quit and navigation blocked forever while nothing runs any more; Git keeps its native files on disk, so closing cannot lose work.
|
|
99
|
+
"""
|
|
100
|
+
if self._close_busy(session_id):
|
|
101
|
+
return False
|
|
102
|
+
ready = True
|
|
103
|
+
for identity, session in tuple(self.session_registry_controller.session_by_id.items()):
|
|
104
|
+
if session_id is not None and identity != session_id:
|
|
105
|
+
continue
|
|
106
|
+
key = WorktreeKey.from_context(session.repository_context)
|
|
107
|
+
state = self.rebase.state_by_key.get(key)
|
|
108
|
+
attempts = self.session_registry_controller.close_reread_count_by_key.get(key)
|
|
109
|
+
if state is None or state.fresh or attempts is None:
|
|
110
|
+
self.session_registry_controller.close_reread_count_by_key.pop(key, None)
|
|
111
|
+
continue
|
|
112
|
+
if key in self.rebase.observers_by_key:
|
|
113
|
+
# A reread is still running; its published result decides whether another attempt is needed.
|
|
114
|
+
ready = False
|
|
115
|
+
continue
|
|
116
|
+
if attempts >= REBASE_CLOSE_REREAD_ATTEMPTS:
|
|
117
|
+
self.session_registry_controller.close_reread_count_by_key.pop(key, None)
|
|
118
|
+
continue
|
|
119
|
+
self.session_registry_controller.close_reread_count_by_key[key] = attempts + 1
|
|
120
|
+
self.rebase_controller.observe_rebase(identity)
|
|
121
|
+
ready = False
|
|
122
|
+
return ready
|
|
123
|
+
|
|
124
|
+
def navigation_ready(self, session_id: str) -> bool:
|
|
125
|
+
"""Tell whether the window may leave its repository now.
|
|
126
|
+
|
|
127
|
+
Besides what closing the window waits for (the native repository state), a change of repository also waits for
|
|
128
|
+
any reserved operation holding the working tree, Fetch and Push included, and for any staging write in it:
|
|
129
|
+
leaving the repository would otherwise stop them halfway. The change waits for them to finish instead.
|
|
130
|
+
"""
|
|
131
|
+
session = self.session_registry_controller.session_by_id.get(session_id)
|
|
132
|
+
if session is None:
|
|
133
|
+
return False
|
|
134
|
+
if not self.close_ready(session_id):
|
|
135
|
+
return False
|
|
136
|
+
key = WorktreeKey.from_context(session.repository_context)
|
|
137
|
+
return not self.repository_operation.owns_worktree(key) and key not in self.mutation.active_key_set
|
|
138
|
+
|
|
139
|
+
def show_close_wait(self, session_id: str | None = None, *, navigation: bool = False) -> None:
|
|
140
|
+
"""Keep a visible explanation while the original close request waits for native work.
|
|
141
|
+
|
|
142
|
+
While Git waits for an edit, the explanation sends the user to the GitPane editor window, which comes forward;
|
|
143
|
+
nothing answers Git in the user's place.
|
|
144
|
+
"""
|
|
145
|
+
subject = "The repository will change" if navigation else "GitPane will close"
|
|
146
|
+
editor_waiting = bool(self.editor.active_by_id)
|
|
147
|
+
if editor_waiting:
|
|
148
|
+
message = f"{SharedText.REBASE_EDITOR_CLOSE_WAIT.value} {subject} after Git reaches a stable state."
|
|
149
|
+
else:
|
|
150
|
+
message = f"Waiting for Git and external tools to finish. {subject} after the repository state has been read."
|
|
151
|
+
editor_wait_started = False
|
|
152
|
+
for target_id, window in tuple(self.session_registry_controller.window_by_session.items()):
|
|
153
|
+
if session_id is not None and target_id != session_id:
|
|
154
|
+
continue
|
|
155
|
+
if not isValid(window) or window.is_closed:
|
|
156
|
+
continue
|
|
157
|
+
text = self._close_reread_message(target_id, message, subject)
|
|
158
|
+
if editor_waiting and window.rebase_label.text() != text:
|
|
159
|
+
editor_wait_started = True
|
|
160
|
+
window.rebase_label.setText(text)
|
|
161
|
+
window.rebase_banner.show()
|
|
162
|
+
window.show()
|
|
163
|
+
# The editor windows come forward when a banner starts asking for them, not at each retry of the close timer,
|
|
164
|
+
# so a long wait never keeps taking the keyboard from another window.
|
|
165
|
+
if editor_wait_started:
|
|
166
|
+
self.rebase_editor_controller.raise_windows()
|
|
167
|
+
|
|
168
|
+
def clear_navigation_wait(self, session_id: str) -> None:
|
|
169
|
+
"""Put back the real rebase state in a window whose change of repository stopped without happening.
|
|
170
|
+
|
|
171
|
+
While a change of repository waits for Git, the rebase banner says the repository will change, with its Open
|
|
172
|
+
rebase button; only a published change hides it. A change that stops instead (folder gone, window opened
|
|
173
|
+
meanwhile, failed read) would otherwise keep announcing a change that will not come. A pending close keeps its
|
|
174
|
+
own message, and a running rebase command writes its progress there and publishes its state when it ends.
|
|
175
|
+
"""
|
|
176
|
+
window = self.session_registry_controller.window_by_session.get(session_id)
|
|
177
|
+
session = self.session_registry_controller.session_by_id.get(session_id)
|
|
178
|
+
if window is None or not isValid(window) or window.is_closed or session is None or session.is_closed:
|
|
179
|
+
return
|
|
180
|
+
if self.session_registry_controller.quit_pending or session_id in self.session_registry_controller.close_session_set:
|
|
181
|
+
return
|
|
182
|
+
key = WorktreeKey.from_context(session.repository_context)
|
|
183
|
+
for intent in self.rebase_controller.rebase_intent_by_id.values():
|
|
184
|
+
if intent.operation.key == key:
|
|
185
|
+
return
|
|
186
|
+
state = self.rebase.state_by_key.get(key)
|
|
187
|
+
if state is None:
|
|
188
|
+
window.rebase_banner.hide()
|
|
189
|
+
return
|
|
190
|
+
window.show_rebase_state(state)
|
|
191
|
+
|
|
192
|
+
def _close_reread_message(self, session_id: str, message: str, subject: str) -> str:
|
|
193
|
+
"""Name the reread cause and attempt count instead of a generic wait once closing depends on rereading the native state."""
|
|
194
|
+
session = self.session_registry_controller.session_by_id.get(session_id)
|
|
195
|
+
if session is None or self.editor.active_by_id:
|
|
196
|
+
return message
|
|
197
|
+
key = WorktreeKey.from_context(session.repository_context)
|
|
198
|
+
attempts = self.session_registry_controller.close_reread_count_by_key.get(key, 0)
|
|
199
|
+
state = self.rebase.state_by_key.get(key)
|
|
200
|
+
if not attempts or state is None or state.fresh:
|
|
201
|
+
return message
|
|
202
|
+
return (f"Rereading the native rebase state, attempt {attempts} of {REBASE_CLOSE_REREAD_ATTEMPTS}. {subject} once it has been read, or after the last attempt."
|
|
203
|
+
+ (" " + state.diagnostic if state.diagnostic else ""))
|
|
204
|
+
|
|
205
|
+
def defer_repository_close(self, session_id: str) -> bool:
|
|
206
|
+
"""Record a close before any window or session callback can be invalidated."""
|
|
207
|
+
if self.close_ready(session_id):
|
|
208
|
+
return False
|
|
209
|
+
self.session_registry_controller.close_session_set.add(session_id)
|
|
210
|
+
self.show_close_wait(session_id)
|
|
211
|
+
self.close_timer.start()
|
|
212
|
+
return True
|