History

Avoid user NPM config/cache & put NodeRuntime installation behind a lock (#3324)

Release Notes: - Fixed a case where system NPM configuration could effect Node based language server installation.

Julia committed 3 years ago

Commit 75490fe2 parents 5c8db99 59ec9e51 file · +26 −3Browse files

Unified · Split

crates/node_runtime/src/node_runtime.rs+26−3
@@ -2,7 +2,7 @@ use anyhow::{anyhow, bail, Context, Result}; · 1 unmodified line
2use async_compression::futures::bufread::GzipDecoder;2use async_compression::futures::bufread::GzipDecoder;
3use async_tar::Archive;3use async_tar::Archive;
4use serde::Deserialize;4use serde::Deserialize;
5use smol::{fs, io::BufReader, process::Command};5use smol::{fs, io::BufReader, lock::Mutex, process::Command};
6use std::process::{Output, Stdio};6use std::process::{Output, Stdio};
7use std::{7use std::{
8 env::consts,8 env::consts,
@@ -45,14 +45,19 @@ pub trait NodeRuntime: Send + Sync { · 36 unmodified lines
45 45
46pub struct RealNodeRuntime {46pub struct RealNodeRuntime {
47 http: Arc<dyn HttpClient>,47 http: Arc<dyn HttpClient>,
48 installation_lock: Mutex<()>,
48}49}
49 50
50impl RealNodeRuntime {51impl RealNodeRuntime {
51 pub fn new(http: Arc<dyn HttpClient>) -> Arc<dyn NodeRuntime> {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 async fn install_if_needed(&self) -> Result<PathBuf> {59 async fn install_if_needed(&self) -> Result<PathBuf> {
60 let _lock = self.installation_lock.lock().await;
56 log::info!("Node runtime install_if_needed");61 log::info!("Node runtime install_if_needed");
57 62
58 let arch = match consts::ARCH {63 let arch = match consts::ARCH {
@@ -73,6 +78,9 @@ impl RealNodeRuntime { · 14 unmodified lines
73 .stdin(Stdio::null())78 .stdin(Stdio::null())
74 .stdout(Stdio::null())79 .stdout(Stdio::null())
75 .stderr(Stdio::null())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 .status()84 .status()
77 .await;85 .await;
78 let valid = matches!(result, Ok(status) if status.success());86 let valid = matches!(result, Ok(status) if status.success());
@@ -96,6 +104,11 @@ impl RealNodeRuntime { · 17 unmodified lines
96 archive.unpack(&node_containing_dir).await?;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 anyhow::Ok(node_dir)112 anyhow::Ok(node_dir)
100 }113 }
101}114}
@@ -137,7 +150,17 @@ impl NodeRuntime for RealNodeRuntime { · 35 unmodified lines
137 150
138 let mut command = Command::new(node_binary);151 let mut command = Command::new(node_binary);
139 command.env("PATH", env_path);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 if let Some(directory) = directory {165 if let Some(directory) = directory {
143 command.current_dir(directory);166 command.current_dir(directory);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t