Remove the need for a current working directory.

This commit includes several breaking changes:

  * `Config{new,development,staging,production}` constructors return a
    `Config` instead of a `Result<Config>`.
  * `Config.root()` returns an `Option<&Path>` instead of `&Path`.
  * `ConfigError::BadCWD` was removed.
  * `Config` no longer exposes a `config_path` field.

Resolves #809.
This commit is contained in:
Sergio Benitez 2018-11-12 02:17:55 -08:00
parent 4dea9eed36
commit 834c91ae9d
9 changed files with 182 additions and 242 deletions

View File

@ -26,21 +26,16 @@ pub struct ConfigBuilder {
pub limits: Limits,
/// Any extra parameters that aren't part of Rocket's config.
pub extras: HashMap<String, Value>,
/// The root directory of this config.
pub root: PathBuf,
/// The root directory of this config, if any.
pub root: Option<PathBuf>,
}
impl ConfigBuilder {
/// Create a new `ConfigBuilder` instance using the default parameters from
/// the given `environment`. The root configuration directory is set to the
/// current working directory.
/// the given `environment`.
///
/// This method is typically called indirectly via [`Config::build()`].
///
/// # Panics
///
/// Panics if the current directory cannot be retrieved.
///
/// # Example
///
/// ```rust
@ -55,10 +50,7 @@ impl ConfigBuilder {
/// # assert!(config.is_ok());
/// ```
pub fn new(environment: Environment) -> ConfigBuilder {
let config = Config::new(environment)
.expect("ConfigBuilder::new(): couldn't get current directory.");
let root_dir = PathBuf::from(config.root());
let config = Config::new(environment);
ConfigBuilder {
environment: config.environment,
address: config.address,
@ -70,7 +62,7 @@ impl ConfigBuilder {
tls: None,
limits: config.limits,
extras: config.extras,
root: root_dir,
root: None,
}
}
@ -263,10 +255,10 @@ impl ConfigBuilder {
/// .root("/my_app/dir")
/// .unwrap();
///
/// assert_eq!(config.root(), Path::new("/my_app/dir"));
/// assert_eq!(config.root().unwrap(), Path::new("/my_app/dir"));
/// ```
pub fn root<P: AsRef<Path>>(mut self, path: P) -> Self {
self.root = path.as_ref().to_path_buf();
self.root = Some(path.as_ref().to_path_buf());
self
}
@ -298,9 +290,7 @@ impl ConfigBuilder {
///
/// # Errors
///
/// If the current working directory cannot be retrieved, returns a `BadCWD`
/// error. If the address or secret key fail to parse, returns a `BadType`
/// error.
/// If the address or secret key fail to parse, returns a `BadType` error.
///
/// # Example
///
@ -323,16 +313,19 @@ impl ConfigBuilder {
/// assert!(config.is_err());
/// ```
pub fn finalize(self) -> Result<Config> {
let mut config = Config::new(self.environment)?;
let mut config = Config::new(self.environment);
config.set_address(self.address)?;
config.set_port(self.port);
config.set_workers(self.workers);
config.set_keep_alive(self.keep_alive);
config.set_log_level(self.log_level);
config.set_extras(self.extras);
config.set_root(self.root);
config.set_limits(self.limits);
if let Some(root) = self.root {
config.set_root(root);
}
if let Some((certs_path, key_path)) = self.tls {
config.set_tls(&certs_path, &key_path)?;
}
@ -348,8 +341,8 @@ impl ConfigBuilder {
///
/// # Panics
///
/// Panics if the current working directory cannot be retrieved or if the
/// supplied address, secret key, or TLS configuration fail to parse.
/// Panics if the supplied address, secret key, or TLS configuration fail to
/// parse.
///
/// # Example
///
@ -371,9 +364,8 @@ impl ConfigBuilder {
///
/// # Panics
///
/// Panics if the current working directory cannot be retrieved or if the
/// supplied address, secret key, or TLS configuration fail to parse. If a
/// panic occurs, the error message `msg` is printed.
/// Panics if the supplied address, secret key, or TLS configuration fail to
/// parse. If a panic occurs, the error message `msg` is printed.
///
/// # Example
///

View File

@ -3,7 +3,6 @@ use std::net::ToSocketAddrs;
use std::path::{Path, PathBuf};
use std::convert::AsRef;
use std::fmt;
use std::env;
use super::custom_values::*;
use {num_cpus, base64};
@ -57,8 +56,10 @@ pub struct Config {
pub limits: Limits,
/// Extra parameters that aren't part of Rocket's core config.
pub extras: HashMap<String, Value>,
/// The path to the configuration file this config belongs to.
pub config_path: PathBuf,
/// The path to the configuration file this config was loaded from, if any.
crate config_file_path: Option<PathBuf>,
/// The path root-relative files will be rooted from.
crate root_path: Option<PathBuf>,
}
macro_rules! config_from_raw {
@ -76,12 +77,7 @@ macro_rules! config_from_raw {
impl Config {
/// Returns a builder for `Config` structure where the default parameters
/// are set to those of `env`. The root configuration directory is set to
/// the current working directory.
///
/// # Panics
///
/// Panics if the current directory cannot be retrieved.
/// are set to those of `env`.
///
/// # Example
///
@ -99,25 +95,18 @@ impl Config {
ConfigBuilder::new(env)
}
/// Returns a `Config` with the parameters for the environment `env`. The
/// root configuration directory is set to the current working directory.
///
/// # Errors
///
/// If the current directory cannot be retrieved, a `BadCWD` error is
/// returned.
/// Returns a `Config` with the parameters for the environment `env`.
///
/// # Example
///
/// ```rust
/// use rocket::config::{Config, Environment};
///
/// let mut my_config = Config::new(Environment::Production).expect("cwd");
/// let mut my_config = Config::new(Environment::Production);
/// my_config.set_port(1001);
/// ```
pub fn new(env: Environment) -> Result<Config> {
let cwd = env::current_dir().map_err(|_| ConfigError::BadCWD)?;
Config::default(env, cwd.as_path().join("Rocket.custom.toml"))
pub fn new(env: Environment) -> Config {
Config::default(env)
}
/// Returns a `Config` with the default parameters of the active environment
@ -126,16 +115,14 @@ impl Config {
/// If `ROCKET_ENV` is not set, the returned `Config` uses development
/// environment parameters when the application was compiled in `debug` mode
/// and production environment parameters when the application was compiled
/// in `release` mode. The root configuration directory is set to the
/// current working directory.
/// in `release` mode.
///
/// This is equivalent to `Config::new(Environment::active()?)`.
///
/// # Errors
///
/// If the current directory cannot be retrieved, a `BadCWD` error is
/// returned. Returns a `BadEnv` error if `ROCKET_ENV` is set and contains
/// an invalid or unknown environment name.
/// Returns a `BadEnv` error if `ROCKET_ENV` is set and contains an invalid
/// or unknown environment name.
///
/// # Example
///
@ -146,95 +133,94 @@ impl Config {
/// my_config.set_port(1001);
/// ```
pub fn active() -> Result<Config> {
Config::new(Environment::active()?)
Ok(Config::new(Environment::active()?))
}
/// Returns a `Config` with the default parameters of the development
/// environment. The root configuration directory is set to the current
/// working directory.
///
/// # Errors
///
/// If the current directory cannot be retrieved, a `BadCWD` error is
/// returned.
/// environment.
///
/// # Example
///
/// ```rust
/// use rocket::config::{Config, Environment};
///
/// let mut my_config = Config::development().unwrap();
/// let mut my_config = Config::development();
/// my_config.set_port(1001);
/// ```
pub fn development() -> Result<Config> {
pub fn development() -> Config {
Config::new(Environment::Development)
}
/// Returns a `Config` with the default parameters of the staging
/// environment. The root configuration directory is set to the current
/// working directory.
///
/// # Errors
///
/// If the current directory cannot be retrieved, a `BadCWD` error is
/// returned.
/// environment.
///
/// # Example
///
/// ```rust
/// use rocket::config::{Config, Environment};
///
/// let mut my_config = Config::staging().expect("cwd");
/// let mut my_config = Config::staging();
/// my_config.set_port(1001);
/// ```
pub fn staging() -> Result<Config> {
pub fn staging() -> Config {
Config::new(Environment::Staging)
}
/// Returns a `Config` with the default parameters of the production
/// environment. The root configuration directory is set to the current
/// working directory.
///
/// # Errors
///
/// If the current directory cannot be retrieved, a `BadCWD` error is
/// returned.
/// environment.
///
/// # Example
///
/// ```rust
/// use rocket::config::{Config, Environment};
///
/// let mut my_config = Config::production().expect("cwd");
/// let mut my_config = Config::production();
/// my_config.set_port(1001);
/// ```
pub fn production() -> Result<Config> {
pub fn production() -> Config {
Config::new(Environment::Production)
}
/// Returns the default configuration for the environment `env` given that
/// the configuration was stored at `config_path`. If `config_path` is not
/// an absolute path, an `Err` of `ConfigError::BadFilePath` is returned.
/// the configuration was stored at `config_file_path`.
///
/// # Error
///
/// Return a `BadFilePath` error if `path` does not have a parent.
///
/// # Panics
///
/// Panics if randomness cannot be retrieved from the OS.
crate fn default<P>(env: Environment, path: P) -> Result<Config>
crate fn default_from<P>(env: Environment, path: P) -> Result<Config>
where P: AsRef<Path>
{
let config_path = path.as_ref().to_path_buf();
if config_path.parent().is_none() {
return Err(ConfigError::BadFilePath(config_path,
"Configuration files must be rooted in a directory."));
let mut config = Config::default(env);
let config_file_path = path.as_ref().to_path_buf();
if let Some(parent) = config_file_path.parent() {
config.set_root(parent);
} else {
let msg = "Configuration files must be rooted in a directory.";
return Err(ConfigError::BadFilePath(config_file_path.clone(), msg));
}
config.config_file_path = Some(config_file_path);
Ok(config)
}
/// Returns the default configuration for the environment `env`.
///
/// # Panics
///
/// Panics if randomness cannot be retrieved from the OS.
crate fn default(env: Environment) -> Config {
// Note: This may truncate if num_cpus::get() / 2 > u16::max. That's okay.
let default_workers = (num_cpus::get() * 2) as u16;
// Use a generated secret key by default.
let key = SecretKey::Generated(Key::generate());
Ok(match env {
match env {
Development => {
Config {
environment: Development,
@ -247,7 +233,8 @@ impl Config {
tls: None,
limits: Limits::default(),
extras: HashMap::new(),
config_path,
config_file_path: None,
root_path: None,
}
}
Staging => {
@ -262,7 +249,8 @@ impl Config {
tls: None,
limits: Limits::default(),
extras: HashMap::new(),
config_path,
config_file_path: None,
root_path: None,
}
}
Production => {
@ -277,10 +265,11 @@ impl Config {
tls: None,
limits: Limits::default(),
extras: HashMap::new(),
config_path,
config_file_path: None,
root_path: None,
}
}
})
}
}
/// Constructs a `BadType` error given the entry `name`, the invalid `val`
@ -291,7 +280,7 @@ impl Config {
actual: &'static str,
expect: &'static str) -> ConfigError {
let id = format!("{}.{}", self.environment, name);
ConfigError::BadType(id, expect, actual, self.config_path.clone())
ConfigError::BadType(id, expect, actual, self.config_file_path.clone())
}
/// Sets the configuration `val` for the `name` entry. If the `name` is one
@ -336,22 +325,16 @@ impl Config {
/// # use std::path::Path;
/// use rocket::config::{Config, Environment};
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::new(Environment::Staging)?;
/// config.set_root("/tmp/my_app");
/// let mut config = Config::new(Environment::Staging);
/// config.set_root("/var/my_app");
///
/// assert_eq!(config.root(), Path::new("/tmp/my_app"));
/// # Ok(())
/// # }
/// # #[cfg(not(windows))]
/// assert_eq!(config.root().unwrap(), Path::new("/var/my_app"));
/// # #[cfg(windows)]
/// assert_eq!(config.root().unwrap(), Path::new("C:\\var\\my_app"));
/// ```
pub fn set_root<P: AsRef<Path>>(&mut self, path: P) {
let new_path = match self.config_path.file_name() {
Some(file) => path.as_ref().join(file),
None => path.as_ref().join("Rocket.custom.toml")
};
self.config_path = new_path
self.root_path = Some(path.as_ref().into());
}
/// Sets the address of `self` to `address`.
@ -366,14 +349,10 @@ impl Config {
/// ```rust
/// use rocket::config::{Config, Environment};
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::new(Environment::Staging)?;
/// let mut config = Config::new(Environment::Staging);
/// assert!(config.set_address("localhost").is_ok());
/// assert!(config.set_address("::").is_ok());
/// assert!(config.set_address("?").is_err());
/// # Ok(())
/// # }
/// ```
pub fn set_address<A: Into<String>>(&mut self, address: A) -> Result<()> {
let address = address.into();
@ -392,12 +371,9 @@ impl Config {
/// ```rust
/// use rocket::config::{Config, Environment};
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::new(Environment::Staging)?;
/// let mut config = Config::new(Environment::Staging);
/// config.set_port(1024);
/// # Ok(())
/// # }
/// assert_eq!(config.port, 1024);
/// ```
#[inline]
pub fn set_port(&mut self, port: u16) {
@ -411,12 +387,9 @@ impl Config {
/// ```rust
/// use rocket::config::{Config, Environment};
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::new(Environment::Staging)?;
/// let mut config = Config::new(Environment::Staging);
/// config.set_workers(64);
/// # Ok(())
/// # }
/// assert_eq!(config.workers, 64);
/// ```
#[inline]
pub fn set_workers(&mut self, workers: u16) {
@ -431,17 +404,15 @@ impl Config {
/// ```rust
/// use rocket::config::Config;
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::development()?;
/// let mut config = Config::development();
///
/// // Set keep-alive timeout to 10 seconds.
/// config.set_keep_alive(10);
/// assert_eq!(config.keep_alive, Some(10));
///
/// // Disable keep-alive.
/// config.set_keep_alive(0);
/// # Ok(())
/// # }
/// assert_eq!(config.keep_alive, None);
/// ```
#[inline]
pub fn set_keep_alive(&mut self, timeout: u32) {
@ -465,14 +436,10 @@ impl Config {
/// ```rust
/// use rocket::config::{Config, Environment};
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::new(Environment::Staging)?;
/// let mut config = Config::new(Environment::Staging);
/// let key = "8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg=";
/// assert!(config.set_secret_key(key).is_ok());
/// assert!(config.set_secret_key("hello? anyone there?").is_err());
/// # Ok(())
/// # }
/// ```
pub fn set_secret_key<K: Into<String>>(&mut self, key: K) -> Result<()> {
let key = key.into();
@ -499,12 +466,9 @@ impl Config {
/// ```rust
/// use rocket::config::{Config, LoggingLevel, Environment};
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::new(Environment::Staging)?;
/// let mut config = Config::new(Environment::Staging);
/// config.set_log_level(LoggingLevel::Critical);
/// # Ok(())
/// # }
/// assert_eq!(config.log_level, LoggingLevel::Critical);
/// ```
#[inline]
pub fn set_log_level(&mut self, log_level: LoggingLevel) {
@ -518,12 +482,8 @@ impl Config {
/// ```rust
/// use rocket::config::{Config, Limits};
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::development()?;
/// let mut config = Config::development();
/// config.set_limits(Limits::default().limit("json", 4 * (1 << 20)));
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn set_limits(&mut self, limits: Limits) {
@ -550,7 +510,7 @@ impl Config {
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::development()?;
/// let mut config = Config::development();
/// config.set_tls("/etc/ssl/my_certs.pem", "/etc/ssl/priv.key")?;
/// # Ok(())
/// # }
@ -605,9 +565,7 @@ impl Config {
/// use std::collections::HashMap;
/// use rocket::config::{Config, Environment};
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::new(Environment::Staging)?;
/// let mut config = Config::new(Environment::Staging);
///
/// // Create the `extras` map.
/// let mut extras = HashMap::new();
@ -615,8 +573,6 @@ impl Config {
/// extras.insert("templates".to_string(), "my_dir".into());
///
/// config.set_extras(extras);
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn set_extras(&mut self, extras: HashMap<String, Value>) {
@ -632,9 +588,7 @@ impl Config {
/// use std::collections::HashMap;
/// use rocket::config::{Config, Environment};
///
/// # use rocket::config::ConfigError;
/// # fn config_test() -> Result<(), ConfigError> {
/// let mut config = Config::new(Environment::Staging)?;
/// let mut config = Config::new(Environment::Staging);
/// assert_eq!(config.extras().count(), 0);
///
/// // Add a couple of extras to the config.
@ -644,8 +598,6 @@ impl Config {
/// config.set_extras(extras);
///
/// assert_eq!(config.extras().count(), 2);
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn extras<'a>(&'a self) -> impl Iterator<Item=(&'a str, &'a Value)> {
@ -889,9 +841,13 @@ impl Config {
.ok_or_else(|| self.bad_type(name, val.type_str(), "a datetime"))
}
/// Returns the path at which the configuration file for `self` is stored.
/// For instance, if the configuration file is at `/tmp/Rocket.toml`, the
/// path `/tmp` is returned.
/// Returns the root path of the configuration, if one is known.
///
/// For configurations loaded from a `Rocket.toml` file, this will be the
/// directory in which the file is stored. For instance, if the
/// configuration file is at `/tmp/Rocket.toml`, the path `/tmp` is
/// returned. For other configurations, this will be the path set via
/// [`Config::set_root()`] or [`ConfigBuilder::root()`].
///
/// # Example
///
@ -899,35 +855,47 @@ impl Config {
/// use std::env::current_dir;
/// use rocket::config::{Config, Environment};
///
/// let config = Config::new(Environment::Staging)
/// .expect("can retrieve current directory");
/// let mut config = Config::new(Environment::Staging);
/// assert_eq!(config.root(), None);
///
/// assert_eq!(config.root(), current_dir().unwrap());
/// let cwd = current_dir().expect("have cwd");
/// config.set_root(&cwd);
/// assert_eq!(config.root().unwrap(), cwd);
/// ```
pub fn root(&self) -> &Path {
match self.config_path.parent() {
Some(parent) => parent,
None => panic!("root(): path {:?} has no parent", self.config_path)
}
pub fn root(&self) -> Option<&Path> {
self.root_path.as_ref().map(|p| p.as_ref())
}
/// If `path` is a relative path, `path` is appended to the
/// [`Config::root()`] at which the configuration file for `self` is stored
/// and the new path is returned. If `path` is absolute, `path` is returned
/// unaltered.
/// Returns `path` relative to this configuration.
///
/// The path that is returned depends on whether:
///
/// 1. Whether `path` is absolute or relative.
/// 2. Whether there is a [`Config::root()`] configured.
/// 3. Whether there is a current directory.
///
/// If `path` is absolute, it is returned unaltered. Otherwise, if `path` is
/// relative and there is a root configured, the root is prepended to `path`
/// and the newlt concatenated path is returned. Otherwise, if there is a
/// current directory, it is preprended to `path` and the newly concatenated
/// path is returned. Finally, if all else fails, the path is simply
/// returned.
///
/// # Example
///
/// ```rust
/// use std::env::current_dir;
/// use std::path::Path;
/// use std::env::current_dir;
///
/// use rocket::config::{Config, Environment};
///
/// let config = Config::new(Environment::Staging)
/// .expect("can retrieve current directory");
/// let mut config = Config::new(Environment::Staging);
///
/// assert_eq!(config.root(), current_dir().unwrap());
/// assert_eq!(config.root_relative("abc"), config.root().join("abc"));
/// let cwd = current_dir().expect("have cwd");
/// config.set_root(&cwd);
/// assert_eq!(config.root().unwrap(), cwd);
///
/// assert_eq!(config.root_relative("abc"), cwd.join("abc"));
/// # #[cfg(not(windows))]
/// assert_eq!(config.root_relative("/abc"), Path::new("/abc"));
/// # #[cfg(windows)]
@ -937,8 +905,12 @@ impl Config {
let path = path.as_ref();
if path.is_absolute() {
path.into()
} else if let Some(root) = self.root() {
root.join(path)
} else if let Ok(cwd) = ::std::env::current_dir() {
cwd.join(path)
} else {
self.root().join(path)
path.into()
}
}
}

View File

@ -20,6 +20,12 @@ pub enum Environment {
}
impl Environment {
/// List of all of the possible environments.
crate const ALL: [Environment; 3] = [Development, Staging, Production];
/// String of all valid environments.
crate const VALID: &'static str = "development, staging, production";
/// Retrieves the "active" environment as determined by the `ROCKET_ENV`
/// environment variable. If `ROCKET_ENV` is not set, returns `Development`
/// when the application was compiled in `debug` mode and `Production` when
@ -39,17 +45,6 @@ impl Environment {
}
}
/// Returns a string with a comma-separated list of valid environments.
crate fn valid() -> &'static str {
"development, staging, production"
}
/// Returns a list of all of the possible environments.
#[inline]
crate fn all() -> [Environment; 3] {
[Development, Staging, Production]
}
/// Returns `true` if `self` is `Environment::Development`.
///
/// # Example

View File

@ -10,8 +10,6 @@ use yansi::Color::White;
/// The type of a configuration error.
#[derive(Debug)]
pub enum ConfigError {
/// The current working directory could not be determined.
BadCWD,
/// The configuration file was not found.
NotFound,
/// There was an I/O error while reading the configuration file.
@ -35,7 +33,7 @@ pub enum ConfigError {
/// A config key was specified with a value of the wrong type.
///
/// Parameters: (entry_name, expected_type, actual_type, filename)
BadType(String, &'static str, &'static str, PathBuf),
BadType(String, &'static str, &'static str, Option<PathBuf>),
/// There was a TOML parsing error.
///
/// Parameters: (toml_source_string, filename, error_description, line/col)
@ -57,9 +55,8 @@ pub enum ConfigError {
impl ConfigError {
/// Prints this configuration error with Rocket formatting.
pub fn pretty_print(&self) {
let valid_envs = Environment::valid();
let valid_envs = Environment::VALID;
match *self {
BadCWD => error!("couldn't get current working directory"),
NotFound => error!("config file was not found"),
IoError => error!("failed reading the config file: IO error"),
Io(ref error, param) => {
@ -82,7 +79,10 @@ impl ConfigError {
}
BadType(ref name, expected, actual, ref filename) => {
error!("{} key could not be parsed", White.paint(name));
info_!("in {:?}", White.paint(filename));
if let Some(filename) = filename {
info_!("in {:?}", White.paint(filename));
}
info_!("expected value to be {}, but found {}",
White.paint(expected), White.paint(actual));
}
@ -133,7 +133,6 @@ impl ConfigError {
impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
BadCWD => write!(f, "couldn't get current working directory"),
NotFound => write!(f, "config file was not found"),
IoError => write!(f, "I/O error while reading the config file"),
Io(ref e, p) => write!(f, "I/O error while setting '{}': {}", p, e),
@ -158,7 +157,6 @@ impl fmt::Display for ConfigError {
impl Error for ConfigError {
fn description(&self) -> &str {
match *self {
BadCWD => "the current working directory could not be determined",
NotFound => "config file was not found",
IoError => "there was an I/O error while reading the config file",
Io(..) => "an I/O error occured while setting a configuration parameter",
@ -177,7 +175,6 @@ impl Error for ConfigError {
impl PartialEq for ConfigError {
fn eq(&self, other: &ConfigError) -> bool {
match (self, other) {
(&BadCWD, &BadCWD) => true,
(&NotFound, &NotFound) => true,
(&IoError, &IoError) => true,
(&Io(_, p1), &Io(_, p2)) => p1 == p2,
@ -193,7 +190,7 @@ impl PartialEq for ConfigError {
k1 == k2 && v1 == v2
}
(&Missing(ref k1), &Missing(ref k2)) => k1 == k2,
(&BadCWD, _) | (&NotFound, _) | (&IoError, _) | (&Io(..), _)
(&NotFound, _) | (&IoError, _) | (&Io(..), _)
| (&BadFilePath(..), _) | (&BadEnv(..), _) | (&ParseError(..), _)
| (&UnknownKey(..), _) | (&BadEntry(..), _) | (&BadType(..), _)
| (&BadEnvVal(..), _) | (&Missing(..), _) => false

View File

@ -229,29 +229,6 @@ pub struct RocketConfig {
}
impl RocketConfig {
/// Create a new configuration using the passed in `config` for all
/// environments. The Rocket.toml file is ignored, as are environment
/// variables.
///
/// # Panics
///
/// If the current working directory can't be retrieved, this function
/// panics.
pub fn new(config: Config) -> RocketConfig {
let f = config.config_path.clone();
let active_env = config.environment;
// None of these unwraps should fail since the filename is coming from
// an existing config.
let mut configs = HashMap::new();
configs.insert(Development, Config::default(Development, &f).unwrap());
configs.insert(Staging, Config::default(Staging, &f).unwrap());
configs.insert(Production, Config::default(Production, &f).unwrap());
configs.insert(active_env, config);
RocketConfig { active_env, config: configs }
}
/// Read the configuration from the `Rocket.toml` file. The file is search
/// for recursively up the tree, starting from the CWD.
pub fn read() -> Result<RocketConfig> {
@ -271,11 +248,17 @@ impl RocketConfig {
/// Return the default configuration for all environments and marks the
/// active environment (via the CONFIG_ENV variable) as active.
pub fn active_default<P: AsRef<Path>>(filename: P) -> Result<RocketConfig> {
pub fn active_default_from(filename: Option<&Path>) -> Result<RocketConfig> {
let mut defaults = HashMap::new();
defaults.insert(Development, Config::default(Development, &filename)?);
defaults.insert(Staging, Config::default(Staging, &filename)?);
defaults.insert(Production, Config::default(Production, &filename)?);
if let Some(path) = filename {
defaults.insert(Development, Config::default_from(Development, &path)?);
defaults.insert(Staging, Config::default_from(Staging, &path)?);
defaults.insert(Production, Config::default_from(Production, &path)?);
} else {
defaults.insert(Development, Config::default(Development));
defaults.insert(Staging, Config::default(Staging));
defaults.insert(Production, Config::default(Production));
}
let mut config = RocketConfig {
active_env: Environment::active()?,
@ -287,12 +270,18 @@ impl RocketConfig {
Ok(config)
}
/// Return the default configuration for all environments and marks the
/// active environment (via the CONFIG_ENV variable) as active.
pub fn active_default() -> Result<RocketConfig> {
RocketConfig::active_default_from(None)
}
/// Iteratively search for `CONFIG_FILENAME` starting at the current working
/// directory and working up through its parents. Returns the path to the
/// file or an Error::NoKey if the file couldn't be found. If the current
/// working directory can't be determined, return `BadCWD`.
fn find() -> Result<PathBuf> {
let cwd = env::current_dir().map_err(|_| ConfigError::BadCWD)?;
let cwd = env::current_dir().map_err(|_| ConfigError::NotFound)?;
let mut current = cwd.as_path();
loop {
@ -365,7 +354,7 @@ impl RocketConfig {
Err(e) => return Err(ConfigError::BadEnvVal(key, val, e))
};
for env in &Environment::all() {
for env in &Environment::ALL {
match self.get_mut(*env).set_raw(&key, &toml_val) {
Err(ConfigError::BadType(_, exp, actual, _)) => {
let e = format!("expected {}, but found {}", exp, actual);
@ -397,7 +386,7 @@ impl RocketConfig {
};
// Create a config with the defaults; set the env to the active one.
let mut config = RocketConfig::active_default(filename)?;
let mut config = RocketConfig::active_default_from(Some(filename.as_ref()))?;
// Store all of the global overrides, if any, for later use.
let mut global = None;
@ -408,7 +397,7 @@ impl RocketConfig {
let kv_pairs = match value.as_table() {
Some(table) => table,
None => return Err(ConfigError::BadType(
entry, "a table", value.type_str(), path.clone()
entry, "a table", value.type_str(), Some(path.clone())
))
};
@ -428,7 +417,7 @@ impl RocketConfig {
// Override all of the environments with the global values.
if let Some(ref global_kv_pairs) = global {
for env in &Environment::all() {
for env in &Environment::ALL {
config.set_from_table(*env, global_kv_pairs)?;
}
}
@ -467,16 +456,11 @@ crate fn init() -> Config {
| ParseError(..) | BadEntry(..) | BadEnv(..) | BadType(..) | Io(..)
| BadFilePath(..) | BadEnvVal(..) | UnknownKey(..)
| Missing(..) => bail(e),
IoError | BadCWD => warn!("Failed reading Rocket.toml. Using defaults."),
IoError => warn!("Failed reading Rocket.toml. Using defaults."),
NotFound => { /* try using the default below */ }
}
let default_path = match env::current_dir() {
Ok(path) => path.join(&format!(".{}.{}", "default", CONFIG_FILENAME)),
Err(_) => bail(ConfigError::BadCWD)
};
RocketConfig::active_default(&default_path).unwrap_or_else(|e| bail(e))
RocketConfig::active_default().unwrap_or_else(|e| bail(e))
});
// FIXME: Should probably store all of the config.
@ -522,7 +506,7 @@ mod test {
}
fn active_default() -> Result<RocketConfig> {
RocketConfig::active_default(TEST_CONFIG_FILENAME)
RocketConfig::active_default()
}
fn default_config(env: Environment) -> ConfigBuilder {
@ -1073,7 +1057,7 @@ mod test {
let _env_lock = ENV_LOCK.lock().unwrap();
// Test first that we can override each environment.
for env in &Environment::all() {
for env in &Environment::ALL {
env::set_var(CONFIG_ENV, env.to_string());
check_config!(RocketConfig::parse(format!(r#"
@ -1127,14 +1111,14 @@ mod test {
let rconfig = active_default().unwrap();
// Check that it overrides the active config.
for env in &Environment::all() {
for env in &Environment::ALL {
env::set_var(CONFIG_ENV, env.to_string());
let rconfig = active_default().unwrap();
check_value(&*key.to_lowercase(), val, rconfig.active());
}
// And non-active configs.
for env in &Environment::all() {
for env in &Environment::ALL {
check_value(&*key.to_lowercase(), val, rconfig.get(*env));
}
}
@ -1172,7 +1156,7 @@ mod test {
check_value(&*key.to_lowercase(), val, r.active());
// And non-active configs.
for env in &Environment::all() {
for env in &Environment::ALL {
check_value(&*key.to_lowercase(), val, r.get(*env));
}
}

View File

@ -697,7 +697,7 @@ impl<'r> Request<'r> {
impl<'r> Request<'r> {
// Only used by doc-tests! Needs to be `pub` because doc-test are external.
pub fn example<F: Fn(&mut Request)>(method: Method, uri: &str, f: F) {
let rocket = Rocket::custom(Config::development().unwrap());
let rocket = Rocket::custom(Config::development());
let uri = Origin::parse(uri).expect("invalid URI in example");
let mut request = Request::new(&rocket, method, uri);
f(&mut request);

View File

@ -20,7 +20,7 @@ macro_rules! assert_headers {
$(expected.entry($key).or_insert(vec![]).append(&mut vec![$($value),+]);)+
// Dispatch the request and check that the headers are what we expect.
let config = Config::development().unwrap();
let config = Config::development();
let r = Rocket::custom(config);
let req = Request::from_hyp(&r, h_method, h_headers, h_uri, h_addr).unwrap();
let actual_headers = req.headers();

View File

@ -401,7 +401,7 @@ mod tests {
fn req_route_mt_collide<S1, S2>(m: Method, mt1: S1, mt2: S2) -> bool
where S1: Into<Option<&'static str>>, S2: Into<Option<&'static str>>
{
let rocket = Rocket::custom(Config::development().unwrap());
let rocket = Rocket::custom(Config::development());
let mut req = Request::new(&rocket, m, Origin::dummy());
if let Some(mt_str) = mt1.into() {
if m.supports_payload() {
@ -468,7 +468,7 @@ mod tests {
}
fn req_route_path_match(a: &'static str, b: &'static str) -> bool {
let rocket = Rocket::custom(Config::development().unwrap());
let rocket = Rocket::custom(Config::development());
let req = Request::new(&rocket, Get, Origin::parse(a).expect("valid URI"));
let route = Route::ranked(0, Get, b.to_string(), dummy_handler);
route.matches(&req)

View File

@ -228,7 +228,7 @@ mod test {
}
fn route<'a>(router: &'a Router, method: Method, uri: &str) -> Option<&'a Route> {
let rocket = Rocket::custom(Config::development().unwrap());
let rocket = Rocket::custom(Config::development());
let request = Request::new(&rocket, method, Origin::parse(uri).unwrap());
let matches = router.route(&request);
if matches.len() > 0 {
@ -239,7 +239,7 @@ mod test {
}
fn matches<'a>(router: &'a Router, method: Method, uri: &str) -> Vec<&'a Route> {
let rocket = Rocket::custom(Config::development().unwrap());
let rocket = Rocket::custom(Config::development());
let request = Request::new(&rocket, method, Origin::parse(uri).unwrap());
router.route(&request)
}