mirror of
https://github.com/denoland/deno.git
synced 2025-02-08 07:16:56 -05:00
fix(npmrc): merge .npmrc
in user's homedir and project (#27119)
This commit is contained in:
parent
d58c70fbd1
commit
3097d99d76
7 changed files with 124 additions and 34 deletions
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
@ -103,7 +104,7 @@ fn discover_npmrc<TSys: EnvVar + EnvHomeDir + FsRead>(
|
||||||
sys: &impl EnvVar,
|
sys: &impl EnvVar,
|
||||||
source: &str,
|
source: &str,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
) -> Result<ResolvedNpmRc, NpmRcDiscoverError> {
|
) -> Result<NpmRc, NpmRcDiscoverError> {
|
||||||
let npmrc = NpmRc::parse(source, &|name| sys.env_var(name).ok()).map_err(
|
let npmrc = NpmRc::parse(source, &|name| sys.env_var(name).ok()).map_err(
|
||||||
|source| {
|
|source| {
|
||||||
NpmRcParseError {
|
NpmRcParseError {
|
||||||
|
@ -113,52 +114,50 @@ fn discover_npmrc<TSys: EnvVar + EnvHomeDir + FsRead>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let resolved =
|
|
||||||
npmrc
|
|
||||||
.as_resolved(&npm_registry_url(sys))
|
|
||||||
.map_err(|source| NpmRcOptionsResolveError {
|
|
||||||
path: path.to_path_buf(),
|
|
||||||
source,
|
|
||||||
})?;
|
|
||||||
log::debug!(".npmrc found at: '{}'", path.display());
|
log::debug!(".npmrc found at: '{}'", path.display());
|
||||||
Ok(resolved)
|
Ok(npmrc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Try `.npmrc` next to `package.json`
|
fn merge_npm_rc(project_rc: NpmRc, home_rc: NpmRc) -> NpmRc {
|
||||||
if let Some(package_json_path) = maybe_package_json_path {
|
fn merge_maps<TValue>(
|
||||||
if let Some(package_json_dir) = package_json_path.parent() {
|
mut project: HashMap<String, TValue>,
|
||||||
if let Some((source, path)) = try_to_read_npmrc(sys, package_json_dir)? {
|
home: HashMap<String, TValue>,
|
||||||
return try_to_parse_npmrc(sys, &source, &path)
|
) -> HashMap<String, TValue> {
|
||||||
.map(|r| (r, Some(path)));
|
for (key, value) in home {
|
||||||
|
project.entry(key).or_insert(value);
|
||||||
}
|
}
|
||||||
|
project
|
||||||
|
}
|
||||||
|
|
||||||
|
NpmRc {
|
||||||
|
registry: project_rc.registry.or(home_rc.registry),
|
||||||
|
scope_registries: merge_maps(
|
||||||
|
project_rc.scope_registries,
|
||||||
|
home_rc.scope_registries,
|
||||||
|
),
|
||||||
|
registry_configs: merge_maps(
|
||||||
|
project_rc.registry_configs,
|
||||||
|
home_rc.registry_configs,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Try `.npmrc` next to `deno.json(c)`
|
let mut home_npmrc = None;
|
||||||
if let Some(deno_json_path) = maybe_deno_json_path {
|
let mut project_npmrc = None;
|
||||||
if let Some(deno_json_dir) = deno_json_path.parent() {
|
|
||||||
if let Some((source, path)) = try_to_read_npmrc(sys, deno_json_dir)? {
|
|
||||||
return try_to_parse_npmrc(sys, &source, &path)
|
|
||||||
.map(|r| (r, Some(path)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(bartlomieju): update to read both files - one in the project root and one and
|
// 1. Try `.npmrc` in the user's home directory
|
||||||
// home dir and then merge them.
|
|
||||||
// 3. Try `.npmrc` in the user's home directory
|
|
||||||
if let Some(home_dir) = sys.env_home_dir() {
|
if let Some(home_dir) = sys.env_home_dir() {
|
||||||
match try_to_read_npmrc(sys, &home_dir) {
|
match try_to_read_npmrc(sys, &home_dir) {
|
||||||
Ok(Some((source, path))) => {
|
Ok(Some((source, path))) => {
|
||||||
return try_to_parse_npmrc(sys, &source, &path)
|
let npmrc = try_to_parse_npmrc(sys, &source, &path)?;
|
||||||
.map(|r| (r, Some(path)));
|
home_npmrc = Some((path, npmrc));
|
||||||
}
|
}
|
||||||
Ok(None) => {}
|
Ok(None) => {}
|
||||||
Err(err) if err.source.kind() == std::io::ErrorKind::PermissionDenied => {
|
Err(err) if err.source.kind() == std::io::ErrorKind::PermissionDenied => {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"Skipping .npmrc in home directory due to permission denied error. {:#}",
|
"Skipping .npmrc in home directory due to permission denied error. {:#}",
|
||||||
err
|
err
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(err.into());
|
return Err(err.into());
|
||||||
|
@ -166,8 +165,59 @@ fn discover_npmrc<TSys: EnvVar + EnvHomeDir + FsRead>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::debug!("No .npmrc file found");
|
// 2. Try `.npmrc` next to `package.json`
|
||||||
Ok((create_default_npmrc(sys), None))
|
if let Some(package_json_path) = maybe_package_json_path {
|
||||||
|
if let Some(package_json_dir) = package_json_path.parent() {
|
||||||
|
if let Some((source, path)) = try_to_read_npmrc(sys, package_json_dir)? {
|
||||||
|
let npmrc = try_to_parse_npmrc(sys, &source, &path)?;
|
||||||
|
project_npmrc = Some((path, npmrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Try `.npmrc` next to `deno.json(c)` when not found `package.json`
|
||||||
|
if project_npmrc.is_none() {
|
||||||
|
if let Some(deno_json_path) = maybe_deno_json_path {
|
||||||
|
if let Some(deno_json_dir) = deno_json_path.parent() {
|
||||||
|
if let Some((source, path)) = try_to_read_npmrc(sys, deno_json_dir)? {
|
||||||
|
let npmrc = try_to_parse_npmrc(sys, &source, &path)?;
|
||||||
|
project_npmrc = Some((path, npmrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let resolve_npmrc = |path: PathBuf, npm_rc: NpmRc| {
|
||||||
|
Ok((
|
||||||
|
npm_rc
|
||||||
|
.as_resolved(&npm_registry_url(sys))
|
||||||
|
.map_err(|source| NpmRcOptionsResolveError {
|
||||||
|
path: path.to_path_buf(),
|
||||||
|
source,
|
||||||
|
})?,
|
||||||
|
Some(path),
|
||||||
|
))
|
||||||
|
};
|
||||||
|
|
||||||
|
match (home_npmrc, project_npmrc) {
|
||||||
|
(None, None) => {
|
||||||
|
log::debug!("No .npmrc file found");
|
||||||
|
Ok((create_default_npmrc(sys), None))
|
||||||
|
}
|
||||||
|
(None, Some((npmrc_path, project_rc))) => {
|
||||||
|
log::debug!("Only project .npmrc file found");
|
||||||
|
resolve_npmrc(npmrc_path, project_rc)
|
||||||
|
}
|
||||||
|
(Some((npmrc_path, home_rc)), None) => {
|
||||||
|
log::debug!("Only home .npmrc file found");
|
||||||
|
resolve_npmrc(npmrc_path, home_rc)
|
||||||
|
}
|
||||||
|
(Some((_, home_rc)), Some((npmrc_path, project_rc))) => {
|
||||||
|
log::debug!("Both home and project .npmrc files found");
|
||||||
|
let merged_npmrc = merge_npm_rc(project_rc, home_rc);
|
||||||
|
resolve_npmrc(npmrc_path, merged_npmrc)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_default_npmrc(sys: &impl EnvVar) -> ResolvedNpmRc {
|
pub fn create_default_npmrc(sys: &impl EnvVar) -> ResolvedNpmRc {
|
||||||
|
|
4
tests/specs/npm/npmrc_homedir_package_both/.npmrc
Normal file
4
tests/specs/npm/npmrc_homedir_package_both/.npmrc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
@denotest:registry=http://localhost:4261/
|
||||||
|
//localhost:4261/:_authToken=private-reg-token
|
||||||
|
@denotest2:registry=http://localhost:4262/
|
||||||
|
//localhost:4262/:_authToken=private-reg-token2
|
10
tests/specs/npm/npmrc_homedir_package_both/__test__.jsonc
Normal file
10
tests/specs/npm/npmrc_homedir_package_both/__test__.jsonc
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"tempDir": true,
|
||||||
|
"envs": {
|
||||||
|
"HOME": "$PWD/../",
|
||||||
|
"USERPROFILE": "$PWD\\..\\"
|
||||||
|
},
|
||||||
|
"cwd": "subdir",
|
||||||
|
"args": "install",
|
||||||
|
"output": "install.out"
|
||||||
|
}
|
8
tests/specs/npm/npmrc_homedir_package_both/install.out
Normal file
8
tests/specs/npm/npmrc_homedir_package_both/install.out
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[UNORDERED_START]
|
||||||
|
Download http://localhost:4262/@denotest2%2fbasic
|
||||||
|
Download http://localhost:4261/@denotest%2fbasic
|
||||||
|
Download http://localhost:4262/@denotest2/basic/1.0.0.tgz
|
||||||
|
Download http://localhost:4261/@denotest/basic/1.0.0.tgz
|
||||||
|
Initialize @denotest2/basic@1.0.0
|
||||||
|
Initialize @denotest/basic@1.0.0
|
||||||
|
[UNORDERED_END]
|
2
tests/specs/npm/npmrc_homedir_package_both/subdir/.npmrc
Normal file
2
tests/specs/npm/npmrc_homedir_package_both/subdir/.npmrc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
@denotest:registry=http://localhost:4261/
|
||||||
|
@denotest2:registry=http://localhost:4262/
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { getValue, setValue } from "@denotest/basic";
|
||||||
|
import * as test from "@denotest2/basic";
|
||||||
|
|
||||||
|
console.log(getValue());
|
||||||
|
setValue(42);
|
||||||
|
console.log(getValue());
|
||||||
|
|
||||||
|
console.log(test.getValue());
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "npmrc_homedir_package_both",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"@denotest/basic": "1.0.0",
|
||||||
|
"@denotest2/basic": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue