mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
feat(cli): Add --frozen
flag to error out if lockfile is out of date (#24355)
Closes #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. 
This commit is contained in:
parent
d379c0b299
commit
c13b6d1413
29 changed files with 477 additions and 30 deletions
|
@ -498,6 +498,7 @@ pub struct Flags {
|
||||||
pub argv: Vec<String>,
|
pub argv: Vec<String>,
|
||||||
pub subcommand: DenoSubcommand,
|
pub subcommand: DenoSubcommand,
|
||||||
|
|
||||||
|
pub frozen_lockfile: bool,
|
||||||
pub ca_stores: Option<Vec<String>>,
|
pub ca_stores: Option<Vec<String>>,
|
||||||
pub ca_data: Option<CaData>,
|
pub ca_data: Option<CaData>,
|
||||||
pub cache_blocklist: Vec<String>,
|
pub cache_blocklist: Vec<String>,
|
||||||
|
@ -1487,12 +1488,15 @@ Future runs of this module will trigger no downloads or compilation unless
|
||||||
--reload is specified.",
|
--reload is specified.",
|
||||||
)
|
)
|
||||||
.defer(|cmd| {
|
.defer(|cmd| {
|
||||||
compile_args(cmd).arg(check_arg(false)).arg(
|
compile_args(cmd)
|
||||||
Arg::new("file")
|
.arg(check_arg(false))
|
||||||
.num_args(1..)
|
.arg(
|
||||||
.required(true)
|
Arg::new("file")
|
||||||
.value_hint(ValueHint::FilePath),
|
.num_args(1..)
|
||||||
)
|
.required(true)
|
||||||
|
.value_hint(ValueHint::FilePath),
|
||||||
|
)
|
||||||
|
.arg(frozen_lockfile_arg())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3271,6 +3275,7 @@ fn runtime_args(
|
||||||
app
|
app
|
||||||
};
|
};
|
||||||
app
|
app
|
||||||
|
.arg(frozen_lockfile_arg())
|
||||||
.arg(cached_only_arg())
|
.arg(cached_only_arg())
|
||||||
.arg(location_arg())
|
.arg(location_arg())
|
||||||
.arg(v8_flags_arg())
|
.arg(v8_flags_arg())
|
||||||
|
@ -3384,6 +3389,17 @@ fn cached_only_arg() -> Arg {
|
||||||
.help("Require that remote dependencies are already cached")
|
.help("Require that remote dependencies are already cached")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frozen_lockfile_arg() -> Arg {
|
||||||
|
Arg::new("frozen")
|
||||||
|
.long("frozen")
|
||||||
|
.alias("frozen-lockfile")
|
||||||
|
.value_parser(value_parser!(bool))
|
||||||
|
.num_args(0..=1)
|
||||||
|
.require_equals(true)
|
||||||
|
.default_missing_value("true")
|
||||||
|
.help("Error out if lockfile is out of date")
|
||||||
|
}
|
||||||
|
|
||||||
/// Used for subcommands that operate on executable scripts only.
|
/// Used for subcommands that operate on executable scripts only.
|
||||||
/// `deno fmt` has its own `--ext` arg because its possible values differ.
|
/// `deno fmt` has its own `--ext` arg because its possible values differ.
|
||||||
/// If --ext is not provided and the script doesn't have a file extension,
|
/// 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) {
|
||||||
|
|
||||||
fn cache_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
fn cache_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
||||||
compile_args_parse(flags, matches);
|
compile_args_parse(flags, matches);
|
||||||
|
frozen_lockfile_arg_parse(flags, matches);
|
||||||
let files = matches.remove_many::<String>("file").unwrap().collect();
|
let files = matches.remove_many::<String>("file").unwrap().collect();
|
||||||
flags.subcommand = DenoSubcommand::Cache(CacheFlags { files });
|
flags.subcommand = DenoSubcommand::Cache(CacheFlags { files });
|
||||||
}
|
}
|
||||||
|
@ -4576,6 +4593,7 @@ fn runtime_args_parse(
|
||||||
) {
|
) {
|
||||||
compile_args_parse(flags, matches);
|
compile_args_parse(flags, matches);
|
||||||
cached_only_arg_parse(flags, matches);
|
cached_only_arg_parse(flags, matches);
|
||||||
|
frozen_lockfile_arg_parse(flags, matches);
|
||||||
if include_perms {
|
if include_perms {
|
||||||
permission_args_parse(flags, matches);
|
permission_args_parse(flags, matches);
|
||||||
}
|
}
|
||||||
|
@ -4667,6 +4685,12 @@ fn cached_only_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frozen_lockfile_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
||||||
|
if let Some(&v) = matches.get_one::<bool>("frozen") {
|
||||||
|
flags.frozen_lockfile = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ext_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
fn ext_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
||||||
flags.ext = matches.remove_one::<String>("ext");
|
flags.ext = matches.remove_one::<String>("ext");
|
||||||
}
|
}
|
||||||
|
@ -9845,4 +9869,33 @@ mod tests {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn run_with_frozen_lockfile() {
|
||||||
|
let cases = [
|
||||||
|
(Some("--frozen"), true),
|
||||||
|
(Some("--frozen=true"), true),
|
||||||
|
(Some("--frozen=false"), false),
|
||||||
|
(None, false),
|
||||||
|
];
|
||||||
|
for (flag, frozen) in cases {
|
||||||
|
let mut args = svec!["deno", "run"];
|
||||||
|
if let Some(f) = flag {
|
||||||
|
args.push(f.into());
|
||||||
|
}
|
||||||
|
args.push("script.ts".into());
|
||||||
|
let r = flags_from_vec(args);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Run(RunFlags::new_default(
|
||||||
|
"script.ts".to_string(),
|
||||||
|
)),
|
||||||
|
frozen_lockfile: frozen,
|
||||||
|
code_cache_enabled: true,
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ use deno_lockfile::Lockfile;
|
||||||
pub struct CliLockfile {
|
pub struct CliLockfile {
|
||||||
lockfile: Mutex<Lockfile>,
|
lockfile: Mutex<Lockfile>,
|
||||||
pub filename: PathBuf,
|
pub filename: PathBuf,
|
||||||
|
pub frozen: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Guard<'a, T> {
|
pub struct Guard<'a, T> {
|
||||||
|
@ -44,11 +45,12 @@ impl<'a, T> std::ops::DerefMut for Guard<'a, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliLockfile {
|
impl CliLockfile {
|
||||||
pub fn new(lockfile: Lockfile) -> Self {
|
pub fn new(lockfile: Lockfile, frozen: bool) -> Self {
|
||||||
let filename = lockfile.filename.clone();
|
let filename = lockfile.filename.clone();
|
||||||
Self {
|
Self {
|
||||||
lockfile: Mutex::new(lockfile),
|
lockfile: Mutex::new(lockfile),
|
||||||
filename,
|
filename,
|
||||||
|
frozen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +73,7 @@ impl CliLockfile {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_if_changed(&self) -> Result<(), AnyError> {
|
pub fn write_if_changed(&self) -> Result<(), AnyError> {
|
||||||
|
self.error_if_changed()?;
|
||||||
let mut lockfile = self.lockfile.lock();
|
let mut lockfile = self.lockfile.lock();
|
||||||
let Some(bytes) = lockfile.resolve_write_bytes() else {
|
let Some(bytes) = lockfile.resolve_write_bytes() else {
|
||||||
return Ok(()); // nothing to do
|
return Ok(()); // nothing to do
|
||||||
|
@ -127,23 +130,55 @@ impl CliLockfile {
|
||||||
};
|
};
|
||||||
|
|
||||||
let lockfile = if flags.lock_write {
|
let lockfile = if flags.lock_write {
|
||||||
CliLockfile::new(Lockfile::new_empty(filename, true))
|
CliLockfile::new(
|
||||||
|
Lockfile::new_empty(filename, true),
|
||||||
|
flags.frozen_lockfile,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Self::read_from_path(filename)?
|
Self::read_from_path(filename, flags.frozen_lockfile)?
|
||||||
};
|
};
|
||||||
Ok(Some(lockfile))
|
Ok(Some(lockfile))
|
||||||
}
|
}
|
||||||
pub fn read_from_path(filename: PathBuf) -> Result<CliLockfile, AnyError> {
|
pub fn read_from_path(
|
||||||
|
filename: PathBuf,
|
||||||
|
frozen: bool,
|
||||||
|
) -> Result<CliLockfile, AnyError> {
|
||||||
match std::fs::read_to_string(&filename) {
|
match std::fs::read_to_string(&filename) {
|
||||||
Ok(text) => Ok(CliLockfile::new(Lockfile::with_lockfile_content(
|
Ok(text) => Ok(CliLockfile::new(
|
||||||
filename, &text, false,
|
Lockfile::with_lockfile_content(filename, &text, false)?,
|
||||||
)?)),
|
frozen,
|
||||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
)),
|
||||||
Ok(CliLockfile::new(Lockfile::new_empty(filename, false)))
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(
|
||||||
}
|
CliLockfile::new(Lockfile::new_empty(filename, false), frozen),
|
||||||
|
),
|
||||||
Err(err) => Err(err).with_context(|| {
|
Err(err) => Err(err).with_context(|| {
|
||||||
format!("Failed reading lockfile '{}'", filename.display())
|
format!("Failed reading lockfile '{}'", filename.display())
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn error_if_changed(&self) -> Result<(), AnyError> {
|
||||||
|
if !self.frozen {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let lockfile = self.lockfile.lock();
|
||||||
|
if lockfile.has_content_changed {
|
||||||
|
let suggested = if *super::DENO_FUTURE {
|
||||||
|
"`deno cache --frozen=false`, `deno install --frozen=false`,"
|
||||||
|
} else {
|
||||||
|
"`deno cache --frozen=false`"
|
||||||
|
};
|
||||||
|
|
||||||
|
let contents =
|
||||||
|
std::fs::read_to_string(&lockfile.filename).unwrap_or_default();
|
||||||
|
let new_contents = lockfile.as_json_string();
|
||||||
|
let diff = crate::util::diff::diff(&contents, &new_contents);
|
||||||
|
// has an extra newline at the end
|
||||||
|
let diff = diff.trim_end();
|
||||||
|
Err(deno_core::anyhow::anyhow!(
|
||||||
|
"The lockfile is out of date. Run {suggested} or rerun with `--frozen=false` to update it.\nchanges:\n{diff}"
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1825,7 +1825,7 @@ fn resolve_node_modules_dir(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_lockfile_from_path(lockfile_path: PathBuf) -> Option<CliLockfile> {
|
fn resolve_lockfile_from_path(lockfile_path: PathBuf) -> Option<CliLockfile> {
|
||||||
match CliLockfile::read_from_path(lockfile_path) {
|
match CliLockfile::read_from_path(lockfile_path, false) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
if value.filename.exists() {
|
if value.filename.exists() {
|
||||||
if let Ok(specifier) = ModuleSpecifier::from_file_path(&value.filename)
|
if let Ok(specifier) = ModuleSpecifier::from_file_path(&value.filename)
|
||||||
|
|
|
@ -72,10 +72,13 @@ use deno_semver::npm::NpmPackageReqReference;
|
||||||
pub async fn load_top_level_deps(factory: &CliFactory) -> Result<(), AnyError> {
|
pub async fn load_top_level_deps(factory: &CliFactory) -> Result<(), AnyError> {
|
||||||
let npm_resolver = factory.npm_resolver().await?;
|
let npm_resolver = factory.npm_resolver().await?;
|
||||||
if let Some(npm_resolver) = npm_resolver.as_managed() {
|
if let Some(npm_resolver) = npm_resolver.as_managed() {
|
||||||
npm_resolver.ensure_top_level_package_json_install().await?;
|
if !npm_resolver.ensure_top_level_package_json_install().await? {
|
||||||
// TODO(nathanwhit): we call `cache_packages` if the lockfile is modified,
|
if let Some(lockfile) = factory.maybe_lockfile() {
|
||||||
// so by calling it here it's possible we end up calling it twice
|
lockfile.error_if_changed()?;
|
||||||
npm_resolver.cache_packages().await?;
|
}
|
||||||
|
|
||||||
|
npm_resolver.cache_packages().await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// cache as many entries in the import map as we can
|
// cache as many entries in the import map as we can
|
||||||
if let Some(import_map) = factory.maybe_import_map().await? {
|
if let Some(import_map) = factory.maybe_import_map().await? {
|
||||||
|
|
|
@ -361,12 +361,15 @@ impl ManagedCliNpmResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds package requirements to the resolver and ensures everything is setup.
|
/// Adds package requirements to the resolver and ensures everything is setup.
|
||||||
|
/// This includes setting up the `node_modules` directory, if applicable.
|
||||||
pub async fn add_package_reqs(
|
pub async fn add_package_reqs(
|
||||||
&self,
|
&self,
|
||||||
packages: &[PackageReq],
|
packages: &[PackageReq],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let result = self.add_package_reqs_raw(packages).await;
|
self
|
||||||
result.dependencies_result
|
.add_package_reqs_raw(packages)
|
||||||
|
.await
|
||||||
|
.dependencies_result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_package_reqs_raw(
|
pub async fn add_package_reqs_raw(
|
||||||
|
@ -381,6 +384,12 @@ impl ManagedCliNpmResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = self.resolution.add_package_reqs(packages).await;
|
let mut result = self.resolution.add_package_reqs(packages).await;
|
||||||
|
|
||||||
|
if result.dependencies_result.is_ok() {
|
||||||
|
if let Some(lockfile) = self.maybe_lockfile.as_ref() {
|
||||||
|
result.dependencies_result = lockfile.error_if_changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
if result.dependencies_result.is_ok() {
|
if result.dependencies_result.is_ok() {
|
||||||
result.dependencies_result =
|
result.dependencies_result =
|
||||||
self.cache_packages().await.map_err(AnyError::from);
|
self.cache_packages().await.map_err(AnyError::from);
|
||||||
|
@ -442,14 +451,19 @@ impl ManagedCliNpmResolver {
|
||||||
self.resolution.resolve_pkg_id_from_pkg_req(req)
|
self.resolution.resolve_pkg_id_from_pkg_req(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ensures that the top level `package.json` dependencies are installed.
|
||||||
|
/// This may set up the `node_modules` directory.
|
||||||
|
///
|
||||||
|
/// Returns `true` if any changes (such as caching packages) were made.
|
||||||
|
/// If this returns `false`, `node_modules` has _not_ been set up.
|
||||||
pub async fn ensure_top_level_package_json_install(
|
pub async fn ensure_top_level_package_json_install(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<bool, AnyError> {
|
||||||
let Some(reqs) = self.package_json_deps_provider.reqs() else {
|
let Some(reqs) = self.package_json_deps_provider.reqs() else {
|
||||||
return Ok(());
|
return Ok(false);
|
||||||
};
|
};
|
||||||
if !self.top_level_install_flag.raise() {
|
if !self.top_level_install_flag.raise() {
|
||||||
return Ok(()); // already did this
|
return Ok(false); // already did this
|
||||||
}
|
}
|
||||||
// check if something needs resolving before bothering to load all
|
// check if something needs resolving before bothering to load all
|
||||||
// the package information (which is slow)
|
// the package information (which is slow)
|
||||||
|
@ -460,11 +474,11 @@ impl ManagedCliNpmResolver {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"All package.json deps resolvable. Skipping top level install."
|
"All package.json deps resolvable. Skipping top level install."
|
||||||
);
|
);
|
||||||
return Ok(()); // everything is already resolvable
|
return Ok(false); // everything is already resolvable
|
||||||
}
|
}
|
||||||
|
|
||||||
let reqs = reqs.into_iter().cloned().collect::<Vec<_>>();
|
let reqs = reqs.into_iter().cloned().collect::<Vec<_>>();
|
||||||
self.add_package_reqs(&reqs).await
|
self.add_package_reqs(&reqs).await.map(|_| true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cache_package_info(
|
pub async fn cache_package_info(
|
||||||
|
|
|
@ -824,7 +824,10 @@ impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let top_level_result = if self.found_package_json_dep_flag.is_raised() {
|
let top_level_result = if self.found_package_json_dep_flag.is_raised() {
|
||||||
npm_resolver.ensure_top_level_package_json_install().await
|
npm_resolver
|
||||||
|
.ensure_top_level_package_json_install()
|
||||||
|
.await
|
||||||
|
.map(|_| ())
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
|
@ -466,6 +466,10 @@ async fn resolve_shim_data(
|
||||||
executable_args.push("--cached-only".to_string());
|
executable_args.push("--cached-only".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if flags.frozen_lockfile {
|
||||||
|
executable_args.push("--frozen".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
if resolve_no_prompt(&flags.permissions) {
|
if resolve_no_prompt(&flags.permissions) {
|
||||||
executable_args.push("--no-prompt".to_string());
|
executable_args.push("--no-prompt".to_string());
|
||||||
}
|
}
|
||||||
|
|
157
tests/specs/lockfile/frozen_lockfile/__test__.jsonc
Normal file
157
tests/specs/lockfile/frozen_lockfile/__test__.jsonc
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
{
|
||||||
|
"tempDir": true,
|
||||||
|
"tests": {
|
||||||
|
"error_with_new_npm_dep": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "cache add.ts",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// sub.ts imports from an npm package
|
||||||
|
// that's not in the lockfile
|
||||||
|
"args": "run --frozen sub.ts",
|
||||||
|
"output": "frozen_new_dep_run.out",
|
||||||
|
"exitCode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "cache --frozen sub.ts",
|
||||||
|
"output": "frozen_new_dep_cache.out",
|
||||||
|
"exitCode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// update the lockfile
|
||||||
|
"args": "cache sub.ts",
|
||||||
|
"output": "update_lockfile.out"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "run --frozen sub.ts",
|
||||||
|
"output": "3 - 2 = 1\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"error_with_new_jsr_dep": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "cache jsr.ts",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "run --frozen jsr2.ts",
|
||||||
|
"output": "frozen_new_dep_jsr_run.out",
|
||||||
|
"exitCode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "cache --frozen jsr2.ts",
|
||||||
|
"output": "frozen_new_dep_jsr_cache.out",
|
||||||
|
"exitCode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// update the lockfile
|
||||||
|
"args": "cache jsr2.ts",
|
||||||
|
"output": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "run --frozen jsr2.ts",
|
||||||
|
"output": "1 + 2 = 3\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"error_when_package_json_changed": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "cache add.ts",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": [
|
||||||
|
"eval",
|
||||||
|
"Deno.writeTextFileSync(\"package.json\", JSON.stringify({ dependencies: { \"@denotest/bin\": \"0.7.0\" } }))"
|
||||||
|
],
|
||||||
|
"output": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "cache --frozen add.ts",
|
||||||
|
"output": "frozen_package_json_changed.out",
|
||||||
|
"exitCode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"envs": {
|
||||||
|
"DENO_FUTURE": "1"
|
||||||
|
},
|
||||||
|
"args": "install --frozen",
|
||||||
|
"output": "frozen_package_json_changed_install.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"no_error_when_in_lockfile": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "cache add.ts",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "run --frozen add.ts",
|
||||||
|
"output": "1 + 2 = 3\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"errors_if_creates_lockfile": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": [
|
||||||
|
"eval",
|
||||||
|
"Deno.statSync('lock.json')"
|
||||||
|
],
|
||||||
|
"output": "[WILDCARD]NotFound[WILDCARD]",
|
||||||
|
"exitCode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "run --frozen add.ts",
|
||||||
|
"output": "no_lockfile_run.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"non_analyzable_dynamic_npm": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "cache add.ts",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "run --frozen sub-dynamic.ts",
|
||||||
|
"output": "frozen_new_dep_dynamic_npm.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"non_analyzable_dynamic_jsr": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "cache add.ts",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "run --frozen --allow-net jsr-dynamic.ts",
|
||||||
|
"output": "frozen_new_dep_dynamic_jsr.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"non_analyzable_dynamic_http": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "cache add.ts",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "run --frozen --allow-net http-dynamic.ts",
|
||||||
|
"output": "frozen_new_dep_dynamic_http.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
tests/specs/lockfile/frozen_lockfile/add.ts
Normal file
2
tests/specs/lockfile/frozen_lockfile/add.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import { add } from "npm:@denotest/add@1";
|
||||||
|
console.log(`1 + 2 = ${add(1, 2)}`);
|
3
tests/specs/lockfile/frozen_lockfile/deno.json
Normal file
3
tests/specs/lockfile/frozen_lockfile/deno.json
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"nodeModulesDir": true
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
|
||||||
|
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
|
||||||
|
6 | + "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0"
|
||||||
|
11 | - }
|
||||||
|
12 | + },
|
||||||
|
13 | + "@denotest/subtract@1.0.0": {
|
||||||
|
14 | + "integrity": "[WILDCARD]",
|
||||||
|
15 | + "dependencies": {}
|
||||||
|
16 | + }
|
|
@ -0,0 +1,10 @@
|
||||||
|
Download http://localhost:4545/welcome.ts
|
||||||
|
error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
14 | - "remote": {}
|
||||||
|
14 | + "remote": {
|
||||||
|
15 | + "http://localhost:4545/welcome.ts": "[WILDCARD]"
|
||||||
|
16 | + }
|
||||||
|
const _ = await import(scheme + "localhost:4545/welcome.ts");
|
||||||
|
^
|
||||||
|
at [WILDCARD]
|
|
@ -0,0 +1,16 @@
|
||||||
|
Download http://127.0.0.1:4250/@denotest/add/meta.json
|
||||||
|
Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json
|
||||||
|
Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts
|
||||||
|
error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
|
||||||
|
5 | + "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0",
|
||||||
|
6 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
|
||||||
|
7 | + },
|
||||||
|
8 | + "jsr": {
|
||||||
|
9 | + "@denotest/add@1.0.0": {
|
||||||
|
10 | + "integrity": "[WILDCARD]"
|
||||||
|
11 | + }
|
||||||
|
const { add } = await import(scheme + "@denotest/add@1");
|
||||||
|
^
|
||||||
|
at [WILDCARD]
|
|
@ -0,0 +1,15 @@
|
||||||
|
Download http://localhost:4260/@denotest/subtract
|
||||||
|
error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
|
||||||
|
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
|
||||||
|
6 | + "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0"
|
||||||
|
11 | - }
|
||||||
|
12 | + },
|
||||||
|
13 | + "@denotest/subtract@1.0.0": {
|
||||||
|
14 | + "integrity": "[WILDCARD]",
|
||||||
|
15 | + "dependencies": {}
|
||||||
|
16 | + }
|
||||||
|
const { subtract } = await import(scheme + "@denotest/subtract@1");
|
||||||
|
^
|
||||||
|
at [WILDCARD]
|
|
@ -0,0 +1,12 @@
|
||||||
|
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
5 | - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0"
|
||||||
|
6 | - },
|
||||||
|
7 | - "jsr": {
|
||||||
|
5 | + "jsr:@denotest/add@0.2.0": "jsr:@denotest/add@0.2.0",
|
||||||
|
6 | + "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0"
|
||||||
|
7 | + },
|
||||||
|
8 | + "jsr": {
|
||||||
|
9 | + "@denotest/add@0.2.0": {
|
||||||
|
10 | + "integrity": "[WILDCARD]"
|
||||||
|
11 | + },
|
|
@ -0,0 +1,14 @@
|
||||||
|
Download http://127.0.0.1:4250/@denotest/add/0.2.0_meta.json
|
||||||
|
Download http://127.0.0.1:4250/@denotest/add/0.2.0/mod.ts
|
||||||
|
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
5 | - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0"
|
||||||
|
6 | - },
|
||||||
|
7 | - "jsr": {
|
||||||
|
5 | + "jsr:@denotest/add@0.2.0": "jsr:@denotest/add@0.2.0",
|
||||||
|
6 | + "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0"
|
||||||
|
7 | + },
|
||||||
|
8 | + "jsr": {
|
||||||
|
9 | + "@denotest/add@0.2.0": {
|
||||||
|
10 | + "integrity": "[WILDCARD]"
|
||||||
|
11 | + },
|
12
tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out
Normal file
12
tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Download http://localhost:4260/@denotest/subtract
|
||||||
|
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
|
||||||
|
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
|
||||||
|
6 | + "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0"
|
||||||
|
11 | - }
|
||||||
|
12 | + },
|
||||||
|
13 | + "@denotest/subtract@1.0.0": {
|
||||||
|
14 | + "integrity": "[WILDCARD]",
|
||||||
|
15 | + "dependencies": {}
|
||||||
|
16 | + }
|
|
@ -0,0 +1,25 @@
|
||||||
|
Download http://localhost:4260/@denotest/bin
|
||||||
|
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
|
||||||
|
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
|
||||||
|
6 | + "npm:@denotest/bin@0.7.0": "npm:@denotest/bin@0.7.0"
|
||||||
|
11 | - }
|
||||||
|
12 | - }
|
||||||
|
13 | - },
|
||||||
|
14 | - "remote": {}
|
||||||
|
12 | + },
|
||||||
|
13 | + "@denotest/bin@0.7.0": {
|
||||||
|
14 | + "integrity": "[WILDCARD]",
|
||||||
|
15 | + "dependencies": {}
|
||||||
|
16 | + }
|
||||||
|
17 | + }
|
||||||
|
18 | + },
|
||||||
|
19 | + "remote": {},
|
||||||
|
20 | + "workspace": {
|
||||||
|
21 | + "packageJson": {
|
||||||
|
22 | + "dependencies": [
|
||||||
|
23 | + "npm:@denotest/bin@0.7.0"
|
||||||
|
24 | + ]
|
||||||
|
25 | + }
|
||||||
|
26 | + }
|
|
@ -0,0 +1,25 @@
|
||||||
|
⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag.
|
||||||
|
error: The lockfile is out of date. Run `deno cache --frozen=false`, `deno install --frozen=false`, or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
|
||||||
|
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
|
||||||
|
6 | + "npm:@denotest/bin@0.7.0": "npm:@denotest/bin@0.7.0"
|
||||||
|
11 | - }
|
||||||
|
12 | - }
|
||||||
|
13 | - },
|
||||||
|
14 | - "remote": {}
|
||||||
|
12 | + },
|
||||||
|
13 | + "@denotest/bin@0.7.0": {
|
||||||
|
14 | + "integrity": "[WILDCARD]",
|
||||||
|
15 | + "dependencies": {}
|
||||||
|
16 | + }
|
||||||
|
17 | + }
|
||||||
|
18 | + },
|
||||||
|
19 | + "remote": {},
|
||||||
|
20 | + "workspace": {
|
||||||
|
21 | + "packageJson": {
|
||||||
|
22 | + "dependencies": [
|
||||||
|
23 | + "npm:@denotest/bin@0.7.0"
|
||||||
|
24 | + ]
|
||||||
|
25 | + }
|
||||||
|
26 | + }
|
2
tests/specs/lockfile/frozen_lockfile/http-dynamic.ts
Normal file
2
tests/specs/lockfile/frozen_lockfile/http-dynamic.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
const scheme = "http://";
|
||||||
|
const _ = await import(scheme + "localhost:4545/welcome.ts");
|
2
tests/specs/lockfile/frozen_lockfile/jsr-dynamic.ts
Normal file
2
tests/specs/lockfile/frozen_lockfile/jsr-dynamic.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
const scheme = "jsr:";
|
||||||
|
const { add } = await import(scheme + "@denotest/add@1");
|
1
tests/specs/lockfile/frozen_lockfile/jsr.ts
Normal file
1
tests/specs/lockfile/frozen_lockfile/jsr.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import { add } from "jsr:@denotest/add@1";
|
2
tests/specs/lockfile/frozen_lockfile/jsr2.ts
Normal file
2
tests/specs/lockfile/frozen_lockfile/jsr2.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import { sum } from "jsr:@denotest/add@0.2.0";
|
||||||
|
console.log(`1 + 2 = ${sum(1, 2)}`);
|
20
tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out
Normal file
20
tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
Download http://localhost:4260/@denotest/add
|
||||||
|
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
|
||||||
|
changes:
|
||||||
|
1 | -
|
||||||
|
1 | +{
|
||||||
|
2 | + "version": "3",
|
||||||
|
3 | + "packages": {
|
||||||
|
4 | + "specifiers": {
|
||||||
|
5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
|
||||||
|
6 | + },
|
||||||
|
7 | + "npm": {
|
||||||
|
8 | + "@denotest/add@1.0.0": {
|
||||||
|
9 | + "integrity": "[WILDCARD]",
|
||||||
|
10 | + "dependencies": {}
|
||||||
|
11 | + }
|
||||||
|
12 | + }
|
||||||
|
13 | + },
|
||||||
|
14 | + "remote": {}
|
||||||
|
15 | +}
|
||||||
|
16 | +
|
1
tests/specs/lockfile/frozen_lockfile/package.json
Normal file
1
tests/specs/lockfile/frozen_lockfile/package.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
2
tests/specs/lockfile/frozen_lockfile/sub-dynamic.ts
Normal file
2
tests/specs/lockfile/frozen_lockfile/sub-dynamic.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
const scheme = "npm:";
|
||||||
|
const { subtract } = await import(scheme + "@denotest/subtract@1");
|
2
tests/specs/lockfile/frozen_lockfile/sub.ts
Normal file
2
tests/specs/lockfile/frozen_lockfile/sub.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import { subtract } from "npm:@denotest/subtract@1";
|
||||||
|
console.log(`3 - 2 = ${subtract(3, 2)}`);
|
2
tests/specs/lockfile/frozen_lockfile/update_lockfile.out
Normal file
2
tests/specs/lockfile/frozen_lockfile/update_lockfile.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Download http://localhost:4260/@denotest/subtract/1.0.0.tgz
|
||||||
|
Initialize @denotest/subtract@1.0.0
|
|
@ -4,4 +4,3 @@
|
||||||
[WILDCARD]
|
[WILDCARD]
|
||||||
Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz
|
Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz
|
||||||
Initialize @denotest/esm-basic@1.0.0
|
Initialize @denotest/esm-basic@1.0.0
|
||||||
[WILDCARD]
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue