diff options
Diffstat (limited to 'vendor/gix-config/src/file/init/from_env.rs')
-rw-r--r-- | vendor/gix-config/src/file/init/from_env.rs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/vendor/gix-config/src/file/init/from_env.rs b/vendor/gix-config/src/file/init/from_env.rs new file mode 100644 index 000000000..167d37399 --- /dev/null +++ b/vendor/gix-config/src/file/init/from_env.rs @@ -0,0 +1,88 @@ +use std::convert::TryFrom; + +use bstr::{BStr, ByteSlice}; + +use crate::{file, file::init, parse, parse::section, path::interpolate, File}; + +/// Represents the errors that may occur when calling [`File::from_env()`]. +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +pub enum Error { + #[error("Configuration {kind} at index {index} contained illformed UTF-8")] + IllformedUtf8 { index: usize, kind: &'static str }, + #[error("GIT_CONFIG_COUNT was not a positive integer: {}", .input)] + InvalidConfigCount { input: String }, + #[error("GIT_CONFIG_KEY_{} was not set", .key_id)] + InvalidKeyId { key_id: usize }, + #[error("GIT_CONFIG_KEY_{} was set to an invalid value: {}", .key_id, .key_val)] + InvalidKeyValue { key_id: usize, key_val: String }, + #[error("GIT_CONFIG_VALUE_{} was not set", .value_id)] + InvalidValueId { value_id: usize }, + #[error(transparent)] + PathInterpolationError(#[from] interpolate::Error), + #[error(transparent)] + Includes(#[from] init::includes::Error), + #[error(transparent)] + Section(#[from] section::header::Error), + #[error(transparent)] + Key(#[from] section::key::Error), +} + +/// Instantiation from environment variables +impl File<'static> { + /// Generates a config from `GIT_CONFIG_*` environment variables or returns `Ok(None)` if no configuration was found. + /// See [`gix-config`'s documentation] for more information on the environment variables in question. + /// + /// With `options` configured, it's possible to resolve `include.path` or `includeIf.<condition>.path` directives as well. + /// + /// [`gix-config`'s documentation]: https://git-scm.com/docs/gix-config#Documentation/gix-config.txt-GITCONFIGCOUNT + pub fn from_env(options: init::Options<'_>) -> Result<Option<File<'static>>, Error> { + use std::env; + let count: usize = match env::var("GIT_CONFIG_COUNT") { + Ok(v) => v.parse().map_err(|_| Error::InvalidConfigCount { input: v })?, + Err(_) => return Ok(None), + }; + + if count == 0 { + return Ok(None); + } + + let meta = file::Metadata { + path: None, + source: crate::Source::Env, + level: 0, + trust: gix_sec::Trust::Full, + }; + let mut config = File::new(meta); + for i in 0..count { + let key = gix_path::os_string_into_bstring( + env::var_os(format!("GIT_CONFIG_KEY_{i}")).ok_or(Error::InvalidKeyId { key_id: i })?, + ) + .map_err(|_| Error::IllformedUtf8 { index: i, kind: "key" })?; + let value = env::var_os(format!("GIT_CONFIG_VALUE_{i}")).ok_or(Error::InvalidValueId { value_id: i })?; + let key = parse::key(<_ as AsRef<BStr>>::as_ref(&key)).ok_or_else(|| Error::InvalidKeyValue { + key_id: i, + key_val: key.to_string(), + })?; + + config + .section_mut_or_create_new(key.section_name, key.subsection_name)? + .push( + section::Key::try_from(key.value_name.to_owned())?, + Some( + gix_path::os_str_into_bstr(&value) + .map_err(|_| Error::IllformedUtf8 { + index: i, + kind: "value", + })? + .as_bytes() + .into(), + ), + ); + } + + let mut buf = Vec::new(); + init::includes::resolve(&mut config, &mut buf, options)?; + Ok(Some(config)) + } +} |