mirror of
https://github.com/storytold/craft-libs.git
synced 2026-10-31 07:39:23 +00:00
craft-fonts-build: reject faces under a non-UTF-8 path instead of embedding a lossy include_bytes! path
This commit is contained in:
1 parent
d413913b6b
commit
a30ff6bf2f
2 files changed
+26
-5
No files matched your search
@@ -181,8 +181,9 @@ impl Embed {
|
||||
self.check_coverage(faces, dir, cargo);
|
||||
}
|
||||
}
|
||||
let (table, faces) = match selected {
|
||||
Ok(faces) => (table(&faces), faces.into_iter().map(|face| face.entry).collect()),
|
||||
let tabled = selected.and_then(|faces| Ok((table(&faces)?, faces.into_iter().map(|face| face.entry).collect())));
|
||||
let (table, faces) = match tabled {
|
||||
Ok(tabled) => tabled,
|
||||
Err(e) if required => {
|
||||
write(&out, EMPTY_TABLE)?;
|
||||
return Err(e);
|
||||
@@ -400,9 +401,12 @@ pub(crate) struct Env {
|
||||
pub out_dir: Option<OsString>,
|
||||
}
|
||||
|
||||
fn table(faces: &[Face]) -> String {
|
||||
/// The generated source; `include_bytes!` takes a string, so a face under a path that isn't UTF-8
|
||||
/// is an error rather than a lossy path the consumer's build can't find.
|
||||
fn table(faces: &[Face]) -> Result<String, Error> {
|
||||
let mut src = String::from("// Generated by craft-fonts-build. Do not edit.\n&[\n");
|
||||
for Face { entry, path, index, .. } in faces {
|
||||
let file = path.to_str().ok_or_else(|| Error::NonUtf8Path { path: path.clone() })?;
|
||||
let scripts: Vec<String> = entry.scripts.iter().map(|s| format!("{s:?}")).collect();
|
||||
let _ = writeln!(
|
||||
src,
|
||||
@@ -411,11 +415,11 @@ fn table(faces: &[Face]) -> String {
|
||||
entry.style,
|
||||
scripts.join(", "),
|
||||
index,
|
||||
path.display().to_string(),
|
||||
file,
|
||||
);
|
||||
}
|
||||
src.push_str("]\n");
|
||||
src
|
||||
Ok(src)
|
||||
}
|
||||
|
||||
fn write(path: &Path, contents: &str) -> Result<(), Error> {
|
||||
@@ -446,6 +450,8 @@ pub enum Error {
|
||||
Subset { path: PathBuf, reason: String },
|
||||
/// [`Embed::documents`] names families the manifest lacks; `known` lists the manifest's.
|
||||
UnknownFamilies { manifest: PathBuf, families: Vec<String>, known: Vec<String> },
|
||||
/// A face to embed has a path that isn't UTF-8, which `include_bytes!` can't name.
|
||||
NonUtf8Path { path: PathBuf },
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
@@ -477,6 +483,7 @@ impl fmt::Display for Error {
|
||||
families.join(", "),
|
||||
known.join(", ")
|
||||
),
|
||||
Self::NonUtf8Path { path } => write!(f, "cannot embed {}: include_bytes! needs a UTF-8 path", path.display()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,20 @@ fn required_fails_without_a_usable_checkout() {
|
||||
assert!(matches!(run(Embed::new(), Some(&scratch.0), Some("1")).result, Err(Error::NoFaces { .. })));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn rejects_a_checkout_under_a_non_utf8_path() {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
let scratch = Scratch::new("non-utf8");
|
||||
let dir = scratch.0.join(std::ffi::OsStr::from_bytes(b"craft-fonts-\xff"));
|
||||
std::fs::create_dir_all(dir.join("fonts")).unwrap();
|
||||
std::fs::copy(fixture().join("fonts/sans-arabic/SansArabic.ttf"), dir.join("fonts/a.ttf")).unwrap();
|
||||
std::fs::write(dir.join("fonts/manifest.txt"), "A | Regular | fonts/a.ttf | Arab | OFL-1.1 | OFL.txt | 00 | src\n").unwrap();
|
||||
let r = run(Embed::new(), Some(&dir), Some("1"));
|
||||
assert!(matches!(r.result, Err(Error::NonUtf8Path { .. })), "{:?}", r.result);
|
||||
assert_eq!(r.table.trim(), "&[]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn embeds_the_selected_scripts() {
|
||||
let r = run(Embed::new(), Some(&fixture()), Some("1"));
|
||||
|
||||
Reference in new issue
Block a user