Fix gopls langserver downloads (#7571)

Fixes https://github.com/zed-industries/zed/issues/7534 by not requiring
assets for gopls and vscode-eslint langservers — those two are the only
ones in Zed that do not use assets directly when determining langserver
version and retrieving those.
All other servers deal with assets, hence require those to be present.

The problem with https://github.com/tamasfe/taplo/releases is that they
host multiple binary releases in the same release list, so for now the
code works because only the langserver has assets — but as soon as
another release there gets assets, it will break again.
We could filter out those by names also, but they also tend to change
(and can be edited manually), so keeping it as is for now.

Release Notes:

- Fixed gopls language server downloads
([7534](https://github.com/zed-industries/zed/issues/7534))
This commit is contained in:
Kirill Bulatov 2024-02-08 16:17:47 +02:00 committed by GitHub
parent f734365b7b
commit 89b1e76003
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 57 additions and 31 deletions

View file

@ -976,7 +976,8 @@ async fn get_copilot_lsp(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
///Check for the latest copilot language server and download it if we haven't already
async fn fetch_latest(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
let release = latest_github_release("zed-industries/copilot", false, http.clone()).await?;
let release =
latest_github_release("zed-industries/copilot", true, false, http.clone()).await?;
let version_dir = &*paths::COPILOT_DIR.join(format!("copilot-{}", release.name));
@ -997,7 +998,7 @@ async fn get_copilot_lsp(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
let mut response = http
.get(url, Default::default(), true)
.await
.map_err(|err| anyhow!("error downloading copilot release: {}", err))?;
.context("error downloading copilot release")?;
let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut()));
let archive = Archive::new(decompressed_bytes);
archive.unpack(dist_dir).await?;

View file

@ -27,6 +27,7 @@ pub struct GithubReleaseAsset {
pub async fn latest_github_release(
repo_name_with_owner: &str,
require_assets: bool,
pre_release: bool,
http: Arc<dyn HttpClient>,
) -> Result<GithubRelease, anyhow::Error> {
@ -68,6 +69,7 @@ pub async fn latest_github_release(
releases
.into_iter()
.find(|release| !release.assets.is_empty() && release.pre_release == pre_release)
.filter(|release| !require_assets || !release.assets.is_empty())
.find(|release| release.pre_release == pre_release)
.ok_or(anyhow!("Failed to find a release"))
}

View file

@ -28,7 +28,8 @@ impl super::LspAdapter for CLspAdapter {
&self,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release = latest_github_release("clangd/clangd", false, delegate.http_client()).await?;
let release =
latest_github_release("clangd/clangd", true, false, delegate.http_client()).await?;
let asset_name = format!("clangd-mac-{}.zip", release.name);
let asset = release
.assets

View file

@ -29,10 +29,6 @@ impl super::LspAdapter for OmniSharpAdapter {
&self,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release =
latest_github_release("OmniSharp/omnisharp-roslyn", false, delegate.http_client())
.await?;
let mapped_arch = match ARCH {
"aarch64" => Some("arm64"),
"x86_64" => Some("x64"),
@ -42,6 +38,13 @@ impl super::LspAdapter for OmniSharpAdapter {
match mapped_arch {
None => Ok(Box::new(())),
Some(arch) => {
let release = latest_github_release(
"OmniSharp/omnisharp-roslyn",
true,
false,
delegate.http_client(),
)
.await?;
let asset_name = format!("omnisharp-osx-{}-net6.0.tar.gz", arch);
let asset = release
.assets

View file

@ -70,7 +70,8 @@ impl LspAdapter for DenoLspAdapter {
&self,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release = latest_github_release("denoland/deno", false, delegate.http_client()).await?;
let release =
latest_github_release("denoland/deno", true, false, delegate.http_client()).await?;
let asset_name = format!("deno-{}-apple-darwin.zip", consts::ARCH);
let asset = release
.assets

View file

@ -111,19 +111,19 @@ impl LspAdapter for ElixirLspAdapter {
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let http = delegate.http_client();
let release = latest_github_release("elixir-lsp/elixir-ls", false, http).await?;
let release = latest_github_release("elixir-lsp/elixir-ls", true, false, http).await?;
let version_name = release
.name
.strip_prefix("Release ")
.context("Elixir-ls release name does not start with prefix")?
.to_owned();
let asset_name = format!("elixir-ls-{}.zip", &version_name);
let asset_name = format!("elixir-ls-{version_name}.zip");
let asset = release
.assets
.iter()
.find(|asset| asset.name == asset_name)
.ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
.ok_or_else(|| anyhow!("no asset found matching {asset_name:?}"))?;
let version = GitHubLspBinaryVersion {
name: version_name,
@ -313,20 +313,21 @@ impl LspAdapter for NextLspAdapter {
&self,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release =
latest_github_release("elixir-tools/next-ls", false, delegate.http_client()).await?;
let version = release.name.clone();
let platform = match consts::ARCH {
"x86_64" => "darwin_amd64",
"aarch64" => "darwin_arm64",
other => bail!("Running on unsupported platform: {other}"),
};
let asset_name = format!("next_ls_{}", platform);
let release =
latest_github_release("elixir-tools/next-ls", true, false, delegate.http_client())
.await?;
let version = release.name;
let asset_name = format!("next_ls_{platform}");
let asset = release
.assets
.iter()
.find(|asset| asset.name == asset_name)
.ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
.with_context(|| format!("no asset found matching {asset_name:?}"))?;
let version = GitHubLspBinaryVersion {
name: version,
url: asset.browser_download_url.clone(),

View file

@ -35,7 +35,7 @@ impl LspAdapter for GleamLspAdapter {
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release =
latest_github_release("gleam-lang/gleam", false, delegate.http_client()).await?;
latest_github_release("gleam-lang/gleam", true, false, delegate.http_client()).await?;
let asset_name = format!(
"gleam-{version}-{arch}-apple-darwin.tar.gz",

View file

@ -45,7 +45,8 @@ impl super::LspAdapter for GoLspAdapter {
&self,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release = latest_github_release("golang/tools", false, delegate.http_client()).await?;
let release =
latest_github_release("golang/tools", false, false, delegate.http_client()).await?;
let version: Option<String> = release.name.strip_prefix("gopls/v").map(str::to_string);
if version.is_none() {
log::warn!(

View file

@ -30,15 +30,19 @@ impl super::LspAdapter for LuaLspAdapter {
&self,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release =
latest_github_release("LuaLS/lua-language-server", false, delegate.http_client())
.await?;
let version = release.name.clone();
let platform = match consts::ARCH {
"x86_64" => "x64",
"aarch64" => "arm64",
other => bail!("Running on unsupported platform: {other}"),
};
let release = latest_github_release(
"LuaLS/lua-language-server",
true,
false,
delegate.http_client(),
)
.await?;
let version = &release.name;
let asset_name = format!("lua-language-server-{version}-darwin-{platform}.tar.gz");
let asset = release
.assets
@ -46,7 +50,7 @@ impl super::LspAdapter for LuaLspAdapter {
.find(|asset| asset.name == asset_name)
.ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
let version = GitHubLspBinaryVersion {
name: release.name.clone(),
name: release.name,
url: asset.browser_download_url.clone(),
};
Ok(Box::new(version) as Box<_>)

View file

@ -31,8 +31,13 @@ impl LspAdapter for RustLspAdapter {
&self,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release =
latest_github_release("rust-lang/rust-analyzer", false, delegate.http_client()).await?;
let release = latest_github_release(
"rust-lang/rust-analyzer",
true,
false,
delegate.http_client(),
)
.await?;
let asset_name = format!("rust-analyzer-{}-apple-darwin.gz", consts::ARCH);
let asset = release
.assets

View file

@ -26,7 +26,8 @@ impl LspAdapter for TaploLspAdapter {
&self,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release = latest_github_release("tamasfe/taplo", false, delegate.http_client()).await?;
let release =
latest_github_release("tamasfe/taplo", true, false, delegate.http_client()).await?;
let asset_name = format!("taplo-full-darwin-{arch}.gz", arch = std::env::consts::ARCH);
let asset = release

View file

@ -246,8 +246,13 @@ impl LspAdapter for EsLintLspAdapter {
// At the time of writing the latest vscode-eslint release was released in 2020 and requires
// special custom LSP protocol extensions be handled to fully initialize. Download the latest
// prerelease instead to sidestep this issue
let release =
latest_github_release("microsoft/vscode-eslint", true, delegate.http_client()).await?;
let release = latest_github_release(
"microsoft/vscode-eslint",
false,
false,
delegate.http_client(),
)
.await?;
Ok(Box::new(GitHubLspBinaryVersion {
name: release.name,
url: release.tarball_url,

View file

@ -28,8 +28,9 @@ impl LspAdapter for ZlsAdapter {
&self,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
let release = latest_github_release("zigtools/zls", false, delegate.http_client()).await?;
let asset_name = format!("zls-{}-macos.tar.gz", ARCH);
let release =
latest_github_release("zigtools/zls", true, false, delegate.http_client()).await?;
let asset_name = format!("zls-{ARCH}-macos.tar.gz");
let asset = release
.assets
.iter()