Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
Envish
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Libraries
Envish
Commits
da8b8ae5
Verified
Commit
da8b8ae5
authored
4 months ago
by
Louis
Browse files
Options
Downloads
Patches
Plain Diff
Improve docs
parent
82b69a23
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Pipeline
#711
passed with stage
in 11 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
src/env_file.rs
+17
-0
17 additions, 0 deletions
src/env_file.rs
src/filesystem.rs
+91
-0
91 additions, 0 deletions
src/filesystem.rs
src/lib.rs
+13
-0
13 additions, 0 deletions
src/lib.rs
src/parser.rs
+32
-3
32 additions, 3 deletions
src/parser.rs
with
153 additions
and
3 deletions
src/env_file.rs
+
17
−
0
View file @
da8b8ae5
...
...
@@ -105,9 +105,26 @@ impl EnvironmentFile {
}
}
/// Varies the behaviour of applying an environment file.
///
/// ## Defaults
///
/// When not provided, `envish` will use the default values for this type:
/// - `prefix` is set to `None` (Keys in env files will be used as-written)
/// - `overwrite` is set to `false` (If a variable is already set, the value in the file will not be used)
#[derive(Clone,
Debug,
Default)]
pub
struct
ApplyOptions
{
/// If present, this exact string will be prepended to the names of all environment variables
/// when applying.
///
/// ### Example
///
/// With the prefix "APP_", a variable with the key "DATABASE_URL" will be added to the environment as
/// "APP_DATABASE_URL".
pub
prefix
:
Option
<
String
>
,
/// By default, `envish` will not update an existing environment variable, ignoring the value
/// in the environment file. When the `overwrite` option is set to `true`, `envish` will apply
/// any values from the file regardless of whether they are already set.
pub
overwrite
:
bool
,
}
...
...
This diff is collapsed.
Click to expand it.
src/filesystem.rs
+
91
−
0
View file @
da8b8ae5
...
...
@@ -8,22 +8,36 @@ use std::path::Path;
#[derive(Debug,
thiserror::Error)]
#[allow(clippy::enum_variant_names)]
pub
enum
EnvFsError
{
/// Error opening the file, or reading it into a buffer.
#[error(transparent)]
IoError
(
#[from]
std
::
io
::
Error
),
/// Error parsing the file from a string into an EnvironmentFile. Denotes syntax errors in the
/// file.
#[error(transparent)]
ParseError
(
#[from]
crate
::
EnvironmentFileError
),
/// An error thrown specifically when the given environment variable exists, but is cannot be
/// represented in Rust (e.g. not Unicode). This error does **not** occur when the environment
/// variable exists as valid Unicode.
#[error(
"The target environment variable exists, but is not Unicode"
)]
EnvironmentError
,
}
/// Reads the file `.env` into memory, but does not apply it to the environment.
pub
fn
env_file
()
->
Result
<
EnvironmentFile
,
EnvFsError
>
{
env_file_from_path
(
".env"
)
}
/// Reads the file `.env.<environment>` into memory, but does not apply it to the environment.
///
/// ### Example
///
/// Calling `env_file_suffix("production")` will attempt to read the file `.env.production` in the
/// directory the server was launched from.
pub
fn
env_file_suffix
(
environment
:
impl
Display
)
->
Result
<
EnvironmentFile
,
EnvFsError
>
{
env_file_from_path
(
format!
(
".env.{}"
,
environment
))
}
/// Reads the file at the specified path into memory, but does not apply it to the environment.
pub
fn
env_file_from_path
(
path
:
impl
AsRef
<
Path
>
)
->
Result
<
EnvironmentFile
,
EnvFsError
>
{
let
mut
file
=
File
::
open
(
path
)
?
;
let
mut
buffer
=
String
::
new
();
...
...
@@ -31,20 +45,97 @@ pub fn env_file_from_path(path: impl AsRef<Path>) -> Result<EnvironmentFile, Env
Ok
(
buffer
.parse
()
?
)
}
/// Look up a `.env` file in the working directory and apply its contents to the current environment.
///
/// ### Errors
///
/// This method returns an error under the following circumstances:
///
/// - The target file does not exist
/// - There was an error when reading the target file
/// - The target was not a correctly formatted `.env` file
///
/// ### Example
///
/// This example will attempt to read the file `.env` in the directory the server was launched from.
/// ```rust
/// use envish::dotenv;
/// let _ = dotenv();
/// ```
pub
fn
dotenv
()
->
Result
<
(),
EnvFsError
>
{
env_file
()
?
.apply
(
Default
::
default
());
Ok
(())
}
/// Look up a `.env` file in the working directory and apply its contents to the current environment,
/// with the provided options, allowing for prefixing and overwriting existing values.
///
/// ### Errors
///
/// This method returns an error under the following circumstances:
///
/// - The target file does not exist
/// - There was an error when reading the target file
/// - The target was not a correctly formatted `.env` file
///
/// ### Example
///
/// This example will attempt to read the file `.env`, and will prepend the given prefix to all the
/// contained variables. For example, a variable in the file named "DATABASE_URL" will be added to
/// the environment as "APP_DATABASE_URL".
///
/// ```rust
/// use envish::{dotenv_opts, ApplyOptions};
/// let _ = dotenv_opts(ApplyOptions::with_prefix("APP_"));
/// ```
pub
fn
dotenv_opts
(
options
:
ApplyOptions
)
->
Result
<
(),
EnvFsError
>
{
env_file
()
?
.apply
(
options
);
Ok
(())
}
/// Look up a `.env` file with the provided suffix in the working directory and apply its contents
/// to the current environment.
///
/// ### Errors
///
/// This method returns an error under the following circumstances:
///
/// - The target file does not exist
/// - There was an error when reading the target file
/// - The target was not a correctly formatted `.env` file
///
/// ### Example
///
/// This example will attempt to read the file `.env.development`
///
/// ```rust
/// use envish::dotenv_suffix;
/// let _ = dotenv_suffix("development");
/// ```
pub
fn
dotenv_suffix
(
environment
:
impl
Display
)
->
Result
<
(),
EnvFsError
>
{
env_file_suffix
(
environment
)
?
.apply
(
Default
::
default
());
Ok
(())
}
/// Look up an environment file at the given path and apply its contents to the current environment.
///
/// ### Errors
///
/// This method returns an error under the following circumstances:
///
/// - The target file does not exist
/// - There was an error when reading the target file
/// - The target was not a correctly formatted `.env` file
///
/// ### Example
///
/// This example will attempt to read the file `my_dotenv_file` at the specified path. The file must
/// be correctly formatted as any other .env file, but does not need to have a specific name.
///
/// ```rust
/// use envish::dotenv_from;
/// let _ = dotenv_from("/some/other/path/to/my_dotenv_file");
/// ```
pub
fn
dotenv_from
(
path
:
impl
AsRef
<
Path
>
)
->
Result
<
(),
EnvFsError
>
{
env_file_from_path
(
path
)
?
.apply
(
Default
::
default
());
Ok
(())
...
...
This diff is collapsed.
Click to expand it.
src/lib.rs
+
13
−
0
View file @
da8b8ae5
#![allow(unused_labels)]
//! This crate provides a simple interface for reading, parsing, and using `.env` style environment
//! files. The goal is to provide comprehensive compatibility with the variety of .env formats
//! and options found in popular tools across languages, both for reading and writing.
//!
//! ## Embedding
//!
//! This library is designed to be easy to use with both Rust and non-Rust projects. The core
//! functionality covers parsing and manipulating environment files. By default, `envish` also
//! includes filesystem support for reading and writing `.env` files, but this can be disabled by
//! turning off default features.
//!
//! It is recommended to disable filesystem support when embedding `envish`, and instead
//! using the platform-native filesystem operations in tandem with this crate's parsing module.
mod
env_file
;
#[cfg(feature
=
"fs"
)]
...
...
This diff is collapsed.
Click to expand it.
src/parser.rs
+
32
−
3
View file @
da8b8ae5
...
...
@@ -13,10 +13,17 @@ use nom::{
};
use
std
::
fmt
::
Display
;
/// Holds one part of the value of an environment variable. Static parts will be used verbatim,
/// while variables will be looked up at render time when an environment file is applied.
/// Comments are always ignored by the renderer, but are preserved for serialization.
#[derive(Clone,
Debug,
PartialEq)]
pub
enum
ValuePart
{
/// A static value that will be rendered verbatim.
Static
(
String
),
/// The exact name of an environment variable that will be looked up at render time.
/// Case-sensitivity is dependent on the operating system.
Variable
(
String
),
/// Arbitrary text that will not be added to the environment.
Comment
(
String
),
}
...
...
@@ -31,12 +38,15 @@ impl Display for ValuePart {
}
impl
ValuePart
{
/// Create a static value that will be used verbatim.
pub
fn
new
(
value
:
impl
ToString
)
->
Self
{
Self
::
Static
(
value
.to_string
())
}
/// Create a reference to another environment variable that will be interpolated into the value.
pub
fn
variable
(
value
:
impl
ToString
)
->
Self
{
Self
::
Variable
(
value
.to_string
())
}
/// Create a comment that will be ignored by the value renderer.
pub
fn
comment
(
value
:
impl
ToString
)
->
Self
{
Self
::
Comment
(
value
.to_string
())
}
...
...
@@ -59,10 +69,18 @@ impl ValuePart {
}
}
/// A whole line of an environment file. May contain comments, static strings, or interpolation
/// variables.
#[derive(Clone,
Debug,
PartialEq)]
pub
enum
FileLine
{
/// A blank lin in a file, containing only whitespace. Ignored for all purposes except 1-1
/// serialisation.
Empty
,
/// A full line comment, starting with a '#' and containing arbitrary text for the rest of the
/// line.
Comment
(
String
),
/// A key-value pair, where the key is a string and the value is a combination of static parts,
/// dynamic parts, and comments.
KeyValue
{
key
:
String
,
value
:
Vec
<
ValuePart
>
},
}
...
...
@@ -79,14 +97,22 @@ impl Display for FileLine {
}
impl
FileLine
{
/// Create a new empty line.
pub
fn
empty
()
->
Self
{
Self
::
Empty
}
/// Create a new full line comment.
pub
fn
comment
(
comment
:
impl
ToString
)
->
Self
{
Self
::
Comment
(
comment
.to_string
())
}
/// Create a new key-value line, where the value may be a combination of static strings,
/// variable references, and comments.
///
/// Lines constructed this way may contain comments in the middle of strings and references
/// without issue, but will not be able to correctly serialise if writing the non-compliant
/// line to a file.
pub
fn
key_value
(
key
:
impl
ToString
,
value
:
impl
ToOwned
<
Owned
=
Vec
<
ValuePart
>>
)
->
Self
{
Self
::
KeyValue
{
key
:
key
.to_string
(),
...
...
@@ -107,8 +133,8 @@ impl FileLine {
Self
::
Comment
(
span
.fragment
()
.to_string
())
}
///
Whether this line is entirely self contained. If the line is a kv pair that requires
/// i
nterpolation, it i
s
n
ot
considered complete
.
///
Returns true if this line can be evaluated by itself. A line cannot be evaluated by itself
/// i
f it reference
s ot
her environment variables
.
pub
fn
is_complete
(
&
self
)
->
bool
{
match
self
{
Self
::
KeyValue
{
value
,
..
}
=>
value
.iter
()
.all
(|
part
|
!
matches!
(
part
,
&
ValuePart
::
Variable
(
..
))),
...
...
@@ -116,6 +142,8 @@ impl FileLine {
}
}
/// Returns a copy of this line without comments. If the entire line is a comment, it is
/// converted to `Line::Empty`. Otherwise, comment parts of key-value lines are removed.
pub
fn
strip_comments
(
&
self
)
->
Self
{
match
self
{
Self
::
Empty
=>
Self
::
Empty
,
...
...
@@ -131,7 +159,8 @@ impl FileLine {
}
}
/// Convert the line into a complete value string
/// Convert the line into a complete value string, interpolating dynamic variables and stripping
/// comments. Empty lines or whole line comments will return an empty string.
pub
fn
assemble_value
(
&
self
)
->
String
{
match
self
{
Self
::
Empty
=>
String
::
new
(),
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment