Preserve restored screen during ticket reattach
ci / test (push) Waiting to run
ci / fuzz-smoke (push) Waiting to run
ci / windows-client (push) Waiting to run
ci / package-release (linux-x86_64, ubuntu-latest) (push) Waiting to run
ci / package-release (macos-aarch64, macos-14) (push) Waiting to run
ci / package-release (macos-x86_64, macos-13) (push) Waiting to run
ci / package-release (windows-x86_64, windows-latest) (push) Waiting to run
ci / publish-gitea-release (push) Blocked by required conditions
ci / remote-bench (push) Waiting to run
ci / test (push) Waiting to run
ci / fuzz-smoke (push) Waiting to run
ci / windows-client (push) Waiting to run
ci / package-release (linux-x86_64, ubuntu-latest) (push) Waiting to run
ci / package-release (macos-aarch64, macos-14) (push) Waiting to run
ci / package-release (macos-x86_64, macos-13) (push) Waiting to run
ci / package-release (windows-x86_64, windows-latest) (push) Waiting to run
ci / publish-gitea-release (push) Blocked by required conditions
ci / remote-bench (push) Waiting to run
This commit is contained in:
+22
@@ -426,6 +426,27 @@ escape_key = "^]"
|
|||||||
"@ | Set-Content -NoNewline -Encoding utf8 $clientConfig
|
"@ | Set-Content -NoNewline -Encoding utf8 $clientConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hostsConfig = Join-Path $configDir "hosts.toml"
|
||||||
|
if ($ForceConfig -or -not (Test-Path $hostsConfig)) {
|
||||||
|
$defaultServer = if ($Server) { $Server } else { "user@example.com" }
|
||||||
|
$hostUdp = if ($DoshHost) { $DoshHost } else { $defaultServer }
|
||||||
|
@"
|
||||||
|
# Example:
|
||||||
|
# [server]
|
||||||
|
# ssh = "server"
|
||||||
|
# dosh_host = "server.example.com"
|
||||||
|
# port = 50000
|
||||||
|
# default_command = "tm"
|
||||||
|
# predict = true
|
||||||
|
|
||||||
|
[default]
|
||||||
|
ssh = "$defaultServer"
|
||||||
|
dosh_host = "$hostUdp"
|
||||||
|
port = $Port
|
||||||
|
predict = true
|
||||||
|
"@ | Set-Content -NoNewline -Encoding utf8 $hostsConfig
|
||||||
|
}
|
||||||
|
|
||||||
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
||||||
if (-not (($userPath -split ';') -contains $bindir)) {
|
if (-not (($userPath -split ';') -contains $bindir)) {
|
||||||
[Environment]::SetEnvironmentVariable("Path", "$userPath;$bindir", "User")
|
[Environment]::SetEnvironmentVariable("Path", "$userPath;$bindir", "User")
|
||||||
@@ -442,5 +463,6 @@ Write-Host " $bindir\dosh.exe update --check"
|
|||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Client config:"
|
Write-Host "Client config:"
|
||||||
Write-Host " $configDir\client.toml"
|
Write-Host " $configDir\client.toml"
|
||||||
|
Write-Host " $configDir\hosts.toml"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Open a new terminal for PATH changes to apply."
|
Write-Host "Open a new terminal for PATH changes to apply."
|
||||||
|
|||||||
+23
-2
@@ -813,6 +813,10 @@ fn attach_snapshot(session: &Session, cols: u16, rows: u16) -> Vec<u8> {
|
|||||||
screen_snapshot(session.parser.screen())
|
screen_snapshot(session.parser.screen())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn restored_screen_is_pending_reattach(session: &Session) -> bool {
|
||||||
|
session.restored_screen.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
fn mode_allows_terminal_updates(mode: &str) -> bool {
|
fn mode_allows_terminal_updates(mode: &str) -> bool {
|
||||||
mode != "view-only" && mode != "forward-only"
|
mode != "view-only" && mode != "forward-only"
|
||||||
}
|
}
|
||||||
@@ -3707,7 +3711,7 @@ async fn broadcast_output(
|
|||||||
// short wall-clock age so low-throughput prompt/TUI changes persist
|
// short wall-clock age so low-throughput prompt/TUI changes persist
|
||||||
// quickly while large bursts still avoid per-packet disk writes. The
|
// quickly while large bursts still avoid per-packet disk writes. The
|
||||||
// actual file write happens after the lock is dropped.
|
// actual file write happens after the lock is dropped.
|
||||||
if session.persistent {
|
if session.persistent && !restored_screen_is_pending_reattach(session) {
|
||||||
session.bytes_since_persist = session
|
session.bytes_since_persist = session
|
||||||
.bytes_since_persist
|
.bytes_since_persist
|
||||||
.saturating_add(output.bytes.len());
|
.saturating_add(output.bytes.len());
|
||||||
@@ -4060,7 +4064,10 @@ fn flush_persistent_screens(state: &Arc<Mutex<ServerState>>) {
|
|||||||
let sessions_dir = locked.sessions_dir();
|
let sessions_dir = locked.sessions_dir();
|
||||||
let mut to_write: Vec<(String, u16, u16, u64, Vec<u8>)> = Vec::new();
|
let mut to_write: Vec<(String, u16, u16, u64, Vec<u8>)> = Vec::new();
|
||||||
for (name, session) in locked.sessions.iter_mut() {
|
for (name, session) in locked.sessions.iter_mut() {
|
||||||
if !session.persistent || session.output_seq == session.last_persisted_seq {
|
if !session.persistent
|
||||||
|
|| restored_screen_is_pending_reattach(session)
|
||||||
|
|| session.output_seq == session.last_persisted_seq
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
session.bytes_since_persist = 0;
|
session.bytes_since_persist = 0;
|
||||||
@@ -4411,6 +4418,20 @@ mod tests {
|
|||||||
let session = locked.sessions.get("work").unwrap();
|
let session = locked.sessions.get("work").unwrap();
|
||||||
assert!(session.restored_screen.is_some());
|
assert!(session.restored_screen.is_some());
|
||||||
assert_eq!(attach_snapshot(session, 80, 24), restored);
|
assert_eq!(attach_snapshot(session, 80, 24), restored);
|
||||||
|
assert_eq!(
|
||||||
|
session.last_persisted_seq, 7,
|
||||||
|
"pre-reattach PTY output must not overwrite the persisted restored screen"
|
||||||
|
);
|
||||||
|
drop(locked);
|
||||||
|
|
||||||
|
flush_persistent_screens(&state);
|
||||||
|
|
||||||
|
let locked = state.lock().unwrap();
|
||||||
|
let session = locked.sessions.get("work").unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
session.last_persisted_seq, 7,
|
||||||
|
"periodic flush must not replace restored screen before client-visible output"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -157,6 +157,29 @@ fn installers_generate_same_native_auth_client_defaults() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn windows_installer_generates_hosts_config_like_unix() {
|
||||||
|
let install = include_str!("../install.sh");
|
||||||
|
let ps1 = include_str!("../install.ps1");
|
||||||
|
for setting in [
|
||||||
|
"hosts.toml",
|
||||||
|
"# default_command = \"tm\"",
|
||||||
|
"[default]",
|
||||||
|
"predict = true",
|
||||||
|
] {
|
||||||
|
assert!(
|
||||||
|
install.contains(setting),
|
||||||
|
"Unix installer missing host config setting {setting}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
ps1.contains(setting),
|
||||||
|
"Windows installer missing host config setting {setting}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
assert!(ps1.contains("$hostUdp = if ($DoshHost) { $DoshHost } else { $defaultServer }"));
|
||||||
|
assert!(ps1.contains("Set-Content -NoNewline -Encoding utf8 $hostsConfig"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn package_check_verifies_only_artifacts_it_builds() {
|
fn package_check_verifies_only_artifacts_it_builds() {
|
||||||
let makefile = include_str!("../Makefile");
|
let makefile = include_str!("../Makefile");
|
||||||
|
|||||||
Reference in New Issue
Block a user