Skip to content

Commit 97d9833

Browse files
nathanwhitzebreus
authored andcommittedJul 8, 2024
feat(cli): Add --frozen flag to error out if lockfile is out of date (denoland#24355)
Closes denoland#18296. Adds a `--frozen` (alias `--frozen-lockfile`) flag that errors out if the lockfile is out of date. This is useful for running in CI (where an out of date lockfile is usually a mistake) or to prevent accidental changes in dependencies. ![Screenshot 2024-06-26 at 7 11 13 PM](https://github.com/denoland/deno/assets/17734409/538404b8-b422-4f05-89e8-4c9b1c248576)
1 parent a8654ab commit 97d9833

29 files changed

+477
-30
lines changed
 

‎cli/args/flags.rs

+59-6
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ pub struct Flags {
498498
pub argv: Vec<String>,
499499
pub subcommand: DenoSubcommand,
500500

501+
pub frozen_lockfile: bool,
501502
pub ca_stores: Option<Vec<String>>,
502503
pub ca_data: Option<CaData>,
503504
pub cache_blocklist: Vec<String>,
@@ -1487,12 +1488,15 @@ Future runs of this module will trigger no downloads or compilation unless
14871488
--reload is specified.",
14881489
)
14891490
.defer(|cmd| {
1490-
compile_args(cmd).arg(check_arg(false)).arg(
1491-
Arg::new("file")
1492-
.num_args(1..)
1493-
.required(true)
1494-
.value_hint(ValueHint::FilePath),
1495-
)
1491+
compile_args(cmd)
1492+
.arg(check_arg(false))
1493+
.arg(
1494+
Arg::new("file")
1495+
.num_args(1..)
1496+
.required(true)
1497+
.value_hint(ValueHint::FilePath),
1498+
)
1499+
.arg(frozen_lockfile_arg())
14961500
})
14971501
}
14981502

@@ -3271,6 +3275,7 @@ fn runtime_args(
32713275
app
32723276
};
32733277
app
3278+
.arg(frozen_lockfile_arg())
32743279
.arg(cached_only_arg())
32753280
.arg(location_arg())
32763281
.arg(v8_flags_arg())
@@ -3384,6 +3389,17 @@ fn cached_only_arg() -> Arg {
33843389
.help("Require that remote dependencies are already cached")
33853390
}
33863391

3392+
fn frozen_lockfile_arg() -> Arg {
3393+
Arg::new("frozen")
3394+
.long("frozen")
3395+
.alias("frozen-lockfile")
3396+
.value_parser(value_parser!(bool))
3397+
.num_args(0..=1)
3398+
.require_equals(true)
3399+
.default_missing_value("true")
3400+
.help("Error out if lockfile is out of date")
3401+
}
3402+
33873403
/// Used for subcommands that operate on executable scripts only.
33883404
/// `deno fmt` has its own `--ext` arg because its possible values differ.
33893405
/// If --ext is not provided and the script doesn't have a file extension,
@@ -3774,6 +3790,7 @@ fn bundle_parse(flags: &mut Flags, matches: &mut ArgMatches) {
37743790

37753791
fn cache_parse(flags: &mut Flags, matches: &mut ArgMatches) {
37763792
compile_args_parse(flags, matches);
3793+
frozen_lockfile_arg_parse(flags, matches);
37773794
let files = matches.remove_many::<String>("file").unwrap().collect();
37783795
flags.subcommand = DenoSubcommand::Cache(CacheFlags { files });
37793796
}
@@ -4576,6 +4593,7 @@ fn runtime_args_parse(
45764593
) {
45774594
compile_args_parse(flags, matches);
45784595
cached_only_arg_parse(flags, matches);
4596+
frozen_lockfile_arg_parse(flags, matches);
45794597
if include_perms {
45804598
permission_args_parse(flags, matches);
45814599
}
@@ -4667,6 +4685,12 @@ fn cached_only_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
46674685
}
46684686
}
46694687

4688+
fn frozen_lockfile_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
4689+
if let Some(&v) = matches.get_one::<bool>("frozen") {
4690+
flags.frozen_lockfile = v;
4691+
}
4692+
}
4693+
46704694
fn ext_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
46714695
flags.ext = matches.remove_one::<String>("ext");
46724696
}
@@ -9845,4 +9869,33 @@ mod tests {
98459869
}
98469870
);
98479871
}
9872+
9873+
#[test]
9874+
fn run_with_frozen_lockfile() {
9875+
let cases = [
9876+
(Some("--frozen"), true),
9877+
(Some("--frozen=true"), true),
9878+
(Some("--frozen=false"), false),
9879+
(None, false),
9880+
];
9881+
for (flag, frozen) in cases {
9882+
let mut args = svec!["deno", "run"];
9883+
if let Some(f) = flag {
9884+
args.push(f.into());
9885+
}
9886+
args.push("script.ts".into());
9887+
let r = flags_from_vec(args);
9888+
assert_eq!(
9889+
r.unwrap(),
9890+
Flags {
9891+
subcommand: DenoSubcommand::Run(RunFlags::new_default(
9892+
"script.ts".to_string(),
9893+
)),
9894+
frozen_lockfile: frozen,
9895+
code_cache_enabled: true,
9896+
..Flags::default()
9897+
}
9898+
);
9899+
}
9900+
}
98489901
}

‎cli/args/lockfile.rs

+45-10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use deno_lockfile::Lockfile;
2323
pub struct CliLockfile {
2424
lockfile: Mutex<Lockfile>,
2525
pub filename: PathBuf,
26+
pub frozen: bool,
2627
}
2728

2829
pub struct Guard<'a, T> {
@@ -44,11 +45,12 @@ impl<'a, T> std::ops::DerefMut for Guard<'a, T> {
4445
}
4546

4647
impl CliLockfile {
47-
pub fn new(lockfile: Lockfile) -> Self {
48+
pub fn new(lockfile: Lockfile, frozen: bool) -> Self {
4849
let filename = lockfile.filename.clone();
4950
Self {
5051
lockfile: Mutex::new(lockfile),
5152
filename,
53+
frozen,
5254
}
5355
}
5456

@@ -71,6 +73,7 @@ impl CliLockfile {
7173
}
7274

7375
pub fn write_if_changed(&self) -> Result<(), AnyError> {
76+
self.error_if_changed()?;
7477
let mut lockfile = self.lockfile.lock();
7578
let Some(bytes) = lockfile.resolve_write_bytes() else {
7679
return Ok(()); // nothing to do
@@ -127,23 +130,55 @@ impl CliLockfile {
127130
};
128131

129132
let lockfile = if flags.lock_write {
130-
CliLockfile::new(Lockfile::new_empty(filename, true))
133+
CliLockfile::new(
134+
Lockfile::new_empty(filename, true),
135+
flags.frozen_lockfile,
136+
)
131137
} else {
132-
Self::read_from_path(filename)?
138+
Self::read_from_path(filename, flags.frozen_lockfile)?
133139
};
134140
Ok(Some(lockfile))
135141
}
136-
pub fn read_from_path(filename: PathBuf) -> Result<CliLockfile, AnyError> {
142+
pub fn read_from_path(
143+
filename: PathBuf,
144+
frozen: bool,
145+
) -> Result<CliLockfile, AnyError> {
137146
match std::fs::read_to_string(&filename) {
138-
Ok(text) => Ok(CliLockfile::new(Lockfile::with_lockfile_content(
139-
filename, &text, false,
140-
)?)),
141-
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
142-
Ok(CliLockfile::new(Lockfile::new_empty(filename, false)))
143-
}
147+
Ok(text) => Ok(CliLockfile::new(
148+
Lockfile::with_lockfile_content(filename, &text, false)?,
149+
frozen,
150+
)),
151+
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(
152+
CliLockfile::new(Lockfile::new_empty(filename, false), frozen),
153+
),
144154
Err(err) => Err(err).with_context(|| {
145155
format!("Failed reading lockfile '{}'", filename.display())
146156
}),
147157
}
148158
}
159+
pub fn error_if_changed(&self) -> Result<(), AnyError> {
160+
if !self.frozen {
161+
return Ok(());
162+
}
163+
let lockfile = self.lockfile.lock();
164+
if lockfile.has_content_changed {
165+
let suggested = if *super::DENO_FUTURE {
166+
"`deno cache --frozen=false`, `deno install --frozen=false`,"
167+
} else {
168+
"`deno cache --frozen=false`"
169+
};
170+
171+
let contents =
172+
std::fs::read_to_string(&lockfile.filename).unwrap_or_default();
173+
let new_contents = lockfile.as_json_string();
174+
let diff = crate::util::diff::diff(&contents, &new_contents);
175+
// has an extra newline at the end
176+
let diff = diff.trim_end();
177+
Err(deno_core::anyhow::anyhow!(
178+
"The lockfile is out of date. Run {suggested} or rerun with `--frozen=false` to update it.\nchanges:\n{diff}"
179+
))
180+
} else {
181+
Ok(())
182+
}
183+
}
149184
}

‎cli/lsp/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1825,7 +1825,7 @@ fn resolve_node_modules_dir(
18251825
}
18261826

18271827
fn resolve_lockfile_from_path(lockfile_path: PathBuf) -> Option<CliLockfile> {
1828-
match CliLockfile::read_from_path(lockfile_path) {
1828+
match CliLockfile::read_from_path(lockfile_path, false) {
18291829
Ok(value) => {
18301830
if value.filename.exists() {
18311831
if let Ok(specifier) = ModuleSpecifier::from_file_path(&value.filename)

‎cli/module_loader.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,13 @@ use deno_semver::npm::NpmPackageReqReference;
7272
pub async fn load_top_level_deps(factory: &CliFactory) -> Result<(), AnyError> {
7373
let npm_resolver = factory.npm_resolver().await?;
7474
if let Some(npm_resolver) = npm_resolver.as_managed() {
75-
npm_resolver.ensure_top_level_package_json_install().await?;
76-
// TODO(nathanwhit): we call `cache_packages` if the lockfile is modified,
77-
// so by calling it here it's possible we end up calling it twice
78-
npm_resolver.cache_packages().await?;
75+
if !npm_resolver.ensure_top_level_package_json_install().await? {
76+
if let Some(lockfile) = factory.maybe_lockfile() {
77+
lockfile.error_if_changed()?;
78+
}
79+
80+
npm_resolver.cache_packages().await?;
81+
}
7982
}
8083
// cache as many entries in the import map as we can
8184
if let Some(import_map) = factory.maybe_import_map().await? {

‎cli/npm/managed/mod.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -361,12 +361,15 @@ impl ManagedCliNpmResolver {
361361
}
362362

363363
/// Adds package requirements to the resolver and ensures everything is setup.
364+
/// This includes setting up the `node_modules` directory, if applicable.
364365
pub async fn add_package_reqs(
365366
&self,
366367
packages: &[PackageReq],
367368
) -> Result<(), AnyError> {
368-
let result = self.add_package_reqs_raw(packages).await;
369-
result.dependencies_result
369+
self
370+
.add_package_reqs_raw(packages)
371+
.await
372+
.dependencies_result
370373
}
371374

372375
pub async fn add_package_reqs_raw(
@@ -381,6 +384,12 @@ impl ManagedCliNpmResolver {
381384
}
382385

383386
let mut result = self.resolution.add_package_reqs(packages).await;
387+
388+
if result.dependencies_result.is_ok() {
389+
if let Some(lockfile) = self.maybe_lockfile.as_ref() {
390+
result.dependencies_result = lockfile.error_if_changed();
391+
}
392+
}
384393
if result.dependencies_result.is_ok() {
385394
result.dependencies_result =
386395
self.cache_packages().await.map_err(AnyError::from);
@@ -442,14 +451,19 @@ impl ManagedCliNpmResolver {
442451
self.resolution.resolve_pkg_id_from_pkg_req(req)
443452
}
444453

454+
/// Ensures that the top level `package.json` dependencies are installed.
455+
/// This may set up the `node_modules` directory.
456+
///
457+
/// Returns `true` if any changes (such as caching packages) were made.
458+
/// If this returns `false`, `node_modules` has _not_ been set up.
445459
pub async fn ensure_top_level_package_json_install(
446460
&self,
447-
) -> Result<(), AnyError> {
461+
) -> Result<bool, AnyError> {
448462
let Some(reqs) = self.package_json_deps_provider.reqs() else {
449-
return Ok(());
463+
return Ok(false);
450464
};
451465
if !self.top_level_install_flag.raise() {
452-
return Ok(()); // already did this
466+
return Ok(false); // already did this
453467
}
454468
// check if something needs resolving before bothering to load all
455469
// the package information (which is slow)
@@ -460,11 +474,11 @@ impl ManagedCliNpmResolver {
460474
log::debug!(
461475
"All package.json deps resolvable. Skipping top level install."
462476
);
463-
return Ok(()); // everything is already resolvable
477+
return Ok(false); // everything is already resolvable
464478
}
465479

466480
let reqs = reqs.into_iter().cloned().collect::<Vec<_>>();
467-
self.add_package_reqs(&reqs).await
481+
self.add_package_reqs(&reqs).await.map(|_| true)
468482
}
469483

470484
pub async fn cache_package_info(

‎cli/resolver.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,10 @@ impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> {
824824
};
825825

826826
let top_level_result = if self.found_package_json_dep_flag.is_raised() {
827-
npm_resolver.ensure_top_level_package_json_install().await
827+
npm_resolver
828+
.ensure_top_level_package_json_install()
829+
.await
830+
.map(|_| ())
828831
} else {
829832
Ok(())
830833
};

‎cli/tools/installer.rs

+4
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@ async fn resolve_shim_data(
466466
executable_args.push("--cached-only".to_string());
467467
}
468468

469+
if flags.frozen_lockfile {
470+
executable_args.push("--frozen".to_string());
471+
}
472+
469473
if resolve_no_prompt(&flags.permissions) {
470474
executable_args.push("--no-prompt".to_string());
471475
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
{
2+
"tempDir": true,
3+
"tests": {
4+
"error_with_new_npm_dep": {
5+
"steps": [
6+
{
7+
"args": "cache add.ts",
8+
"output": "[WILDCARD]"
9+
},
10+
{
11+
// sub.ts imports from an npm package
12+
// that's not in the lockfile
13+
"args": "run --frozen sub.ts",
14+
"output": "frozen_new_dep_run.out",
15+
"exitCode": 1
16+
},
17+
{
18+
"args": "cache --frozen sub.ts",
19+
"output": "frozen_new_dep_cache.out",
20+
"exitCode": 1
21+
},
22+
{
23+
// update the lockfile
24+
"args": "cache sub.ts",
25+
"output": "update_lockfile.out"
26+
},
27+
{
28+
"args": "run --frozen sub.ts",
29+
"output": "3 - 2 = 1\n"
30+
}
31+
]
32+
},
33+
"error_with_new_jsr_dep": {
34+
"steps": [
35+
{
36+
"args": "cache jsr.ts",
37+
"output": "[WILDCARD]"
38+
},
39+
{
40+
"args": "run --frozen jsr2.ts",
41+
"output": "frozen_new_dep_jsr_run.out",
42+
"exitCode": 1
43+
},
44+
{
45+
"args": "cache --frozen jsr2.ts",
46+
"output": "frozen_new_dep_jsr_cache.out",
47+
"exitCode": 1
48+
},
49+
{
50+
// update the lockfile
51+
"args": "cache jsr2.ts",
52+
"output": ""
53+
},
54+
{
55+
"args": "run --frozen jsr2.ts",
56+
"output": "1 + 2 = 3\n"
57+
}
58+
]
59+
},
60+
"error_when_package_json_changed": {
61+
"steps": [
62+
{
63+
"args": "cache add.ts",
64+
"output": "[WILDCARD]"
65+
},
66+
{
67+
"args": [
68+
"eval",
69+
"Deno.writeTextFileSync(\"package.json\", JSON.stringify({ dependencies: { \"@denotest/bin\": \"0.7.0\" } }))"
70+
],
71+
"output": ""
72+
},
73+
{
74+
"args": "cache --frozen add.ts",
75+
"output": "frozen_package_json_changed.out",
76+
"exitCode": 1
77+
},
78+
{
79+
"envs": {
80+
"DENO_FUTURE": "1"
81+
},
82+
"args": "install --frozen",
83+
"output": "frozen_package_json_changed_install.out",
84+
"exitCode": 1
85+
}
86+
]
87+
},
88+
"no_error_when_in_lockfile": {
89+
"steps": [
90+
{
91+
"args": "cache add.ts",
92+
"output": "[WILDCARD]"
93+
},
94+
{
95+
"args": "run --frozen add.ts",
96+
"output": "1 + 2 = 3\n"
97+
}
98+
]
99+
},
100+
"errors_if_creates_lockfile": {
101+
"steps": [
102+
{
103+
"args": [
104+
"eval",
105+
"Deno.statSync('lock.json')"
106+
],
107+
"output": "[WILDCARD]NotFound[WILDCARD]",
108+
"exitCode": 1
109+
},
110+
{
111+
"args": "run --frozen add.ts",
112+
"output": "no_lockfile_run.out",
113+
"exitCode": 1
114+
}
115+
]
116+
},
117+
"non_analyzable_dynamic_npm": {
118+
"steps": [
119+
{
120+
"args": "cache add.ts",
121+
"output": "[WILDCARD]"
122+
},
123+
{
124+
"args": "run --frozen sub-dynamic.ts",
125+
"output": "frozen_new_dep_dynamic_npm.out",
126+
"exitCode": 1
127+
}
128+
]
129+
},
130+
"non_analyzable_dynamic_jsr": {
131+
"steps": [
132+
{
133+
"args": "cache add.ts",
134+
"output": "[WILDCARD]"
135+
},
136+
{
137+
"args": "run --frozen --allow-net jsr-dynamic.ts",
138+
"output": "frozen_new_dep_dynamic_jsr.out",
139+
"exitCode": 1
140+
}
141+
]
142+
},
143+
"non_analyzable_dynamic_http": {
144+
"steps": [
145+
{
146+
"args": "cache add.ts",
147+
"output": "[WILDCARD]"
148+
},
149+
{
150+
"args": "run --frozen --allow-net http-dynamic.ts",
151+
"output": "frozen_new_dep_dynamic_http.out",
152+
"exitCode": 1
153+
}
154+
]
155+
}
156+
}
157+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import { add } from "npm:@denotest/add@1";
2+
console.log(`1 + 2 = ${add(1, 2)}`);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"nodeModulesDir": true
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
2+
changes:
3+
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
4+
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
5+
6 | + "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0"
6+
11 | - }
7+
12 | + },
8+
13 | + "@denotest/subtract@1.0.0": {
9+
14 | + "integrity": "[WILDCARD]",
10+
15 | + "dependencies": {}
11+
16 | + }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Download http://localhost:4545/welcome.ts
2+
error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
3+
changes:
4+
14 | - "remote": {}
5+
14 | + "remote": {
6+
15 | + "http://localhost:4545/welcome.ts": "[WILDCARD]"
7+
16 | + }
8+
const _ = await import(scheme + "localhost:4545/welcome.ts");
9+
^
10+
at [WILDCARD]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Download http://127.0.0.1:4250/@denotest/add/meta.json
2+
Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json
3+
Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts
4+
error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
5+
changes:
6+
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
7+
5 | + "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0",
8+
6 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
9+
7 | + },
10+
8 | + "jsr": {
11+
9 | + "@denotest/add@1.0.0": {
12+
10 | + "integrity": "[WILDCARD]"
13+
11 | + }
14+
const { add } = await import(scheme + "@denotest/add@1");
15+
^
16+
at [WILDCARD]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Download http://localhost:4260/@denotest/subtract
2+
error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
3+
changes:
4+
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
5+
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
6+
6 | + "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0"
7+
11 | - }
8+
12 | + },
9+
13 | + "@denotest/subtract@1.0.0": {
10+
14 | + "integrity": "[WILDCARD]",
11+
15 | + "dependencies": {}
12+
16 | + }
13+
const { subtract } = await import(scheme + "@denotest/subtract@1");
14+
^
15+
at [WILDCARD]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
2+
changes:
3+
5 | - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0"
4+
6 | - },
5+
7 | - "jsr": {
6+
5 | + "jsr:@denotest/add@0.2.0": "jsr:@denotest/add@0.2.0",
7+
6 | + "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0"
8+
7 | + },
9+
8 | + "jsr": {
10+
9 | + "@denotest/add@0.2.0": {
11+
10 | + "integrity": "[WILDCARD]"
12+
11 | + },
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Download http://127.0.0.1:4250/@denotest/add/0.2.0_meta.json
2+
Download http://127.0.0.1:4250/@denotest/add/0.2.0/mod.ts
3+
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
4+
changes:
5+
5 | - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0"
6+
6 | - },
7+
7 | - "jsr": {
8+
5 | + "jsr:@denotest/add@0.2.0": "jsr:@denotest/add@0.2.0",
9+
6 | + "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0"
10+
7 | + },
11+
8 | + "jsr": {
12+
9 | + "@denotest/add@0.2.0": {
13+
10 | + "integrity": "[WILDCARD]"
14+
11 | + },
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Download http://localhost:4260/@denotest/subtract
2+
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
3+
changes:
4+
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
5+
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
6+
6 | + "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0"
7+
11 | - }
8+
12 | + },
9+
13 | + "@denotest/subtract@1.0.0": {
10+
14 | + "integrity": "[WILDCARD]",
11+
15 | + "dependencies": {}
12+
16 | + }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Download http://localhost:4260/@denotest/bin
2+
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
3+
changes:
4+
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
5+
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
6+
6 | + "npm:@denotest/bin@0.7.0": "npm:@denotest/bin@0.7.0"
7+
11 | - }
8+
12 | - }
9+
13 | - },
10+
14 | - "remote": {}
11+
12 | + },
12+
13 | + "@denotest/bin@0.7.0": {
13+
14 | + "integrity": "[WILDCARD]",
14+
15 | + "dependencies": {}
15+
16 | + }
16+
17 | + }
17+
18 | + },
18+
19 | + "remote": {},
19+
20 | + "workspace": {
20+
21 | + "packageJson": {
21+
22 | + "dependencies": [
22+
23 | + "npm:@denotest/bin@0.7.0"
23+
24 | + ]
24+
25 | + }
25+
26 | + }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag.
2+
error: The lockfile is out of date. Run `deno cache --frozen=false`, `deno install --frozen=false`, or rerun with `--frozen=false` to update it.
3+
changes:
4+
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
5+
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
6+
6 | + "npm:@denotest/bin@0.7.0": "npm:@denotest/bin@0.7.0"
7+
11 | - }
8+
12 | - }
9+
13 | - },
10+
14 | - "remote": {}
11+
12 | + },
12+
13 | + "@denotest/bin@0.7.0": {
13+
14 | + "integrity": "[WILDCARD]",
14+
15 | + "dependencies": {}
15+
16 | + }
16+
17 | + }
17+
18 | + },
18+
19 | + "remote": {},
19+
20 | + "workspace": {
20+
21 | + "packageJson": {
21+
22 | + "dependencies": [
22+
23 | + "npm:@denotest/bin@0.7.0"
23+
24 | + ]
24+
25 | + }
25+
26 | + }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const scheme = "http://";
2+
const _ = await import(scheme + "localhost:4545/welcome.ts");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const scheme = "jsr:";
2+
const { add } = await import(scheme + "@denotest/add@1");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import { add } from "jsr:@denotest/add@1";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import { sum } from "jsr:@denotest/add@0.2.0";
2+
console.log(`1 + 2 = ${sum(1, 2)}`);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Download http://localhost:4260/@denotest/add
2+
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
3+
changes:
4+
1 | -
5+
1 | +{
6+
2 | + "version": "3",
7+
3 | + "packages": {
8+
4 | + "specifiers": {
9+
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
10+
6 | + },
11+
7 | + "npm": {
12+
8 | + "@denotest/add@1.0.0": {
13+
9 | + "integrity": "[WILDCARD]",
14+
10 | + "dependencies": {}
15+
11 | + }
16+
12 | + }
17+
13 | + },
18+
14 | + "remote": {}
19+
15 | +}
20+
16 | +
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const scheme = "npm:";
2+
const { subtract } = await import(scheme + "@denotest/subtract@1");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import { subtract } from "npm:@denotest/subtract@1";
2+
console.log(`3 - 2 = ${subtract(3, 2)}`);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Download http://localhost:4260/@denotest/subtract/1.0.0.tgz
2+
Initialize @denotest/subtract@1.0.0

‎tests/specs/npm/npmrc_not_next_to_package_json/main.out

-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@
44
[WILDCARD]
55
Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz
66
Initialize @denotest/esm-basic@1.0.0
7-
[WILDCARD]

0 commit comments

Comments
 (0)
Please sign in to comment.