Skip to content

Commit

Permalink
Dummy commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexhuszagh committed Jul 10, 2022
1 parent 4e79118 commit be5a562
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 32 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ directories = "4.0.1"
walkdir = { version = "2", optional = true }
tempfile = "3.3.0"
owo-colors = { version = "3.4.0", features = ["supports-colors"] }
once_cell = "1.12"

[target.'cfg(not(windows))'.dependencies]
nix = { version = "0.24", default-features = false, features = ["user"] }
Expand Down
150 changes: 132 additions & 18 deletions src/cargo_toml.rs → src/cargo_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,44 @@ use std::path::Path;

use crate::errors::*;
use crate::file;
use crate::shell::MessageInfo;
use once_cell::sync::OnceCell;

type Table = toml::value::Table;
type Value = toml::value::Value;

pub const CARGO_NO_PREFIX_ENVVARS: &[&str] = &[
"http_proxy",
"TERM",
"RUSTDOCFLAGS",
"RUSTFLAGS",
"BROWSER",
"HTTPS_PROXY",
"HTTP_TIMEOUT",
"https_proxy",
];

// TODO(ahuszagh) This should really be cargo_toml and cargo_env.
// Should have it as a once_cell?

// CARGO_ALIAS_

// the strategy is to merge, with arrays merging together
// and the deeper the config file is, the higher its priority.
// arrays merge, numbers/strings get replaced, objects merge in.
// we don't want to make any assumptions about the cargo
// config data, in case we need to use it later.
#[derive(Debug, Clone, Default)]
pub struct CargoConfig(Table);
pub struct CargoToml(Table);

impl CargoConfig {
fn merge(&mut self, parent: &CargoConfig) -> Result<()> {
impl CargoToml {
fn parse(path: &Path) -> Result<CargoToml> {
let contents = file::read(&path)
.wrap_err_with(|| format!("could not read cargo config file at `{path:?}`"))?;
Ok(CargoToml(toml::from_str(&contents)?))
}

fn merge(&mut self, parent: &CargoToml) -> Result<()> {
// can error on mismatched-data

fn validate_types(x: &Value, y: &Value) -> Option<()> {
Expand Down Expand Up @@ -66,6 +90,8 @@ impl CargoConfig {
}

// get all the aliases from the map
// TODO(ahuszagh) This needs to be an result of an option.
// If we don't have as_str, needs to fail as a result
pub fn alias<'a>(&'a self) -> Option<BTreeMap<&'a str, Vec<&'a str>>> {
let parse_alias = |v: &'a Value| -> Option<Vec<&'a str>> {
if let Some(s) = v.as_str() {
Expand All @@ -86,35 +112,99 @@ impl CargoConfig {
}
}

fn parse_config_file(path: &Path) -> Result<CargoConfig> {
let contents = file::read(&path)
.wrap_err_with(|| format!("could not read cargo config file `{path:?}`"))?;
Ok(CargoConfig(toml::from_str(&contents)?))
// wrapper for all the cargo environment variables.
#[derive(Debug, Clone, Default)]
pub struct CargoEnv(BTreeMap<String, String>);

impl CargoEnv {
fn create() -> CargoEnv {
let mut result = BTreeMap::new();
for (key, value) in env::vars() {
if key.starts_with("CARGO_") || CARGO_NO_PREFIX_ENVVARS.contains(&key.as_str()) {
result.insert(key, value);
}
}

CargoEnv(result)
}

// get all the aliases from the map
pub fn alias<'a>(&'a self) -> Result<BTreeMap<String, Vec<&'a str>>> {
let mut result = BTreeMap::new();
for (key, value) in &self.0 {
if let Some(alias) = key.strip_prefix("CARGO_ALIAS_") {
// cargo skips empty aliases
match alias.chars().all(char::is_uppercase) {
true if !alias.is_empty() => {
let value = value.split_whitespace().collect();
result.insert(key.to_lowercase(), value);
}
false => {
MessageInfo::default().warn(format_args!(
"Environment variables are expected to use uppercase letters and underscores, the variable `{key}` will be ignored and have no effect"
))?;
}
// `CARGO_ALIAS_` is ignored
_ => (),
}
}
}

Ok(result)
}
}

// merged result of cargo TOML config and environment variables
// we use a toml setting here, since it abstracts the types
#[derive(Debug, Clone, Default)]
pub struct CargoConfig(BTreeMap<String, Value>);

impl CargoConfig {
fn create(config_toml: &CargoToml, config_env: &CargoEnv) -> Result<CargoConfig> {
let mut result = BTreeMap::new();
let toml_aliases = config_toml.alias(); // TODO(ahuszagh) Must be used
let env_aliases = config_env.alias()?;
// TODO(ahuszagh) Here...
// We only care about values we actually know.


// for (key, value) in env::vars() {
// if key.starts_with("CARGO_") || CARGO_NO_PREFIX_ENVVARS.contains(&key.as_str()) {
// result.insert(key, value);
// }
// }

Ok(CargoConfig(result))
}

fn alias(&self) -> BTreeMap<String, Vec<String>> {
todo!();
}
}

// finding cargo config files actually runs from the
// current working directory the command is invoked,
// not from the project root. same is true with work
// spaces: the project layout does not matter.
pub fn read_config_files() -> Result<CargoConfig> {
pub fn read_config_files() -> Result<CargoToml> {
// note: cargo supports both `config` and `config.toml`
// `config` exists for compatibility reasons, but if
// present, only it will be read.
let read_and_merge = |result: &mut CargoConfig, dir: &Path| -> Result<()> {
let read_and_merge = |result: &mut CargoToml, dir: &Path| -> Result<()> {
let noext = dir.join("config");
let ext = dir.join("config.toml");
if noext.exists() {
let parent = parse_config_file(&noext)?;
let parent = CargoToml::parse(&noext)?;
result.merge(&parent)?;
} else if ext.exists() {
let parent = parse_config_file(&ext)?;
let parent = CargoToml::parse(&ext)?;
result.merge(&parent)?;
}

Ok(())
};

let mut result = CargoConfig::default();
let mut result = CargoToml::default();
let cwd = env::current_dir()?;
let mut dir: &Path = &cwd;
loop {
Expand All @@ -131,14 +221,40 @@ pub fn read_config_files() -> Result<CargoConfig> {
Ok(result)
}

static CARGO_TOML: OnceCell<CargoToml> = OnceCell::new();

pub fn get_cargo_toml() -> &'static CargoToml {
CARGO_TOML
.get_or_try_init::<_, eyre::Report>(|| {
read_config_files()
})
.unwrap()
}

static CARGO_ENV: OnceCell<CargoEnv> = OnceCell::new();

pub fn get_cargo_env() -> &'static CargoEnv {
CARGO_ENV.get_or_init(|| CargoEnv::create())
}

static CARGO_CONFIG: OnceCell<CargoConfig> = OnceCell::new();

pub fn get_cargo_config() -> &'static CargoConfig {
CARGO_CONFIG
.get_or_try_init::<_, eyre::Report>(|| {
CargoConfig::create(get_cargo_toml(), get_cargo_env())
})
.unwrap()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_parse() -> Result<()> {
let config1 = CargoConfig(toml::from_str(CARGO_TOML1)?);
let config2 = CargoConfig(toml::from_str(CARGO_TOML2)?);
let config1 = CargoToml(toml::from_str(CARGO_TOML1)?);
let config2 = CargoToml(toml::from_str(CARGO_TOML2)?);
let alias1 = config1.alias().expect("unable to get aliases.");
let alias2 = config2.alias().expect("unable to get aliases.");
assert_eq!(
Expand Down Expand Up @@ -184,9 +300,9 @@ mod tests {
}

#[test]
fn test_read_config() -> Result<()> {
fn test_read_config() {
// cross contains a few aliases, so test those
let config = read_config_files()?;
let config = get_cargo_toml();
let aliases = config.alias().expect("must have aliases");
assert_eq!(
aliases.get("build-docker-image"),
Expand All @@ -196,8 +312,6 @@ mod tests {
aliases.get("xtask"),
Some(&vec!["run", "-p", "xtask", "--"]),
);

Ok(())
}

const CARGO_TOML1: &str = r#"
Expand Down
5 changes: 3 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::{env, path::PathBuf};

use crate::cargo::Subcommand;
use crate::cargo_toml::read_config_files;
// TODO(ahuszagh) Change to get_cargo_config
use crate::cargo_config::get_cargo_toml;
use crate::errors::Result;
use crate::rustc::TargetList;
use crate::shell::{self, MessageInfo};
Expand Down Expand Up @@ -150,7 +151,7 @@ fn parse_subcommand(
}
let subcommand = Subcommand::from(arg.as_ref());
if subcommand == Subcommand::Other {
let config = read_config_files()?;
let config = get_cargo_toml();
if let Some(aliases) = config.alias() {
if let Some(alias) = aliases.get(arg.as_str()) {
let mut iter = alias.iter().cloned().map(|x| x.to_owned());
Expand Down
13 changes: 2 additions & 11 deletions src/docker/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{env, fs};
use super::custom::{Dockerfile, PreBuild};
use super::engine::*;
use crate::cargo::{cargo_metadata_with_args, CargoMetadata};
use crate::cargo_config::CARGO_NO_PREFIX_ENVVARS;
use crate::config::{bool_from_envvar, Config};
use crate::errors::*;
use crate::extensions::{CommandExt, SafeCommand};
Expand Down Expand Up @@ -425,16 +426,6 @@ pub(crate) fn cargo_safe_command(uses_xargo: bool) -> SafeCommand {
}

fn add_cargo_configuration_envvars(docker: &mut Command) {
let non_cargo_prefix = &[
"http_proxy",
"TERM",
"RUSTDOCFLAGS",
"RUSTFLAGS",
"BROWSER",
"HTTPS_PROXY",
"HTTP_TIMEOUT",
"https_proxy",
];
let cargo_prefix_skip = &[
"CARGO_HOME",
"CARGO_TARGET_DIR",
Expand All @@ -445,7 +436,7 @@ fn add_cargo_configuration_envvars(docker: &mut Command) {
"CARGO_BUILD_RUSTDOC",
];
let is_cargo_passthrough = |key: &str| -> bool {
non_cargo_prefix.contains(&key)
CARGO_NO_PREFIX_ENVVARS.contains(&key)
|| key.starts_with("CARGO_") && !cargo_prefix_skip.contains(&key)
};

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
mod tests;

mod cargo;
mod cargo_toml;
mod cargo_config;
mod cli;
mod config;
mod cross_toml;
Expand Down

0 comments on commit be5a562

Please sign in to comment.