ssh remoting: Check nightly version correctly by comparing commit SHA (#19884)

This ensures that we detect if a new nightly version of the remote
server is available.
Previously we would always mark a version as matching if they had the
same semantic version.
However, for nightly versions we also need to check if they have the
same commit SHA.

Co-Authored-by: Thorsten <thorsten@zed.dev>

Release Notes:

- N/A

---------

Co-authored-by: Thorsten <thorsten@zed.dev>
This commit is contained in:
Bennet Bo Fenner 2024-10-29 11:32:55 +01:00 committed by GitHub
parent 7a6b6435c4
commit f7b2b41df9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 107 additions and 41 deletions

View file

@ -227,6 +227,20 @@ pub enum ServerBinary {
ReleaseUrl { url: String, body: String },
}
pub enum ServerVersion {
Semantic(SemanticVersion),
Commit(String),
}
impl std::fmt::Display for ServerVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Semantic(version) => write!(f, "{}", version),
Self::Commit(commit) => write!(f, "{}", commit),
}
}
}
pub trait SshClientDelegate: Send + Sync {
fn ask_password(
&self,
@ -243,7 +257,7 @@ pub trait SshClientDelegate: Send + Sync {
platform: SshPlatform,
upload_binary_over_ssh: bool,
cx: &mut AsyncAppContext,
) -> oneshot::Receiver<Result<(ServerBinary, SemanticVersion)>>;
) -> oneshot::Receiver<Result<(ServerBinary, ServerVersion)>>;
fn set_status(&self, status: Option<&str>, cx: &mut AsyncAppContext);
}
@ -1714,34 +1728,47 @@ impl SshRemoteConnection {
}
let upload_binary_over_ssh = self.socket.connection_options.upload_binary_over_ssh;
let (binary, version) = delegate
let (binary, new_server_version) = delegate
.get_server_binary(platform, upload_binary_over_ssh, cx)
.await??;
let mut remote_version = None;
if cfg!(not(debug_assertions)) {
if let Ok(installed_version) =
let installed_version = if let Ok(version_output) =
run_cmd(self.socket.ssh_command(dst_path).arg("version")).await
{
if let Ok(version) = installed_version.trim().parse::<SemanticVersion>() {
remote_version = Some(version);
if let Ok(version) = version_output.trim().parse::<SemanticVersion>() {
Some(ServerVersion::Semantic(version))
} else {
log::warn!("failed to parse version of remote server: {installed_version:?}",);
Some(ServerVersion::Commit(version_output.trim().to_string()))
}
}
} else {
None
};
if let Some(remote_version) = remote_version {
if remote_version == version {
log::info!("remote development server present and matching client version");
return Ok(());
} else if remote_version > version {
let error = anyhow!("The version of the remote server ({}) is newer than the Zed version ({}). Please update Zed.", remote_version, version);
return Err(error);
} else {
log::info!(
"remote development server has older version: {}. updating...",
remote_version
);
if let Some(installed_version) = installed_version {
use ServerVersion::*;
match (installed_version, new_server_version) {
(Semantic(installed), Semantic(new)) if installed == new => {
log::info!("remote development server present and matching client version");
return Ok(());
}
(Semantic(installed), Semantic(new)) if installed > new => {
let error = anyhow!("The version of the remote server ({}) is newer than the Zed version ({}). Please update Zed.", installed, new);
return Err(error);
}
(Commit(installed), Commit(new)) if installed == new => {
log::info!(
"remote development server present and matching client version {}",
installed
);
return Ok(());
}
(installed, _) => {
log::info!(
"remote development server has version: {}. updating...",
installed
);
}
}
}
}
@ -2224,12 +2251,12 @@ mod fake {
},
select_biased, FutureExt, SinkExt, StreamExt,
};
use gpui::{AsyncAppContext, SemanticVersion, Task};
use gpui::{AsyncAppContext, Task};
use rpc::proto::Envelope;
use super::{
ChannelClient, RemoteConnection, ServerBinary, SshClientDelegate, SshConnectionOptions,
SshPlatform,
ChannelClient, RemoteConnection, ServerBinary, ServerVersion, SshClientDelegate,
SshConnectionOptions, SshPlatform,
};
pub(super) struct FakeRemoteConnection {
@ -2349,7 +2376,7 @@ mod fake {
_: SshPlatform,
_: bool,
_: &mut AsyncAppContext,
) -> oneshot::Receiver<Result<(ServerBinary, SemanticVersion)>> {
) -> oneshot::Receiver<Result<(ServerBinary, ServerVersion)>> {
unreachable!()
}