windows: Fix eslint installation (#15331)

Close #13786. To make `eslint` running on Windows, I made the following
changes:

1. Ensure that `zed` downloads the `.zip` file.
2. Handle the `$shared` symbolic link by copying files to the link
location.
3. In #13891, I mentioned that the `npm` `post-install` script was
always failing. After debugging, I found it was due to missing
environment variables. This has been fixed, and I will submit a new PR
to address the changes in #13891.

With this PR, `eslint` can now successfully run on Windows. Video:



https://github.com/user-attachments/assets/e85451b8-0388-490a-8a75-01c12d744f7c



Release Notes:

- Fixed `eslint` not running on Windows
([#13786](https://github.com/zed-industries/zed/issues/13786)).

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
张小白 2024-07-27 22:24:05 +08:00 committed by GitHub
parent 138c3fcfdd
commit 4976a9e9d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 59 additions and 0 deletions

View file

@ -296,7 +296,11 @@ pub struct EsLintLspAdapter {
impl EsLintLspAdapter {
const CURRENT_VERSION: &'static str = "release/2.4.4";
#[cfg(not(windows))]
const GITHUB_ASSET_KIND: AssetKind = AssetKind::TarGz;
#[cfg(windows)]
const GITHUB_ASSET_KIND: AssetKind = AssetKind::Zip;
const SERVER_PATH: &'static str = "vscode-eslint/server/out/eslintServer.js";
const SERVER_NAME: &'static str = "eslint";
@ -443,6 +447,13 @@ impl LspAdapter for EsLintLspAdapter {
let archive = Archive::new(decompressed_bytes);
archive.unpack(&destination_path).await?;
}
AssetKind::Zip => {
node_runtime::extract_zip(
&destination_path,
BufReader::new(response.body_mut()),
)
.await?;
}
}
let mut dir = fs::read_dir(&destination_path).await?;
@ -450,6 +461,20 @@ impl LspAdapter for EsLintLspAdapter {
let repo_root = destination_path.join("vscode-eslint");
fs::rename(first.path(), &repo_root).await?;
#[cfg(target_os = "windows")]
{
handle_symlink(
repo_root.join("$shared"),
repo_root.join("client").join("src").join("shared"),
)
.await?;
handle_symlink(
repo_root.join("$shared"),
repo_root.join("server").join("src").join("shared"),
)
.await?;
}
self.node
.run_npm_subcommand(Some(&repo_root), "install", &[])
.await?;
@ -505,6 +530,25 @@ async fn get_cached_eslint_server_binary(
.log_err()
}
#[cfg(target_os = "windows")]
async fn handle_symlink(src_dir: PathBuf, dest_dir: PathBuf) -> Result<()> {
if fs::metadata(&src_dir).await.is_err() {
return Err(anyhow!("Directory {} not present.", src_dir.display()));
}
if fs::metadata(&dest_dir).await.is_ok() {
fs::remove_file(&dest_dir).await?;
}
fs::create_dir_all(&dest_dir).await?;
let mut entries = fs::read_dir(&src_dir).await?;
while let Some(entry) = entries.try_next().await? {
let entry_path = entry.path();
let entry_name = entry.file_name();
let dest_path = dest_dir.join(&entry_name);
fs::copy(&entry_path, &dest_path).await?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use gpui::{Context, TestAppContext};