Merge branch 'main' into faster_macos
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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<()> {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user