Skip to content

feat(unstable/npm): support peer dependencies #16561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 47 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
b2e36a3
Start of work
dsherret Nov 1, 2022
fa2d28d
Fix.
dsherret Nov 1, 2022
225187b
Merge branch 'main' into npm_peer_deps
dsherret Nov 2, 2022
c725a9c
More work.
dsherret Nov 2, 2022
b7f1424
Committing current state.
dsherret Nov 2, 2022
a6973aa
Merge branch 'main' into npm_peer_deps
dsherret Nov 2, 2022
19dd3d7
Serialization and deserialization of npm package ids
dsherret Nov 2, 2022
2d9b75b
Compiling...
dsherret Nov 2, 2022
53f11d7
Passing existing tests... now to write new ones
dsherret Nov 3, 2022
b4c0d71
Split up resolution.rs into multiple files
dsherret Nov 3, 2022
96a8975
Ability to inject a custom npm registry api for testing purposes
dsherret Nov 3, 2022
8e8c438
Start of adding unit tests for graph resolver code.
dsherret Nov 3, 2022
c2899a6
More progress, but test is still failing
dsherret Nov 3, 2022
5338523
Working basic resolution... now to add more complex tests.
dsherret Nov 4, 2022
13d4f01
Tests for resolving ancestor sibling not at the top of the tree.
dsherret Nov 4, 2022
d1867f4
More tests.
dsherret Nov 4, 2022
6f02b54
Fix another failing test.
dsherret Nov 5, 2022
db8465f
Fix tests.
dsherret Nov 5, 2022
b2dac59
Handle dependency being specified as dep and peer dep
dsherret Nov 5, 2022
01c05f2
Starting to add support for handling circular stuff.
dsherret Nov 5, 2022
de0e1bc
Working resolution::graph tests
dsherret Nov 5, 2022
f71961c
Fix clippy.
dsherret Nov 5, 2022
647e391
Add test for circular dependencies
dsherret Nov 5, 2022
86227ca
Add comment.
dsherret Nov 6, 2022
e316c67
Basic idea for linking this up to the cache folder.
dsherret Nov 6, 2022
b481234
Working on hooking up the cache with the snapshot.
dsherret Nov 6, 2022
406c923
Hooked up resolution to execution. Untested.
dsherret Nov 7, 2022
b5342a7
Clippy.
dsherret Nov 7, 2022
7dee311
Add test and fix issues for "copy_index"
dsherret Nov 7, 2022
b4979c5
Update monch
dsherret Nov 7, 2022
846a83e
Fix lack of determinism going up the tree
dsherret Nov 7, 2022
422b512
Use hard links.
dsherret Nov 7, 2022
d37eab6
Failing refactor.
dsherret Nov 7, 2022
9a40e57
Revert "Failing refactor."
dsherret Nov 7, 2022
15a06af
Not sure if faster... maybe slower?
dsherret Nov 7, 2022
0e929fe
Add `GraphSpecifierPath`
dsherret Nov 7, 2022
d719c5c
Adding integration test and fixing bugs.
dsherret Nov 7, 2022
9f429dc
--reload fixes
dsherret Nov 7, 2022
044dfef
Merge branch 'main' into npm_peer_deps
dsherret Nov 7, 2022
500dab6
Fix broken test.
dsherret Nov 8, 2022
ebf24a9
Clippy
dsherret Nov 8, 2022
7cbc849
Add more information for panic.
dsherret Nov 8, 2022
999fb28
Fix infinite loop
dsherret Nov 8, 2022
e2202cd
Add deno info support.
dsherret Nov 8, 2022
db16f8f
Merge branch 'main' into npm_peer_deps
dsherret Nov 8, 2022
0468e83
Clippy.
dsherret Nov 8, 2022
c483944
Fix.
dsherret Nov 8, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ deno_emit = "0.10.0"
deno_graph = "0.37.1"
deno_lint = { version = "0.34.0", features = ["docs"] }
deno_runtime = { version = "0.83.0", path = "../runtime" }
deno_task_shell = "0.7.0"
deno_task_shell = "0.7.2"
napi_sym = { path = "./napi_sym", version = "0.5.0" }

atty = "=0.2.14"
Expand Down Expand Up @@ -86,7 +86,7 @@ libc = "=0.2.126"
log = { version = "=0.4.17", features = ["serde"] }
lsp-types = "=0.93.2" # used by tower-lsp and "proposed" feature is unstable in patch releases
mitata = "=0.0.7"
monch = "=0.2.1"
monch = "=0.4.0"
notify = "=5.0.0"
once_cell = "=1.14.0"
os_pipe = "=1.0.1"
Expand Down
79 changes: 79 additions & 0 deletions cli/fs_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::io::ErrorKind;
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
use std::time::Duration;
use walkdir::WalkDir;

pub fn atomic_write_file<T: AsRef<[u8]>>(
Expand Down Expand Up @@ -357,6 +358,84 @@ pub fn copy_dir_recursive(from: &Path, to: &Path) -> Result<(), AnyError> {
Ok(())
}

/// Hardlinks the files in one directory to another directory.
///
/// Note: Does not handle symlinks.
pub fn hard_link_dir_recursive(from: &Path, to: &Path) -> Result<(), AnyError> {
std::fs::create_dir_all(&to)
.with_context(|| format!("Creating {}", to.display()))?;
let read_dir = std::fs::read_dir(&from)
.with_context(|| format!("Reading {}", from.display()))?;

for entry in read_dir {
let entry = entry?;
let file_type = entry.file_type()?;
let new_from = from.join(entry.file_name());
let new_to = to.join(entry.file_name());

if file_type.is_dir() {
hard_link_dir_recursive(&new_from, &new_to).with_context(|| {
format!("Dir {} to {}", new_from.display(), new_to.display())
})?;
} else if file_type.is_file() {
// note: chance for race conditions here between attempting to create,
// then removing, then attempting to create. There doesn't seem to be
// a way to hard link with overwriting in Rust, but maybe there is some
// way with platform specific code. The workaround here is to handle
// scenarios where something else might create or remove files.
if let Err(err) = std::fs::hard_link(&new_from, &new_to) {
if err.kind() == ErrorKind::AlreadyExists {
if let Err(err) = std::fs::remove_file(&new_to) {
if err.kind() == ErrorKind::NotFound {
// Assume another process/thread created this hard link to the file we are wanting
// to remove then sleep a little bit to let the other process/thread move ahead
// faster to reduce contention.
std::thread::sleep(Duration::from_millis(10));
} else {
return Err(err).with_context(|| {
format!(
"Removing file to hard link {} to {}",
new_from.display(),
new_to.display()
)
});
}
}

// Always attempt to recreate the hardlink. In contention scenarios, the other process
// might have been killed or exited after removing the file, but before creating the hardlink
if let Err(err) = std::fs::hard_link(&new_from, &new_to) {
// Assume another process/thread created this hard link to the file we are wanting
// to now create then sleep a little bit to let the other process/thread move ahead
// faster to reduce contention.
if err.kind() == ErrorKind::AlreadyExists {
std::thread::sleep(Duration::from_millis(10));
} else {
return Err(err).with_context(|| {
format!(
"Hard linking {} to {}",
new_from.display(),
new_to.display()
)
});
}
}
} else {
return Err(err).with_context(|| {
format!(
"Hard linking {} to {}",
new_from.display(),
new_to.display()
)
});
}
}
}
}

Ok(())
}

pub fn symlink_dir(oldpath: &Path, newpath: &Path) -> Result<(), AnyError> {
let err_mapper = |err: Error| {
Error::new(
Expand Down
42 changes: 26 additions & 16 deletions cli/lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::rc::Rc;
use std::sync::Arc;

use crate::args::ConfigFile;
use crate::npm::NpmPackageId;
use crate::npm::NpmPackageReq;
use crate::npm::NpmResolutionPackage;
use crate::tools::fmt::format_json;
Expand All @@ -40,7 +41,7 @@ pub struct NpmPackageInfo {

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct NpmContent {
/// Mapping between requests for npm packages and resolved specifiers, eg.
/// Mapping between requests for npm packages and resolved packages, eg.
/// {
/// "chalk": "[email protected]"
/// "react@17": "[email protected]"
Expand Down Expand Up @@ -269,7 +270,7 @@ impl Lockfile {
&mut self,
package: &NpmResolutionPackage,
) -> Result<(), LockfileError> {
let specifier = package.id.serialize_for_lock_file();
let specifier = package.id.as_serialized();
if let Some(package_info) = self.content.npm.packages.get(&specifier) {
let integrity = package
.dist
Expand All @@ -286,7 +287,7 @@ This could be caused by:
* the source itself may be corrupt

Use \"--lock-write\" flag to regenerate the lockfile at \"{}\".",
package.id, self.filename.display()
package.id.display(), self.filename.display()
)));
}
} else {
Expand All @@ -300,7 +301,7 @@ Use \"--lock-write\" flag to regenerate the lockfile at \"{}\".",
let dependencies = package
.dependencies
.iter()
.map(|(name, id)| (name.to_string(), id.serialize_for_lock_file()))
.map(|(name, id)| (name.to_string(), id.as_serialized()))
.collect::<BTreeMap<String, String>>();

let integrity = package
Expand All @@ -309,7 +310,7 @@ Use \"--lock-write\" flag to regenerate the lockfile at \"{}\".",
.as_ref()
.unwrap_or(&package.dist.shasum);
self.content.npm.packages.insert(
package.id.serialize_for_lock_file(),
package.id.as_serialized(),
NpmPackageInfo {
integrity: integrity.to_string(),
dependencies,
Expand All @@ -321,12 +322,13 @@ Use \"--lock-write\" flag to regenerate the lockfile at \"{}\".",
pub fn insert_npm_specifier(
&mut self,
package_req: &NpmPackageReq,
version: String,
package_id: &NpmPackageId,
) {
self.content.npm.specifiers.insert(
package_req.to_string(),
format!("{}@{}", package_req.name, version),
);
self
.content
.npm
.specifiers
.insert(package_req.to_string(), package_id.as_serialized());
self.has_content_changed = true;
}
}
Expand Down Expand Up @@ -559,10 +561,12 @@ mod tests {
id: NpmPackageId {
name: "nanoid".to_string(),
version: NpmVersion::parse("3.3.4").unwrap(),
peer_dependencies: Vec::new(),
},
copy_index: 0,
dist: NpmPackageVersionDistInfo {
tarball: "foo".to_string(),
shasum: "foo".to_string(),
tarball: "foo".to_string(),
shasum: "foo".to_string(),
integrity: Some("sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==".to_string())
},
dependencies: HashMap::new(),
Expand All @@ -574,10 +578,12 @@ mod tests {
id: NpmPackageId {
name: "picocolors".to_string(),
version: NpmVersion::parse("1.0.0").unwrap(),
peer_dependencies: Vec::new(),
},
copy_index: 0,
dist: NpmPackageVersionDistInfo {
tarball: "foo".to_string(),
shasum: "foo".to_string(),
tarball: "foo".to_string(),
shasum: "foo".to_string(),
integrity: Some("sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==".to_string())
},
dependencies: HashMap::new(),
Expand All @@ -590,10 +596,12 @@ mod tests {
id: NpmPackageId {
name: "source-map-js".to_string(),
version: NpmVersion::parse("1.0.2").unwrap(),
peer_dependencies: Vec::new(),
},
copy_index: 0,
dist: NpmPackageVersionDistInfo {
tarball: "foo".to_string(),
shasum: "foo".to_string(),
tarball: "foo".to_string(),
shasum: "foo".to_string(),
integrity: Some("sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==".to_string())
},
dependencies: HashMap::new(),
Expand All @@ -606,7 +614,9 @@ mod tests {
id: NpmPackageId {
name: "source-map-js".to_string(),
version: NpmVersion::parse("1.0.2").unwrap(),
peer_dependencies: Vec::new(),
},
copy_index: 0,
dist: NpmPackageVersionDistInfo {
tarball: "foo".to_string(),
shasum: "foo".to_string(),
Expand Down
6 changes: 3 additions & 3 deletions cli/lsp/language_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ use crate::fs_util;
use crate::graph_util::graph_valid;
use crate::npm::NpmCache;
use crate::npm::NpmPackageResolver;
use crate::npm::NpmRegistryApi;
use crate::npm::RealNpmRegistryApi;
use crate::proc_state::import_map_from_text;
use crate::proc_state::ProcState;
use crate::progress_bar::ProgressBar;
Expand Down Expand Up @@ -258,7 +258,7 @@ impl Inner {
ts_server.clone(),
);
let assets = Assets::new(ts_server.clone());
let registry_url = NpmRegistryApi::default_url();
let registry_url = RealNpmRegistryApi::default_url();
// Use an "only" cache setting in order to make the
// user do an explicit "cache" command and prevent
// the cache from being filled with lots of packages while
Expand All @@ -270,7 +270,7 @@ impl Inner {
cache_setting.clone(),
progress_bar.clone(),
);
let api = NpmRegistryApi::new(
let api = RealNpmRegistryApi::new(
registry_url,
npm_cache.clone(),
cache_setting,
Expand Down
Loading