Skip to content

Commit b071768

Browse files
committed
Fix Windows CRLF Issue
Cargo configs are injected as a literal string which, on Windows, can end up with escaped CRLF line endings in cargo-bazel.json causing the digests to be different on mac/windows. This parses the inner string literal to prevent platform specific differences.
1 parent b0daae0 commit b071768

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

crate_universe/src/config.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,13 +706,34 @@ pub(crate) struct Config {
706706
pub(crate) rendering: RenderConfig,
707707

708708
/// The contents of a Cargo configuration file
709+
#[serde(default, deserialize_with = "deserialize_cargo_config")]
709710
pub(crate) cargo_config: Option<toml::Value>,
710711

711712
/// A set of platform triples to use in generated select statements
712713
#[serde(default, skip_serializing_if = "BTreeSet::is_empty")]
713714
pub(crate) supported_platform_triples: BTreeSet<TargetTriple>,
714715
}
715716

717+
// rules_rust/crate_universe/private/generate_utils.bzl:generate_config
718+
// injects the cargo_config as a literal JSON string, this causes line ending
719+
// instability in Unix vs Windows. Parsing it here fixes any cross platform differences.
720+
fn deserialize_cargo_config<'de, D>(deserializer: D) -> Result<Option<toml::Value>, D::Error>
721+
where
722+
D: serde::Deserializer<'de>,
723+
{
724+
let value: Option<serde_json::Value> = Option::deserialize(deserializer)?;
725+
match value {
726+
None | Some(serde_json::Value::Null) => Ok(None),
727+
Some(serde_json::Value::String(s)) => s
728+
.parse::<toml::Value>()
729+
.map(Some)
730+
.map_err(serde::de::Error::custom),
731+
Some(other) => serde_json::from_value(other)
732+
.map(Some)
733+
.map_err(serde::de::Error::custom),
734+
}
735+
}
736+
716737
impl Config {
717738
pub(crate) fn try_from_path<T: AsRef<Path>>(path: T) -> Result<Self> {
718739
let data = fs::read_to_string(path)?;

crate_universe/src/lockfile.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,4 +376,57 @@ mod test {
376376
digest,
377377
);
378378
}
379+
380+
#[test]
381+
fn digest_stable_with_crlf_cargo_config() {
382+
let context = Context::default();
383+
let splicing_metadata = SplicingMetadata::default();
384+
385+
let json_config = |cargo_config: &str| {
386+
serde_json::to_string(&serde_json::json!({
387+
"generate_binaries": false,
388+
"generate_build_scripts": false,
389+
"cargo_config": cargo_config,
390+
"rendering": {
391+
"repository_name": "test",
392+
"regen_command": "//test",
393+
"generate_cargo_toml_env_vars": true
394+
}
395+
}))
396+
.unwrap()
397+
};
398+
399+
let config_crlf: Config = serde_json::from_str(&json_config(
400+
"[registries.my-registry]\r\nindex = \"sparse+https://example.com/\"",
401+
))
402+
.unwrap();
403+
404+
let config_lf: Config = serde_json::from_str(&json_config(
405+
"[registries.my-registry]\nindex = \"sparse+https://example.com/\"",
406+
))
407+
.unwrap();
408+
409+
let digest_crlf = Digest::compute(
410+
&context,
411+
&config_crlf,
412+
&splicing_metadata,
413+
"0.1.0",
414+
"cargo 1.57.0 (b2e52d7ca 2021-10-21)",
415+
"rustc 1.57.0 (f1edd0429 2021-11-29)",
416+
);
417+
418+
let digest_lf = Digest::compute(
419+
&context,
420+
&config_lf,
421+
&splicing_metadata,
422+
"0.1.0",
423+
"cargo 1.57.0 (b2e52d7ca 2021-10-21)",
424+
"rustc 1.57.0 (f1edd0429 2021-11-29)",
425+
);
426+
427+
assert_eq!(
428+
digest_crlf, digest_lf,
429+
"Digests should be identical regardless of CRLF vs LF line endings in cargo_config"
430+
);
431+
}
379432
}

0 commit comments

Comments
 (0)