Keep session manager open on launch failure
This commit is contained in:
+95
-29
@@ -17,6 +17,7 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
from typing import Callable, Iterable, Mapping, Sequence
|
||||
from urllib.parse import quote
|
||||
|
||||
@@ -986,21 +987,72 @@ class TmuxHub:
|
||||
return self.window_for_key(endpoint.key) or replaced
|
||||
|
||||
@serialized_hub_mutation
|
||||
def activate_endpoint(self, endpoint: Endpoint, herdr_bin: str) -> ManagedWindow:
|
||||
def activate_endpoint(
|
||||
self,
|
||||
endpoint: Endpoint,
|
||||
herdr_bin: str,
|
||||
*,
|
||||
verify_startup: bool = False,
|
||||
) -> ManagedWindow:
|
||||
window = self.window_for_key(endpoint.key)
|
||||
started = False
|
||||
if window is None:
|
||||
window = self.create_window(endpoint, herdr_bin)
|
||||
self.remove_bootstrap()
|
||||
started = True
|
||||
elif window.endpoint is not None and (
|
||||
window.endpoint.remote_transport != endpoint.remote_transport
|
||||
or window.endpoint.remote_keybindings != endpoint.remote_keybindings
|
||||
):
|
||||
window = self.replace_endpoint(window, endpoint, herdr_bin)
|
||||
started = True
|
||||
elif window.dead:
|
||||
self.reconnect(window.window_id)
|
||||
started = True
|
||||
if verify_startup and started:
|
||||
window = self.wait_for_window_startup(window.window_id)
|
||||
self.select_window(window.window_id)
|
||||
return window
|
||||
|
||||
def wait_for_window_startup(
|
||||
self,
|
||||
window_id: str,
|
||||
*,
|
||||
timeout: float = 0.4,
|
||||
) -> ManagedWindow:
|
||||
"""Catch commands that exit immediately before presenting their UI."""
|
||||
deadline = time.monotonic() + timeout
|
||||
while True:
|
||||
window = next(
|
||||
(
|
||||
candidate
|
||||
for candidate in self.managed_windows()
|
||||
if candidate.window_id == window_id
|
||||
),
|
||||
None,
|
||||
)
|
||||
if window is None:
|
||||
raise HubError("Session Tab 在启动过程中消失")
|
||||
if window.dead:
|
||||
capture = self.run(
|
||||
["capture-pane", "-p", "-t", window_id, "-S", "-20"],
|
||||
check=False,
|
||||
)
|
||||
lines = [
|
||||
line.strip()
|
||||
for line in (capture.stdout or "").splitlines()
|
||||
if line.strip()
|
||||
]
|
||||
detail = " · ".join(lines[-3:])
|
||||
message = "Session 进程启动后立即退出"
|
||||
if detail:
|
||||
message += f":{detail}"
|
||||
raise HubError(message)
|
||||
remaining = deadline - time.monotonic()
|
||||
if remaining <= 0:
|
||||
return window
|
||||
time.sleep(min(0.05, remaining))
|
||||
|
||||
def attach(self) -> None:
|
||||
if inside_any_tmux():
|
||||
if inside_socket(self.socket_name):
|
||||
@@ -1292,6 +1344,46 @@ def command_choose(arguments: argparse.Namespace) -> int:
|
||||
]
|
||||
return StopSessionOutcome(tuple(updated), tab_closed, warning)
|
||||
|
||||
def activate_selection(result: SelectorResult) -> None:
|
||||
if result.kind == "window":
|
||||
assert result.window_id is not None
|
||||
if result.dead:
|
||||
hub.reconnect(result.window_id)
|
||||
hub.wait_for_window_startup(result.window_id)
|
||||
hub.select_window(result.window_id)
|
||||
return
|
||||
if result.kind == "local":
|
||||
assert result.session is not None
|
||||
hub.activate_endpoint(
|
||||
Endpoint.local(result.session),
|
||||
resolve_herdr(),
|
||||
verify_startup=True,
|
||||
)
|
||||
return
|
||||
|
||||
assert result.target is not None and result.session is not None
|
||||
endpoint = Endpoint.remote(
|
||||
result.target,
|
||||
result.session,
|
||||
result.remote_keybindings,
|
||||
result.remote_transport,
|
||||
)
|
||||
try:
|
||||
remote_registry.upsert(
|
||||
RemoteEntry(
|
||||
endpoint.target,
|
||||
endpoint.remote_keybindings,
|
||||
endpoint.remote_transport,
|
||||
)
|
||||
)
|
||||
except RegistryError as error:
|
||||
hub.display_message(f"herdr-hub: remote registry: {error}")
|
||||
hub.activate_endpoint(
|
||||
endpoint,
|
||||
resolve_herdr(),
|
||||
verify_startup=True,
|
||||
)
|
||||
|
||||
try:
|
||||
selector = SessionSelector(
|
||||
catalog_windows(windows),
|
||||
@@ -1299,6 +1391,7 @@ def command_choose(arguments: argparse.Namespace) -> int:
|
||||
ssh_bin,
|
||||
local_sessions=(endpoint.session for endpoint in local_report.endpoints),
|
||||
aliases=hub.aliases,
|
||||
activate_handler=activate_selection,
|
||||
rename_handler=rename_session,
|
||||
close_window_handler=close_window,
|
||||
delete_session_handler=delete_session,
|
||||
@@ -1326,34 +1419,7 @@ def command_choose(arguments: argparse.Namespace) -> int:
|
||||
assert result.window_id is not None
|
||||
hub.dismiss_window(result.window_id)
|
||||
return 0
|
||||
if result.kind == "window":
|
||||
assert result.window_id is not None
|
||||
if result.dead:
|
||||
hub.reconnect(result.window_id)
|
||||
hub.select_window(result.window_id)
|
||||
return 0
|
||||
if result.kind == "local":
|
||||
assert result.session is not None
|
||||
hub.activate_endpoint(Endpoint.local(result.session), resolve_herdr())
|
||||
return 0
|
||||
assert result.target is not None and result.session is not None
|
||||
endpoint = Endpoint.remote(
|
||||
result.target,
|
||||
result.session,
|
||||
result.remote_keybindings,
|
||||
result.remote_transport,
|
||||
)
|
||||
try:
|
||||
remote_registry.upsert(
|
||||
RemoteEntry(
|
||||
endpoint.target,
|
||||
endpoint.remote_keybindings,
|
||||
endpoint.remote_transport,
|
||||
)
|
||||
)
|
||||
except RegistryError as error:
|
||||
hub.display_message(f"herdr-hub: remote registry: {error}")
|
||||
hub.activate_endpoint(endpoint, resolve_herdr())
|
||||
activate_selection(result)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user