Merge branch 'main' into faster_macos

This commit is contained in:
Peter Tripp
2024-10-25 13:04:39 -04:00
5 changed files with 135 additions and 86 deletions

View File

@@ -4,6 +4,7 @@ use assistant_slash_command::{
SlashCommandOutput, SlashCommandOutputSection, SlashCommandResult,
};
use futures::channel::mpsc;
use futures::Stream;
use fuzzy::PathMatch;
use gpui::{AppContext, Model, Task, View, WeakView};
use language::{BufferSnapshot, CodeLabel, HighlightId, LineEnding, LspAdapterDelegate};
@@ -196,7 +197,12 @@ impl SlashCommand for FileSlashCommand {
return Task::ready(Err(anyhow!("missing path")));
};
collect_files(workspace.read(cx).project().clone(), arguments, cx)
Task::ready(Ok(collect_files(
workspace.read(cx).project().clone(),
arguments,
cx,
)
.boxed()))
}
}
@@ -204,7 +210,7 @@ fn collect_files(
project: Model<Project>,
glob_inputs: &[String],
cx: &mut AppContext,
) -> Task<SlashCommandResult> {
) -> impl Stream<Item = Result<SlashCommandEvent>> {
let Ok(matchers) = glob_inputs
.into_iter()
.map(|glob_input| {
@@ -213,7 +219,7 @@ fn collect_files(
})
.collect::<anyhow::Result<Vec<custom_path_matcher::PathMatcher>>>()
else {
return Task::ready(Err(anyhow!("invalid path")));
return futures::stream::once(async { Err(anyhow!("invalid path")) }).boxed();
};
let project_handle = project.downgrade();
@@ -357,8 +363,12 @@ fn collect_files(
events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection { metadata: None }))?;
}
}
Ok(events_rx.boxed())
anyhow::Ok(())
})
.detach_and_log_err(cx);
events_rx.boxed()
}
pub fn codeblock_fence_for_path(
@@ -550,6 +560,7 @@ mod test {
use project::Project;
use serde_json::json;
use settings::SettingsStore;
use smol::stream::StreamExt;
use crate::slash_command::file_command::collect_files;
@@ -590,11 +601,9 @@ mod test {
let project = Project::test(fs, ["/root".as_ref()], cx).await;
let result_1 = cx
.update(|cx| collect_files(project.clone(), &["root/dir".to_string()], cx))
.await
.unwrap();
let result_1 = SlashCommandOutput::from_event_stream(result_1)
let result_1 =
cx.update(|cx| collect_files(project.clone(), &["root/dir".to_string()], cx));
let result_1 = SlashCommandOutput::from_event_stream(result_1.boxed())
.await
.unwrap();
@@ -602,20 +611,16 @@ mod test {
// 4 files + 2 directories
assert_eq!(result_1.sections.len(), 6);
let result_2 = cx
.update(|cx| collect_files(project.clone(), &["root/dir/".to_string()], cx))
.await
.unwrap();
let result_2 = SlashCommandOutput::from_event_stream(result_2)
let result_2 =
cx.update(|cx| collect_files(project.clone(), &["root/dir/".to_string()], cx));
let result_2 = SlashCommandOutput::from_event_stream(result_2.boxed())
.await
.unwrap();
assert_eq!(result_1, result_2);
let result = cx
.update(|cx| collect_files(project.clone(), &["root/dir*".to_string()], cx))
.await
.unwrap();
let result =
cx.update(|cx| collect_files(project.clone(), &["root/dir*".to_string()], cx).boxed());
let result = SlashCommandOutput::from_event_stream(result).await.unwrap();
assert!(result.text.starts_with("root/dir"));
@@ -659,11 +664,11 @@ mod test {
let project = Project::test(fs, ["/zed".as_ref()], cx).await;
let result = cx
.update(|cx| collect_files(project.clone(), &["zed/assets/themes".to_string()], cx))
let result =
cx.update(|cx| collect_files(project.clone(), &["zed/assets/themes".to_string()], cx));
let result = SlashCommandOutput::from_event_stream(result.boxed())
.await
.unwrap();
let result = SlashCommandOutput::from_event_stream(result).await.unwrap();
// Sanity check
assert!(result.text.starts_with("zed/assets/themes\n"));
@@ -721,11 +726,11 @@ mod test {
let project = Project::test(fs, ["/zed".as_ref()], cx).await;
let result = cx
.update(|cx| collect_files(project.clone(), &["zed/assets/themes".to_string()], cx))
let result =
cx.update(|cx| collect_files(project.clone(), &["zed/assets/themes".to_string()], cx));
let result = SlashCommandOutput::from_event_stream(result.boxed())
.await
.unwrap();
let result = SlashCommandOutput::from_event_stream(result).await.unwrap();
assert!(result.text.starts_with("zed/assets/themes\n"));
assert_eq!(result.sections[0].label, "zed/assets/themes/LICENSE");

View File

@@ -432,10 +432,11 @@ impl AutoUpdater {
cx.notify();
}
pub async fn get_latest_remote_server_release(
pub async fn download_remote_server_release(
os: &str,
arch: &str,
mut release_channel: ReleaseChannel,
release_channel: ReleaseChannel,
version: Option<SemanticVersion>,
cx: &mut AsyncAppContext,
) -> Result<PathBuf> {
let this = cx.update(|cx| {
@@ -445,15 +446,12 @@ impl AutoUpdater {
.ok_or_else(|| anyhow!("auto-update not initialized"))
})??;
if release_channel == ReleaseChannel::Dev {
release_channel = ReleaseChannel::Nightly;
}
let release = Self::get_latest_release(
let release = Self::get_release(
&this,
"zed-remote-server",
os,
arch,
version,
Some(release_channel),
cx,
)
@@ -468,17 +466,21 @@ impl AutoUpdater {
let client = this.read_with(cx, |this, _| this.http_client.clone())?;
if smol::fs::metadata(&version_path).await.is_err() {
log::info!("downloading zed-remote-server {os} {arch}");
log::info!(
"downloading zed-remote-server {os} {arch} version {}",
release.version
);
download_remote_server_binary(&version_path, release, client, cx).await?;
}
Ok(version_path)
}
pub async fn get_latest_remote_server_release_url(
pub async fn get_remote_server_release_url(
os: &str,
arch: &str,
mut release_channel: ReleaseChannel,
release_channel: ReleaseChannel,
version: Option<SemanticVersion>,
cx: &mut AsyncAppContext,
) -> Result<(String, String)> {
let this = cx.update(|cx| {
@@ -488,15 +490,12 @@ impl AutoUpdater {
.ok_or_else(|| anyhow!("auto-update not initialized"))
})??;
if release_channel == ReleaseChannel::Dev {
release_channel = ReleaseChannel::Nightly;
}
let release = Self::get_latest_release(
let release = Self::get_release(
&this,
"zed-remote-server",
os,
arch,
version,
Some(release_channel),
cx,
)
@@ -508,6 +507,56 @@ impl AutoUpdater {
Ok((release.url, body))
}
async fn get_release(
this: &Model<Self>,
asset: &str,
os: &str,
arch: &str,
version: Option<SemanticVersion>,
release_channel: Option<ReleaseChannel>,
cx: &mut AsyncAppContext,
) -> Result<JsonRelease> {
let client = this.read_with(cx, |this, _| this.http_client.clone())?;
if let Some(version) = version {
let channel = release_channel.map(|c| c.dev_name()).unwrap_or("stable");
let url = format!("/api/releases/{channel}/{version}/{asset}-{os}-{arch}.gz?update=1",);
Ok(JsonRelease {
version: version.to_string(),
url: client.build_url(&url),
})
} else {
let mut url_string = client.build_url(&format!(
"/api/releases/latest?asset={}&os={}&arch={}",
asset, os, arch
));
if let Some(param) = release_channel.and_then(|c| c.release_query_param()) {
url_string += "&";
url_string += param;
}
let mut response = client.get(&url_string, Default::default(), true).await?;
let mut body = Vec::new();
response.body_mut().read_to_end(&mut body).await?;
if !response.status().is_success() {
return Err(anyhow!(
"failed to fetch release: {:?}",
String::from_utf8_lossy(&body),
));
}
serde_json::from_slice(body.as_slice()).with_context(|| {
format!(
"error deserializing release {:?}",
String::from_utf8_lossy(&body),
)
})
}
}
async fn get_latest_release(
this: &Model<Self>,
asset: &str,
@@ -516,38 +565,7 @@ impl AutoUpdater {
release_channel: Option<ReleaseChannel>,
cx: &mut AsyncAppContext,
) -> Result<JsonRelease> {
let client = this.read_with(cx, |this, _| this.http_client.clone())?;
let mut url_string = client.build_url(&format!(
"/api/releases/latest?asset={}&os={}&arch={}",
asset, os, arch
));
if let Some(param) = release_channel.and_then(|c| c.release_query_param()) {
url_string += "&";
url_string += param;
}
let mut response = client.get(&url_string, Default::default(), true).await?;
let mut body = Vec::new();
response
.body_mut()
.read_to_end(&mut body)
.await
.context("error reading release")?;
if !response.status().is_success() {
Err(anyhow!(
"failed to fetch release: {:?}",
String::from_utf8_lossy(&body),
))?;
}
serde_json::from_slice(body.as_slice()).with_context(|| {
format!(
"error deserializing release {:?}",
String::from_utf8_lossy(&body),
)
})
Self::get_release(this, asset, os, arch, None, release_channel, cx).await
}
async fn update(this: Model<Self>, mut cx: AsyncAppContext) -> Result<()> {

View File

@@ -517,17 +517,31 @@ impl SshClientDelegate {
}
}
// For nightly channel, always get latest
let current_version = if release_channel == ReleaseChannel::Nightly {
None
} else {
Some(version)
};
self.update_status(
Some(&format!("Checking remote server release {}", version)),
cx,
);
if download_binary_on_host {
let (request_url, request_body) = AutoUpdater::get_latest_remote_server_release_url(
let (request_url, request_body) = AutoUpdater::get_remote_server_release_url(
platform.os,
platform.arch,
release_channel,
current_version,
cx,
)
.await
.map_err(|e| {
anyhow!(
"Failed to get remote server binary download url (os: {}, arch: {}): {}",
"Failed to get remote server binary download url (version: {}, os: {}, arch: {}): {}",
version,
platform.os,
platform.arch,
e
@@ -542,17 +556,18 @@ impl SshClientDelegate {
version,
))
} else {
self.update_status(Some("Checking for latest version of remote server"), cx);
let binary_path = AutoUpdater::get_latest_remote_server_release(
let binary_path = AutoUpdater::download_remote_server_release(
platform.os,
platform.arch,
release_channel,
current_version,
cx,
)
.await
.map_err(|e| {
anyhow!(
"Failed to download remote server binary (os: {}, arch: {}): {}",
"Failed to download remote server binary (version: {}, os: {}, arch: {}): {}",
version,
platform.os,
platform.arch,
e

View File

@@ -1707,21 +1707,32 @@ impl SshRemoteConnection {
let (binary, version) = delegate.get_server_binary(platform, cx).await??;
let mut server_binary_exists = false;
if !server_binary_exists && cfg!(not(debug_assertions)) {
let mut remote_version = None;
if cfg!(not(debug_assertions)) {
if let Ok(installed_version) =
run_cmd(self.socket.ssh_command(dst_path).arg("version")).await
{
if installed_version.trim() == version.to_string() {
server_binary_exists = true;
if let Ok(version) = installed_version.trim().parse::<SemanticVersion>() {
remote_version = Some(version);
} else {
log::warn!("failed to parse version of remote server: {installed_version:?}",);
}
log::info!("checked remote server binary for version. latest version: {}. remote server version: {}", version.to_string(), installed_version.trim());
}
}
if server_binary_exists {
log::info!("remote development server already present",);
return Ok(());
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
);
}
}
}
match binary {

View File

@@ -90,7 +90,7 @@ function build() {
channel=$(<RELEASE_CHANNEL)
cp Cargo.toml Cargo.toml.backup
sed -i .backup \
sed -i.backup \
"s/package.metadata.bundle-${channel}/package.metadata.bundle/" \
Cargo.toml
if [ "$local_only" = true ]; then