Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
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
182e5a54
Verified
Commit
182e5a54
authored
6 months ago
by
Louis
Browse files
Options
Downloads
Patches
Plain Diff
Make 'apply' work with EnvFile and Result<EnvFile, T>
parent
3071390e
No related branches found
No related tags found
No related merge requests found
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
src/env_file.rs
+59
-6
59 additions, 6 deletions
src/env_file.rs
src/filesystem.rs
+11
-6
11 additions, 6 deletions
src/filesystem.rs
src/lib.rs
+2
-2
2 additions, 2 deletions
src/lib.rs
src/parser.rs
+1
-1
1 addition, 1 deletion
src/parser.rs
tests/integration.rs
+28
-3
28 additions, 3 deletions
tests/integration.rs
with
101 additions
and
18 deletions
src/env_file.rs
+
59
−
6
View file @
182e5a54
use
std
::
env
;
use
std
::
env
;
use
std
::
env
::
VarError
;
use
std
::
env
::
VarError
;
use
std
::
fmt
::
Display
;
use
crate
::
parser
::{
file
,
FileLine
};
use
crate
::
parser
::{
file
,
FileLine
};
use
nom_locate
::
LocatedSpan
;
use
nom_locate
::
LocatedSpan
;
use
std
::
str
::
FromStr
;
use
std
::
str
::
FromStr
;
...
@@ -102,12 +103,52 @@ impl EnvironmentFile {
...
@@ -102,12 +103,52 @@ impl EnvironmentFile {
pub
fn
is_empty
(
&
self
)
->
bool
{
pub
fn
is_empty
(
&
self
)
->
bool
{
self
.lines
.is_empty
()
self
.lines
.is_empty
()
}
}
}
pub
fn
apply
(
&
self
)
->
Result
<
(),
EnvironmentFileError
>
{
#[derive(Clone,
Debug,
Default)]
set_from_file
(
self
)
pub
struct
ApplyOptions
{
pub
prefix
:
Option
<
String
>
,
pub
overwrite
:
bool
,
}
impl
ApplyOptions
{
pub
fn
new
(
prefix
:
impl
Display
,
overwrite
:
bool
)
->
Self
{
Self
{
prefix
:
Some
(
prefix
.to_string
()),
overwrite
,
}
}
pub
fn
with_prefix
(
prefix
:
impl
Display
)
->
Self
{
Self
::
new
(
prefix
,
false
)
}
pub
fn
with_overwrite
(
overwrite
:
bool
)
->
Self
{
Self
{
prefix
:
None
,
overwrite
,
}
}
}
}
}
pub
trait
ApplyEnvironmentFile
{
fn
apply
(
&
self
,
options
:
ApplyOptions
);
}
impl
ApplyEnvironmentFile
for
EnvironmentFile
{
fn
apply
(
&
self
,
options
:
ApplyOptions
)
{
let
_
=
set_from_file
(
self
,
options
);
}
}
impl
<
E
>
ApplyEnvironmentFile
for
Result
<
EnvironmentFile
,
E
>
{
fn
apply
(
&
self
,
options
:
ApplyOptions
)
{
if
let
Ok
(
file
)
=
self
{
file
.apply
(
options
);
}
}
}
pub
struct
EnvFileIterator
<
'a
>
{
pub
struct
EnvFileIterator
<
'a
>
{
lines
:
&
'a
[
FileLine
],
lines
:
&
'a
[
FileLine
],
current
:
usize
,
current
:
usize
,
...
@@ -166,14 +207,21 @@ fn is_missing_key(key: &str) -> Result<bool, EnvironmentFileError> {
...
@@ -166,14 +207,21 @@ fn is_missing_key(key: &str) -> Result<bool, EnvironmentFileError> {
}
}
}
}
fn
set_from_file
(
file
:
&
EnvironmentFile
)
->
Result
<
(),
EnvironmentFileError
>
{
fn
set_from_file
(
file
:
&
EnvironmentFile
,
options
:
ApplyOptions
)
->
Result
<
(),
EnvironmentFileError
>
{
let
mut
defferred
=
Vec
::
with_capacity
(
file
.len
());
let
mut
defferred
=
Vec
::
with_capacity
(
file
.len
());
for
line
in
file
.lines_kv
()
{
for
line
in
file
.lines_kv
()
{
if
let
FileLine
::
KeyValue
{
key
,
..
}
=
&
line
{
if
let
FileLine
::
KeyValue
{
key
,
..
}
=
&
line
{
if
is_missing_key
(
key
)
?
{
let
key_name
=
if
let
Some
(
prefix
)
=
&
options
.prefix
{
format!
(
"{}{}"
,
prefix
,
key
)
}
else
{
key
.to_string
()
};
if
options
.overwrite
||
is_missing_key
(
&
key_name
)
?
{
if
line
.is_complete
()
{
if
line
.is_complete
()
{
env
::
set_var
(
key
,
line
.assemble_value
());
eprintln!
(
"Setting {} with value {}"
,
key_name
,
line
.assemble_value
());
env
::
set_var
(
key_name
,
line
.assemble_value
());
}
else
{
}
else
{
defferred
.push
(
line
);
defferred
.push
(
line
);
}
}
...
@@ -183,7 +231,12 @@ fn set_from_file(file: &EnvironmentFile) -> Result<(), EnvironmentFileError> {
...
@@ -183,7 +231,12 @@ fn set_from_file(file: &EnvironmentFile) -> Result<(), EnvironmentFileError> {
for
line
in
defferred
{
for
line
in
defferred
{
if
let
FileLine
::
KeyValue
{
key
,
..
}
=
line
{
if
let
FileLine
::
KeyValue
{
key
,
..
}
=
line
{
env
::
set_var
(
key
,
line
.assemble_value
());
let
key_name
=
if
let
Some
(
prefix
)
=
&
options
.prefix
{
format!
(
"{}{}"
,
prefix
,
key
)
}
else
{
key
.to_string
()
};
env
::
set_var
(
key_name
,
line
.assemble_value
());
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
src/filesystem.rs
+
11
−
6
View file @
182e5a54
...
@@ -3,6 +3,7 @@ use std::fmt::Display;
...
@@ -3,6 +3,7 @@ use std::fmt::Display;
use
std
::
fs
::
File
;
use
std
::
fs
::
File
;
use
std
::
io
::
Read
;
use
std
::
io
::
Read
;
use
std
::
path
::
Path
;
use
std
::
path
::
Path
;
use
crate
::
env_file
::{
ApplyEnvironmentFile
,
ApplyOptions
};
#[derive(Debug,
thiserror::Error)]
#[derive(Debug,
thiserror::Error)]
#[allow(clippy::enum_variant_names)]
#[allow(clippy::enum_variant_names)]
...
@@ -31,17 +32,21 @@ pub fn env_file_from_path(path: impl AsRef<Path>) -> Result<EnvironmentFile, Env
...
@@ -31,17 +32,21 @@ pub fn env_file_from_path(path: impl AsRef<Path>) -> Result<EnvironmentFile, Env
}
}
pub
fn
dotenv
()
->
Result
<
(),
EnvFsError
>
{
pub
fn
dotenv
()
->
Result
<
(),
EnvFsError
>
{
let
file
=
env_file
()
?
;
env_file
()
?
.apply
(
Default
::
default
());
file
.apply
()
.map_err
(|
_
|
EnvFsError
::
EnvironmentError
)
Ok
(())
}
pub
fn
dotenv_opts
(
options
:
ApplyOptions
)
->
Result
<
(),
EnvFsError
>
{
env_file
()
?
.apply
(
options
);
Ok
(())
}
}
pub
fn
dotenv_suffix
(
environment
:
impl
Display
)
->
Result
<
(),
EnvFsError
>
{
pub
fn
dotenv_suffix
(
environment
:
impl
Display
)
->
Result
<
(),
EnvFsError
>
{
let
file
=
env_file_suffix
(
environment
)
?
;
env_file_suffix
(
environment
)
?
.apply
(
Default
::
default
())
;
file
.apply
()
.map_err
(|
_
|
EnvFsError
::
EnvironmentError
)
Ok
(()
)
}
}
pub
fn
dotenv_from
(
path
:
impl
AsRef
<
Path
>
)
->
Result
<
(),
EnvFsError
>
{
pub
fn
dotenv_from
(
path
:
impl
AsRef
<
Path
>
)
->
Result
<
(),
EnvFsError
>
{
let
file
=
env_file_from_path
(
path
)
?
;
env_file_from_path
(
path
)
?
.apply
(
Default
::
default
())
;
file
.apply
()
.map_err
(|
_
|
EnvFsError
::
EnvironmentError
)
Ok
(()
)
}
}
This diff is collapsed.
Click to expand it.
src/lib.rs
+
2
−
2
View file @
182e5a54
...
@@ -5,8 +5,8 @@ mod env_file;
...
@@ -5,8 +5,8 @@ mod env_file;
mod
filesystem
;
mod
filesystem
;
mod
parser
;
mod
parser
;
pub
use
env_file
::{
EnvironmentFile
,
EnvironmentFileError
};
pub
use
env_file
::{
EnvironmentFile
,
EnvironmentFileError
,
ApplyEnvironmentFile
,
ApplyOptions
};
pub
use
parser
::{
FileLine
,
ValuePart
};
pub
use
parser
::{
FileLine
,
ValuePart
};
#[cfg(feature
=
"fs"
)]
#[cfg(feature
=
"fs"
)]
pub
use
filesystem
::{
dotenv
,
dotenv_from
,
dotenv_suffix
};
pub
use
filesystem
::{
dotenv
,
dotenv_from
,
dotenv_suffix
,
dotenv_opts
};
This diff is collapsed.
Click to expand it.
src/parser.rs
+
1
−
1
View file @
182e5a54
...
@@ -123,7 +123,7 @@ impl FileLine {
...
@@ -123,7 +123,7 @@ impl FileLine {
Self
::
KeyValue
{
key
,
value
}
=>
Self
::
KeyValue
{
Self
::
KeyValue
{
key
,
value
}
=>
Self
::
KeyValue
{
key
:
key
.clone
(),
key
:
key
.clone
(),
value
:
value
value
:
value
.
into_
iter
()
.iter
()
.filter
(|
part
|
!
matches!
(
part
,
ValuePart
::
Comment
(
..
)))
.filter
(|
part
|
!
matches!
(
part
,
ValuePart
::
Comment
(
..
)))
.cloned
()
.cloned
()
.collect
(),
.collect
(),
...
...
This diff is collapsed.
Click to expand it.
tests/integration.rs
+
28
−
3
View file @
182e5a54
use
envish
::
EnvironmentFile
;
use
envish
::
{
Apply
EnvironmentFile
,
ApplyOptions
,
EnvironmentFile
}
;
#[test]
#[test]
fn
it_parses_basic_dotenv_file
()
{
fn
it_parses_basic_dotenv_file
()
{
...
@@ -14,12 +14,13 @@ fn it_parses_basic_dotenv_file() {
...
@@ -14,12 +14,13 @@ fn it_parses_basic_dotenv_file() {
std
::
env
::
var
(
"SOME_OTHER_VARIABLE"
)
.expect_err
(
"SOME_OTHER_VARIABLE should not be set"
);
std
::
env
::
var
(
"SOME_OTHER_VARIABLE"
)
.expect_err
(
"SOME_OTHER_VARIABLE should not be set"
);
let
file
=
EnvironmentFile
::
parse
(
file_contents
)
.expect
(
"Failed to parse environment file"
);
let
file
=
EnvironmentFile
::
parse
(
file_contents
)
.expect
(
"Failed to parse environment file"
);
file
.apply
(
)
.expect
(
"Failed to apply environment file"
);
file
.apply
(
Default
::
default
()
);
assert_eq!
(
std
::
env
::
var
(
"MY_BEST_VARIABLE"
)
.unwrap
(),
"some_value"
);
assert_eq!
(
std
::
env
::
var
(
"MY_BEST_VARIABLE"
)
.unwrap
(),
"some_value"
);
assert_eq!
(
std
::
env
::
var
(
"SOME_OTHER_VARIABLE"
)
.unwrap
(),
"1234"
);
assert_eq!
(
std
::
env
::
var
(
"SOME_OTHER_VARIABLE"
)
.unwrap
(),
"1234"
);
}
}
#[test]
fn
it_parses_dotenv_file_with_interpolation
()
{
fn
it_parses_dotenv_file_with_interpolation
()
{
let
file_contents
=
r#"
let
file_contents
=
r#"
# This value won't be set in the test, and this comment will be ignored
# This value won't be set in the test, and this comment will be ignored
...
@@ -36,9 +37,33 @@ fn it_parses_dotenv_file_with_interpolation() {
...
@@ -36,9 +37,33 @@ fn it_parses_dotenv_file_with_interpolation() {
std
::
env
::
var
(
"INTERPOLATED_VARIABLE"
)
.expect_err
(
"INTERPOLATED_VARIABLE should not be set"
);
std
::
env
::
var
(
"INTERPOLATED_VARIABLE"
)
.expect_err
(
"INTERPOLATED_VARIABLE should not be set"
);
let
file
=
EnvironmentFile
::
parse
(
file_contents
)
.expect
(
"Failed to parse environment file"
);
let
file
=
EnvironmentFile
::
parse
(
file_contents
)
.expect
(
"Failed to parse environment file"
);
file
.apply
(
)
.expect
(
"Failed to apply environment file"
);
file
.apply
(
Default
::
default
()
);
assert_eq!
(
std
::
env
::
var
(
"MY_BEST_VARIABLE"
)
.unwrap
(),
"some_value"
);
assert_eq!
(
std
::
env
::
var
(
"MY_BEST_VARIABLE"
)
.unwrap
(),
"some_value"
);
assert_eq!
(
std
::
env
::
var
(
"SOME_OTHER_VARIABLE"
)
.unwrap
(),
"1234"
);
assert_eq!
(
std
::
env
::
var
(
"SOME_OTHER_VARIABLE"
)
.unwrap
(),
"1234"
);
assert_eq!
(
std
::
env
::
var
(
"INTERPOLATED_VARIABLE"
)
.unwrap
(),
"1234567"
);
assert_eq!
(
std
::
env
::
var
(
"INTERPOLATED_VARIABLE"
)
.unwrap
(),
"1234567"
);
}
#[test]
fn
it_parses_dotenv_file_with_interpolation_and_prefix_option
()
{
let
file_contents
=
r#"
# This value won't be set in the test, and this comment will be ignored
MY_BEST_VARIABLE=some_value
# This variable is also not defined, and it'll still be a string,
# because all environment variables are strings without being converted to other data types
SOME_OTHER_VARIABLE=1234
# This variable contains an interpolated value
INTERPOLATED_VARIABLE=${SOME_OTHER_VARIABLE}567
"#
;
std
::
env
::
var
(
"MY_BEST_VARIABLE"
)
.expect_err
(
"MY_BEST_VARIABLE should not be set"
);
std
::
env
::
var
(
"SOME_OTHER_VARIABLE"
)
.expect_err
(
"SOME_OTHER_VARIABLE should not be set"
);
std
::
env
::
var
(
"INTERPOLATED_VARIABLE"
)
.expect_err
(
"INTERPOLATED_VARIABLE should not be set"
);
let
file
=
EnvironmentFile
::
parse
(
file_contents
)
.expect
(
"Failed to parse environment file"
);
file
.apply
(
ApplyOptions
::
with_prefix
(
"APP_"
));
assert_eq!
(
std
::
env
::
var
(
"APP_MY_BEST_VARIABLE"
)
.unwrap
(),
"some_value"
);
assert_eq!
(
std
::
env
::
var
(
"APP_SOME_OTHER_VARIABLE"
)
.unwrap
(),
"1234"
);
assert_eq!
(
std
::
env
::
var
(
"APP_INTERPOLATED_VARIABLE"
)
.unwrap
(),
"1234567"
);
}
}
\ No newline at end of file
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