@@ -120,6 +120,7 @@ pub async fn get_release_by_tag_name(
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum AssetKind {
TarGz,
+ Zip,
}
pub fn build_asset_url(repo_name_with_owner: &str, tag: &str, kind: AssetKind) -> Result<String> {
@@ -132,6 +133,7 @@ pub fn build_asset_url(repo_name_with_owner: &str, tag: &str, kind: AssetKind) -
"{tag}.{extension}",
extension = match kind {
AssetKind::TarGz => "tar.gz",
+ AssetKind::Zip => "zip",
}
);
url.path_segments_mut()
@@ -154,5 +156,11 @@ mod tests {
tarball,
"https://github.com/microsoft/vscode-eslint/archive/refs/tags/release%2F2.3.5.tar.gz"
);
+
+ let zip = build_asset_url(repo_name_with_owner, tag, AssetKind::Zip).unwrap();
+ assert_eq!(
+ zip,
+ "https://github.com/microsoft/vscode-eslint/archive/refs/tags/release%2F2.3.5.zip"
+ );
}
}
@@ -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};
@@ -290,6 +290,13 @@ impl NodeRuntime for RealNodeRuntime {
{
command.env("SYSTEMROOT", val);
}
+ // Without ComSpec, the post-install will always fail.
+ if let Some(val) = std::env::var("ComSpec")
+ .context("Missing environment variable: ComSpec!")
+ .log_err()
+ {
+ command.env("ComSpec", val);
+ }
command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
}