diff options
Diffstat (limited to 'cli/lockfile.rs')
-rw-r--r-- | cli/lockfile.rs | 109 |
1 files changed, 87 insertions, 22 deletions
diff --git a/cli/lockfile.rs b/cli/lockfile.rs index a2658918d..afbd8d287 100644 --- a/cli/lockfile.rs +++ b/cli/lockfile.rs @@ -1,8 +1,12 @@ // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. +#![allow(dead_code)] + use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; +use deno_core::serde::Deserialize; +use deno_core::serde::Serialize; use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::ModuleSpecifier; @@ -16,9 +20,20 @@ use std::sync::Arc; use crate::tools::fmt::format_json; +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LockfileV2Content { + version: String, + // Mapping between URLs and their checksums + remote: BTreeMap<String, String>, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct LockfileV1Content(BTreeMap<String, String>); + #[derive(Debug, Clone)] -pub struct LockfileContent { - map: BTreeMap<String, String>, +enum LockfileContent { + V1(LockfileV1Content), + V2(LockfileV2Content), } #[derive(Debug, Clone)] @@ -30,19 +45,33 @@ pub struct Lockfile { impl Lockfile { pub fn new(filename: PathBuf, write: bool) -> Result<Lockfile, AnyError> { - let map = if write { - BTreeMap::new() + // Writing a lock file always uses the new format. + let content = if write { + LockfileContent::V2(LockfileV2Content { + version: "2".to_string(), + remote: BTreeMap::new(), + }) } else { let s = std::fs::read_to_string(&filename).with_context(|| { format!("Unable to read lockfile: {}", filename.display()) })?; - serde_json::from_str(&s) - .context("Unable to parse contents of the lockfile")? + let value: serde_json::Value = serde_json::from_str(&s) + .context("Unable to parse contents of the lockfile")?; + let version = value.get("version").and_then(|v| v.as_str()); + if version == Some("2") { + let content: LockfileV2Content = + serde_json::from_value(value).context("Unable to parse lockfile")?; + LockfileContent::V2(content) + } else { + let content: LockfileV1Content = + serde_json::from_value(value).context("Unable to parse lockfile")?; + LockfileContent::V1(content) + } }; Ok(Lockfile { write, - content: LockfileContent { map }, + content, filename, }) } @@ -52,13 +81,19 @@ impl Lockfile { if !self.write { return Ok(()); } - let j = json!(&self.content.map); - let s = serde_json::to_string_pretty(&j).unwrap(); - let format_s = format_json(&s, &Default::default()) + let json_string = match &self.content { + LockfileContent::V1(c) => { + let j = json!(&c.0); + serde_json::to_string(&j).unwrap() + } + LockfileContent::V2(c) => serde_json::to_string(&c).unwrap(), + }; + + let format_s = format_json(&json_string, &Default::default()) .ok() .flatten() - .unwrap_or(s); + .unwrap_or(json_string); let mut f = std::fs::OpenOptions::new() .write(true) .create(true) @@ -85,11 +120,23 @@ impl Lockfile { if specifier.starts_with("file:") { return true; } - if let Some(lockfile_checksum) = self.content.map.get(specifier) { - let compiled_checksum = crate::checksum::gen(&[code.as_bytes()]); - lockfile_checksum == &compiled_checksum - } else { - false + match &self.content { + LockfileContent::V1(c) => { + if let Some(lockfile_checksum) = c.0.get(specifier) { + let compiled_checksum = crate::checksum::gen(&[code.as_bytes()]); + lockfile_checksum == &compiled_checksum + } else { + false + } + } + LockfileContent::V2(c) => { + if let Some(lockfile_checksum) = c.remote.get(specifier) { + let compiled_checksum = crate::checksum::gen(&[code.as_bytes()]); + lockfile_checksum == &compiled_checksum + } else { + false + } + } } } @@ -98,7 +145,14 @@ impl Lockfile { return; } let checksum = crate::checksum::gen(&[code.as_bytes()]); - self.content.map.insert(specifier.to_string(), checksum); + match &mut self.content { + LockfileContent::V1(c) => { + c.0.insert(specifier.to_string(), checksum); + } + LockfileContent::V2(c) => { + c.remote.insert(specifier.to_string(), checksum); + } + }; } } @@ -154,8 +208,11 @@ mod tests { let mut file = File::create(file_path).expect("write file fail"); let value: serde_json::Value = json!({ - "https://deno.land/std@0.71.0/textproto/mod.ts": "3118d7a42c03c242c5a49c2ad91c8396110e14acca1324e7aaefd31a999b71a4", - "https://deno.land/std@0.71.0/async/delay.ts": "35957d585a6e3dd87706858fb1d6b551cb278271b03f52c5a2cb70e65e00c26a" + "version": "2", + "remote": { + "https://deno.land/std@0.71.0/textproto/mod.ts": "3118d7a42c03c242c5a49c2ad91c8396110e14acca1324e7aaefd31a999b71a4", + "https://deno.land/std@0.71.0/async/delay.ts": "35957d585a6e3dd87706858fb1d6b551cb278271b03f52c5a2cb70e65e00c26a" + } }); file.write_all(value.to_string().as_bytes()).unwrap(); @@ -176,7 +233,11 @@ mod tests { let result = Lockfile::new(file_path, false).unwrap(); - let keys: Vec<String> = result.content.map.keys().cloned().collect(); + let remote = match result.content { + LockfileContent::V2(c) => c.remote, + _ => unreachable!(), + }; + let keys: Vec<String> = remote.keys().cloned().collect(); let expected_keys = vec![ String::from("https://deno.land/std@0.71.0/async/delay.ts"), String::from("https://deno.land/std@0.71.0/textproto/mod.ts"), @@ -198,7 +259,11 @@ mod tests { "Here is some source code", ); - let keys: Vec<String> = lockfile.content.map.keys().cloned().collect(); + let remote = match lockfile.content { + LockfileContent::V2(c) => c.remote, + _ => unreachable!(), + }; + let keys: Vec<String> = remote.keys().cloned().collect(); let expected_keys = vec![ String::from("https://deno.land/std@0.71.0/async/delay.ts"), String::from("https://deno.land/std@0.71.0/io/util.ts"), @@ -242,7 +307,7 @@ mod tests { let contents_json = serde_json::from_str::<serde_json::Value>(&contents).unwrap(); - let object = contents_json.as_object().unwrap(); + let object = contents_json["remote"].as_object().unwrap(); assert_eq!( object |