Skip to content

Commit b252052

Browse files
committed
feat: check the archive.json version before using CEF_PATH cached
archive
1 parent 36cd7ad commit b252052

5 files changed

Lines changed: 77 additions & 32 deletions

File tree

download-cef/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ authors.workspace = true
99
repository.workspace = true
1010

1111
[dependencies]
12+
regex.workspace = true
1213
semver.workspace = true
1314
serde.workspace = true
15+
serde_json.workspace = true
1416
thiserror.workspace = true
1517

1618
bzip2 = "0.6"

download-cef/src/lib.rs

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
#![doc = include_str!("../README.md")]
22

33
use bzip2::bufread::BzDecoder;
4+
use regex::Regex;
45
use semver::Version;
56
use serde::{Deserialize, Serialize};
67
use sha1_smol::Sha1;
78
use std::{
89
collections::HashMap,
910
fmt::{self, Display},
1011
fs::{self, File},
11-
io::{self, BufReader, IsTerminal},
12+
io::{self, BufReader, IsTerminal, Write},
1213
path::{Path, PathBuf},
1314
sync::{Mutex, OnceLock},
1415
};
@@ -40,6 +41,18 @@ pub enum Error {
4041
CorruptedFile(String),
4142
#[error("Invalid archive file path: {0}")]
4243
InvalidArchiveFile(String),
44+
#[error("JSON serialization error: {0}")]
45+
Json(#[from] serde_json::Error),
46+
#[error(
47+
"Undexpected archive version: location: {location} archive {archive} expected {expected}"
48+
)]
49+
VersionMismatch {
50+
location: String,
51+
archive: String,
52+
expected: String,
53+
},
54+
#[error("Invalid regex pattern: {0}")]
55+
InvalidRegexPattern(#[from] regex::Error),
4356
}
4457

4558
pub type Result<T> = std::result::Result<T, Error>;
@@ -59,20 +72,55 @@ pub const WINDOWS_TARGETS: &[&str] = &[
5972
];
6073

6174
pub fn default_version(version: &str) -> String {
62-
static VERSIONS: OnceLock<Mutex<HashMap<String, String>>> = OnceLock::new();
75+
unwrap_cef_version(version).unwrap_or_else(|_| version.to_string())
76+
}
77+
78+
fn unwrap_cef_version(version: &str) -> Result<String> {
79+
static VERSIONS: OnceLock<Mutex<HashMap<Version, String>>> = OnceLock::new();
6380
let mut versions = VERSIONS
6481
.get_or_init(Default::default)
6582
.lock()
6683
.expect("Lock error");
67-
versions
68-
.entry(version.to_string())
69-
.or_insert_with(|| {
70-
Version::parse(version)
71-
.ok()
72-
.and_then(|version| (!version.build.is_empty()).then(|| version.build.to_string()))
73-
.unwrap_or_else(|| version.to_string())
84+
Ok(versions
85+
.entry(Version::parse(version)?)
86+
.or_insert_with_key(|v| {
87+
if v.build.is_empty() {
88+
version.to_string()
89+
} else {
90+
v.build.to_string()
91+
}
7492
})
75-
.clone()
93+
.clone())
94+
}
95+
96+
pub fn check_archive_json(version: &str, location: &str) -> Result<()> {
97+
let expected = Version::parse(&unwrap_cef_version(version)?)?;
98+
99+
static PATTERN: OnceLock<core::result::Result<Regex, regex::Error>> = OnceLock::new();
100+
let pattern = PATTERN
101+
.get_or_init(|| Regex::new(r"^cef_binary_([^+]+)(:?\+.+)?$"))
102+
.as_ref()
103+
.map_err(Clone::clone)?;
104+
let archive_json: CefFile = serde_json::from_reader(File::open(archive_json_path(location))?)?;
105+
let archive_version = pattern.replace(&archive_json.name, "$1");
106+
let archive = Version::parse(&archive_version)?;
107+
108+
if archive == expected {
109+
Ok(())
110+
} else {
111+
Err(Error::VersionMismatch {
112+
location: location.to_string(),
113+
expected: expected.to_string(),
114+
archive: archive.to_string(),
115+
})
116+
}
117+
}
118+
119+
fn archive_json_path<P>(location: P) -> PathBuf
120+
where
121+
P: AsRef<Path>,
122+
{
123+
location.as_ref().join("archive.json")
76124
}
77125

78126
const URL: &str = "https://cef-builds.spotifycdn.com";
@@ -230,9 +278,19 @@ impl CefVersion {
230278
.find(|f| f.file_type == "minimal")
231279
.ok_or_else(|| Error::VersionNotFound(self.cef_version.clone()))
232280
}
281+
282+
pub fn write_archive_json<P>(&self, location: P) -> Result<()>
283+
where
284+
P: AsRef<Path>,
285+
{
286+
let archive_version = serde_json::to_string_pretty(self.minimal()?)?;
287+
let mut archive_json = File::create(archive_json_path(location))?;
288+
archive_json.write_all(archive_version.as_bytes())?;
289+
Ok(())
290+
}
233291
}
234292

235-
#[derive(Deserialize, Serialize)]
293+
#[derive(Eq, PartialEq, Deserialize, Serialize)]
236294
pub struct CefFile {
237295
#[serde(rename = "type")]
238296
pub file_type: String,

export-cef-dir/src/main.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@
22

33
use clap::Parser;
44
use download_cef::{CefIndex, OsAndArch, DEFAULT_TARGET};
5-
use std::{
6-
fs::{self, File},
7-
io::Write,
8-
path::PathBuf,
9-
sync::OnceLock,
10-
};
5+
use std::{fs, path::PathBuf, sync::OnceLock};
116

127
fn default_version() -> &'static str {
138
static DEFAULT_VERSION: OnceLock<String> = OnceLock::new();
@@ -91,11 +86,7 @@ fn main() -> anyhow::Result<()> {
9186
fs::remove_file(archive)?;
9287
}
9388

94-
{
95-
let archive_version = serde_json::to_string_pretty(version.minimal()?)?;
96-
let mut archive_json = File::create(extracted_dir.join("archive.json"))?;
97-
archive_json.write_all(archive_version.as_bytes())?;
98-
}
89+
version.write_archive_json(extracted_dir)?;
9990

10091
if output != cef_dir {
10192
println!("Renaming: {}", output.display());

sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ doctest = false
1616
dox = []
1717

1818
[package.metadata.docs.rs]
19-
features = [ "dox" ]
19+
features = ["dox"]
2020

2121
[build-dependencies]
2222
anyhow.workspace = true

sys/build.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
#[cfg(not(feature = "dox"))]
22
fn main() -> anyhow::Result<()> {
33
use download_cef::{CefIndex, OsAndArch};
4-
use std::{
5-
env,
6-
fs::{self, File},
7-
io::Write,
8-
path::PathBuf,
9-
};
4+
use std::{env, fs, path::PathBuf};
105

116
println!("cargo::rerun-if-changed=build.rs");
127

@@ -23,6 +18,7 @@ fn main() -> anyhow::Result<()> {
2318
Ok(cef_path) => {
2419
// Allow overriding the CEF path with environment variables.
2520
println!("Using CEF path from environment: {cef_path}");
21+
download_cef::check_archive_json(&env::var("CARGO_PKG_VERSION")?, &cef_path)?;
2622
PathBuf::from(cef_path)
2723
}
2824
Err(_) => {
@@ -45,9 +41,7 @@ fn main() -> anyhow::Result<()> {
4541
));
4642
}
4743

48-
let archive_version = serde_json::to_string_pretty(version.minimal()?)?;
49-
let mut archive_json = File::create(extracted_dir.join("archive.json"))?;
50-
archive_json.write_all(archive_version.as_bytes())?;
44+
version.write_archive_json(extracted_dir)?;
5145
}
5246

5347
cef_dir

0 commit comments

Comments
 (0)