Skip to content

Commit 84a80d8

Browse files
committed
Use new config API.
Also, require "override" feature if used in a config.
1 parent 2f7b522 commit 84a80d8

File tree

4 files changed

+136
-188
lines changed

4 files changed

+136
-188
lines changed

src/cargo/core/profiles.rs

Lines changed: 31 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
use std::collections::{HashMap, HashSet};
2-
use std::sync::atomic;
1+
use std::collections::HashSet;
32
use std::{cmp, fmt, hash};
43

54
use core::compiler::CompileMode;
65
use core::interning::InternedString;
76
use core::{Features, PackageId, PackageIdSpec, PackageSet, Shell};
7+
use util::errors::CargoResultExt;
88
use util::lev_distance::lev_distance;
99
use util::toml::{ProfilePackageSpec, StringOrBool, TomlProfile, TomlProfiles, U32OrBool};
10-
use util::{CargoResult, Config, ConfigValue};
10+
use util::{CargoResult, Config};
1111

1212
/// Collection of all user profiles.
1313
#[derive(Clone, Debug)]
@@ -29,18 +29,20 @@ impl Profiles {
2929
if let Some(profiles) = profiles {
3030
profiles.validate(features, warnings)?;
3131
}
32-
Profiles::validate_config(config, warnings)?;
32+
33+
let config_profiles = config.profiles()?;
34+
config_profiles.validate(features, warnings)?;
3335

3436
Ok(Profiles {
3537
dev: ProfileMaker {
3638
default: Profile::default_dev(),
3739
toml: profiles.and_then(|p| p.dev.clone()),
38-
config: TomlProfile::from_config(config, "dev", warnings)?,
40+
config: config_profiles.dev.clone(),
3941
},
4042
release: ProfileMaker {
4143
default: Profile::default_release(),
4244
toml: profiles.and_then(|p| p.release.clone()),
43-
config: TomlProfile::from_config(config, "release", warnings)?,
45+
config: config_profiles.release.clone(),
4446
},
4547
test: ProfileMaker {
4648
default: Profile::default_test(),
@@ -137,71 +139,6 @@ impl Profiles {
137139
self.doc.validate_packages(shell, packages)?;
138140
Ok(())
139141
}
140-
141-
fn validate_config(config: &Config, warnings: &mut Vec<String>) -> CargoResult<()> {
142-
static VALIDATE_ONCE: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;
143-
144-
if VALIDATE_ONCE.swap(true, atomic::Ordering::SeqCst) {
145-
return Ok(());
146-
}
147-
148-
// cv: Value<HashMap<String, CV>>
149-
if let Some(cv) = config.get_table("profile")? {
150-
// Warn if config profiles without CLI option.
151-
if !config.cli_unstable().config_profile {
152-
warnings.push(format!(
153-
"profile in config `{}` requires `-Z config-profile` command-line option",
154-
cv.definition
155-
));
156-
// Ignore the rest.
157-
return Ok(());
158-
}
159-
// Warn about unsupported profile names.
160-
for (key, profile_cv) in cv.val.iter() {
161-
if key != "dev" && key != "release" {
162-
warnings.push(format!(
163-
"profile `{}` in config `{}` is not supported",
164-
key,
165-
profile_cv.definition_path().display()
166-
));
167-
}
168-
}
169-
// Warn about incorrect key names.
170-
for profile_cv in cv.val.values() {
171-
if let ConfigValue::Table(ref profile, _) = *profile_cv {
172-
validate_profile_keys(profile, warnings);
173-
if let Some(&ConfigValue::Table(ref bo_profile, _)) =
174-
profile.get("build-override")
175-
{
176-
validate_profile_keys(bo_profile, warnings);
177-
}
178-
if let Some(&ConfigValue::Table(ref os, _)) = profile.get("overrides") {
179-
for o_profile_cv in os.values() {
180-
if let ConfigValue::Table(ref o_profile, _) = *o_profile_cv {
181-
validate_profile_keys(o_profile, warnings);
182-
}
183-
}
184-
}
185-
}
186-
}
187-
}
188-
return Ok(());
189-
190-
fn validate_profile_keys(
191-
profile: &HashMap<String, ConfigValue>,
192-
warnings: &mut Vec<String>,
193-
) {
194-
for (key, value_cv) in profile.iter() {
195-
if !TOML_PROFILE_KEYS.iter().any(|k| k == key) {
196-
warnings.push(format!(
197-
"unused profile key `{}` in config `{}`",
198-
key,
199-
value_cv.definition_path().display()
200-
));
201-
}
202-
}
203-
}
204-
}
205142
}
206143

207144
/// An object used for handling the profile override hierarchy.
@@ -449,20 +386,6 @@ pub struct Profile {
449386
pub panic: Option<InternedString>,
450387
}
451388

452-
const TOML_PROFILE_KEYS: [&str; 11] = [
453-
"opt-level",
454-
"lto",
455-
"codegen-units",
456-
"debug",
457-
"debug-assertions",
458-
"rpath",
459-
"panic",
460-
"overflow-checks",
461-
"incremental",
462-
"overrides",
463-
"build-override",
464-
];
465-
466389
impl Default for Profile {
467390
fn default() -> Profile {
468391
Profile {
@@ -605,3 +528,26 @@ impl ProfileFor {
605528
&ALL
606529
}
607530
}
531+
532+
/// Profiles loaded from .cargo/config files.
533+
#[derive(Clone, Debug, Deserialize, Default)]
534+
pub struct ConfigProfiles {
535+
dev: Option<TomlProfile>,
536+
release: Option<TomlProfile>,
537+
}
538+
539+
impl ConfigProfiles {
540+
pub fn validate(&self, features: &Features, warnings: &mut Vec<String>) -> CargoResult<()> {
541+
if let Some(ref profile) = self.dev {
542+
profile
543+
.validate("dev", features, warnings)
544+
.chain_err(|| format_err!("config profile `profile.dev` is not valid"))?;
545+
}
546+
if let Some(ref profile) = self.release {
547+
profile
548+
.validate("release", features, warnings)
549+
.chain_err(|| format_err!("config profile `profile.release` is not valid"))?;
550+
}
551+
Ok(())
552+
}
553+
}

src/cargo/util/config.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use lazycell::LazyCell;
2222
use serde::{de, de::IntoDeserializer, Serialize, Serializer};
2323
use toml;
2424

25+
use core::profiles::ConfigProfiles;
2526
use core::shell::Verbosity;
2627
use core::{CliUnstable, Shell, SourceId, Workspace};
2728
use ops;
@@ -77,6 +78,8 @@ pub struct Config {
7778
target_dir: Option<Filesystem>,
7879
/// Environment variables, separated to assist testing.
7980
env: HashMap<String, String>,
81+
/// Profiles loaded from config.
82+
profiles: LazyCell<ConfigProfiles>,
8083
}
8184

8285
impl Config {
@@ -132,6 +135,7 @@ impl Config {
132135
creation_time: Instant::now(),
133136
target_dir: None,
134137
env,
138+
profiles: LazyCell::new(),
135139
}
136140
}
137141

@@ -246,6 +250,25 @@ impl Config {
246250
.map(AsRef::as_ref)
247251
}
248252

253+
pub fn profiles(&self) -> CargoResult<&ConfigProfiles> {
254+
self.profiles.try_borrow_with(|| {
255+
let ocp = self.get::<Option<ConfigProfiles>>("profile")?;
256+
if let Some(config_profiles) = ocp {
257+
// Warn if config profiles without CLI option.
258+
if !self.cli_unstable().config_profile {
259+
self.shell().warn(
260+
"profiles in config files require `-Z config-profile` \
261+
command-line option",
262+
)?;
263+
return Ok(ConfigProfiles::default());
264+
}
265+
Ok(config_profiles)
266+
} else {
267+
Ok(ConfigProfiles::default())
268+
}
269+
})
270+
}
271+
249272
pub fn values(&self) -> CargoResult<&HashMap<String, ConfigValue>> {
250273
self.values.try_borrow_with(|| self.load_values())
251274
}
@@ -1380,7 +1403,7 @@ impl ConfigValue {
13801403
}
13811404
}
13821405

1383-
pub fn into_toml(self) -> toml::Value {
1406+
fn into_toml(self) -> toml::Value {
13841407
match self {
13851408
CV::Boolean(s, _) => toml::Value::Boolean(s),
13861409
CV::String(s, _) => toml::Value::String(s),
@@ -1425,6 +1448,7 @@ impl ConfigValue {
14251448
};
14261449
}
14271450
}
1451+
// Allow switching types except for tables or arrays.
14281452
(expected @ &mut CV::List(_, _), found)
14291453
| (expected @ &mut CV::Table(_, _), found)
14301454
| (expected, found @ CV::List(_, _))

src/cargo/util/toml/mod.rs

Lines changed: 9 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::path::{Path, PathBuf};
55
use std::rc::Rc;
66
use std::str;
77

8-
use failure::Error;
98
use semver::{self, VersionReq};
109
use serde::de::{self, Deserialize};
1110
use serde::ser;
@@ -22,7 +21,7 @@ use core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, WorkspaceRoot
2221
use sources::CRATES_IO;
2322
use util::errors::{CargoError, CargoResult, CargoResultExt};
2423
use util::paths;
25-
use util::{self, Config, ConfigValue, ToUrl};
24+
use util::{self, Config, ToUrl};
2625

2726
mod targets;
2827
use self::targets::targets;
@@ -248,19 +247,19 @@ pub struct TomlProfiles {
248247
impl TomlProfiles {
249248
pub fn validate(&self, features: &Features, warnings: &mut Vec<String>) -> CargoResult<()> {
250249
if let Some(ref test) = self.test {
251-
test.validate("test", Some(features), warnings)?;
250+
test.validate("test", features, warnings)?;
252251
}
253252
if let Some(ref doc) = self.doc {
254-
doc.validate("doc", Some(features), warnings)?;
253+
doc.validate("doc", features, warnings)?;
255254
}
256255
if let Some(ref bench) = self.bench {
257-
bench.validate("bench", Some(features), warnings)?;
256+
bench.validate("bench", features, warnings)?;
258257
}
259258
if let Some(ref dev) = self.dev {
260-
dev.validate("dev", Some(features), warnings)?;
259+
dev.validate("dev", features, warnings)?;
261260
}
262261
if let Some(ref release) = self.release {
263-
release.validate("release", Some(features), warnings)?;
262+
release.validate("release", features, warnings)?;
264263
}
265264
Ok(())
266265
}
@@ -420,71 +419,18 @@ impl<'de> de::Deserialize<'de> for ProfilePackageSpec {
420419
}
421420

422421
impl TomlProfile {
423-
pub fn from_config(
424-
config: &Config,
425-
name: &str,
426-
warnings: &mut Vec<String>,
427-
) -> CargoResult<Option<TomlProfile>> {
428-
if !config.cli_unstable().config_profile {
429-
return Ok(None);
430-
}
431-
if let Some(util::config::Value { val, .. }) =
432-
config.get_table(&format!("profile.{}", name))?
433-
{
434-
let cv = ConfigValue::Table(val.clone(), PathBuf::new());
435-
let toml = cv.into_toml();
436-
let profile: TomlProfile =
437-
Deserialize::deserialize(toml).chain_err(|| error_path(&val))?;
438-
profile
439-
.validate(name, None, warnings)
440-
.chain_err(|| error_path(&val))?;
441-
return Ok(Some(profile));
442-
}
443-
return Ok(None);
444-
445-
fn error_path(table: &HashMap<String, ConfigValue>) -> Error {
446-
let mut paths = HashSet::new();
447-
error_path_rec(table, &mut paths);
448-
if paths.len() == 1 {
449-
format_err!(
450-
"error in config profile `{}`",
451-
paths.into_iter().next().unwrap()
452-
)
453-
} else {
454-
let mut ps = paths.into_iter().collect::<Vec<_>>();
455-
ps.sort(); // to help with testing
456-
format_err!(
457-
"error in config profile, possible locations: {}",
458-
ps.join(", ")
459-
)
460-
}
461-
}
462-
fn error_path_rec(table: &HashMap<String, ConfigValue>, paths: &mut HashSet<String>) {
463-
for cv in table.values() {
464-
paths.insert(cv.definition_path().display().to_string());
465-
if let &ConfigValue::Table(ref t, _) = cv {
466-
error_path_rec(t, paths);
467-
}
468-
}
469-
}
470-
}
471-
472422
pub fn validate(
473423
&self,
474424
name: &str,
475-
features: Option<&Features>,
425+
features: &Features,
476426
warnings: &mut Vec<String>,
477427
) -> CargoResult<()> {
478428
if let Some(ref profile) = self.build_override {
479-
if let Some(features) = features {
480-
features.require(Feature::profile_overrides())?;
481-
}
429+
features.require(Feature::profile_overrides())?;
482430
profile.validate_override()?;
483431
}
484432
if let Some(ref override_map) = self.overrides {
485-
if let Some(features) = features {
486-
features.require(Feature::profile_overrides())?;
487-
}
433+
features.require(Feature::profile_overrides())?;
488434
for profile in override_map.values() {
489435
profile.validate_override()?;
490436
}

0 commit comments

Comments
 (0)