Skip to content

Commit 697a206

Browse files
committed
refactor: env_config supports resolve case insensitive env.
1 parent ab9438f commit 697a206

File tree

4 files changed

+55
-39
lines changed

4 files changed

+55
-39
lines changed

src/cargo/core/compiler/fingerprint/dep_info.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
//! [the documentation]: crate::core::compiler::fingerprint#dep-info-files
55
66
use std::collections::HashMap;
7-
use std::ffi::OsString;
87
use std::fmt;
98
use std::io;
109
use std::io::Read;
@@ -19,6 +18,7 @@ use cargo_util::paths;
1918
use cargo_util::ProcessBuilder;
2019
use cargo_util::Sha256;
2120

21+
use crate::util::context::EnvConfigResolved;
2222
use crate::CargoResult;
2323
use crate::CARGO_ENV;
2424

@@ -294,7 +294,7 @@ pub fn translate_dep_info(
294294
target_root: &Path,
295295
rustc_cmd: &ProcessBuilder,
296296
allow_package: bool,
297-
env_config: &Arc<HashMap<String, OsString>>,
297+
env_config: &Arc<EnvConfigResolved>,
298298
) -> CargoResult<()> {
299299
let depinfo = parse_rustc_dep_info(rustc_dep_info)?;
300300

@@ -334,7 +334,9 @@ pub fn translate_dep_info(
334334
//
335335
// For cargo#13280, We trace env vars that are defined in the `[env]` config table.
336336
on_disk_info.env.retain(|(key, _)| {
337-
env_config.contains_key(key) || !rustc_cmd.get_envs().contains_key(key) || key == CARGO_ENV
337+
env_config.env.contains_key(key)
338+
|| !rustc_cmd.get_envs().contains_key(key)
339+
|| key == CARGO_ENV
338340
});
339341

340342
let serialize_path = |file| {

src/cargo/core/compiler/fingerprint/mod.rs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,8 @@
362362
mod dep_info;
363363
mod dirty_reason;
364364

365-
use std::cell::OnceCell;
366365
use std::collections::hash_map::{Entry, HashMap};
367366
use std::env;
368-
use std::ffi::OsString;
369367
use std::fs;
370368
use std::fs::File;
371369
use std::hash::{self, Hash, Hasher};
@@ -382,10 +380,12 @@ use serde::de;
382380
use serde::ser;
383381
use serde::{Deserialize, Serialize};
384382
use tracing::{debug, info};
383+
use unicase::Ascii as UncasedAscii;
385384

386385
use crate::core::compiler::unit_graph::UnitDep;
387386
use crate::core::Package;
388387
use crate::util;
388+
use crate::util::context::EnvConfigResolved;
389389
use crate::util::errors::CargoResult;
390390
use crate::util::interning::InternedString;
391391
use crate::util::{internal, path_args, StableHasher};
@@ -799,33 +799,25 @@ impl LocalFingerprint {
799799
/// Read the environment variable of the given env `key`, and creates a new
800800
/// [`LocalFingerprint::RerunIfEnvChanged`] for it.
801801
#[allow(clippy::disallowed_methods)]
802-
fn from_env<K: AsRef<str>>(
803-
key: K,
804-
env_config: &Arc<HashMap<String, OsString>>,
805-
env_config_insensitive: &Arc<OnceCell<HashMap<String, OsString>>>,
806-
) -> LocalFingerprint {
802+
fn from_env<K: AsRef<str>>(key: K, env_config: &Arc<EnvConfigResolved>) -> LocalFingerprint {
807803
let key = key.as_ref();
808804
let var = key.to_owned();
809-
let val = if let Some(val) = match env_config.get(key) {
810-
Some(value) => value.to_str().map(|s| str::to_string(s)),
811-
None => {
812-
if cfg!(windows) {
813-
let env_config_insensitive = env_config_insensitive.get_or_init(|| {
814-
env_config
815-
.iter()
816-
.map(|(k, v)| (k.to_uppercase().clone(), v.clone()))
817-
.collect()
818-
});
819-
let val = env_config_insensitive
820-
.get(&key.to_uppercase())
821-
.and_then(|s| s.to_str().map(|s| str::to_string(s)));
822-
823-
val
824-
} else {
825-
None
805+
let val = if let Some(val) =
806+
match env_config.env.get(key) {
807+
Some(value) => value.to_str().map(|s| str::to_string(s)),
808+
None => {
809+
if cfg!(windows) {
810+
let val = env_config.case_insensitive_env.as_ref().and_then(
811+
|case_insensitive_env| {
812+
case_insensitive_env.get(&UncasedAscii::new(str::to_string(key)))
813+
},
814+
);
815+
val.and_then(|s| s.to_str().map(|s| str::to_string(s)))
816+
} else {
817+
None
818+
}
826819
}
827-
}
828-
} {
820+
} {
829821
Some(val)
830822
} else {
831823
env::var(key).ok()
@@ -874,7 +866,7 @@ impl LocalFingerprint {
874866
)
875867
})?)
876868
} else {
877-
if let Some(value) = gctx.env_config()?.get(key) {
869+
if let Some(value) = gctx.env_config()?.env.get(key) {
878870
value.to_str()
879871
} else {
880872
gctx.get_env(key).ok()
@@ -1797,7 +1789,7 @@ fn local_fingerprints_deps(
17971789
deps: &BuildDeps,
17981790
target_root: &Path,
17991791
pkg_root: &Path,
1800-
env_config: &Arc<HashMap<String, OsString>>,
1792+
env_config: &Arc<EnvConfigResolved>,
18011793
) -> Vec<LocalFingerprint> {
18021794
debug!("new local fingerprints deps {:?}", pkg_root);
18031795
let mut local = Vec::new();
@@ -1818,11 +1810,10 @@ fn local_fingerprints_deps(
18181810
.collect();
18191811
local.push(LocalFingerprint::RerunIfChanged { output, paths });
18201812
}
1821-
let env_config_insensitive = Arc::new(OnceCell::new());
18221813
local.extend(
18231814
deps.rerun_if_env_changed
18241815
.iter()
1825-
.map(|s| LocalFingerprint::from_env(s, env_config, &env_config_insensitive)),
1816+
.map(|s| LocalFingerprint::from_env(s, env_config)),
18261817
);
18271818

18281819
local

src/cargo/core/compiler/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1983,7 +1983,7 @@ pub(crate) fn apply_env_config(
19831983
gctx: &crate::GlobalContext,
19841984
cmd: &mut ProcessBuilder,
19851985
) -> CargoResult<()> {
1986-
for (key, value) in gctx.env_config()?.iter() {
1986+
for (key, value) in gctx.env_config()?.env.iter() {
19871987
// never override a value that has already been set by cargo
19881988
if cmd.get_envs().contains_key(key) {
19891989
continue;

src/cargo/util/context/mod.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ use serde::Deserialize;
9191
use serde_untagged::UntaggedEnumVisitor;
9292
use time::OffsetDateTime;
9393
use toml_edit::Item;
94+
use unicase::Ascii as UncasedAscii;
9495
use url::Url;
9596

9697
mod de;
@@ -227,7 +228,7 @@ pub struct GlobalContext {
227228
target_cfgs: LazyCell<Vec<(String, TargetCfgConfig)>>,
228229
doc_extern_map: LazyCell<RustdocExternMap>,
229230
progress_config: ProgressConfig,
230-
env_config: LazyCell<Arc<HashMap<String, OsString>>>,
231+
env_config: LazyCell<Arc<EnvConfigResolved>>,
231232
/// This should be false if:
232233
/// - this is an artifact of the rustc distribution process for "stable" or for "beta"
233234
/// - this is an `#[test]` that does not opt in with `enable_nightly_features`
@@ -1835,7 +1836,7 @@ impl GlobalContext {
18351836

18361837
/// Get the env vars from the config `[env]` table which
18371838
/// are `force = true` or don't exist in the env snapshot [`GlobalContext::get_env`].
1838-
pub fn env_config(&self) -> CargoResult<&Arc<HashMap<String, OsString>>> {
1839+
pub fn env_config(&self) -> CargoResult<&Arc<EnvConfigResolved>> {
18391840
let env_config = self.env_config.try_borrow_with(|| {
18401841
CargoResult::Ok(Arc::new({
18411842
let env_config = self.get::<EnvConfig>("env")?;
@@ -1862,7 +1863,7 @@ impl GlobalContext {
18621863
);
18631864
}
18641865
}
1865-
env_config
1866+
let env_config: HashMap<String, OsString> = env_config
18661867
.into_iter()
18671868
.filter_map(|(k, v)| {
18681869
if v.is_force() || self.get_env_os(&k).is_none() {
@@ -1871,7 +1872,23 @@ impl GlobalContext {
18711872
None
18721873
}
18731874
})
1874-
.collect()
1875+
.collect();
1876+
EnvConfigResolved {
1877+
case_insensitive_env: {
1878+
if cfg!(windows) {
1879+
Some(
1880+
env_config
1881+
.clone()
1882+
.into_iter()
1883+
.map(|(k, v)| (UncasedAscii::new(k), v))
1884+
.collect(),
1885+
)
1886+
} else {
1887+
None
1888+
}
1889+
},
1890+
env: env_config,
1891+
}
18751892
}))
18761893
})?;
18771894

@@ -2867,7 +2884,13 @@ impl EnvConfigValue {
28672884
}
28682885
}
28692886

2870-
pub type EnvConfig = HashMap<String, EnvConfigValue>;
2887+
type EnvConfig = HashMap<String, EnvConfigValue>;
2888+
2889+
#[derive(Debug)]
2890+
pub struct EnvConfigResolved {
2891+
pub case_insensitive_env: Option<HashMap<UncasedAscii<String>, OsString>>,
2892+
pub env: HashMap<String, OsString>,
2893+
}
28712894

28722895
fn parse_document(toml: &str, _file: &Path, _gctx: &GlobalContext) -> CargoResult<toml::Table> {
28732896
// At the moment, no compatibility checks are needed.

0 commit comments

Comments
 (0)