Skip to content
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

feat: improve lockfile v4 to store normalized version constraints and be more terse #25247

Merged
merged 6 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 13 additions & 10 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ deno_ast = { version = "=0.41.2", features = ["transpiling"] }
deno_core = { version = "0.306.0" }

deno_bench_util = { version = "0.160.0", path = "./bench_util" }
deno_lockfile = "=0.22.0"
deno_lockfile = "=0.23.0"
deno_media_type = { version = "0.1.4", features = ["module_specifier"] }
deno_permissions = { version = "0.26.0", path = "./runtime/permissions" }
deno_runtime = { version = "0.175.0", path = "./runtime" }
deno_semver = "=0.5.12"
deno_terminal = "0.2.0"
napi_sym = { version = "0.96.0", path = "./cli/napi/sym" }
test_util = { package = "test_server", path = "./tests/util/server" }
Expand Down
8 changes: 4 additions & 4 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ deno_emit = "=0.44.0"
deno_graph = { version = "=0.81.3" }
deno_lint = { version = "=0.63.1", features = ["docs"] }
deno_lockfile.workspace = true
deno_npm = "=0.24.0"
deno_npm = "=0.25.0"
deno_package_json.workspace = true
deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_semver = "=0.5.10"
deno_semver.workspace = true
deno_task_shell = "=0.17.0"
deno_terminal.workspace = true
eszip = "=0.76.0"
eszip = "=0.77.0"
libsui = "0.3.0"
napi_sym.workspace = true
node_resolver.workspace = true
Expand Down Expand Up @@ -115,7 +115,7 @@ http.workspace = true
http-body.workspace = true
http-body-util.workspace = true
hyper-util.workspace = true
import_map = { version = "=0.20.0", features = ["ext"] }
import_map = { version = "=0.20.1", features = ["ext"] }
indexmap.workspace = true
jsonc-parser.workspace = true
jupyter_runtime = { package = "runtimelib", version = "=0.14.0" }
Expand Down
16 changes: 10 additions & 6 deletions cli/args/lockfile.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

use std::collections::BTreeSet;
use std::collections::HashSet;
use std::path::PathBuf;

use deno_config::deno_json::ConfigFile;
Expand All @@ -12,6 +12,7 @@ use deno_core::parking_lot::MutexGuard;
use deno_lockfile::WorkspaceMemberConfig;
use deno_package_json::PackageJsonDepValue;
use deno_runtime::deno_node::PackageJson;
use deno_semver::jsr::JsrDepPackageReq;

use crate::cache;
use crate::util::fs::atomic_write_file_with_retries;
Expand Down Expand Up @@ -98,7 +99,9 @@ impl CliLockfile {
flags: &Flags,
workspace: &Workspace,
) -> Result<Option<CliLockfile>, AnyError> {
fn pkg_json_deps(maybe_pkg_json: Option<&PackageJson>) -> BTreeSet<String> {
fn pkg_json_deps(
maybe_pkg_json: Option<&PackageJson>,
) -> HashSet<JsrDepPackageReq> {
let Some(pkg_json) = maybe_pkg_json else {
return Default::default();
};
Expand All @@ -107,21 +110,21 @@ impl CliLockfile {
.values()
.filter_map(|dep| dep.as_ref().ok())
.filter_map(|dep| match dep {
PackageJsonDepValue::Req(req) => Some(req),
PackageJsonDepValue::Req(req) => {
Some(JsrDepPackageReq::npm(req.clone()))
}
PackageJsonDepValue::Workspace(_) => None,
})
.map(|r| format!("npm:{}", r))
.collect()
}

fn deno_json_deps(
maybe_deno_json: Option<&ConfigFile>,
) -> BTreeSet<String> {
) -> HashSet<JsrDepPackageReq> {
maybe_deno_json
.map(|c| {
crate::args::deno_json::deno_json_deps(c)
.into_iter()
.map(|req| req.to_string())
.collect()
})
.unwrap_or_default()
Expand Down Expand Up @@ -207,6 +210,7 @@ impl CliLockfile {

Ok(Some(lockfile))
}

pub fn read_from_path(
file_path: PathBuf,
frozen: bool,
Expand Down
95 changes: 74 additions & 21 deletions cli/graph_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@ use deno_graph::SpecifierError;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_semver::jsr::JsrDepPackageReq;
use deno_semver::package::PackageNv;
use deno_semver::package::PackageReq;
use deno_semver::Version;
use import_map::ImportMapError;
use std::collections::HashSet;
use std::error::Error;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;

Expand Down Expand Up @@ -110,7 +113,7 @@ pub fn graph_valid(
ModuleGraphError::ModuleError(error) => {
enhanced_lockfile_error_message(error)
.or_else(|| enhanced_sloppy_imports_error_message(fs, error))
.unwrap_or_else(|| format!("{}", error))
.unwrap_or_else(|| format_deno_graph_error(error))
}
};

Expand Down Expand Up @@ -164,7 +167,10 @@ pub fn graph_valid(
} else {
// finally surface the npm resolution result
if let Err(err) = &graph.npm_dep_graph_result {
return Err(custom_error(get_error_class_name(err), format!("{}", err)));
return Err(custom_error(
get_error_class_name(err),
format_deno_graph_error(err.as_ref().deref()),
));
}
Ok(())
}
Expand Down Expand Up @@ -463,7 +469,7 @@ impl ModuleGraphBuilder {
.content
.packages
.jsr
.get(&package_nv.to_string())
.get(package_nv)
.map(|s| LoaderChecksum::new(s.integrity.clone()))
}

Expand All @@ -477,7 +483,7 @@ impl ModuleGraphBuilder {
self
.0
.lock()
.insert_package(package_nv.to_string(), checksum.into_string());
.insert_package(package_nv.clone(), checksum.into_string());
}
}

Expand Down Expand Up @@ -556,16 +562,21 @@ impl ModuleGraphBuilder {
}
}
}
for (key, value) in &lockfile.content.packages.specifiers {
if let Some(key) = key
.strip_prefix("jsr:")
.and_then(|key| PackageReq::from_str(key).ok())
{
if let Some(value) = value
.strip_prefix("jsr:")
.and_then(|value| PackageNv::from_str(value).ok())
{
graph.packages.add_nv(key, value);
for (req_dep, value) in &lockfile.content.packages.specifiers {
match req_dep.kind {
deno_semver::package::PackageKind::Jsr => {
if let Ok(version) = Version::parse_standard(value) {
graph.packages.add_nv(
req_dep.req.clone(),
PackageNv {
name: req_dep.req.name.clone(),
version,
},
);
}
}
deno_semver::package::PackageKind::Npm => {
// ignore
}
}
}
Expand Down Expand Up @@ -603,16 +614,15 @@ impl ModuleGraphBuilder {
if has_jsr_package_mappings_changed {
for (from, to) in graph.packages.mappings() {
lockfile.insert_package_specifier(
format!("jsr:{}", from),
format!("jsr:{}", to),
JsrDepPackageReq::jsr(from.clone()),
to.version.to_string(),
);
}
}
// jsr packages
if has_jsr_package_deps_changed {
for (name, deps) in graph.packages.packages_with_deps() {
lockfile
.add_package_deps(&name.to_string(), deps.map(|s| s.to_string()));
for (nv, deps) in graph.packages.packages_with_deps() {
lockfile.add_package_deps(nv, deps.cloned());
}
}
}
Expand Down Expand Up @@ -726,7 +736,7 @@ pub fn error_for_any_npm_specifier(

/// Adds more explanatory information to a resolution error.
pub fn enhanced_resolution_error_message(error: &ResolutionError) -> String {
let mut message = format!("{error}");
let mut message = format_deno_graph_error(error);

if let Some(specifier) = get_resolution_error_bare_node_specifier(error) {
if !*DENO_DISABLE_PEDANTIC_NODE_WARNINGS {
Expand Down Expand Up @@ -1022,6 +1032,49 @@ impl deno_graph::source::JsrUrlProvider for CliJsrUrlProvider {
}
}

// todo(dsherret): We should change ModuleError to use thiserror so that
// we don't need to do this.
fn format_deno_graph_error(err: &dyn Error) -> String {
use std::fmt::Write;

let mut message = format!("{}", err);
let mut maybe_source = err.source();

if maybe_source.is_some() {
let mut past_message = message.clone();
let mut count = 0;
let mut display_count = 0;
while let Some(source) = maybe_source {
let current_message = format!("{}", source);
maybe_source = source.source();

// sometimes an error might be repeated due to
// being boxed multiple times in another AnyError
if current_message != past_message {
write!(message, "\n {}: ", display_count,).unwrap();
for (i, line) in current_message.lines().enumerate() {
if i > 0 {
write!(message, "\n {}", line).unwrap();
} else {
write!(message, "{}", line).unwrap();
}
}
display_count += 1;
}

if count > 8 {
write!(message, "\n {}: ...", count).unwrap();
break;
}

past_message = current_message;
count += 1;
}
}

message
}

#[cfg(test)]
mod test {
use std::sync::Arc;
Expand Down
8 changes: 3 additions & 5 deletions cli/lsp/documents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1410,11 +1410,9 @@ impl Documents {
if let Some(lockfile) = config_data.lockfile.as_ref() {
let reqs = npm_reqs_by_scope.entry(Some(scope.clone())).or_default();
let lockfile = lockfile.lock();
for key in lockfile.content.packages.specifiers.keys() {
if let Some(key) = key.strip_prefix("npm:") {
if let Ok(req) = PackageReq::from_str(key) {
reqs.insert(req);
}
for dep_req in lockfile.content.packages.specifiers.keys() {
if dep_req.kind == deno_semver::package::PackageKind::Npm {
reqs.insert(dep_req.req.clone());
}
}
}
Expand Down
25 changes: 14 additions & 11 deletions cli/lsp/jsr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,23 @@ impl JsrCacheResolver {
}
}
if let Some(lockfile) = config_data.and_then(|d| d.lockfile.as_ref()) {
for (req_url, nv_url) in &lockfile.lock().content.packages.specifiers {
let Some(req) = req_url.strip_prefix("jsr:") else {
continue;
};
let Some(nv) = nv_url.strip_prefix("jsr:") else {
continue;
};
let Ok(req) = PackageReq::from_str(req) else {
continue;
for (dep_req, version) in &lockfile.lock().content.packages.specifiers {
let req = match dep_req.kind {
deno_semver::package::PackageKind::Jsr => &dep_req.req,
deno_semver::package::PackageKind::Npm => {
continue;
}
};
let Ok(nv) = PackageNv::from_str(nv) else {
let Ok(version) = Version::parse_standard(version) else {
continue;
};
nv_by_req.insert(req, Some(nv));
nv_by_req.insert(
req.clone(),
Some(PackageNv {
name: req.name.clone(),
version,
}),
);
}
}
Self {
Expand Down
Loading