Release Notes: - Fixed a case where system NPM configuration could effect Node based language server installation.
Unified · Split
| @@ -2,7 +2,7 @@ use anyhow::{anyhow, bail, Context, Result}; · 1 unmodified line | ||
| 2 | 2 | use async_compression::futures::bufread::GzipDecoder; |
| 3 | 3 | use async_tar::Archive; |
| 4 | 4 | use serde::Deserialize; |
| 5 | −use smol::{fs, io::BufReader, process::Command}; | |
| 5 | +use smol::{fs, io::BufReader, lock::Mutex, process::Command}; | |
| 6 | 6 | use std::process::{Output, Stdio}; |
| 7 | 7 | use std::{ |
| 8 | 8 | env::consts, |
| @@ -45,14 +45,19 @@ pub trait NodeRuntime: Send + Sync { · 36 unmodified lines | ||
| 45 | 45 | |
| 46 | 46 | pub struct RealNodeRuntime { |
| 47 | 47 | http: Arc<dyn HttpClient>, |
| 48 | + installation_lock: Mutex<()>, | |
| 48 | 49 | } |
| 49 | 50 | |
| 50 | 51 | impl RealNodeRuntime { |
| 51 | 52 | pub fn new(http: Arc<dyn HttpClient>) -> Arc<dyn NodeRuntime> { |
| 52 | − Arc::new(RealNodeRuntime { http }) | |
| 53 | + Arc::new(RealNodeRuntime { | |
| 54 | + http, | |
| 55 | + installation_lock: Mutex::new(()), | |
| 56 | + }) | |
| 53 | 57 | } |
| 54 | 58 | |
| 55 | 59 | async fn install_if_needed(&self) -> Result<PathBuf> { |
| 60 | + let _lock = self.installation_lock.lock().await; | |
| 56 | 61 | log::info!("Node runtime install_if_needed"); |
| 57 | 62 | |
| 58 | 63 | let arch = match consts::ARCH { |
| @@ -73,6 +78,9 @@ impl RealNodeRuntime { · 14 unmodified lines | ||
| 73 | 78 | .stdin(Stdio::null()) |
| 74 | 79 | .stdout(Stdio::null()) |
| 75 | 80 | .stderr(Stdio::null()) |
| 81 | + .args(["--cache".into(), node_dir.join("cache")]) | |
| 82 | + .args(["--userconfig".into(), node_dir.join("blank_user_npmrc")]) | |
| 83 | + .args(["--globalconfig".into(), node_dir.join("blank_global_npmrc")]) | |
| 76 | 84 | .status() |
| 77 | 85 | .await; |
| 78 | 86 | let valid = matches!(result, Ok(status) if status.success()); |
| @@ -96,6 +104,11 @@ impl RealNodeRuntime { · 17 unmodified lines | ||
| 96 | 104 | archive.unpack(&node_containing_dir).await?; |
| 97 | 105 | } |
| 98 | 106 | |
| 107 | + // Note: Not in the `if !valid {}` so we can populate these for existing installations | |
| 108 | + _ = fs::create_dir(node_dir.join("cache")).await; | |
| 109 | + _ = fs::write(node_dir.join("blank_user_npmrc"), []).await; | |
| 110 | + _ = fs::write(node_dir.join("blank_global_npmrc"), []).await; | |
| 111 | + | |
| 99 | 112 | anyhow::Ok(node_dir) |
| 100 | 113 | } |
| 101 | 114 | } |
| @@ -137,7 +150,17 @@ impl NodeRuntime for RealNodeRuntime { · 35 unmodified lines | ||
| 137 | 150 | |
| 138 | 151 | let mut command = Command::new(node_binary); |
| 139 | 152 | command.env("PATH", env_path); |
| 140 | − command.arg(npm_file).arg(subcommand).args(args); | |
| 153 | + command.arg(npm_file).arg(subcommand); | |
| 154 | + command.args(["--cache".into(), installation_path.join("cache")]); | |
| 155 | + command.args([ | |
| 156 | + "--userconfig".into(), | |
| 157 | + installation_path.join("blank_user_npmrc"), | |
| 158 | + ]); | |
| 159 | + command.args([ | |
| 160 | + "--globalconfig".into(), | |
| 161 | + installation_path.join("blank_global_npmrc"), | |
| 162 | + ]); | |
| 163 | + command.args(args); | |
| 141 | 164 | |
| 142 | 165 | if let Some(directory) = directory { |
| 143 | 166 | command.current_dir(directory); |