Skip to content

Commit 4abe7e9

Browse files
Nemo157jyn514
authored andcommitted
More precise rerun-if-changed tracking
Ensure that all files grass attempts to load get tracked, and simplify other file tracking
1 parent c655f83 commit 4abe7e9

File tree

2 files changed

+88
-23
lines changed

2 files changed

+88
-23
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ string_cache_codegen = "0.5.1"
122122
walkdir = "2"
123123
anyhow = { version = "1.0.42", features = ["backtrace"] }
124124
grass = { version = "0.11.0", default-features = false }
125+
once_cell = { version = "1.4.0", features = ["parking_lot"] }
125126

126127
[[bench]]
127128
name = "compression"

build.rs

+87-23
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,70 @@ use anyhow::{Context as _, Error, Result};
22
use git2::Repository;
33
use std::{env, path::Path};
44

5+
mod tracked {
6+
use once_cell::sync::Lazy;
7+
use std::{
8+
collections::HashSet,
9+
io::{Error, ErrorKind, Result},
10+
path::{Path, PathBuf},
11+
sync::Mutex,
12+
};
13+
14+
static SEEN: Lazy<Mutex<HashSet<PathBuf>>> = Lazy::new(|| Mutex::new(HashSet::new()));
15+
16+
pub(crate) fn track(path: impl AsRef<Path>) -> Result<()> {
17+
let path = path.as_ref();
18+
if path.exists() {
19+
let mut seen = SEEN.lock().unwrap();
20+
// TODO: Needs something like `HashSet::insert_owned` to check before cloning
21+
// https://github.com/rust-lang/rust/issues/60896
22+
if !seen.contains(path) {
23+
seen.insert(path.to_owned());
24+
let path = path.to_str().ok_or_else(|| {
25+
Error::new(
26+
ErrorKind::Other,
27+
format!("{} is a non-utf-8 path", path.display()),
28+
)
29+
})?;
30+
println!("cargo:rerun-if-changed={path}");
31+
}
32+
} else if let Some(parent) = path.parent() {
33+
// if the file doesn't exist, we need to notice if it begins existing
34+
track(parent)?;
35+
}
36+
Ok(())
37+
}
38+
39+
pub(crate) fn read(path: impl AsRef<Path>) -> Result<Vec<u8>> {
40+
let path = path.as_ref();
41+
track(path)?;
42+
std::fs::read(path)
43+
}
44+
45+
pub(crate) fn read_to_string(path: impl AsRef<Path>) -> Result<String> {
46+
let path = path.as_ref();
47+
track(path)?;
48+
std::fs::read_to_string(path)
49+
}
50+
51+
#[derive(Debug)]
52+
pub(crate) struct Fs;
53+
54+
impl grass::Fs for Fs {
55+
fn is_dir(&self, path: &Path) -> bool {
56+
track(path).unwrap();
57+
path.is_dir()
58+
}
59+
fn is_file(&self, path: &Path) -> bool {
60+
track(path).unwrap();
61+
path.is_file()
62+
}
63+
fn read(&self, path: &Path) -> Result<Vec<u8>> {
64+
read(path)
65+
}
66+
}
67+
}
68+
569
fn main() -> Result<()> {
670
let out_dir = env::var("OUT_DIR").context("missing OUT_DIR")?;
771
let out_dir = Path::new(&out_dir);
@@ -22,10 +86,6 @@ fn write_git_version(out_dir: &Path) -> Result<()> {
2286
format!("({} {})", git_hash, build_date),
2387
)?;
2488

25-
// TODO: are these right?
26-
println!("cargo:rerun-if-changed=.git/HEAD");
27-
println!("cargo:rerun-if-changed=.git/index");
28-
2989
Ok(())
3090
}
3191

@@ -34,6 +94,10 @@ fn get_git_hash() -> Result<Option<String>> {
3494
Ok(repo) => {
3595
let head = repo.head()?;
3696

97+
// TODO: are these right?
98+
tracked::track(".git/HEAD")?;
99+
tracked::track(".git/index")?;
100+
37101
Ok(head.target().map(|h| {
38102
let mut h = format!("{}", h);
39103
h.truncate(7);
@@ -51,7 +115,9 @@ fn compile_sass_file(src: &Path, dest: &Path) -> Result<()> {
51115
let css = grass::from_path(
52116
src.to_str()
53117
.context("source file path must be a utf-8 string")?,
54-
&grass::Options::default().style(grass::OutputStyle::Compressed),
118+
&grass::Options::default()
119+
.fs(&tracked::Fs)
120+
.style(grass::OutputStyle::Compressed),
55121
)
56122
.map_err(|e| Error::msg(e.to_string()))?;
57123

@@ -65,29 +131,27 @@ fn compile_sass(out_dir: &Path) -> Result<()> {
65131

66132
for entry in walkdir::WalkDir::new(STYLE_DIR) {
67133
let entry = entry?;
68-
println!(
69-
"cargo:rerun-if-changed={}",
70-
entry
71-
.path()
134+
if entry.metadata()?.is_dir() {
135+
tracked::track(entry.path())?;
136+
} else {
137+
let file_name = entry
138+
.file_name()
72139
.to_str()
73-
.with_context(|| format!("{} is a non-utf-8 path", entry.path().display()))?
74-
);
75-
let file_name = entry.file_name().to_str().unwrap();
76-
if entry.metadata()?.is_file() && !file_name.starts_with('_') {
77-
let dest = out_dir
78-
.join(entry.path().strip_prefix(STYLE_DIR)?)
79-
.with_extension("css");
80-
compile_sass_file(entry.path(), &dest).with_context(|| {
81-
format!("compiling {} to {}", entry.path().display(), dest.display())
82-
})?;
140+
.context("file name must be a utf-8 string")?;
141+
if !file_name.starts_with('_') {
142+
let dest = out_dir
143+
.join(entry.path().strip_prefix(STYLE_DIR)?)
144+
.with_extension("css");
145+
compile_sass_file(entry.path(), &dest).with_context(|| {
146+
format!("compiling {} to {}", entry.path().display(), dest.display())
147+
})?;
148+
}
83149
}
84150
}
85151

86152
// Compile vendored.css
87-
println!("cargo:rerun-if-changed=vendor/pure-css/css/pure-min.css");
88-
let pure = std::fs::read_to_string("vendor/pure-css/css/pure-min.css")?;
89-
println!("cargo:rerun-if-changed=vendor/pure-css/css/grids-responsive-min.css");
90-
let grids = std::fs::read_to_string("vendor/pure-css/css/grids-responsive-min.css")?;
153+
let pure = tracked::read_to_string("vendor/pure-css/css/pure-min.css")?;
154+
let grids = tracked::read_to_string("vendor/pure-css/css/grids-responsive-min.css")?;
91155
let vendored = pure + &grids;
92156
std::fs::write(out_dir.join("vendored").with_extension("css"), vendored)?;
93157

0 commit comments

Comments
 (0)