mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Exports: say that an encrypted PDF still differs, and test the fallback
Two review points on #2880. The reproducibility claim needed qualifying. PDF encryption draws its AES initialisation vectors and the file `/ID` from a random seed, which `SOURCE_DATE_EPOCH` deliberately does not reach, so a PDF exported with a password never repeats however the variable is set. The docs and the ROADMAP line say so now. The byte-identity test passes an explicit `created`, so it never exercised the clock-or-variable fallback. `pinned_or` takes the environment and the clock as arguments, and the new test shows the variable is preferred, that a blank, negative or non-numeric value leaves it to the clock, and that a host with neither has no date to record. The environment is injected rather than set: a test that changes this process's environment is `unsafe` under edition 2024 and would reach every other test running beside it, which is why `cursor_theme` takes a lookup closure too.
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
@@ -90,7 +90,13 @@ impl DocMetadata {
|
||||
/// The raw clock stays in [`now_unix`], which is what a heartbeat is judged by and what seeds
|
||||
/// encryption: neither may be pinned by the environment.
|
||||
pub fn output_time() -> Option<i64> {
|
||||
stamp_from_env(|n| std::env::var(n).ok()).or_else(now_unix)
|
||||
pinned_or(|n| std::env::var(n).ok(), now_unix)
|
||||
}
|
||||
|
||||
/// [`output_time`] with the environment and the clock supplied, so a test can show that the
|
||||
/// variable is preferred and that the clock answers whenever it does not.
|
||||
fn pinned_or(get: impl Fn(&str) -> Option<String>, clock: impl Fn() -> Option<i64>) -> Option<i64> {
|
||||
stamp_from_env(get).or_else(clock)
|
||||
}
|
||||
|
||||
/// `SOURCE_DATE_EPOCH` as Unix seconds: the reproducible-builds variable
|
||||
@@ -184,4 +190,21 @@ mod tests {
|
||||
assert_eq!(stamp_from_env(|_| Some("1791208980".to_owned())), Some(1_791_208_980));
|
||||
assert_eq!(stamp_from_env(|n: &str| (n == "TZ").then(|| "1791208980".to_owned())), None);
|
||||
}
|
||||
|
||||
/// What a file records: the variable when it is usable, the clock whenever it is not. The
|
||||
/// environment and the clock are passed in, so no test changes this process's environment --
|
||||
/// that is `unsafe` under edition 2024 and would reach every other test running beside it.
|
||||
#[test]
|
||||
fn a_pinned_epoch_is_preferred_and_the_clock_answers_otherwise() {
|
||||
let env = |v: Option<&'static str>| move |_: &str| v.map(str::to_owned);
|
||||
let clock = || Some(1_000_000);
|
||||
assert_eq!(pinned_or(env(Some("1791208980")), clock), Some(1_791_208_980), "the variable wins over the clock");
|
||||
assert_eq!(pinned_or(env(Some("0")), clock), Some(0), "including the epoch itself");
|
||||
for ignored in [None, Some(""), Some("-1"), Some("later")] {
|
||||
assert_eq!(pinned_or(env(ignored), clock), Some(1_000_000), "{ignored:?} leaves it to the clock");
|
||||
}
|
||||
// A platform with no clock and no variable has no date to record.
|
||||
assert_eq!(pinned_or(env(None), || None), None);
|
||||
assert_eq!(pinned_or(env(Some("1791208980")), || None), Some(1_791_208_980), "the variable needs no clock");
|
||||
}
|
||||
}
|
||||
|
||||
+6
-3
@@ -836,9 +836,12 @@ SOURCE_DATE_EPOCH=1791208980 vectorcraft-cli run --cmd file.new --params '{}' --
|
||||
|
||||
A command that takes its own date (`file.new {created}`, a save's `modified`) still wins over the
|
||||
variable. A blank, negative or non-numeric value is ignored and the clock decides, so an export is
|
||||
never refused over the environment. The variable does not reach the recovery heartbeat or the
|
||||
random seed PDF encryption draws on, which must follow the real clock. SVG output carries no time
|
||||
and was already reproducible.
|
||||
never refused over the environment. SVG output carries no time and was already reproducible.
|
||||
|
||||
Two things stay on the real clock and are not pinned by the variable: the recovery heartbeat, and
|
||||
the random seed PDF encryption draws on. **A PDF exported with a password therefore still differs
|
||||
between runs** whatever `SOURCE_DATE_EPOCH` says, because that seed supplies its AES
|
||||
initialisation vectors and its file `/ID`. Reproducible output means an unencrypted export.
|
||||
|
||||
### Parameter keys
|
||||
|
||||
|
||||
Reference in New Issue
Block a user